pax_global_header00006660000000000000000000000064142114357150014515gustar00rootroot0000000000000052 comment=a63c51805eb11390f7e1210e4b6cec59dee1dcc1 libtpms-0.9.3/000077500000000000000000000000001421143571500132005ustar00rootroot00000000000000libtpms-0.9.3/.github/000077500000000000000000000000001421143571500145405ustar00rootroot00000000000000libtpms-0.9.3/.github/ISSUE_TEMPLATE/000077500000000000000000000000001421143571500167235ustar00rootroot00000000000000libtpms-0.9.3/.github/ISSUE_TEMPLATE/bug_report.md000066400000000000000000000010631421143571500214150ustar00rootroot00000000000000--- name: Bug report about: Create a report to help us improve title: '' labels: '' assignees: '' --- **Describe the bug** A clear and concise description of what the bug is. **To Reproduce** Steps to reproduce the behavior: 1. 2. 3. 4. **Expected behavior** A clear and concise description of what you expected to happen. **Desktop (please complete the following information):** - OS: [e.g. Fedora] - Version [e.g. 33] **Versions of relevant components** - libtpms: - openssl: - ...: **Additional context** Add any other context about the problem here. libtpms-0.9.3/.gitignore000066400000000000000000000017161421143571500151750ustar00rootroot00000000000000*.exe *.exe.stackdump *.gcda *.gch *.gcno *.gcov *.la *.lo *.log *.o *.trs *~ .deps .dirstamp .libs .pc/ configure compile depcomp missing Makefile.in Makefile /aclocal.m4 /autom4te.cache /config.h /config.h.in /config.guess /config.log /config.status /config.sub /install-sh /libtool /libtpms.pc /libtpms-*.tar.gz /ltmain.sh /stamp-h1 /test-driver /m4/* !m4/ax_check_define.m4 !m4/ax_check_linker_flag.m4 /man/man3/*.3 !man/man3/TPMLIB_GetState.3 !man/man3/TPMLIB_SetDebugLevel.3 !man/man3/TPMLIB_SetDebugPrefix.3 !man/man3/TPMLIB_Terminate.3 !man/man3/TPM_Free.3 !man/man3/TPM_IO_Hash_Data.3 !man/man3/TPM_IO_Hash_End.3 !man/man3/TPM_IO_TpmEstablished_Reset.3 !man/man3/TPM_Realloc.3 /tests/NVChip /tests/base64decode /tests/fuzz /tests/freebl_sha1flattensize /tests/nvram_offsets /tests/tpm2_createprimary /tests/tpm2_pcr_read /tests/tpm2_selftest /debian/*debhelper* /debian/*substvars /debian/autoreconf.* /debian/files /debian/libtpms-dev /debian/libtpms0 /debian/tmp libtpms-0.9.3/.travis.yml000066400000000000000000000071711421143571500153170ustar00rootroot00000000000000language: c dist: xenial env: global: secure: THraWTkpyL+b3lcnLenhXR6sxphcJS23MoUP36PT9VYhgZRI2YjO1w2h4V0uwzovbGJDU4Tc88Yxn8kL4RSgwy9cIcJcTOAorbePVRd+UFVU0nUjhwYLCKYBTLVLo7lYc0FHTgsdsba65X6keuSlAdegzCRbTvcwNqX9nanSRGI1CvYcwx22Iu5eOdJvMjwIuFOuECs7hVFrGS2rvGoyzqGNMT4A8shXOBZM/pwklRFS1oS/L1g45y3OP27yqINjtfC7wXRGsR8ItH7LAaQ+yCzNg3QzSd/3H3niEC5grcEMS23YugFUkGpqSca8SGJmkK2LFaBctpZS1P75lA/47Bxbh/byu85TUE6wZ+VPm520NkiYtBB+oxIbq1mYv+hhKuxPf5OqzdwLXVO7EAfzO57VkUqQfumWIZqV0WqCU3SdpRk+CUCCURR4P0ww+w6hQx6PzK21+d9tLtqMqdRwuricdyeLvxboWQXXl36fPf4ifmi0AZ6ILaV/LUQu24Di56RG4hO+/Pv/Qqxa8rJLpqJa0PtsYIiBNeVYLH/ZYIlS8saBedMIJ9dqh1dvBw/Jql8EZCOWif6UjYzQFgZAOZQqH9VAp1WVwQxQRo+Sq7dy+MtRKT2GEcNrdfYcL6qucBAQY00vQQBfl+FOnEzIAUImt4tbitnYTxmNx8N+QZU= addons: apt: packages: - automake - autoconf - pkgconf - libtool - libssl-dev - sed - make - gawk - sed - bash - dh-exec - libseccomp-dev coverity_scan: project: name: libtpms description: Build submitted via Travis CI notification_email: stefanb@linux.vnet.ibm.com build_command_prepend: "./autogen.sh --with-openssl --with-tpm2; make clean" build_command: make -j$(nproc) branch_pattern: coverity_scan script: - ./autogen.sh ${CONFIG} - make -j$(${NPROC}) ${TARGET} after_failure: - for f in tests/*.log; do echo ">>>>>>> $f <<<<<<<"; tail -n 50 $f; done before_install: - test $TRAVIS_BRANCH != coverity_scan -o ${TRAVIS_JOB_NUMBER##*.} = 1 || exit 0 matrix: include: - env: CONFIG="--with-openssl --prefix=/usr --with-tpm2" "TARGET=distcheck" NPROC="nproc" CFLAGS="-O3" - env: CONFIG="--with-openssl --prefix=/usr --with-tpm2 --enable-test-coverage" TARGET="install" NPROC="nproc" dist: bionic before_script: - sudo pip install cpp-coveralls script: ./autogen.sh ${CONFIG} && sudo make -j$(nproc) ${TARGET} && sudo make -j$(nproc) check && git clone https://github.com/stefanberger/swtpm.git && pushd swtpm && sudo rm -rf /dev/tpm* && sudo apt -y install devscripts equivs python3-twisted expect libtasn1-dev socat findutils gnutls-dev gnutls-bin tss2 python3-setuptools libjson-glib-dev && ./autogen.sh --with-gnutls --prefix=/usr && export SWTPM_TEST_EXPENSIVE=1 SWTPM_TEST_IBMTSS2=1 && sudo make -j$(nproc) check && popd after_success: uidgid="$(id -nu):$(id -ng)" && sudo chown -R ${uidgid} ./ && cpp-coveralls -b src -e tests -e swtpm --gcov-options '\-lp' - env: CONFIG="--with-openssl --prefix=/usr --with-tpm2 --enable-test-coverage --disable-use-openssl-functions" TARGET="install" NPROC="nproc" dist: bionic script: ./autogen.sh ${CONFIG} && sudo make -j$(nproc) ${TARGET} && sudo make -j$(nproc) check && git clone https://github.com/stefanberger/swtpm.git && pushd swtpm && sudo rm -rf /dev/tpm* && sudo apt -y install devscripts equivs python3-twisted expect libtasn1-dev socat findutils gnutls-dev gnutls-bin tss2 python3-setuptools libjson-glib-dev && ./autogen.sh --with-gnutls --prefix=/usr && export SWTPM_TEST_EXPENSIVE=1 SWTPM_TEST_IBMTSS2=1 && sudo make -j$(nproc) check && popd - env: CONFIG="--with-openssl --prefix=/usr --with-tpm2" "TARGET=check" NPROC="sysctl -n hw.ncpu" CFLAGS="-I/usr/local/opt/openssl/include" LDFLAGS="-L/usr/local/opt/openssl/lib" # 'distcheck' results in duplicate symbol errors os: osx compiler: clang libtpms-0.9.3/CHANGES000066400000000000000000000064671421143571500142100ustar00rootroot00000000000000CHANGES - changes for libtpms version 0.9.3: - build-sys: Add probing for -fstack-protector - tpm2: Do not call EVP_PKEY_CTX_set0_rsa_oaep_label() for label of size (OSSL 3) version 0.9.2: - tpm2: When writing state initialize s_ContextSlotMask if not set version 0.9.1: - tpm2: Do not write permanent state if only clock changed - tpm2: Fix "maybe-uninitialized" warning version 0.9.0: - NOTE: Downgrade to previous versions is not possible. See below. - The size of the context gap has been adjusted to 0xffff from 0xff. As a consequence of this the volatile state's format (STATE_RESET_DATA) has changed and cannot be downgraded. - Applied work-around for Win 2016 & 2019 server related to TPM2_ContextLoad (issue #217) - Check for several more compile-time constants - Enabled Camellia symmetric key encryption algorithm - tpm2: CryptSym: fix AES output IV - tpm2: Added a cache for private exponent D and prime Q - tpm2: bug fixes related to state marshalling - tpm2: Consume padding bytes in TPM2_ContextLoad() (Win2k19, issue #217) - tests: Improvements on the fuzzer - tpm2: Switch to UINT16 for CONTEXT_SLOT and 64k context gap - tpm2: Update to TPM 2 spec rev 164 - build-sys: Enable building --without-tpm1 - tpm2: Marshal event sequence objects' hash state - tpm2: Fixes for build and runtime when using OpenSSL 3.0 version 0.8.0 - NOTE: Downgrade to previous versions is not possible. See below. - Update to TPM 2 code release 159 - X509 support is enabled - SM2 signing of ceritificates is NOT supported - Authenticated timers are disabled - Due to fixes in the TPM 2 prime number generation code in rev155 it is not possible to downgrade from libtpms version 0.8.0 to some previous version. The seeds are now associated with an age so that older seeds use the old TPM 2 prime number generation code while newer seed use the newer code. - Update to TPM 2 code release 162 - ECC encryption / decryption is disabled - Fix support for elliptic curve due to missing unmarshalling code - Runtime filter supported elliptic curves supported by OpenSSL - Fix output buffer parameter and size for RSA decryption that could cause stack corruption under certain circumstances - Set the RSA PSS salt length to the digest length rather than max. possible - Fixes to symmetric decryption related to input size check, defer padding to the user [EVP_CIPHER_CTX_set_padding(ctx, 0)] and to always use a temporary malloc'ed buffer for decryption - Fixed the set of PCRs belonging to the TCB group. This affects the pcrUpdateCounter in TPM2_Pcrread() responses, thus needs latest `swtpm` for test cases to succeed there. version 0.7.0 - use OpenSSL crypto for AES, TDES, EC, and RSA operations when possible version 0.6.0 - added TPM 2 support (revision 150) - New API calls: - TPMLIB_CancelCommand - TPMLIB_ChooseTPMVersion - TPMLIB_SetDebugFD - TPMLIB_SetDebugLevel - TPMLIB_SetDebugPrefix - TPMLIB_SetBufferSize - TPMLIB_ValidateState - TPMLIB_SetState - TPMLIB_GetState version 0.5.1 first public release - release 7 increased NVRAM area for being able to store more data in the TPM's NVRAM areas, i.e., X.509 certificates - release 9 added two more APIs: - TPM_Free - TPMLIB_DecodeBlob libtpms-0.9.3/CREDITS000066400000000000000000000003311421143571500142150ustar00rootroot00000000000000The libtpms code was originally written by Kenneth Goldman . The code has since been modified by Stefan Berger . Other contributors: Corey Bryant libtpms-0.9.3/DCO1.1.txt000066400000000000000000000023601421143571500145670ustar00rootroot00000000000000Developer's Certificate of Origin 1.1 By making a contribution to this project, I certify that: (a) The contribution was created in whole or in part by me and I have the right to submit it under the open source license indicated in the file; or (b) The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate open source license and I have the right under that license to submit that work with modifications, whether created in whole or in part by me, under the same open source license (unless I am permitted to submit under a different license), as indicated in the file; or (c) The contribution was provided directly to me by some other person who certified (a), (b) or (c) and I have not modified it. (d) I understand and agree that this project and the contribution are public and that a record of the contribution (including all personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the open source license(s) involved. libtpms-0.9.3/INSTALL000066400000000000000000000112651421143571500142360ustar00rootroot00000000000000This document contains the following sections: ============================================== - Quick start - Building libtpms - Installing libtpms, include files and man pages - Uninstalling libtpms, include files and man pages - More on man pages Quick start: ------------ The libtpms library can be built using the steps (after installing dependencies): # ./autogen.sh --with-tpm2 --with-openssl --prefix=/usr # make # make check # sudo make install Building libtpms: ----------------- The configure script needs to be run first, and can be done using: ./autogen.sh --with-tpm2 --with-openssl By default, files will be installed in '/usr/local/lib', etc. If you would like to have these files installed in '/usr/lib', etc, then run configure using the following command line. On some distributions it may be necessary to also pass --libdir=/lib64 (for 64 bit systems). ./autogen.sh --prefix=/usr --with-tpm2 --with-openssl For more details on configure options, run "./configure -h". Building libtpms can be done using: make all The library is known to build on Linux and Cygwin systems and possible other Operating Systems that use .so as library extensions. On Linux systems, libtpms can be built with either one of the following crypto backends: - openssl - freebl (TPM 1.2 support only) On Cygwin only openssl is available and therefore can only be built with openssl. To build for openssl, the following development packages must have been installed: Fedora/RedHat: - automake - autoconf - libtool - make - gcc - glibc-headers - openssl-devel Ubuntu: - automake - autoconf - libtool - make - gcc - libc-dev - libssl-dev To build for freebl (TPM 1.2 support only), the following development packages must have been installed prior to compilation: Fedora/RedHat: - glibc-headers - nss-softokn-freebl-devel (preferably version 3.12.9-2 or newer) - nss-softokn-devel (preferably version 3.12.9-2 or newer) - gmp-devel Ubuntu: - libc6-dev - libgmp-dev - libnspr4-dev - libnss3-dev (preferably version 3.17.2; needs to have blapi.h) By default, libtpms is built with the openssl crypto library, which was shown above. To build with the freebl crypto library the following command line can be used (TPM 1.2 support only): ./autogen.sh --prefix=/usr make all install To verify that libtpms was built with freebl as the crypto backend, one can run: ldd /usr/lib/libtpms.so or ldd /usr/lib64/libtpms.so linux-vdso.so.1 => (0x00007fff8d5ff000) libgmp.so.3 => /usr/lib64/libgmp.so.3 (0x00007f5352a13000) libnspr4.so => /lib64/libnspr4.so (0x00007f53527d6000) libnssutil3.so => /usr/lib64/libnssutil3.so (0x00007f53525b6000) libnss3.so => /usr/lib64/libnss3.so (0x00007f535227c000) libc.so.6 => /lib64/libc.so.6 (0x00007f5351ed8000) libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f5351cba000) libdl.so.2 => /lib64/libdl.so.2 (0x00007f5351ab6000) libplc4.so => /lib64/libplc4.so (0x00007f53518b2000) libplds4.so => /lib64/libplds4.so (0x00007f53516ae000) /lib64/ld-linux-x86-64.so.2 (0x0000003a1c000000) The fact that the libraries libgmp, libnspr4, libnssutil3, libnss3, libpc4, and libplds4 are linked against is an indication that the freebl library was used for linking. In case of openssl's libcrypto the output would be the following: linux-vdso.so.1 => (0x00007fffcbdff000) libcrypto.so.10 => /lib64/libcrypto.so.10 (0x00007fdb1d00e000) libc.so.6 => /lib64/libc.so.6 (0x00007fdb1cc6a000) libdl.so.2 => /lib64/libdl.so.2 (0x00007fdb1ca65000) libz.so.1 => /lib64/libz.so.1 (0x00007fdb1c84e000) /lib64/ld-linux-x86-64.so.2 (0x0000003a1c000000) Installing libtpms, include files and man pages: ------------------------------------------------ The installation of libtpms, the development include files (headers) and man pages can be achieved through: make install This will copy libtpms into the standard library directory on your Linux system such as /usr/lib or /usr/lib64, depending on whether you built for a 32 bit or 64 bit machine. The public include files of libtpms will be copied to /usr/include/libtpms. The man pages explaining the libtpms API will be copied to /usr/share/man. Uninstalling libtpms, include files and man pages: -------------------------------------------------- The libtpms library, its development include files (headers) and man pages can be uninstalled from their standard locations using make uninstall More on man pages ----------------- All of the libtpms APIs have a man page. The man pages contain explanations on how to use the APIs as well as examples. Once installed, they can be viewed as a typical man page: man TPMLIB_MainInit Otherwise, if they are not installed, they can then be viewed from the libtpms root directory using: man -M ./man TPMLIB_MainInit libtpms-0.9.3/LICENSE000066400000000000000000000101541421143571500142060ustar00rootroot00000000000000Libtpms license For the TPM 1.2 code and the library code the following license applies: (c) Copyright IBM Corporation 2006 - 2011 All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the names of the IBM Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. For the TPM 2 code the following license and notices apply: Licenses and Notices 1. Copyright Licenses: - Trusted Computing Group (TCG) grants to the user of the source code in this specification (the "Source Code") a worldwide, irrevocable, nonexclusive, royalty free, copyright license to reproduce, create derivative works, distribute, display and perform the Source Code and derivative works thereof, and to grant others the rights granted herein. - The TCG grants to the user of the other parts of the specification (other than the Source Code) the rights to reproduce, distribute, display, and perform the specification solely for the purpose of developing products based on such documents. 2. Source Code Distribution Conditions: - Redistributions of Source Code must retain the above copyright licenses, this list of conditions and the following disclaimers. - Redistributions in binary form must reproduce the above copyright licenses, this list of conditions and the following disclaimers in the documentation and/or other materials provided with the distribution. 3. Disclaimers: - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. Contact TCG Administration (admin@trustedcomputinggroup.org) for information on specification licensing rights available through TCG membership agreements. - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. - Without limitation, TCG and its members and licensors disclaim all liability, including liability for infringement of any proprietary rights, relating to use of information in this specification and to the implementation of this specification, and TCG disclaims all liability for cost of procurement of substitute goods or services, lost profits, loss of use, loss of data or any incidental, consequential, direct, indirect, or special damages, whether under contract, tort, warranty or otherwise, arising in any way out of use or reliance upon this specification or any information herein. (c) Copyright IBM Corp. and others, 2012-2016 libtpms-0.9.3/Makefile.am000066400000000000000000000023351421143571500152370ustar00rootroot00000000000000# # Makefile.am # # The Initial Developer of the Original Code is International # Business Machines Corporation. Portions created by IBM # Corporation are Copyright (C) 2005, 2011 International Business # Machines Corporation. All Rights Reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of the Common Public License as published by # IBM Corporation; either version 1 of the License, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # Common Public License for more details. # # You should have received a copy of the Common Public License # along with this program; if not, a copy can be viewed at # http://www.opensource.org/licenses/cpl1.0.php. # SUBDIRS = \ include \ man \ src \ tests ACLOCAL_AMFLAGS = -I m4 EXTRA_DIST = \ CHANGES \ INSTALL \ LICENSE \ README \ bootstrap.sh \ libtpms.pc.in \ autogen.sh pkgconfig_DATA = libtpms.pc DISTCHECK_CONFIGURE_FLAGS = --with-openssl --with-tpm2 libtpms-0.9.3/README000066400000000000000000000057301421143571500140650ustar00rootroot00000000000000What is libtpms? ---------------- Libtpms is a library that targets the integration of TPM functionality into hypervisors, primarily into Qemu. Libtpms provides a very narrow public API for this purpose so that integration is possible. Only the minimum of necessary APIs are made publicly available. It is assumed that the user of libtpms is familiar with the concepts of the Trusted Platform Module (TPM). For the interaction with libtpms it is necessary to know how to construct valid TPM commands and to be able to parse their results. It is not within the scope of libtpms's documentation to provide background on this. See the section on references below. What files does the libtpms package provide? -------------------------------------------- The main libtpms package provides the following files: /usr/lib64/libtpms.so.0 /usr/lib64/libtpms.so.0.5.1 /usr/share/doc/libtpms-0.5.1 /usr/share/doc/libtpms-0.5.1/CHANGES /usr/share/doc/libtpms-0.5.1/LICENSE /usr/share/doc/libtpms-0.5.1/README Applications can link with -ltpms. What files does the libtpms development package provide? -------------------------------------------------------- The libtpms development package (libtpms-devel) provides the following include files for applications to use: tpm_error.h tpm_library.h tpm_memory.h tpm_nvfilename.h tpm_tis.h tpm_types.h These files contain the data structures, data types and API calls supported by libtpms. It is recommended to not use any other API calls than those provided in these include files. All APIs are described in man pages. The man pages are part of the libtpms development package as well: TPMLIB_DecodeBlob TPMLIB_GetTPMProperty TPMLIB_GetVersion TPMLIB_MainInit TPMLIB_Process TPMLIB_RegisterCallbacks TPMLIB_Terminate TPMLIB_VolatileAll_Store TPM_Free TPM_IO_Hash_Data TPM_IO_Hash_End TPM_IO_Hash_Start TPM_IO_TpmEstablished_Get TPM_Malloc TPM_Realloc How to contribute? ------------------ The mailing list for libtpms is libtpms@googlegroups.com. For patch submissions, please use a Signed-off-by: to indicate agreement to the DCO1.1.txt. Fuzzing ------- Initial fuzzing is possible with clang & libfuzzer. You have to configure the project with --enable-fuzzer (--enable-sanitizer can also help spot more issues). Then you can build fuzz and run it with the testing corpus. Fuzz testing is known to work with Fedora 28 or later. It requires that the 'clang' package is installed. Ex: $ ./configure --with-openssl --with-tpm2 --enable-sanitizers --enable-fuzzer \ CC=clang CXX=clang++ $ make && make -C tests fuzz $ tests/run-fuzzer.sh oss-fuzz builds with its own fuzzer flags, and set $LIB_FUZZING_ENGINE to be linked with. The script run by oss-fuzz is tests/oss-fuzz.sh. Maintainers ----------- libtpms is currently being maintained by Stefan Berger . References: ----------- Documentation about the Trusted Platform Module (TPM) can be downloaded from the Trusted Computing Group's website at http://www.trustedcomputinggroup.org libtpms-0.9.3/autogen.sh000077500000000000000000000003531421143571500152020ustar00rootroot00000000000000#!/bin/sh set -e # exit on errors srcdir=`dirname $0` test -z "$srcdir" && srcdir=. olddir=`pwd` cd "$srcdir" autoreconf --verbose --force --install cd "$olddir" if [ -z "$NOCONFIGURE" ]; then "$srcdir"/configure ${1+"$@"} fi libtpms-0.9.3/bootstrap.sh000077500000000000000000000002141421143571500155510ustar00rootroot00000000000000#!/bin/sh set -x libtoolize --force || exit 1 aclocal || exit 1 autoheader || exit 1 automake --add-missing -c || exit 1 autoconf || exit 1 libtpms-0.9.3/configure.ac000066400000000000000000000303301421143571500154650ustar00rootroot00000000000000# # configure.in # # See the LICENSE file for the license associated with this file. AC_INIT([libtpms],[0.9.3]) AC_PREREQ([2.69]) AC_CONFIG_SRCDIR(Makefile.am) AC_CONFIG_AUX_DIR([.]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_MACRO_DIR([m4]) AC_CANONICAL_TARGET AM_INIT_AUTOMAKE([foreign 1.6 subdir-objects]) AM_SILENT_RULES([yes]) LIBTPMS_VER_MAJOR=`echo $PACKAGE_VERSION | awk -F. '{print $1}'` LIBTPMS_VER_MINOR=`echo $PACKAGE_VERSION | awk -F. '{print $2}'` LIBTPMS_VER_MICRO=`echo $PACKAGE_VERSION | awk -F. '{print $3}'` LIBTPMS_VERSION=$PACKAGE_VERSION LIBTPMS_VERSION_INFO=`expr $LIBTPMS_VER_MAJOR + $LIBTPMS_VER_MINOR`:$LIBTPMS_VER_MICRO:$LIBTPMS_VER_MINOR AC_SUBST([LIBTPMS_VER_MAJOR]) AC_SUBST([LIBTPMS_VER_MINOR]) AC_SUBST([LIBTPMS_VER_MICRO]) AC_SUBST([LIBTPMS_VERSION]) AC_SUBST([LIBTPMS_VERSION_INFO]) DEBUG="" AC_MSG_CHECKING([for debug-enabled build]) AC_ARG_ENABLE(debug, AS_HELP_STRING([--enable-debug],[create a debug build]), [if test "$enableval" = "yes"; then DEBUG="yes" AC_MSG_RESULT([yes]) else DEBUG="no" AC_MSG_RESULT([no]) fi], [DEBUG="no", AC_MSG_RESULT([no])]) if test "$DEBUG" = "yes"; then CFLAGS="$CFLAGS -O0 -g -DDEBUG" fi debug_defines= if test "$DEBUG" = "yes"; then debug_defines="-DTPM_DEBUG" # Enable the following only if ABSOLUTELY necessary # volatile state will be written and behavior changes #"-DTPM_VOLATILE_STORE" fi AC_SUBST(DEBUG_DEFINES, $debug_defines) # AX_CHECK_LINK_FLAG needs autoconf 2.64 or later have_version_script="no" m4_if( m4_version_compare( m4_defn([AC_AUTOCONF_VERSION]), [2.64]), -1, [], [AX_CHECK_LINK_FLAG([-Wl,--version-script=$srcdir/src/test.syms], [have_version_script="yes"], [])] ) AM_CONDITIONAL([HAVE_VERSION_SCRIPT], [test "x$have_version_script" = "xyes"]) AC_ARG_WITH([tpm1], AS_HELP_STRING([--with-tpm1], [build libtpms with TPM 1.2 support]), [], [with_tpm1=yes]) AM_CONDITIONAL([WITH_TPM1], [test "x$with_tpm1" != "xno"]) AS_IF([test "x$with_tpm1" != "xno"], [ AC_DEFINE([WITH_TPM1], [1], [With TPM 1.2 support]) AC_SUBST([WITH_TPM1], [1]) ]) AC_ARG_WITH([tpm2], AS_HELP_STRING([--with-tpm2],[build libtpms with TPM2 support]), [], [with_tpm2=yes] ) AS_IF([test "x$with_tpm2" = xyes], [ AC_MSG_RESULT([Building with TPM2 support]) AC_DEFINE_UNQUOTED([WITH_TPM2], 1, [whether to support TPM2]) AC_SUBST([WITH_TPM2], [1]) AM_CONDITIONAL(WITH_TPM2, true) cryptolib=openssl ], [ AM_CONDITIONAL(WITH_TPM2, false) cryptolib=freebl ]) AC_SUBST(cryptolib, $cryptolib) AC_ARG_WITH([openssl], AS_HELP_STRING([--with-openssl],[build libtpms with openssl library]), [AC_CHECK_LIB(crypto, [AES_set_encrypt_key], [], AC_MSG_ERROR(Faulty openssl crypto library)) AC_CHECK_HEADERS([openssl/aes.h],[], AC_MSG_ERROR(Is openssl-devel/libssl-dev installed?)) AC_MSG_RESULT([Building with openssl crypto library]) cryptolib=openssl ] ) case "$cryptolib" in freebl) AM_CONDITIONAL(LIBTPMS_USE_FREEBL, true) AM_CONDITIONAL(LIBTPMS_USE_OPENSSL, false) AC_DEFINE([USE_FREEBL_CRYPTO_LIBRARY], [1], [use freebl crypto library]) CFLAGS_save=$CFLAGS AC_CHECK_HEADERS([gmp.h],[], AC_MSG_ERROR(gmp-devel/libgmp-dev is bad)) CFLAGS="$(nspr-config --cflags)" if test $? -ne 0; then AC_MSG_ERROR(Could not find nspr-config. Is nspr-devel/libnspr4-dev installed?) fi CPPFLAGS=$CFLAGS AC_CHECK_HEADERS([plbase64.h],[], AC_MSG_ERROR(You must install nspr-devel/libnspr4-dev)) CFLAGS="$(nss-config --cflags) $CFLAGS" if test $? -ne 0; then AC_MSG_ERROR(Could not find nss-config. Is nss-devel/libnss3-dev installed?) fi CPPFLAGS="$CPPFLAGS $CFLAGS" AC_CHECK_HEADERS([sslerr.h],[], AC_MSG_ERROR(nss-devel/libnss3-dev is bad)) # Check for missing headers AC_CHECK_HEADERS([blapi.h],[], AC_MSG_ERROR(nss-softokn-freebl-devel/libnss3-dev is missing blapi.h)) # Check for missing freebl library or missing library functions LIBS_save="$LIBS" LIBS="$(nss-config --libs) $(nspr-config --libs)" AC_SEARCH_LIBS([AES_CreateContext], [freebl],[], AC_MSG_ERROR("Could not find AES_CreateContext(). Is nss-softokn-freebl-devel/libnss3-dev installed?"), []) LIBS="$LIBS_save" CFLAGS="$CFLAGS_save $CFLAGS" enable_use_openssl_functions=no ;; openssl) AM_CONDITIONAL(LIBTPMS_USE_FREEBL, false) AM_CONDITIONAL(LIBTPMS_USE_OPENSSL, true) AC_DEFINE([USE_OPENSSL_CRYPTO_LIBRARY], [1], [use openssl crypto library]) LIBCRYPTO_EXTRA_CFLAGS="-DOPENSSL_SUPPRESS_DEPRECATED" AC_SUBST([LIBCRYPTO_EXTRA_CFLAGS]) ;; esac use_openssl_functions_for="" use_openssl_functions_symmetric=0 use_openssl_functions_ec=0 use_openssl_functions_ecdsa=0 use_openssl_functions_rsa=0 AC_ARG_ENABLE(use-openssl-functions, AS_HELP_STRING([--disable-use-openssl-functions], [Use TPM 2 crypot code rather than OpenSSL crypto functions]), ) AS_IF([test "x$enable_use_openssl_functions" != "xno"], [ if test "x$cryptolib" != "xopenssl"; then AC_MSG_ERROR([OpenSSL crypto function usage requires openssl as crypto library]) fi LIBS_save=$LIBS # Check for symmetric key crypto functions not_found=0 AC_CHECK_LIB([crypto], [EVP_CIPHER_CTX_new],, not_found=1) AC_CHECK_LIB([crypto], [EVP_EncryptInit_ex],, not_found=1) AC_CHECK_LIB([crypto], [EVP_aes_128_cbc],, not_found=1) AC_CHECK_LIB([crypto], [EVP_des_ede3_cbc],, not_found=1) AC_CHECK_LIB([crypto], [EVP_camellia_128_cbc],, not_found=1) AC_CHECK_LIB([crypto], [DES_random_key],, not_found=1) AC_CHECK_LIB([crypto], [EVP_CIPHER_CTX_iv],, not_found=1) if test "x$not_found" = "x0"; then use_openssl_functions_symmetric=1 use_openssl_functions_for="symmetric (AES, TDES) " fi # Check for EC crypto support not_found=0 AC_CHECK_LIB([crypto], [EC_KEY_set_group],, not_found=1) AC_CHECK_LIB([crypto], [EC_KEY_generate_key],, not_found=1) AC_CHECK_LIB([crypto], [EC_KEY_get0_private_key],, not_found=1) if test "x$not_found" = "x0"; then use_openssl_functions_ec=1 use_openssl_functions_for="${use_openssl_functions_for}general elliptic curve (EC) " fi # Check for ECDSA crypto support not_found=0 AC_CHECK_LIB([crypto], [ECDSA_SIG_new],, not_found=1) AC_CHECK_LIB([crypto], [ECDSA_SIG_set0],, not_found=1) AC_CHECK_LIB([crypto], [ECDSA_do_verify],, not_found=1) AC_CHECK_LIB([crypto], [ECDSA_do_sign],, not_found=1) AC_CHECK_LIB([crypto], [EC_KEY_set_group],, not_found=1) if test "x$not_found" = "x0"; then use_openssl_functions_ecdsa=1 use_openssl_functions_for="${use_openssl_functions_for}elliptic curve (ECDSA) " fi # Check for RSA crypto functions not_found=0 AC_CHECK_LIB([crypto], [RSA_set0_key],, not_found=1) AC_CHECK_LIB([crypto], [RSA_set0_factors],, not_found=1) AC_CHECK_LIB([crypto], [RSA_set0_crt_params],, not_found=1) AC_CHECK_LIB([crypto], [RSA_generate_key_ex],, not_found=1) AC_CHECK_LIB([crypto], [EVP_PKEY_CTX_new],, not_found=1) AC_CHECK_LIB([crypto], [EVP_PKEY_assign],, not_found=1) AC_CHECK_LIB([crypto], [EVP_PKEY_encrypt_init],, not_found=1) AC_CHECK_LIB([crypto], [EVP_PKEY_encrypt],, not_found=1) AC_CHECK_LIB([crypto], [EVP_PKEY_decrypt_init],, not_found=1) AC_CHECK_LIB([crypto], [EVP_PKEY_decrypt],, not_found=1) AC_CHECK_LIB([crypto], [EVP_PKEY_sign_init],, not_found=1) AC_CHECK_LIB([crypto], [EVP_PKEY_sign],, not_found=1) AC_CHECK_LIB([crypto], [EVP_PKEY_verify_init],, not_found=1) AC_CHECK_LIB([crypto], [EVP_PKEY_verify],, not_found=1) AC_CHECK_LIB([crypto], [EVP_get_digestbyname],, not_found=1) # OpenSSL 3.0 turned some #defines into functions AX_CHECK_DEFINE([], [EVP_PKEY_CTX_set0_rsa_oaep_label],, AC_CHECK_LIB([crypto], [EVP_PKEY_CTX_set0_rsa_oaep_label],, not_found=1) ) AX_CHECK_DEFINE([], [EVP_PKEY_CTX_set_rsa_padding],, AC_CHECK_LIB([crypto], [EVP_PKEY_CTX_set_rsa_padding],, not_found=1) ) AX_CHECK_DEFINE([], [EVP_PKEY_CTX_set_rsa_oaep_md],, AC_CHECK_LIB([crypto], [EVP_PKEY_CTX_set_rsa_oaep_md],, not_found=1) ) AX_CHECK_DEFINE([], [EVP_PKEY_CTX_set_signature_md],, AC_CHECK_LIB([crypto], [EVP_PKEY_CTX_set_signature_md],, not_found=1) ) if test "x$not_found" = "x0"; then use_openssl_functions_rsa=1 use_openssl_functions_for="${use_openssl_functions_for}RSA " fi LIBS=$LIBS_save ]) CFLAGS="$CFLAGS -DUSE_OPENSSL_FUNCTIONS_SYMMETRIC=$use_openssl_functions_symmetric" CFLAGS="$CFLAGS -DUSE_OPENSSL_FUNCTIONS_EC=$use_openssl_functions_ec" CFLAGS="$CFLAGS -DUSE_OPENSSL_FUNCTIONS_ECDSA=$use_openssl_functions_ecdsa" CFLAGS="$CFLAGS -DUSE_OPENSSL_FUNCTIONS_RSA=$use_openssl_functions_rsa" AC_ARG_ENABLE([sanitizers], AS_HELP_STRING([--enable-sanitizers], [Enable address sanitizing]), [SANITIZERS="-fsanitize=address,undefined"], []) AC_ARG_ENABLE([fuzzer], AS_HELP_STRING([--enable-fuzzer], [Enable fuzzer]), [FUZZER="$SANITIZERS -fsanitize=fuzzer" AM_CONDITIONAL(WITH_FUZZER, true)], [AM_CONDITIONAL(WITH_FUZZER, false)]) AC_SUBST([SANITIZERS]) AC_SUBST([FUZZER]) AM_CONDITIONAL([WITH_FUZZING_ENGINE], [test "x$LIB_FUZZING_ENGINE" != "x"]) AC_SUBST([LIB_FUZZING_ENGINE]) AC_ARG_ENABLE([test-coverage], AS_HELP_STRING([--enable-test-coverage], [Enable test coverage flags]), [COVERAGE_CFLAGS="-fprofile-arcs -ftest-coverage" COVERAGE_LDFLAGS="-fprofile-arcs"]) LT_INIT AC_PROG_CC AC_PROG_CXX AC_PROG_INSTALL LT_INIT #AM_GNU_GETTEXT_VERSION([0.15]) #AM_GNU_GETTEXT([external]) AC_C_CONST AC_C_INLINE AC_TYPE_SIZE_T AC_CHECK_LIB(c, clock_gettime, LIBRT_LIBS="", LIBRT_LIBS="-lrt") AC_SUBST([LIBRT_LIBS]) AC_ARG_ENABLE([hardening], AS_HELP_STRING([--disable-hardening], [Disable hardening flags])) if test "x$enable_hardening" != "xno"; then # Some versions of gcc fail with -Wstack-protector, # some with -Wstack-protector-strong enabled if ! $CC -fstack-protector-strong $srcdir/include/libtpms/tpm_error.h 2>/dev/null; then if $CC -fstack-protector $srcdir/include/libtpms/tpm_error.h 2>/dev/null; then HARDENING_CFLAGS="-fstack-protector " fi else HARDENING_CFLAGS="-fstack-protector-strong " fi dnl Must not have -O0 but must have a -O for -D_FORTIFY_SOURCE=2 TMP1="$(echo $CFLAGS | sed -n 's/.*\(-O0\).*/\1/p')" TMP2="$(echo $CFLAGS | sed -n 's/.*\(-O\).*/\1/p')" if test -z "$TMP1" && test -n "$TPM2"; then HARDENING_CFLAGS="$HARDENING_CFLAGS -D_FORTIFY_SOURCE=2 " fi dnl Check linker for 'relro' and 'now' save_CFLAGS="$CFLAGS" CFLAGS="-Wl,-z,relro -Werror" AC_MSG_CHECKING([whether linker supports -Wl,-z,relro]) AC_LINK_IFELSE( [AC_LANG_SOURCE([[int main() { return 0; }]])], [HARDENING_LDFLAGS="$HARDENING_LDFLAGS -Wl,-z,relro" AC_MSG_RESULT(yes)], [AC_MSG_RESULT(no)] ) CFLAGS="-Wl,-z,now -Werror" AC_MSG_CHECKING([whether linker supports -Wl,-z,now]) AC_LINK_IFELSE( [AC_LANG_SOURCE([[int main() { return 0; }]])], [HARDENING_LDFLAGS="$HARDENING_LDFLAGS -Wl,-z,now" AC_MSG_RESULT(yes)], [AC_MSG_RESULT(no)] ) CFLAGS="$save_CFLAGS" AC_SUBST([HARDENING_CFLAGS]) AC_SUBST([HARDENING_LDFLAGS]) fi AM_CFLAGS="$CFLAGS $COVERAGE_CFLAGS -Wall -Werror -Wreturn-type -Wsign-compare -Wno-self-assign -Wmissing-prototypes" AM_CFLAGS="$AM_CFLAGS" AM_LDFLAGS="$LDFLAGS $COVERAGE_LDFLAGS" AC_SUBST([AM_CFLAGS]) AC_SUBST([AM_LDFLAGS]) AC_CONFIG_FILES(Makefile \ dist/libtpms.spec \ include/Makefile \ include/libtpms/Makefile \ include/libtpms/tpm_library.h \ man/Makefile \ man/man3/Makefile \ src/Makefile \ libtpms.pc \ tests/Makefile) PKG_INSTALLDIR() AC_OUTPUT if test -z "$enable_debug" ; then enable_debug="no" fi if test -z "$with_tpm2"; then with_tpm2=no fi echo echo "AM_CFLAGS=$AM_CFLAGS" echo "HARDENING_CFLAGS=$HARDENING_CFLAGS" echo "HARDENING_LDFLAGS=$HARDENING_LDFLAGS" echo "AM_LDFLAGS=$AM_LDFLAGS" echo echo "Version to build : $PACKAGE_VERSION" echo "Crypto library : $cryptolib" echo "Debug build : $enable_debug" echo "With TPM1.2 support : $with_tpm1" echo "With TPM2 support : $with_tpm2" echo "HAVE_VERSION_SCRIPT : $have_version_script" echo "Use openssl crypto for : $use_openssl_functions_for" echo echo libtpms-0.9.3/debian/000077500000000000000000000000001421143571500144225ustar00rootroot00000000000000libtpms-0.9.3/debian/changelog000066400000000000000000000036021421143571500162750ustar00rootroot00000000000000libtpms (0.9.3) RELEASED; urgency=medium - build-sys: Add probing for -fstack-protector - tpm2: Do not call EVP_PKEY_CTX_set0_rsa_oaep_label() for label of size (OSSL 3) -- Stefan Berger Mon, 07 Mar 2022 09:00:00 -0500 libtpms (0.9.2) RELEASED; urgency=medium * tpm2: When writing state initialize s_ContextSlotMask if not set -- Stefan Berger Thu, 06 Jan 2022 09:00:00 -0500 libtpms (0.9.1) RELEASED; urgency=medium * tpm2: Do not write permanent state if only clock changed -- Stefan Berger Wed, 24 Nov 2021 09:00:00 -0500 libtpms (0.9.0) RELEASED; urgency=medium * Stable release -- Stefan Berger Wed, 29 Sep 2021 09:00:00 -0500 libtpms (0.9.0~dev1) UNRELEASED; urgency=medium * Developer release 1 -- Stefan Berger Wed, 24 Feb 2021 13:48:00 -0500 libtpms (0.8.0) RELEASED; urgency=medium * Stable release -- Stefan Berger Wed, 24 Feb 2021 10:55:00 -0500 libtpms (0.8.0~dev1) UNRELEASED; urgency=medium * Developer release 1 -- Stefan Berger Fri, 19 Jul 2019 13:38:08 -0500 libtpms (0.7.0-1) RELEASED; urgency=medium * Stable release -- Stefan Berger Thu, 18 Jul 2019 16:26:00 -0500 libtpms (0.7.0~dev1) UNRELEASED; urgency=medium * Stable release -- Stefan Berger Mon, 14 Jan 2019 10:25:08 -0500 libtpms (0.6.0-1) RELEASED; urgency=medium * Stable release -- Stefan Berger Wed, 09 Jan 2019 12:28:12 -0500 libtpms (0.6.0-1~dev1) RELEASED; urgency=medium * Developer release 1 -- Stefan Berger Mon, 13 Nov 2017 13:03:00 -0500 libtpms (0.6.0) UNRELEASED; urgency=medium * Initial Release. -- Stefan Berger Tue, 12 Jan 2016 11:28:33 -0500 libtpms-0.9.3/debian/clean000066400000000000000000000000431421143571500154240ustar00rootroot00000000000000include/libtpms/*.gch tests/NVChip libtpms-0.9.3/debian/compat000066400000000000000000000000021421143571500156200ustar00rootroot0000000000000010libtpms-0.9.3/debian/control000066400000000000000000000014761421143571500160350ustar00rootroot00000000000000Source: libtpms Maintainer: Stefan Berger Section: libs Priority: optional Standards-Version: 4.5.1 Rules-Requires-Root: no Build-Depends: debhelper (>= 10), dh-exec, gawk, libssl-dev, libtool, pkg-config Package: libtpms-dev Architecture: any Section: libdevel Depends: libtpms0 (= ${binary:Version}), ${misc:Depends} Description: libtpms header files and man pages The libtpms-dev package provides header files and man pages for the functions provided by libtpms. Package: libtpms0 Architecture: any Multi-Arch: same Pre-Depends: ${misc:Pre-Depends} Depends: openssl, ${misc:Depends}, ${shlibs:Depends} Description: TPM emulation library Libtpms is a library that provides TPM functionality. libtpms-0.9.3/debian/copyright000066400000000000000000000101601421143571500163530ustar00rootroot00000000000000For the TPM 1.2 code and the library code the following license applies: 3-clause BSD license (c) Copyright IBM Corporation 2006, 2010. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the names of the IBM Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. For the TPM 2 code the following license and notices apply: Licenses and Notices 1. Copyright Licenses: - Trusted Computing Group (TCG) grants to the user of the source code in this specification (the "Source Code") a worldwide, irrevocable, nonexclusive, royalty free, copyright license to reproduce, create derivative works, distribute, display and perform the Source Code and derivative works thereof, and to grant others the rights granted herein. - The TCG grants to the user of the other parts of the specification (other than the Source Code) the rights to reproduce, distribute, display, and perform the specification solely for the purpose of developing products based on such documents. 2. Source Code Distribution Conditions: - Redistributions of Source Code must retain the above copyright licenses, this list of conditions and the following disclaimers. - Redistributions in binary form must reproduce the above copyright licenses, this list of conditions and the following disclaimers in the documentation and/or other materials provided with the distribution. 3. Disclaimers: - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. Contact TCG Administration (admin@trustedcomputinggroup.org) for information on specification licensing rights available through TCG membership agreements. - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. - Without limitation, TCG and its members and licensors disclaim all liability, including liability for infringement of any proprietary rights, relating to use of information in this specification and to the implementation of this specification, and TCG disclaims all liability for cost of procurement of substitute goods or services, lost profits, loss of use, loss of data or any incidental, consequential, direct, indirect, or special damages, whether under contract, tort, warranty or otherwise, arising in any way out of use or reliance upon this specification or any information herein. (c) Copyright IBM Corp. and others, 2012-2016 libtpms-0.9.3/debian/libtpms-dev.install000066400000000000000000000001461421143571500202410ustar00rootroot00000000000000/usr/include/libtpms/*.h /usr/lib/*/*.a /usr/lib/*/*.so /usr/lib/*/pkgconfig/ /usr/share/man/man3/*.3 libtpms-0.9.3/debian/libtpms0.install000066400000000000000000000000221421143571500175360ustar00rootroot00000000000000/usr/lib/*/*.so.* libtpms-0.9.3/debian/not-installed000066400000000000000000000000171421143571500171200ustar00rootroot00000000000000usr/lib/*/*.la libtpms-0.9.3/debian/rules000077500000000000000000000002311421143571500154760ustar00rootroot00000000000000#!/usr/bin/make -f #export DH_VERBOSE=1 %: dh $@ override_dh_auto_configure: dh_auto_configure -- --with-openssl --with-tpm2 override_dh_usrlocal: libtpms-0.9.3/debian/source/000077500000000000000000000000001421143571500157225ustar00rootroot00000000000000libtpms-0.9.3/debian/source/format000066400000000000000000000000151421143571500171310ustar00rootroot000000000000003.0 (native) libtpms-0.9.3/dist/000077500000000000000000000000001421143571500141435ustar00rootroot00000000000000libtpms-0.9.3/dist/libtpms.spec000066400000000000000000000152621421143571500164770ustar00rootroot00000000000000# --- libtpm rpm-spec --- %define name libtpms %define version 0.9.3 %define release 0~dev1 # Valid crypto subsystems are 'freebl' and 'openssl' %if "%{?crypto_subsystem}" == "" %define crypto_subsystem openssl %endif # Valid build types are 'production' or 'debug' %define build_type production Summary: Library providing Trusted Platform Module (TPM) functionality Name: %{name} Version: %{version} Release: %{release}%{?dist} License: BSD Group: Development/Libraries Url: http://github.com/stefanberger/libtpms Source: libtpms-%{version}.tar.gz Provides: libtpms-%{crypto_subsystem} = %{version}-%{release} %if "%{crypto_subsystem}" == "openssl" BuildRequires: openssl-devel %else BuildRequires: nss-devel >= 3.12.9-2 BuildRequires: nss-softokn-freebl-devel >= 3.12.9-2 %if 0%{?rhel} > 6 || 0%{?fedora} >= 13 BuildRequires: nss-softokn-freebl-static >= 3.12.9-2 %endif BuildRequires: nss-softokn-devel >= 3.12.9-2, gmp-devel %endif BuildRequires: pkgconfig gawk sed BuildRequires: automake autoconf libtool bash coreutils gcc-c++ %if "%{crypto_subsystem}" == "openssl" Requires: openssl %else Requires: nss-softokn-freebl >= 3.12.9-2, nss-softokn >= 3.12.9-2 %endif Requires: gmp %description A library providing TPM functionality for VMs. Targeted for integration into Qemu. %package devel Summary: Include files for libtpms Group: Development/Libraries Requires: %{name}%{?_isa} = %{version}-%{release} %description devel Libtpms header files and documentation. %files %defattr(-, root, root, -) %{_libdir}/%{name}.so.%{version} %{_libdir}/%{name}.so.0 %doc LICENSE README CHANGES %files devel %defattr(-, root, root, -) %{_libdir}/%{name}.so %dir %{_includedir}/%{name} %attr(644, root, root) %{_libdir}/pkgconfig/*.pc %attr(644, root, root) %{_includedir}/%{name}/*.h %attr(644, root, root) %{_mandir}/man3/* %prep %setup -q %build %if "%{crypto_subsystem}" == "openssl" %define _with_openssl --with-openssl %endif %if "%{build_type}" == "debug" %define _enable_debug --enable-debug %endif %if "%{build_type}" == "debug" CFLAGS=-O0 %endif ./autogen.sh \ --with-tpm2 \ --disable-static \ --prefix=/usr \ --libdir=%{_libdir} \ %{?_with_openssl} \ %{?_enable_debug} make %{?_smp_mflags} %check make check %install install -d -m 0755 $RPM_BUILD_ROOT%{_libdir} install -d -m 0755 $RPM_BUILD_ROOT%{_includedir}/libtpms install -d -m 0755 $RPM_BUILD_ROOT%{_mandir}/man3 make %{?_smp_mflags} install DESTDIR=${RPM_BUILD_ROOT} rm -f $RPM_BUILD_ROOT%{_libdir}/libtpms.la %post -p /sbin/ldconfig %postun -p /sbin/ldconfig %changelog * Mon Mar 07 2022 Stefan Berger - 0.9.3-1 - Release of version 0.9.3 * Thu Jan 06 2022 Stefan Berger - 0.9.2-1 - Release of version 0.9.2 * Wed Nov 24 2021 Stefan Berger - 0.9.1-1 - Release of version 0.9.1 * Wed Sep 29 2021 Stefan Berger - 0.9.0-1 - Release of version 0.9.0 (rev. 164) * Wed Feb 24 2021 Stefan Berger - 0.8.0-1 - Release of version 0.8.0 (rev. 162) * Fri Jul 19 2019 Stefan Berger - 0.7.0-1 - Release of version 0.7.0 (rev. 150) * Mon Jan 14 2018 Stefan Berger - 0.6.0-1 - Release of version 0.6.0 with TPM 2.0 support * Mon Jun 30 2014 Stefan Berger - 0.5.2-1 - Updated to version 0.5.2 - coverity fixes - fixes for ARM64 using __aarch64__ * Sat Jun 07 2014 Fedora Release Engineering - 0.5.1-20.1 - Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild * Sat Aug 03 2013 Fedora Release Engineering - 0.5.1-19 - Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild * Mon Mar 25 2013 Stefan Berger - 0.5.1-18 - Ran autoreconf for support of aarch64 - Checking for __arm64__ in code * Thu Feb 14 2013 Fedora Release Engineering - 0.5.1-17 - Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild * Thu Jul 19 2012 Fedora Release Engineering - 0.5.1-16 - Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild * Fri Feb 17 2012 Peter Robinson - 0.5.1-15 - Add dist tag as required by package guidelines * Fri Jan 27 2012 Stefan Berger - 0.5.1-14 - fix gcc-4.7 compilation problem * Fri Jan 13 2012 Fedora Release Engineering - 0.5.1-13 - Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild * Tue Dec 20 2011 Dan Horák - 0.5.1-12 - fix build on secondary arches * Wed Nov 2 2011 Stefan Berger - 0.5.1-11 - added (lib)gmp as runtime dependency * Sat Oct 8 2011 Stefan Berger - 0.5.1-10 - internal fixes; callback fixes * Tue Aug 30 2011 Stefan Berger - 0.5.1-9 - new directory structure and build process * Tue Jul 12 2011 Stefan Berger - 0.5.1-8 - added pkgconfig as build dependency - enabling __powerpc__ build following Bz 728220 * Wed May 25 2011 Stefan Berger - 0.5.1-7 - increasing NVRAM area space to have enough room for certificates * Wed May 25 2011 Stefan Berger - 0.5.1-6 - adding libtpms.pc pkg-config file * Wed Apr 13 2011 Stefan Berger - 0.5.1-5 - adding BuildRequires for nss-softokn-freebl-static - several libtpms-internal changes around state serialization and deserialization - fixes to libtpms makefile (makefile-libtpms) - adding build_type to generate a debug or production build - need nss-devel to have nss-config * Tue Mar 08 2011 Stefan Berger - 0.5.1-4 - small fixes to libtpms makefile * Fri Feb 25 2011 Stefan Berger - 0.5.1-3 - removing release from tar ball name - Use {?_smp_mflags} for make rather than hardcoding it - Fixing post and postun scripts; removing the scripts for devel package - Fixing usage of defattr - Adding version information into the changelog headers and spaces between the changelog entries - Adding LICENSE, README and CHANGELOG file into tar ball and main rpm - Removing clean section - removed command to clean the build root - adding library version to the libraries required for building and during runtime - Extended Requires in devel package with {?_isa} * Fri Feb 18 2011 Stefan Berger - 0.5.1-2 - make rpmlint happy by replacing tabs with spaces - providing a valid URL for the tgz file - release is now 2 -> 0.5.1-2 * Mon Jan 17 2011 Stefan Berger - 0.5.1-1 - Update version to 0.5.1 * Fri Jan 14 2011 Stefan Berger - 0.5.0-1 - Changes following Fedora review comments * Thu Dec 2 2010 Stefan Berger - Small tweaks after reading the FedoreCore packaging requirements * Tue Nov 16 2010 Stefan Berger - Created initial version of rpm spec files - Version of library is now 0.5.0 - Debuginfo rpm is built but empty -- seems to be a known problem Check https://bugzilla.redhat.com/show_bug.cgi?id=209316 libtpms-0.9.3/dist/libtpms.spec.in000066400000000000000000000152701421143571500171030ustar00rootroot00000000000000# --- libtpm rpm-spec --- %define name @PACKAGE@ %define version @VERSION@ %define release 0~dev1 # Valid crypto subsystems are 'freebl' and 'openssl' %if "%{?crypto_subsystem}" == "" %define crypto_subsystem openssl %endif # Valid build types are 'production' or 'debug' %define build_type production Summary: Library providing Trusted Platform Module (TPM) functionality Name: %{name} Version: %{version} Release: %{release}%{?dist} License: BSD Group: Development/Libraries Url: http://github.com/stefanberger/libtpms Source: libtpms-%{version}.tar.gz Provides: libtpms-%{crypto_subsystem} = %{version}-%{release} %if "%{crypto_subsystem}" == "openssl" BuildRequires: openssl-devel %else BuildRequires: nss-devel >= 3.12.9-2 BuildRequires: nss-softokn-freebl-devel >= 3.12.9-2 %if 0%{?rhel} > 6 || 0%{?fedora} >= 13 BuildRequires: nss-softokn-freebl-static >= 3.12.9-2 %endif BuildRequires: nss-softokn-devel >= 3.12.9-2, gmp-devel %endif BuildRequires: pkgconfig gawk sed BuildRequires: automake autoconf libtool bash coreutils gcc-c++ %if "%{crypto_subsystem}" == "openssl" Requires: openssl %else Requires: nss-softokn-freebl >= 3.12.9-2, nss-softokn >= 3.12.9-2 %endif Requires: gmp %description A library providing TPM functionality for VMs. Targeted for integration into Qemu. %package devel Summary: Include files for libtpms Group: Development/Libraries Requires: %{name}%{?_isa} = %{version}-%{release} %description devel Libtpms header files and documentation. %files %defattr(-, root, root, -) %{_libdir}/%{name}.so.%{version} %{_libdir}/%{name}.so.0 %doc LICENSE README CHANGES %files devel %defattr(-, root, root, -) %{_libdir}/%{name}.so %dir %{_includedir}/%{name} %attr(644, root, root) %{_libdir}/pkgconfig/*.pc %attr(644, root, root) %{_includedir}/%{name}/*.h %attr(644, root, root) %{_mandir}/man3/* %prep %setup -q %build %if "%{crypto_subsystem}" == "openssl" %define _with_openssl --with-openssl %endif %if "%{build_type}" == "debug" %define _enable_debug --enable-debug %endif %if "%{build_type}" == "debug" CFLAGS=-O0 %endif ./autogen.sh \ --with-tpm2 \ --disable-static \ --prefix=/usr \ --libdir=%{_libdir} \ %{?_with_openssl} \ %{?_enable_debug} make %{?_smp_mflags} %check make check %install install -d -m 0755 $RPM_BUILD_ROOT%{_libdir} install -d -m 0755 $RPM_BUILD_ROOT%{_includedir}/libtpms install -d -m 0755 $RPM_BUILD_ROOT%{_mandir}/man3 make %{?_smp_mflags} install DESTDIR=${RPM_BUILD_ROOT} rm -f $RPM_BUILD_ROOT%{_libdir}/libtpms.la %post -p /sbin/ldconfig %postun -p /sbin/ldconfig %changelog * Mon Mar 07 2022 Stefan Berger - 0.9.3-1 - Release of version 0.9.3 * Thu Jan 06 2022 Stefan Berger - 0.9.2-1 - Release of version 0.9.2 * Wed Nov 24 2021 Stefan Berger - 0.9.1-1 - Release of version 0.9.1 * Wed Sep 29 2021 Stefan Berger - 0.9.0-1 - Release of version 0.9.0 (rev. 164) * Wed Feb 24 2021 Stefan Berger - 0.8.0-1 - Release of version 0.8.0 (rev. 162) * Fri Jul 19 2019 Stefan Berger - 0.7.0-1 - Release of version 0.7.0 (rev. 150) * Mon Jan 14 2018 Stefan Berger - 0.6.0-1 - Release of version 0.6.0 with TPM 2.0 support * Mon Jun 30 2014 Stefan Berger - 0.5.2-1 - Updated to version 0.5.2 - coverity fixes - fixes for ARM64 using __aarch64__ * Sat Jun 07 2014 Fedora Release Engineering - 0.5.1-20.1 - Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild * Sat Aug 03 2013 Fedora Release Engineering - 0.5.1-19 - Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild * Mon Mar 25 2013 Stefan Berger - 0.5.1-18 - Ran autoreconf for support of aarch64 - Checking for __arm64__ in code * Thu Feb 14 2013 Fedora Release Engineering - 0.5.1-17 - Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild * Thu Jul 19 2012 Fedora Release Engineering - 0.5.1-16 - Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild * Fri Feb 17 2012 Peter Robinson - 0.5.1-15 - Add dist tag as required by package guidelines * Fri Jan 27 2012 Stefan Berger - 0.5.1-14 - fix gcc-4.7 compilation problem * Fri Jan 13 2012 Fedora Release Engineering - 0.5.1-13 - Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild * Tue Dec 20 2011 Dan Horák - 0.5.1-12 - fix build on secondary arches * Wed Nov 2 2011 Stefan Berger - 0.5.1-11 - added (lib)gmp as runtime dependency * Sat Oct 8 2011 Stefan Berger - 0.5.1-10 - internal fixes; callback fixes * Tue Aug 30 2011 Stefan Berger - 0.5.1-9 - new directory structure and build process * Tue Jul 12 2011 Stefan Berger - 0.5.1-8 - added pkgconfig as build dependency - enabling __powerpc__ build following Bz 728220 * Wed May 25 2011 Stefan Berger - 0.5.1-7 - increasing NVRAM area space to have enough room for certificates * Wed May 25 2011 Stefan Berger - 0.5.1-6 - adding libtpms.pc pkg-config file * Wed Apr 13 2011 Stefan Berger - 0.5.1-5 - adding BuildRequires for nss-softokn-freebl-static - several libtpms-internal changes around state serialization and deserialization - fixes to libtpms makefile (makefile-libtpms) - adding build_type to generate a debug or production build - need nss-devel to have nss-config * Tue Mar 08 2011 Stefan Berger - 0.5.1-4 - small fixes to libtpms makefile * Fri Feb 25 2011 Stefan Berger - 0.5.1-3 - removing release from tar ball name - Use {?_smp_mflags} for make rather than hardcoding it - Fixing post and postun scripts; removing the scripts for devel package - Fixing usage of defattr - Adding version information into the changelog headers and spaces between the changelog entries - Adding LICENSE, README and CHANGELOG file into tar ball and main rpm - Removing clean section - removed command to clean the build root - adding library version to the libraries required for building and during runtime - Extended Requires in devel package with {?_isa} * Fri Feb 18 2011 Stefan Berger - 0.5.1-2 - make rpmlint happy by replacing tabs with spaces - providing a valid URL for the tgz file - release is now 2 -> 0.5.1-2 * Mon Jan 17 2011 Stefan Berger - 0.5.1-1 - Update version to 0.5.1 * Fri Jan 14 2011 Stefan Berger - 0.5.0-1 - Changes following Fedora review comments * Thu Dec 2 2010 Stefan Berger - Small tweaks after reading the FedoreCore packaging requirements * Tue Nov 16 2010 Stefan Berger - Created initial version of rpm spec files - Version of library is now 0.5.0 - Debuginfo rpm is built but empty -- seems to be a known problem Check https://bugzilla.redhat.com/show_bug.cgi?id=209316 libtpms-0.9.3/include/000077500000000000000000000000001421143571500146235ustar00rootroot00000000000000libtpms-0.9.3/include/Makefile.am000066400000000000000000000001561421143571500166610ustar00rootroot00000000000000# # include/Makefile.am # # For the license, see the LICENSE file in the root directory. # SUBDIRS = libtpms libtpms-0.9.3/include/libtpms/000077500000000000000000000000001421143571500162755ustar00rootroot00000000000000libtpms-0.9.3/include/libtpms/Makefile.am000066400000000000000000000004101421143571500203240ustar00rootroot00000000000000# # include/libtpms/Makefile.am # # For the license, see the LICENSE file in the root directory. # libtpmsincludedir = $(includedir)/libtpms libtpmsinclude_HEADERS = \ tpm_error.h \ tpm_library.h \ tpm_memory.h \ tpm_nvfilename.h \ tpm_tis.h \ tpm_types.h libtpms-0.9.3/include/libtpms/tpm_error.h000066400000000000000000000443571421143571500204740ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Error Response */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_error.h 4071 2010-04-29 19:26:45Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_ERROR_H #define TPM_ERROR_H /* 16. Return codes rev 99 The TPM has five types of return code. One indicates successful operation and four indicate failure. TPM_SUCCESS (00000000) indicates successful execution. The failure reports are: TPM defined fatal errors (00000001 to 000003FF), vendor defined fatal errors (00000400 to 000007FF), TPM defined non-fatal errors (00000800 to 00000BFF), and vendor defined non-fatal errors (00000C00 to 00000FFF). The range of vendor defined non-fatal errors was determined by the TSS-WG, which defined XXXX YCCC with XXXX as OS specific and Y defining the TSS SW stack layer (0: TPM layer) All failure cases return only a non-authenticated fixed set of information. This is because the failure may have been due to authentication or other factors, and there is no possibility of producing an authenticated response. Fatal errors also terminate any authorization sessions. This is a result of returning only the error code, as there is no way to return the nonces necessary to maintain an authorization session. Non-fatal errors do not terminate authorization sessions. The return code MUST use the following base. The return code MAY be TCG defined or vendor defined. */ #define TPM_BASE 0x0 /* The start of TPM return codes */ #define TPM_SUCCESS TPM_BASE /* Successful completion of the operation */ #define TPM_VENDOR_ERROR TPM_Vendor_Specific32 /* Mask to indicate that the error code is vendor specific for vendor specific commands. */ #define TPM_NON_FATAL 0x00000800 /* Mask to indicate that the error code is a non-fatal failure. */ /* TPM-defined fatal error codes */ #define TPM_AUTHFAIL TPM_BASE + 1 /* Authentication failed */ #define TPM_BADINDEX TPM_BASE + 2 /* The index to a PCR, DIR or other register is incorrect */ #define TPM_BAD_PARAMETER TPM_BASE + 3 /* One or more parameter is bad */ #define TPM_AUDITFAILURE TPM_BASE + 4 /* An operation completed successfully but the auditing of that operation failed. */ #define TPM_CLEAR_DISABLED TPM_BASE + 5 /* The clear disable flag is set and all clear operations now require physical access */ #define TPM_DEACTIVATED TPM_BASE + 6 /* The TPM is deactivated */ #define TPM_DISABLED TPM_BASE + 7 /* The TPM is disabled */ #define TPM_DISABLED_CMD TPM_BASE + 8 /* The target command has been disabled */ #define TPM_FAIL TPM_BASE + 9 /* The operation failed */ #define TPM_BAD_ORDINAL TPM_BASE + 10 /* The ordinal was unknown or inconsistent */ #define TPM_INSTALL_DISABLED TPM_BASE + 11 /* The ability to install an owner is disabled */ #define TPM_INVALID_KEYHANDLE TPM_BASE + 12 /* The key handle presented was invalid */ #define TPM_KEYNOTFOUND TPM_BASE + 13 /* The target key was not found */ #define TPM_INAPPROPRIATE_ENC TPM_BASE + 14 /* Unacceptable encryption scheme */ #define TPM_MIGRATEFAIL TPM_BASE + 15 /* Migration authorization failed */ #define TPM_INVALID_PCR_INFO TPM_BASE + 16 /* PCR information could not be interpreted */ #define TPM_NOSPACE TPM_BASE + 17 /* No room to load key. */ #define TPM_NOSRK TPM_BASE + 18 /* There is no SRK set */ #define TPM_NOTSEALED_BLOB TPM_BASE + 19 /* An encrypted blob is invalid or was not created by this TPM */ #define TPM_OWNER_SET TPM_BASE + 20 /* There is already an Owner */ #define TPM_RESOURCES TPM_BASE + 21 /* The TPM has insufficient internal resources to perform the requested action. */ #define TPM_SHORTRANDOM TPM_BASE + 22 /* A random string was too short */ #define TPM_SIZE TPM_BASE + 23 /* The TPM does not have the space to perform the operation. */ #define TPM_WRONGPCRVAL TPM_BASE + 24 /* The named PCR value does not match the current PCR value. */ #define TPM_BAD_PARAM_SIZE TPM_BASE + 25 /* The paramSize argument to the command has the incorrect value */ #define TPM_SHA_THREAD TPM_BASE + 26 /* There is no existing SHA-1 thread. */ #define TPM_SHA_ERROR TPM_BASE + 27 /* The calculation is unable to proceed because the existing SHA-1 thread has already encountered an error. */ #define TPM_FAILEDSELFTEST TPM_BASE + 28 /* Self-test has failed and the TPM has shutdown. */ #define TPM_AUTH2FAIL TPM_BASE + 29 /* The authorization for the second key in a 2 key function failed authorization */ #define TPM_BADTAG TPM_BASE + 30 /* The tag value sent to for a command is invalid */ #define TPM_IOERROR TPM_BASE + 31 /* An IO error occurred transmitting information to the TPM */ #define TPM_ENCRYPT_ERROR TPM_BASE + 32 /* The encryption process had a problem. */ #define TPM_DECRYPT_ERROR TPM_BASE + 33 /* The decryption process did not complete. */ #define TPM_INVALID_AUTHHANDLE TPM_BASE + 34 /* An invalid handle was used. */ #define TPM_NO_ENDORSEMENT TPM_BASE + 35 /* The TPM does not a EK installed */ #define TPM_INVALID_KEYUSAGE TPM_BASE + 36 /* The usage of a key is not allowed */ #define TPM_WRONG_ENTITYTYPE TPM_BASE + 37 /* The submitted entity type is not allowed */ #define TPM_INVALID_POSTINIT TPM_BASE + 38 /* The command was received in the wrong sequence relative to TPM_Init and a subsequent TPM_Startup */ #define TPM_INAPPROPRIATE_SIG TPM_BASE + 39 /* Signed data cannot include additional DER information */ #define TPM_BAD_KEY_PROPERTY TPM_BASE + 40 /* The key properties in TPM_KEY_PARMs are not supported by this TPM */ #define TPM_BAD_MIGRATION TPM_BASE + 41 /* The migration properties of this key are incorrect. */ #define TPM_BAD_SCHEME TPM_BASE + 42 /* The signature or encryption scheme for this key is incorrect or not permitted in this situation. */ #define TPM_BAD_DATASIZE TPM_BASE + 43 /* The size of the data (or blob) parameter is bad or inconsistent with the referenced key */ #define TPM_BAD_MODE TPM_BASE + 44 /* A mode parameter is bad, such as capArea or subCapArea for TPM_GetCapability, physicalPresence parameter for TPM_PhysicalPresence, or migrationType for TPM_CreateMigrationBlob. */ #define TPM_BAD_PRESENCE TPM_BASE + 45 /* Either the physicalPresence or physicalPresenceLock bits have the wrong value */ #define TPM_BAD_VERSION TPM_BASE + 46 /* The TPM cannot perform this version of the capability */ #define TPM_NO_WRAP_TRANSPORT TPM_BASE + 47 /* The TPM does not allow for wrapped transport sessions */ #define TPM_AUDITFAIL_UNSUCCESSFUL TPM_BASE + 48 /* TPM audit construction failed and the underlying command was returning a failure code also */ #define TPM_AUDITFAIL_SUCCESSFUL TPM_BASE + 49 /* TPM audit construction failed and the underlying command was returning success */ #define TPM_NOTRESETABLE TPM_BASE + 50 /* Attempt to reset a PCR register that does not have the resettable attribute */ #define TPM_NOTLOCAL TPM_BASE + 51 /* Attempt to reset a PCR register that requires locality and locality modifier not part of command transport */ #define TPM_BAD_TYPE TPM_BASE + 52 /* Make identity blob not properly typed */ #define TPM_INVALID_RESOURCE TPM_BASE + 53 /* When saving context identified resource type does not match actual resource */ #define TPM_NOTFIPS TPM_BASE + 54 /* The TPM is attempting to execute a command only available when in FIPS mode */ #define TPM_INVALID_FAMILY TPM_BASE + 55 /* The command is attempting to use an invalid family ID */ #define TPM_NO_NV_PERMISSION TPM_BASE + 56 /* The permission to manipulate the NV storage is not available */ #define TPM_REQUIRES_SIGN TPM_BASE + 57 /* The operation requires a signed command */ #define TPM_KEY_NOTSUPPORTED TPM_BASE + 58 /* Wrong operation to load an NV key */ #define TPM_AUTH_CONFLICT TPM_BASE + 59 /* NV_LoadKey blob requires both owner and blob authorization */ #define TPM_AREA_LOCKED TPM_BASE + 60 /* The NV area is locked and not writable */ #define TPM_BAD_LOCALITY TPM_BASE + 61 /* The locality is incorrect for the attempted operation */ #define TPM_READ_ONLY TPM_BASE + 62 /* The NV area is read only and can't be written to */ #define TPM_PER_NOWRITE TPM_BASE + 63 /* There is no protection on the write to the NV area */ #define TPM_FAMILYCOUNT TPM_BASE + 64 /* The family count value does not match */ #define TPM_WRITE_LOCKED TPM_BASE + 65 /* The NV area has already been written to */ #define TPM_BAD_ATTRIBUTES TPM_BASE + 66 /* The NV area attributes conflict */ #define TPM_INVALID_STRUCTURE TPM_BASE + 67 /* The structure tag and version are invalid or inconsistent */ #define TPM_KEY_OWNER_CONTROL TPM_BASE + 68 /* The key is under control of the TPM Owner and can only be evicted by the TPM Owner. */ #define TPM_BAD_COUNTER TPM_BASE + 69 /* The counter handle is incorrect */ #define TPM_NOT_FULLWRITE TPM_BASE + 70 /* The write is not a complete write of the area */ #define TPM_CONTEXT_GAP TPM_BASE + 71 /* The gap between saved context counts is too large */ #define TPM_MAXNVWRITES TPM_BASE + 72 /* The maximum number of NV writes without an owner has been exceeded */ #define TPM_NOOPERATOR TPM_BASE + 73 /* No operator authorization value is set */ #define TPM_RESOURCEMISSING TPM_BASE + 74 /* The resource pointed to by context is not loaded */ #define TPM_DELEGATE_LOCK TPM_BASE + 75 /* The delegate administration is locked */ #define TPM_DELEGATE_FAMILY TPM_BASE + 76 /* Attempt to manage a family other then the delegated family */ #define TPM_DELEGATE_ADMIN TPM_BASE + 77 /* Delegation table management not enabled */ #define TPM_TRANSPORT_NOTEXCLUSIVE TPM_BASE + 78 /* There was a command executed outside of an exclusive transport session */ #define TPM_OWNER_CONTROL TPM_BASE + 79 /* Attempt to context save a owner evict controlled key */ #define TPM_DAA_RESOURCES TPM_BASE + 80 /* The DAA command has no resources available to execute the command */ #define TPM_DAA_INPUT_DATA0 TPM_BASE + 81 /* The consistency check on DAA parameter inputData0 has failed. */ #define TPM_DAA_INPUT_DATA1 TPM_BASE + 82 /* The consistency check on DAA parameter inputData1 has failed. */ #define TPM_DAA_ISSUER_SETTINGS TPM_BASE + 83 /* The consistency check on DAA_issuerSettings has failed. */ #define TPM_DAA_TPM_SETTINGS TPM_BASE + 84 /* The consistency check on DAA_tpmSpecific has failed. */ #define TPM_DAA_STAGE TPM_BASE + 85 /* The atomic process indicated by the submitted DAA command is not the expected process. */ #define TPM_DAA_ISSUER_VALIDITY TPM_BASE + 86 /* The issuer's validity check has detected an inconsistency */ #define TPM_DAA_WRONG_W TPM_BASE + 87 /* The consistency check on w has failed. */ #define TPM_BAD_HANDLE TPM_BASE + 88 /* The handle is incorrect */ #define TPM_BAD_DELEGATE TPM_BASE + 89 /* Delegation is not correct */ #define TPM_BADCONTEXT TPM_BASE + 90 /* The context blob is invalid */ #define TPM_TOOMANYCONTEXTS TPM_BASE + 91 /* Too many contexts held by the TPM */ #define TPM_MA_TICKET_SIGNATURE TPM_BASE + 92 /* Migration authority signature validation failure */ #define TPM_MA_DESTINATION TPM_BASE + 93 /* Migration destination not authenticated */ #define TPM_MA_SOURCE TPM_BASE + 94 /* Migration source incorrect */ #define TPM_MA_AUTHORITY TPM_BASE + 95 /* Incorrect migration authority */ #define TPM_PERMANENTEK TPM_BASE + 97 /* Attempt to revoke the EK and the EK is not revocable */ #define TPM_BAD_SIGNATURE TPM_BASE + 98 /* Bad signature of CMK ticket */ #define TPM_NOCONTEXTSPACE TPM_BASE + 99 /* There is no room in the context list for additional contexts */ /* As error codes are added here, they should also be added to lib/miscfunc.c */ /* TPM-defined non-fatal errors */ #define TPM_RETRY TPM_BASE + TPM_NON_FATAL /* The TPM is too busy to respond to the command immediately, but the command could be submitted at a later time */ #define TPM_NEEDS_SELFTEST TPM_BASE + TPM_NON_FATAL + 1 /* TPM_ContinueSelfTest has has not been run*/ #define TPM_DOING_SELFTEST TPM_BASE + TPM_NON_FATAL + 2 /* The TPM is currently executing the actions of TPM_ContinueSelfTest because the ordinal required resources that have not been tested. */ #define TPM_DEFEND_LOCK_RUNNING TPM_BASE + TPM_NON_FATAL + 3 /* The TPM is defending against dictionary attacks and is in some time-out period. */ #endif libtpms-0.9.3/include/libtpms/tpm_library.h000066400000000000000000000144411421143571500207760ustar00rootroot00000000000000/********************************************************************************/ /* */ /* LibTPM interface functions */ /* Written by Stefan Berger */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_library.h 4623 2011-09-28 15:15:09Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_LIBRARY_H #define TPM_LIBRARY_H #include #include #include "tpm_types.h" #ifdef __cplusplus extern "C" { #endif #define TPM_LIBRARY_VER_MAJOR 0 #define TPM_LIBRARY_VER_MINOR 9 #define TPM_LIBRARY_VER_MICRO 3 #define TPM_LIBRARY_VERSION_GEN(MAJ, MIN, MICRO) \ (( MAJ << 16 ) | ( MIN << 8 ) | ( MICRO )) #define TPM_LIBRARY_VERSION \ TPM_LIBRARY_VERSION_GEN(TPM_LIBRARY_VER_MAJOR, \ TPM_LIBRARY_VER_MINOR, \ TPM_LIBRARY_VER_MICRO) uint32_t TPMLIB_GetVersion(void); /* TPM implementation version to choose */ typedef enum TPMLIB_TPMVersion { TPMLIB_TPM_VERSION_1_2, TPMLIB_TPM_VERSION_2, } TPMLIB_TPMVersion; TPM_RESULT TPMLIB_ChooseTPMVersion(TPMLIB_TPMVersion ver); TPM_RESULT TPMLIB_MainInit(void); void TPMLIB_Terminate(void); TPM_RESULT TPMLIB_Process(unsigned char **respbuffer, uint32_t *resp_size, uint32_t *respbufsize, unsigned char *command, uint32_t command_size); TPM_RESULT TPMLIB_VolatileAll_Store(unsigned char **buffer, uint32_t *buflen); TPM_RESULT TPMLIB_CancelCommand(void); enum TPMLIB_TPMProperty { TPMPROP_TPM_RSA_KEY_LENGTH_MAX = 1, TPMPROP_TPM_BUFFER_MAX, TPMPROP_TPM_KEY_HANDLES, TPMPROP_TPM_OWNER_EVICT_KEY_HANDLES, TPMPROP_TPM_MIN_AUTH_SESSIONS, TPMPROP_TPM_MIN_TRANS_SESSIONS, TPMPROP_TPM_MIN_DAA_SESSIONS, TPMPROP_TPM_MIN_SESSION_LIST, TPMPROP_TPM_MIN_COUNTERS, TPMPROP_TPM_NUM_FAMILY_TABLE_ENTRY_MIN, TPMPROP_TPM_NUM_DELEGATE_TABLE_ENTRY_MIN, TPMPROP_TPM_SPACE_SAFETY_MARGIN, TPMPROP_TPM_MAX_NV_SPACE, TPMPROP_TPM_MAX_SAVESTATE_SPACE, TPMPROP_TPM_MAX_VOLATILESTATE_SPACE, }; TPM_RESULT TPMLIB_GetTPMProperty(enum TPMLIB_TPMProperty prop, int *result); enum TPMLIB_InfoFlags { TPMLIB_INFO_TPMSPECIFICATION = 1, TPMLIB_INFO_TPMATTRIBUTES = 2, TPMLIB_INFO_TPMFEATURES = 4, }; char *TPMLIB_GetInfo(enum TPMLIB_InfoFlags flags); struct libtpms_callbacks { int sizeOfStruct; TPM_RESULT (*tpm_nvram_init)(void); TPM_RESULT (*tpm_nvram_loaddata)(unsigned char **data, uint32_t *length, uint32_t tpm_number, const char *name); TPM_RESULT (*tpm_nvram_storedata)(const unsigned char *data, uint32_t length, uint32_t tpm_number, const char *name); TPM_RESULT (*tpm_nvram_deletename)(uint32_t tpm_number, const char *name, TPM_BOOL mustExist); TPM_RESULT (*tpm_io_init)(void); TPM_RESULT (*tpm_io_getlocality)(TPM_MODIFIER_INDICATOR *localityModifer, uint32_t tpm_number); TPM_RESULT (*tpm_io_getphysicalpresence)(TPM_BOOL *physicalPresence, uint32_t tpm_number); }; TPM_RESULT TPMLIB_RegisterCallbacks(struct libtpms_callbacks *); enum TPMLIB_BlobType { TPMLIB_BLOB_TYPE_INITSTATE, TPMLIB_BLOB_TYPE_LAST, }; #define TPMLIB_INITSTATE_START_TAG "-----BEGIN INITSTATE-----" #define TPMLIB_INITSTATE_END_TAG "-----END INITSTATE-----" TPM_RESULT TPMLIB_DecodeBlob(const char *data, enum TPMLIB_BlobType type, unsigned char **result, size_t *result_len); void TPMLIB_SetDebugFD(int fd); void TPMLIB_SetDebugLevel(unsigned int level); TPM_RESULT TPMLIB_SetDebugPrefix(const char *prefix); uint32_t TPMLIB_SetBufferSize(uint32_t wanted_size, uint32_t *min_size, uint32_t *max_size); enum TPMLIB_StateType { TPMLIB_STATE_PERMANENT = (1 << 0), TPMLIB_STATE_VOLATILE = (1 << 1), TPMLIB_STATE_SAVE_STATE = (1 << 2), }; TPM_RESULT TPMLIB_ValidateState(enum TPMLIB_StateType st, unsigned int flags); TPM_RESULT TPMLIB_SetState(enum TPMLIB_StateType st, const unsigned char *buffer, uint32_t buflen); TPM_RESULT TPMLIB_GetState(enum TPMLIB_StateType st, unsigned char **buffer, uint32_t *buflen); #ifdef __cplusplus } #endif #endif /* TPM_LIBRARY_H */ libtpms-0.9.3/include/libtpms/tpm_library.h.in000066400000000000000000000145271421143571500214100ustar00rootroot00000000000000/********************************************************************************/ /* */ /* LibTPM interface functions */ /* Written by Stefan Berger */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_library.h 4623 2011-09-28 15:15:09Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_LIBRARY_H #define TPM_LIBRARY_H #include #include #include "tpm_types.h" #ifdef __cplusplus extern "C" { #endif #define TPM_LIBRARY_VER_MAJOR @LIBTPMS_VER_MAJOR@ #define TPM_LIBRARY_VER_MINOR @LIBTPMS_VER_MINOR@ #define TPM_LIBRARY_VER_MICRO @LIBTPMS_VER_MICRO@ #define TPM_LIBRARY_VERSION_GEN(MAJ, MIN, MICRO) \ (( MAJ << 16 ) | ( MIN << 8 ) | ( MICRO )) #define TPM_LIBRARY_VERSION \ TPM_LIBRARY_VERSION_GEN(TPM_LIBRARY_VER_MAJOR, \ TPM_LIBRARY_VER_MINOR, \ TPM_LIBRARY_VER_MICRO) uint32_t TPMLIB_GetVersion(void); /* TPM implementation version to choose */ typedef enum TPMLIB_TPMVersion { TPMLIB_TPM_VERSION_1_2, TPMLIB_TPM_VERSION_2, } TPMLIB_TPMVersion; TPM_RESULT TPMLIB_ChooseTPMVersion(TPMLIB_TPMVersion ver); TPM_RESULT TPMLIB_MainInit(void); void TPMLIB_Terminate(void); TPM_RESULT TPMLIB_Process(unsigned char **respbuffer, uint32_t *resp_size, uint32_t *respbufsize, unsigned char *command, uint32_t command_size); TPM_RESULT TPMLIB_VolatileAll_Store(unsigned char **buffer, uint32_t *buflen); TPM_RESULT TPMLIB_CancelCommand(void); enum TPMLIB_TPMProperty { TPMPROP_TPM_RSA_KEY_LENGTH_MAX = 1, TPMPROP_TPM_BUFFER_MAX, TPMPROP_TPM_KEY_HANDLES, TPMPROP_TPM_OWNER_EVICT_KEY_HANDLES, TPMPROP_TPM_MIN_AUTH_SESSIONS, TPMPROP_TPM_MIN_TRANS_SESSIONS, TPMPROP_TPM_MIN_DAA_SESSIONS, TPMPROP_TPM_MIN_SESSION_LIST, TPMPROP_TPM_MIN_COUNTERS, TPMPROP_TPM_NUM_FAMILY_TABLE_ENTRY_MIN, TPMPROP_TPM_NUM_DELEGATE_TABLE_ENTRY_MIN, TPMPROP_TPM_SPACE_SAFETY_MARGIN, TPMPROP_TPM_MAX_NV_SPACE, TPMPROP_TPM_MAX_SAVESTATE_SPACE, TPMPROP_TPM_MAX_VOLATILESTATE_SPACE, }; TPM_RESULT TPMLIB_GetTPMProperty(enum TPMLIB_TPMProperty prop, int *result); enum TPMLIB_InfoFlags { TPMLIB_INFO_TPMSPECIFICATION = 1, TPMLIB_INFO_TPMATTRIBUTES = 2, TPMLIB_INFO_TPMFEATURES = 4, }; char *TPMLIB_GetInfo(enum TPMLIB_InfoFlags flags); struct libtpms_callbacks { int sizeOfStruct; TPM_RESULT (*tpm_nvram_init)(void); TPM_RESULT (*tpm_nvram_loaddata)(unsigned char **data, uint32_t *length, uint32_t tpm_number, const char *name); TPM_RESULT (*tpm_nvram_storedata)(const unsigned char *data, uint32_t length, uint32_t tpm_number, const char *name); TPM_RESULT (*tpm_nvram_deletename)(uint32_t tpm_number, const char *name, TPM_BOOL mustExist); TPM_RESULT (*tpm_io_init)(void); TPM_RESULT (*tpm_io_getlocality)(TPM_MODIFIER_INDICATOR *localityModifer, uint32_t tpm_number); TPM_RESULT (*tpm_io_getphysicalpresence)(TPM_BOOL *physicalPresence, uint32_t tpm_number); }; TPM_RESULT TPMLIB_RegisterCallbacks(struct libtpms_callbacks *); enum TPMLIB_BlobType { TPMLIB_BLOB_TYPE_INITSTATE, TPMLIB_BLOB_TYPE_LAST, }; #define TPMLIB_INITSTATE_START_TAG "-----BEGIN INITSTATE-----" #define TPMLIB_INITSTATE_END_TAG "-----END INITSTATE-----" TPM_RESULT TPMLIB_DecodeBlob(const char *data, enum TPMLIB_BlobType type, unsigned char **result, size_t *result_len); void TPMLIB_SetDebugFD(int fd); void TPMLIB_SetDebugLevel(unsigned int level); TPM_RESULT TPMLIB_SetDebugPrefix(const char *prefix); uint32_t TPMLIB_SetBufferSize(uint32_t wanted_size, uint32_t *min_size, uint32_t *max_size); enum TPMLIB_StateType { TPMLIB_STATE_PERMANENT = (1 << 0), TPMLIB_STATE_VOLATILE = (1 << 1), TPMLIB_STATE_SAVE_STATE = (1 << 2), }; TPM_RESULT TPMLIB_ValidateState(enum TPMLIB_StateType st, unsigned int flags); TPM_RESULT TPMLIB_SetState(enum TPMLIB_StateType st, const unsigned char *buffer, uint32_t buflen); TPM_RESULT TPMLIB_GetState(enum TPMLIB_StateType st, unsigned char **buffer, uint32_t *buflen); #ifdef __cplusplus } #endif #endif /* TPM_LIBRARY_H */ libtpms-0.9.3/include/libtpms/tpm_memory.h000066400000000000000000000055161421143571500206450ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM Memory Allocation */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_memory.h 4609 2011-08-26 19:27:38Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_MEMORY_H #define TPM_MEMORY_H #include "tpm_types.h" #ifdef __cplusplus extern "C" { #endif /* This value is used to limit memory allocation to prevent resource overload. */ #ifndef TPM_ALLOC_MAX #define TPM_ALLOC_MAX 0x20000 /* 128k bytes */ #endif TPM_RESULT TPM_Malloc(unsigned char **buffer, uint32_t size); TPM_RESULT TPM_Realloc(unsigned char **buffer, uint32_t size); void TPM_Free(unsigned char *buffer); #ifdef __cplusplus } #endif #endif libtpms-0.9.3/include/libtpms/tpm_nvfilename.h000066400000000000000000000052441421143571500214570ustar00rootroot00000000000000/********************************************************************************/ /* */ /* NVRAM File Names */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_nvfilename.h 4438 2011-02-13 23:03:56Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ /* Contains the base names used to construct NV storage file names. */ #ifndef TPM_NVFILENAME_H #define TPM_NVFILENAME_H /* Constants for NVRAM names */ #define TPM_PERMANENT_ALL_NAME "permall" #define TPM_SAVESTATE_NAME "savestate" #define TPM_VOLATILESTATE_NAME "volatilestate" #endif libtpms-0.9.3/include/libtpms/tpm_tis.h000066400000000000000000000053401421143571500201270ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM TIS I/O */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_tis.h 4285 2011-01-17 21:27:05Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2011. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_TIS_H #define TPM_TIS_H #include "tpm_types.h" #ifdef __cplusplus extern "C" { #endif TPM_RESULT TPM_IO_Hash_Start(void); TPM_RESULT TPM_IO_Hash_Data(const unsigned char *data, uint32_t data_length); TPM_RESULT TPM_IO_Hash_End(void); TPM_RESULT TPM_IO_TpmEstablished_Get(TPM_BOOL *tpmEstablished); TPM_RESULT TPM_IO_TpmEstablished_Reset(void); #ifdef __cplusplus } #endif #endif libtpms-0.9.3/include/libtpms/tpm_types.h000066400000000000000000000201731421143571500204750ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM Types */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_types.h 4202 2010-11-17 16:26:06Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_TYPES_H #define TPM_TYPES_H #include #if defined (TPM_POSIX) || defined (TPM_SYSTEM_P) #include /* for byte order conversions */ #endif #ifdef __cplusplus extern "C" { #endif /* 2.2.1 Basic data types rev 87 */ #if !defined(TPM_HAVE_TPM2_DECLARATIONS) typedef unsigned char BYTE; /* Basic byte used to transmit all character fields. */ #endif typedef unsigned char TPM_BOOL; /* TRUE/FALSE field. TRUE = 0x01, FALSE = 0x00 Use TPM_BOOL because MS VC++ defines BOOL on Windows */ /* 2.2.2 Boolean types rev 107 */ #undef TRUE #define TRUE 0x01 /* Assertion */ #undef FALSE #define FALSE 0x00 /* Contradiction */ /* 2.2.3 Helper redefinitions rev 101 The following definitions are to make the definitions more explicit and easier to read. NOTE: They cannot be changed without breaking the serialization. */ typedef BYTE TPM_AUTH_DATA_USAGE; /* Indicates the conditions where it is required that authorization be presented. */ typedef BYTE TPM_PAYLOAD_TYPE; /* The information as to what the payload is in an encrypted structure */ typedef BYTE TPM_VERSION_BYTE; /* The version info breakdown */ typedef BYTE TPM_DA_STATE; /* The state of the dictionary attack mitigation logic */ /* added kgold */ typedef BYTE TPM_ENT_TYPE; /* LSB of TPM_ENTITY_TYPE */ typedef BYTE TPM_ADIP_ENC_SCHEME; /* MSB of TPM_ENTITY_TYPE */ typedef uint16_t TPM_PROTOCOL_ID; /* The protocol in use. */ typedef uint16_t TPM_STARTUP_TYPE; /* Indicates the start state. */ typedef uint16_t TPM_ENC_SCHEME; /* The definition of the encryption scheme. */ typedef uint16_t TPM_SIG_SCHEME; /* The definition of the signature scheme. */ typedef uint16_t TPM_MIGRATE_SCHEME; /* The definition of the migration scheme */ typedef uint16_t TPM_PHYSICAL_PRESENCE; /* Sets the state of the physical presence mechanism. */ typedef uint16_t TPM_ENTITY_TYPE; /* Indicates the types of entity that are supported by the TPM. */ typedef uint16_t TPM_KEY_USAGE; /* Indicates the permitted usage of the key. */ typedef uint16_t TPM_EK_TYPE; /* The type of asymmetric encrypted structure in use by the endorsement key */ typedef uint16_t TPM_STRUCTURE_TAG; /* The tag for the structure */ typedef uint16_t TPM_PLATFORM_SPECIFIC; /* The platform specific spec to which the information relates to */ typedef uint32_t TPM_COMMAND_CODE; /* The command ordinal. */ typedef uint32_t TPM_CAPABILITY_AREA; /* Identifies a TPM capability area. */ typedef uint32_t TPM_KEY_FLAGS; /* Indicates information regarding a key. */ #if !defined(TPM_HAVE_TPM2_DECLARATIONS) typedef uint32_t TPM_ALGORITHM_ID; /* Indicates the type of algorithm. */ typedef uint32_t TPM_MODIFIER_INDICATOR; /* The locality modifier */ #endif typedef uint32_t TPM_ACTUAL_COUNT; /* The actual number of a counter. */ typedef uint32_t TPM_TRANSPORT_ATTRIBUTES; /* Attributes that define what options are in use for a transport session */ typedef uint32_t TPM_AUTHHANDLE; /* Handle to an authorization session */ typedef uint32_t TPM_DIRINDEX; /* Index to a DIR register */ typedef uint32_t TPM_KEY_HANDLE; /* The area where a key is held assigned by the TPM. */ typedef uint32_t TPM_PCRINDEX; /* Index to a PCR register */ typedef uint32_t TPM_RESULT; /* The return code from a function */ typedef uint32_t TPM_RESOURCE_TYPE; /* The types of resources that a TPM may have using internal resources */ typedef uint32_t TPM_KEY_CONTROL; /* Allows for controlling of the key when loaded and how to handle TPM_Startup issues */ #if !defined(TPM_HAVE_TPM2_DECLARATIONS) typedef uint32_t TPM_NV_INDEX; /* The index into the NV storage area */ #endif typedef uint32_t TPM_FAMILY_ID; /* The family ID. Families ID's are automatically assigned a sequence number by the TPM. A trusted process can set the FamilyID value in an individual row to zero, which invalidates that row. The family ID resets to zero on each change of TPM Owner. */ typedef uint32_t TPM_FAMILY_VERIFICATION; /* A value used as a label for the most recent verification of this family. Set to zero when not in use. */ typedef uint32_t TPM_STARTUP_EFFECTS; /* How the TPM handles var */ typedef uint32_t TPM_SYM_MODE; /* The mode of a symmetric encryption */ typedef uint32_t TPM_FAMILY_FLAGS; /* The family flags */ typedef uint32_t TPM_DELEGATE_INDEX; /* The index value for the delegate NV table */ typedef uint32_t TPM_CMK_DELEGATE; /* The restrictions placed on delegation of CMK commands */ typedef uint32_t TPM_COUNT_ID; /* The ID value of a monotonic counter */ typedef uint32_t TPM_REDIT_COMMAND; /* A command to execute */ typedef uint32_t TPM_TRANSHANDLE; /* A transport session handle */ #if !defined(TPM_HAVE_TPM2_DECLARATIONS) typedef uint32_t TPM_HANDLE; /* A generic handle could be key, transport etc. */ #endif typedef uint32_t TPM_FAMILY_OPERATION; /* What operation is happening */ /* Not in specification */ typedef uint16_t TPM_TAG; /* The command and response tags */ typedef unsigned char * TPM_SYMMETRIC_KEY_TOKEN; /* abstract symmetric key token */ typedef unsigned char * TPM_BIGNUM; /* abstract bignum */ #ifdef __cplusplus } #endif #endif libtpms-0.9.3/libtpms.pc.in000066400000000000000000000003711421143571500156040ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=${prefix} libdir=@libdir@ includedir=@includedir@ cryptolib=@cryptolib@ with_tpm1=@WITH_TPM1@ with_tpm2=@WITH_TPM2@ Name: libtpms Version: @VERSION@ Description: libtpms Libs: -L${libdir} -ltpms Cflags: -I${includedir} libtpms-0.9.3/m4/000077500000000000000000000000001421143571500135205ustar00rootroot00000000000000libtpms-0.9.3/m4/ax_check_define.m4000066400000000000000000000011631421143571500170420ustar00rootroot00000000000000# SYNOPSIS # # AX_CHECK_DEFINE(includefile, define, [ACTION-SUCCESS], [ACTION-FAILURE]) # # DESCRIPTION # # Check whether the given #define is available in the given #include file # # LICENSE # # See the root directory of the libtpms project for the LICENSE # AC_DEFUN([AX_CHECK_DEFINE], [AC_PREREQ(2.63) AC_MSG_CHECKING(whether $2 is defined in $1) AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([[#include $1]], [[#ifndef $2 #error $2 not defined #endif]])], [ AC_MSG_RESULT([yes]) [$3] ], [ AC_MSG_RESULT([no]) [$4] ] ) ] ) libtpms-0.9.3/m4/ax_check_linker_flag.m4000066400000000000000000000062771421143571500201000ustar00rootroot00000000000000# =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_check_link_flag.html # =========================================================================== # # SYNOPSIS # # AX_CHECK_LINK_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) # # DESCRIPTION # # Check whether the given FLAG works with the linker or gives an error. # (Warnings, however, are ignored) # # ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on # success/failure. # # If EXTRA-FLAGS is defined, it is added to the linker's default flags # when the check is done. The check is thus made with the flags: "LDFLAGS # EXTRA-FLAGS FLAG". This can for example be used to force the linker to # issue an error when a bad flag is given. # # INPUT gives an alternative input source to AC_LINK_IFELSE. # # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this # macro in sync with AX_CHECK_{PREPROC,COMPILE}_FLAG. # # LICENSE # # Copyright (c) 2008 Guido U. Draheim # Copyright (c) 2011 Maarten Bosmans # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation, either version 3 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 5 AC_DEFUN([AX_CHECK_LINK_FLAG], [AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl AC_CACHE_CHECK([whether the linker accepts $1], CACHEVAR, [ ax_check_save_flags=$LDFLAGS LDFLAGS="$LDFLAGS $4 $1" AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[time_t x; int fodder = 0; if (fodder > -1000 && time(&x)) return (int) x]])], [AS_VAR_SET(CACHEVAR,[yes])], [AS_VAR_SET(CACHEVAR,[no])]) LDFLAGS=$ax_check_save_flags]) AS_VAR_IF(CACHEVAR,yes, [m4_default([$2], :)], [m4_default([$3], :)]) AS_VAR_POPDEF([CACHEVAR])dnl ])dnl AX_CHECK_LINK_FLAGS libtpms-0.9.3/man/000077500000000000000000000000001421143571500137535ustar00rootroot00000000000000libtpms-0.9.3/man/Makefile.am000066400000000000000000000001471421143571500160110ustar00rootroot00000000000000# # man/Makefile.am # # For the license, see the LICENSE file in the root directory. # SUBDIRS = man3 libtpms-0.9.3/man/man3/000077500000000000000000000000001421143571500146115ustar00rootroot00000000000000libtpms-0.9.3/man/man3/Makefile.am000066400000000000000000000026071421143571500166520ustar00rootroot00000000000000# # man/man3/Makefile.am # # For the license, see the LICENSE file in the root directory. # man3_PODS = \ TPM_IO_Hash_Start.pod \ TPM_IO_TpmEstablished_Get.pod \ TPMLIB_CancelCommand.pod \ TPMLIB_ChooseTPMVersion.pod \ TPMLIB_DecodeBlob.pod \ TPMLIB_GetInfo.pod \ TPMLIB_GetTPMProperty.pod \ TPMLIB_GetVersion.pod \ TPMLIB_MainInit.pod \ TPMLIB_Process.pod \ TPMLIB_RegisterCallbacks.pod \ TPMLIB_SetBufferSize.pod \ TPMLIB_SetDebugFD.pod \ TPMLIB_SetState.pod \ TPMLIB_ValidateState.pod \ TPMLIB_VolatileAll_Store.pod \ TPM_Malloc.pod man3_MANS = \ TPM_Free.3 \ TPM_IO_Hash_Data.3 \ TPM_IO_Hash_End.3 \ TPMLIB_GetState.3 \ TPMLIB_SetDebugPrefix.3 \ TPMLIB_SetDebugLevel.3 \ TPM_IO_TpmEstablished_Reset.3 \ TPMLIB_Terminate.3 \ TPM_Realloc.3 man3_MANS_generated = \ TPM_IO_Hash_Start.3 \ TPM_IO_TpmEstablished_Get.3 \ TPMLIB_CancelCommand.3 \ TPMLIB_ChooseTPMVersion.3 \ TPMLIB_DecodeBlob.3 \ TPMLIB_GetInfo.3 \ TPMLIB_GetTPMProperty.3 \ TPMLIB_GetVersion.3 \ TPMLIB_MainInit.3 \ TPMLIB_Process.3 \ TPMLIB_SetDebugFD.3 \ TPMLIB_SetBufferSize.3 \ TPMLIB_SetState.3 \ TPMLIB_RegisterCallbacks.3 \ TPMLIB_ValidateState.3 \ TPMLIB_VolatileAll_Store.3 \ TPM_Malloc.3 man3_MANS += $(man3_MANS_generated) %.3 : %.pod @pod2man -r "libtpms" \ -c "" \ -n $(basename $@) \ --section=3 $< > $@ EXTRA_DIST = $(man3_MANS) $(man3_PODS) CLEANFILES = $(man3_MANS_generated) libtpms-0.9.3/man/man3/TPMLIB_CancelCommand.pod000066400000000000000000000011751421143571500210540ustar00rootroot00000000000000=head1 NAME TPMLIB_CancelCommand - Cancel a TPM command =head1 LIBRARY TPM library (libtpms, -ltpms) =head1 SYNOPSIS B<#include > B =head1 DESCRIPTION The B function indicates that the ongoing processing of a TPM command is to be cancelled. The cancellation will only be effective for certain time consuming operations, such as the creation of keys. Note that an implementation that wants to support cancellation of commands needs to process TPM commands in one thread and cancel them in another. =head1 SEE ALSO B(3) =cut libtpms-0.9.3/man/man3/TPMLIB_ChooseTPMVersion.pod000066400000000000000000000022361421143571500215360ustar00rootroot00000000000000=head1 NAME TPMLIB_ChooseTPMVersion - Choose the version of the TPM =head1 SYNOPSIS B<#include > B<#include > B IB<);> typedef enum TPMLIB_TPMVersion { TPMLIB_TPM_VERSION_1_2, TPMLIB_TPM_VERSION_2, } TPMLIB_TPMVersion; =head1 DESCRIPTION The B function is used to choose the version of the TPM, either a TPM 1.2 or TPM 2. This function must be called before B is called and will otherwise return an error. This function may be called again once B has been called. If this function is not called, the last chosen TPM version will be started with B. If this function is not called, a TPM 1.2 will be used. =head1 ERRORS =over 4 =item B The version of the TPM was chosen successfully. =item B The choice of the TPM was wrong, or TPMLIB_MainInit() has already been called. =back For a complete list of TPM error codes please consult the include file B =head1 SEE ALSO B(3), B(3) =cut libtpms-0.9.3/man/man3/TPMLIB_DecodeBlob.pod000066400000000000000000000027641421143571500203570ustar00rootroot00000000000000=head1 NAME TPMLIB_DecodeBlob - Decode a base64-encode TPM blob =head1 SYNOPSIS B<#include > B<#include > B *IB<, enum TPMLIB_BlobType> IB<, unsigned char> **IB< size_t> *IB<);> =head1 DESCRIPTION The B function is used to decode a base64-encoded TPM state blob. The caller must pass what type of blob is expected to be decoded and following that the function will look for the start and end markers of the data. The following types of blobs are supported along with their start and end markers: =over 4 =item B '-----BEGIN INITSTATE-----' marks the beginning of the base64-encoded blob. '-----END INITSTATE-----' marks the end of the base64-encoded blob. =back This function is useful when passing state to the TPM inside the callback that is invoked to get the TPM's state blob. See I(3). =head1 ERRORS =over 4 =item B The function completed successfully. =item B The size of a requested buffer exceeds the limit or the system is out of memory. =item B An error occurred while attempting to decode the blob. =back For a complete list of TPM error codes please consult the include file B =head1 SEE ALSO B(3), B(3) =cut libtpms-0.9.3/man/man3/TPMLIB_GetInfo.pod000066400000000000000000000023531421143571500177220ustar00rootroot00000000000000=head1 NAME TPMLIB_GetInfo - Get Information about the TPM implementation =head1 LIBRARY TPM library (libtpms, -ltpms) =head1 SYNOPSIS B<#include > B =head1 DESCRIPTION The B function allows to query for TPM implementation specifics and get a JSON string in return. Which data is to be returned can be specified in the flags parameter that may be a logical 'or' concatenation of flags. If passed flags are not supported, nothing is returned . If a 0 is passed in, an empty JSON Object '{}' is returned. The following flags are defined and return JSON objects as shown: =over 4 =item B {"TPMSpecification":{"family":"1.2","level":2,"revision":116}} =item B {"TPMAttributes":{"manufacturer":"id:00001014","version":"id:00740001","model":"swtpm"}} =item B (since v0.8.0) {"TPMFeatures":{"RSAKeySizes":[1024,2048,3072]}} This JSON object may be extended in the future. =back =head1 RETURN VALUE This function returns a JSON string on success and a NULL pointer if a memory allocation failure occurred. The caller must free() the returned string. =head1 SEE ALSO =cut libtpms-0.9.3/man/man3/TPMLIB_GetState.3000066400000000000000000000000331421143571500174600ustar00rootroot00000000000000.so man3/TPMLIB_SetState.3 libtpms-0.9.3/man/man3/TPMLIB_GetTPMProperty.pod000066400000000000000000000064571421143571500212450ustar00rootroot00000000000000=head1 NAME TPMLIB_GetTPMProperty - Get a runtime property of the TPM =head1 LIBRARY TPM library (libtpms, -ltpms) =head1 SYNOPSIS B<#include > B =head1 DESCRIPTION The B call is used to retrieve run-time parameters of the TPM such as the number of authorization sessions it can hold or the maximum sizes of the permanent state, savestate or volatile state blobs. This function can be called before or after the TPM has been created. The current implementation of libtpms will return the same value before and after the TPM was started. With the introduction of the function B, the call to this function should be executed after the TPM version has been chosen. The reason is that different TPM versions may return different values. The following properties have been defined: =over 4 =item B The maximum size of an RSA key. =item B The maximum sizes of the TPM command and result buffers. =item B The number of key slots. =item B The number of owner-evict keys. =item B The number of authorization sessions. =item B The number of transport sessions. =item B The number of DAA sessions. =item B The size of the session list. =item B The number of monotonic counters. =item B The number of family entries. =item B The number of delegate entries. =item B The space safety margin used for the worst-case sizes of the savestate and volatile state blobs. This safety margin is not used for the size of the permanent data blob. =item B The maximum size of the permanent data blob. =item B The maximum size of the savestate blob (includes the space safety margin). =item B The maximum size of the volatile state blob (includes the space saferty margin). =back =head1 ERRORS =over 4 =item B The function completed successfully. =item B An undefined property was queried. =back For a complete list of TPM error codes please consult the include file B =head1 EXAMPLE #include #include #include int main(void) { TPM_RESULT res; int result; int rc = 0; if (TPMLIB_MainInit() != TPM_SUCCESS) { fprintf(stderr, "Could not start the TPM.\n"); return 1; } if (TPMLIB_GetTPMProperty(TPMPROP_TPM_RSA_KEY_LENGTH_MAX, &result) != TPM_SUCCESS) { fprintf(stderr, "Could not read the max. size of RSA keys.\n"); goto err_exit; } fprintf(stdout, "Max. size of RSA keys: %d\n", result); err_exit: TPMLIB_Terminate(); return 0; } =head1 SEE ALSO B(3), B(3), B(3), B(3), B(3), B(3) =cut libtpms-0.9.3/man/man3/TPMLIB_GetVersion.pod000066400000000000000000000011431421143571500204500ustar00rootroot00000000000000=head1 NAME TPMLIB_GetVersion - Get the version of the TPM library =head1 LIBRARY TPM library (libtpms, -ltpms) =head1 SYNOPSIS B<#include > B =head1 DESCRIPTION The B function returns the libtpms library version. The TPM library version is formatted as follows: Bits 0 - 7 : revision of the library Bits 8 -15 : minor version number of the library Bits 16-23 : major version number of the library V0.5.1 is therefore represented as 0x00000501. =head1 SEE ALSO B(3), B(3) =cut libtpms-0.9.3/man/man3/TPMLIB_MainInit.pod000066400000000000000000000040301421143571500200710ustar00rootroot00000000000000=head1 NAME TPMLIB_MainInit - Initialize the TPM TPMLIB_Terminate - Terminate the TPM =head1 LIBRARY TPM library (libtpms, -ltpms) =head1 SYNOPSIS B<#include > B<#include > B<#include > B B =head1 DESCRIPTION The B and B functions are used to initialize and terminate the TPM respectively. The B function must be called before the TPM processes any TPM command. The B function is called to free all the internal resources (memory allocations) the TPM has used and must be called after the last TPM command was processed by the TPM. The B function can then be called again. Use B to set callback functions for initialization and writing and restoring the internal state in a portable format. =head1 ERRORS =over 4 =item B The function completed successfully. =item B General failure. =back For a complete list of TPM error codes please consult the include file B =head1 EXAMPLE #include #include #include #include int main(void) { TPM_RESULT res; unsigned char *respbuffer = NULL; uint32_t resp_size = 0; uint32_t respbufsize = 0; unsigned char *command; uint32_t command_size; [...] if (TPMLIB_MainInit() != TPM_SUCCESS) { fprintf(stderr, "Could not start the TPM.\n"); return 1; } [...] /* build TPM command */ [...] res = TPMLIB_Process(&respbuffer, &resp_size, &respbufsize, command, command_size); [...] TPMLIB_Terminate(); return 0; } =head1 SEE ALSO B(3), B(3), B(3) B(3), B(3) =cut libtpms-0.9.3/man/man3/TPMLIB_Process.pod000066400000000000000000000055021421143571500200040ustar00rootroot00000000000000=head1 NAME TPMLIB_Process - process a TPM command =head1 LIBRARY TPM library (libtpms, -ltpms) =head1 SYNOPSIS B<#include > B<#include > B **IB<, uint32_t> *IB<, uint32_t> *IB<, unsigned char> *IB<, uint32_t> IB<);> =head1 DESCRIPTION The B function is used to send TPM commands to the TPM and receive the results. The I parameter provides the buffer for the TPM command and the I the number of valid TPM command bytes within that buffer. The I is a pointer to a buffer where the TPM will return its result. If no buffer is given (I is NULL), the TPM will allocate a buffer. The parameter I returns the number of valid TPM response bytes in the buffer. The number of valid bytes in the response is guaranteed to not exceed the maximum I/O buffer size. Use the I API and parameter I for getting the maximum size. The user must indicate the size of a provided buffer with the I parameter. If the buffer is not big enough for the response, the TPM will free the provided buffer and allocate one of sufficient size and adapt I. The returned buffer is only subject to size restrictions as explained for I. =head1 ERRORS =over 4 =item B The function completed successfully. =item B General failure. =back For a complete list of TPM error codes please consult the include file B =head1 EXAMPLE #include #include #include #include static unsigned char TPM_Startup_ST_CLEAR[] = { 0x00, 0xC1, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x99, 0x00, TPM_ST_CLEAR }; int main(void) { TPM_RESULT res; unsigned char *respbuffer = NULL; uint32_t resp_size = 0; uint32_t respbufsize = 0; unsigned char *command; uint32_t command_size; [...] if (TPMLIB_MainInit() != TPM_SUCCESS) { fprintf(stderr, "Could not start the TPM.\n"); return 1; } [...] /* build TPM command */ command = TPM_Startup_ST_CLEAR; command_size = sizeof(TPM_Startup_ST_CLEAR); [...] res = TPMLIB_Process(&respbuffer, &resp_size, &respbufsize, command, command_size); [...] TPMLIB_Terminate(); return 0; } =head1 SEE ALSO B(3), B(3), B(3) B(3), B(3), B(3) =cut libtpms-0.9.3/man/man3/TPMLIB_RegisterCallbacks.pod000066400000000000000000000226771421143571500217660ustar00rootroot00000000000000 =head1 NAME TPMLIB_RegisterCallbacks - Register callbacks for implementing customized behavior of certain functions =head1 LIBRARY TPM library (libtpms, -ltpms) =head1 SYNOPSIS B<#include > B<#include > B<#include > B =head1 DESCRIPTION The B functions allows to register several callback functions with libtpms that enable a user to implement customized behavior of several library-internal functions. This feature will typically be used if the behavior of the provided internal functions is not as needed. An example would be that libtpms writes all data into files with certain names. If, however, the data needs to be written into a special type of storage the user will register callbacks with the library that are invoked when the TPM needs to write, read or delete data from storage and the user may then implement custom behavior in these functions. The following shows the data structure used for registering the callbacks. struct libtpms_callbacks { int sizeOfStruct; TPM_RESULT (*tpm_nvram_init)(void); TPM_RESULT (*tpm_nvram_loaddata)(unsigned char **data, uint32_t *length, uint32_t tpm_number, const char *name); TPM_RESULT (*tpm_nvram_storedata)(const unsigned char *data, uint32_t length, uint32_t tpm_number, const char *name); TPM_RESULT (*tpm_nvram_deletename)(uint32_t tpm_number, const char *name, TPM_BOOL mustExist); TPM_RESULT (*tpm_io_init)(void); TPM_RESULT (*tpm_io_getlocality)(TPM_MODIFIER_INDICATOR *localityModifer, uint32_t tpm_number); TPM_RESULT (*tpm_io_getphysicalpresence)(TPM_BOOL *physicalPresence, uint32_t tpm_number); }; Currently 7 callbacks are supported. If a callback pointer in the above structure is set to NULL the default library-internal implementation of that function will be used. If one of the callbacks in either the I or I group is set, then all of the callbacks in the respective group should be implemented. =over 4 =item B This function is called before any access to persitent storage is done. It allows the user to perform initialization of access to persitent storage. Upon success this function should return B, a failure code otherwise. The default implementation requires that the environment variable I is set and points to a directory where the TPM's state can be written to. If the variable is not set, it will return B and the initialization of the TPM in B will fail. =item B This function is called when the TPM wants to load state from persistent storage. The implementing function must allocate a buffer (I) and return it to the TPM along with the length of the buffer (I). The I is always 0 and can be ignored. The I parameter is either one of B, B, or B and indicates which one of the 3 types of state is supposed to be loaded. Upon success this function should return B, a failure code otherwise. The default implementation writes the TPM's state into files in a directory where the I environment variable pointed to when B was executed. Failure to write the TPM's state into files will put the TPM into failure mode. If this function is not set (NULL), then the original NVChip file will be read when using a TPM 2. This file contains the memory dump of internal data structures and is neither portable between endianesses or architectures of different sizes (32 bit, 64 bit), nor will it allow handling extensions of those internal data structures it carries through additions in the TPM 2 code. In the worst case this may result in memory access errors by internal functions and result in crashes. Therefore, it is recommended to set this function and handle the writing of the TPM state. =item B This function is called when the TPM wants to store state to persistent storage. The I and I parameters provide the data to be stored and the number of bytes. The implementing function must not free the I buffer. The I is always 0 and can be ignored. The I parameter is either one of B, B, or B and indicates which one of the 3 types of state is supposed to be stored. Upon success this function should return B, a failure code otherwise. The default implementation reads the TPM's state from files in a directory where the I environment variable pointed to when B was executed. Failure to read the TPM's state from files may put the TPM into failure mode. If this function is not set (NULL), the memory dump will be written to the NVChip file (TPM 2) and the same comments apply as when the I interface function is not set. =item B This function is called when the TPM wants to delete state on persistent storage. The I is always 0 and can be ignored. The I parameter is either one of B, B, or B and indicates which one of the 3 types of state is supposed to be deleted. The I parameter indicates whether the given data must exist and the implementing function should return B if the data did not exist. Upon success this function should return B, a failure code otherwise. The default implementation deletes the TPM's state files in a directory where the I environment variable pointed to when B was executed. Failure to delete the TPM's state files may put the TPM into failure mode. =item B This function is called to initialize the IO subsystem of the TPM. Upon success this function should return B, a failure code otherwise. The default implementation simply returns B. =item B This function is called when the TPM needs to determine the locality under which a command is supposed to be executed. The implementing function should return the number of the locality by writing it into the B pointer. Upon success this function should return B, a failure code otherwise. The default implementation returns 0 as the locality. =item B This function is called when the TPM needs to determine whether physical presence has been asserted. The implementing function should write either B or B into the physicalPresence pointer. Upon success this function should return B, a failure code otherwise. The default implementation returns B for physical presence. =back =head1 RETURN VALUE Upon successful completion, B returns B, an error value otherwise. =head1 ERRORS =over 4 =item B The function completed successfully. =item B General failure. =back For a complete list of TPM error codes please consult the include file B =head1 EXAMPLE #include #include #include static TPM_MODIFIER_INDICATOR locality; static TPM_RESULT mytpm_io_init(void) { return TPM_SUCCESS; } static TPM_RESULT mytpm_io_getlocality(TPM_MODIFIER_INDICATOR *locModif, uint32_t tpm_number) { *locModif = locality; return TPM_SUCCESS: } static TPM_RESULT mytpm_io_getphysicalpresence(TPM_BOOL *physicalPresence, uint32_t tpm_number) { *physicalPresence = FALSE; return TPM_SUCCESS; } int main(void) { TPM_RESULT res; unsigned char *respbuffer; uint32_t resp_size; uint32_t respbufsize; unsigned char *command; uint32_t command_size; struct libtpms_callbacks cbs = { .sizeOfStruct = sizeof(struct libtpms_callbacks), .tpm_nvram_init = NULL, .tpm_nvram_loaddata = NULL, .tpm_nvram_storedata = NULL, .tpm_nvram_deletename = NULL, .tpm_io_init = mytpm_io_init, .tpm_io_getlocality = mytpm_io_getlocality, .tpm_io_getphysicalpresence = mytpm_io_getphysicalpresence, }; [...] if (TPMLIB_RegisterCallbacks(&cbs) != TPM_SUCCESS) { fprintf(stderr, "Could not register the callbacks.\n"); return 1; } if (TPMLIB_MainInit()) != TPM_SUCCESS) { fprintf(stderr, "Could not start the TPM.\n"); return 1; } [...] /* build TPM command */ [...] res = TPMLIB_Process(&respbuffer, &resp_size, &respbufsize, command, command_size); [...] TPMLIB_Terminate(); return 0; } =head1 SEE ALSO B(3), B(3), B(3), B(3) =cut libtpms-0.9.3/man/man3/TPMLIB_SetBufferSize.pod000066400000000000000000000021151421143571500211030ustar00rootroot00000000000000=head1 NAME TPMLIB_SetBufferSize - Set the TPM's I/O buffer size =head1 LIBRARY TPM library (libtpms, -ltpms) =head1 SYNOPSIS B<#include > B =head1 DESCRIPTION The B function sets the size of the buffer the TPM can use for input and output and that it advertises to users. It also allows to get the minimum and maximum supported buffer size. If 0 is given on input, the currently used buffer size is returned. Any other number will try to change the buffer size. The returned size may be smaller than the requested one, if the requested one was above a maximum. The returned size may be larger than the requested one, if the requested one was below a minimum. This function must be called after B has been called. It should not be called after B has been called but can again be called once B has been called. =head1 SEE ALSO B(3), B(3), B(3) =cut libtpms-0.9.3/man/man3/TPMLIB_SetDebugFD.pod000066400000000000000000000020001421143571500202700ustar00rootroot00000000000000=head1 NAME TPMLIB_SetDebugFD - Set the file descriptor to send the debug output to TPMLIB_SetDebugLevel - Set the debugging level TPMLIB_SetDebugPrefix - Set the prefix for each debugging line =head1 LIBRARY TPM library (libtpms, -ltpms) =head1 SYNOPSIS B<#include > B B B =head1 DESCRIPTION B allows to set the file descriptor to send the debug output to. B allows to set the debug level. Only debug levels greater than 1 will produce output. The indentation level of a line will determine whether it is printed. Lines with 0 indentation will be printed at debug level 1, 1 space of indentation at debug level 2 and so on. B allows to set a prefix that is to be printed in front of every line of debugging output. The prefix can be used for further indentation. =cut libtpms-0.9.3/man/man3/TPMLIB_SetDebugLevel.3000066400000000000000000000000341421143571500204330ustar00rootroot00000000000000.so man3/TPMLIB_SetDebugFD.3libtpms-0.9.3/man/man3/TPMLIB_SetDebugPrefix.3000066400000000000000000000000341421143571500206210ustar00rootroot00000000000000.so man3/TPMLIB_SetDebugFD.3libtpms-0.9.3/man/man3/TPMLIB_SetState.pod000066400000000000000000000043161421143571500201240ustar00rootroot00000000000000=head1 NAME TPMLIB_SetState - Set the TPM's volatile, permanent, or save state TPMLIB_GetState - Get the TPM's volatile, permanent, or save state =head1 LIBRARY TPM library (libtpms, -ltpms) =head1 SYNOPSIS B<#include > B B =head1 DESCRIPTION The B function allows to set either one of the state blobs of the TPM. The passed state blob is tested for whether it can be accepted and a TPM error code is returned in case it cannot be accepted. In case of acceptance, the state blob will be passed to the TPM upon B. Setting a state blob hides a file that may contain the same type of blob and would be read otherwise. It is required to call this function with a NULL pointer for the buffer parameter to hide a state blob in a file. It is only possible to set the state blobs after B has been called. All state blobs are cleared when a different version of TPM is chosen using B or when a call to B fails because a state blob could not be accepted. The order in which state blobs are set is important. The first state blob has to be the one representing the TPM's permanent state. Only after that either the volatile or save state blobs can be set. The B function allows to get the current state of the TPM. For as long as the TPM has not been started, this function either returns the state blob previously set with B or the state is read from a file. Once the TPM has been start the state of the running TPM is returned. The B (save state) type of TPM state can be set with this function. The same state blob will be returned until TPM_Startup(ST_STATE) has been called, after which an empty blob will be returned. This blob can also only be read after TPM_SaveState() has been sent to the TPM. =head1 SEE ALSO B(3), B(3), B(3) =cut libtpms-0.9.3/man/man3/TPMLIB_Terminate.3000066400000000000000000000000321421143571500176670ustar00rootroot00000000000000.so man3/TPMLIB_MainInit.3libtpms-0.9.3/man/man3/TPMLIB_ValidateState.pod000066400000000000000000000024171421143571500211220ustar00rootroot00000000000000=head1 NAME TPMLIB_ValidateState - Validate the state blobs of the TPM =head1 LIBRARY TPM library (libtpms, -ltpms) =head1 SYNOPSIS B<#include > B =head1 DESCRIPTION The B function allows to validate the state blobs that the TPM would read upon B or once the TPM_Startup command has been sent to it. This function is useful for TPM state migration between possibly different version of libtpms. Here the target libtpms needs to be able to determine whether it can support the version of blobs that were migrated and if this is not the case, the caller can refuse the migration. The B parameter can be a logical 'or' of one or multiple of of the following: B, B, or B. The B parameter is currently not used and should be set to 0. The first state blob that should be loaded is the permanent state, since for example the volatile state requires it to be available for validation. This function should be called before B is invoked. =head1 SEE ALSO B(3), B(3) =cut libtpms-0.9.3/man/man3/TPMLIB_VolatileAll_Store.pod000066400000000000000000000016021421143571500217470ustar00rootroot00000000000000=head1 NAME TPMLIB_VolatileAll_Store - store all volatile state of the TPM in a buffer =head1 LIBRARY TPM library (libtpms, -ltpms) =head1 SYNOPSIS B<#include > B<#include > B =head1 DESCRIPTION The B function is used to get the volatile state of the TPM. The function will allocate a I and return the number of bytes of state information in the I variable. =head1 ERRORS =over 4 =item B The function completed successfully. =item B General failure. =back For a complete list of TPM error codes please consult the include file B =head1 SEE ALSO B(3), B(3), B(3) =cut libtpms-0.9.3/man/man3/TPM_Free.3000066400000000000000000000000261421143571500162740ustar00rootroot00000000000000.so man3/TPM_Malloc.3 libtpms-0.9.3/man/man3/TPM_IO_Hash_Data.3000066400000000000000000000000341421143571500176150ustar00rootroot00000000000000.so man3/TPM_IO_Hash_Start.3libtpms-0.9.3/man/man3/TPM_IO_Hash_End.3000066400000000000000000000000341421143571500174520ustar00rootroot00000000000000.so man3/TPM_IO_Hash_Start.3libtpms-0.9.3/man/man3/TPM_IO_Hash_Start.pod000066400000000000000000000037441421143571500204740ustar00rootroot00000000000000=head1 NAME TPM_IO_Hash_Start - indicate the beginging of a TPM TIS hash operation TPM_IO_Hash_Data - hash the provided data TPM_IO_Hash_End - indicate the end of a TPM TIS hash operation =head1 LIBRARY TPM library (libtpms, -ltpms) =head1 SYNOPSIS B<#include > B<#include > B<#include > B B *IB<, uint32_t> IB<);> B =head1 DESCRIPTION The B function can be used by an implementation of the TPM TIS hardware interface to indicate the beginning of a hash operation. Following the TPM TIS interface specification it resets several PCRs and terminates existing transport sessions. The B function is used to send the data to be hashed to the TPM. The B function calculates the final hash and stores it in the locality 4 PCR. The 3 functions must be called in the order they were explained. The implementation of the above functions handles all TPM-internal actions such as the setting and clearing of permanent flags and PCRs and the calculation of the hash. Any functionality related to the TPM's TIS interface and the handling of flags, locality and state has to be implemented by the caller. =head1 ERRORS =over 4 =item B The function completed successfully. =item B General failure. =item B The B function was called before the TPM received a TPM_Startup command. =item B The B or B functions were called before the B function. =back For a complete list of TPM error codes please consult the include file B =head1 SEE ALSO B(3), B(3), B(3), B(3) =cut libtpms-0.9.3/man/man3/TPM_IO_TpmEstablished_Get.pod000066400000000000000000000022031421143571500221300ustar00rootroot00000000000000=head1 NAME TPM_IO_TpmEstablished_Get - get the value of the TPMEstablished flag TPM_IO_TpmEstablished_Reset - reset the TPMEstablished flag =head1 LIBRARY TPM library (libtpms, -ltpms) =head1 SYNOPSIS B<#include > B<#include > B<#include > B *IB<);> B =head1 DESCRIPTION The B function returns the value of the TPMEstablished flag of the TPM's permanent data. The B function resets the TPMEstablished flag. =head1 ERRORS =over 4 =item B The function completed successfully. =item B General failure. =item B The locality used for resetting the flags is wrong. =back For a complete list of TPM error codes please consult the include file B =head1 SEE ALSO B(3), B(3), B(3), B(3), B(3), B(3), B(3) =cut libtpms-0.9.3/man/man3/TPM_IO_TpmEstablished_Reset.3000066400000000000000000000000451421143571500220550ustar00rootroot00000000000000.so man3/TPM_IO_TpmEstablished_Get.3 libtpms-0.9.3/man/man3/TPM_Malloc.pod000066400000000000000000000034121421143571500172440ustar00rootroot00000000000000=head1 NAME TPM_Malloc - Allocate memory TPM_Realloc - Reallocate memory TPM_Free - Free memory =head1 SYNOPSIS B<#include > B<#include > B<#include > B **IB<, uint32_t> IB<);> B **IB<, uint32_t> IB<);> B *IB<);> =head1 DESCRIPTION The B function is used to allocate a buffer of the given size. The allocated buffer will be returned in the I parameter. The B function is used to resize a buffer. The new size of the buffer is given in the I parameter. The reallocated buffer will contain the data from the original buffer. Both functions have the restriction that the buffer they can allocate is limited to B (64k) bytes. This size is sufficient for all buffers needed by the TPM. Upon successful completion, the functions return B. In case the requested buffer exceeds the limit, B will be returned. See further possible error codes below. The B function frees the memory previously allocated using either B or B. =head1 ERRORS =over 4 =item B The function completed successfully. =item B The size of the requested buffer exceeds the limit or the system is out of memory. =item B Requested buffer is of size 0. =back For a complete list of TPM error codes please consult the include file B =head1 SEE ALSO B(3), B(3) B(3), B(3), B(3) =cut libtpms-0.9.3/man/man3/TPM_Realloc.3000066400000000000000000000000251421143571500167730ustar00rootroot00000000000000.so man3/TPM_Malloc.3libtpms-0.9.3/src/000077500000000000000000000000001421143571500137675ustar00rootroot00000000000000libtpms-0.9.3/src/Makefile.am000066400000000000000000000363171421143571500160350ustar00rootroot00000000000000# # src/Makefile.am # # For the license, see the LICENSE file in the root directory. # AM_CFLAGS = @AM_CFLAGS@ AM_LDFLAGS = @AM_LDFLAGS@ $(HARDENING_LDFLAGS) $(SANITIZERS) $(FUZZER) noinst_LTLIBRARIES = noinst_HEADERS = lib_LTLIBRARIES = libtpms.la libtpms_la_LIBADD = common_CFLAGS = -include tpm_library_conf.h \ -I$(top_srcdir)/include/libtpms \ -I$(top_builddir)/include/libtpms \ $(AM_CFLAGS) \ $(HARDENING_CFLAGS) \ $(SANITIZERS) \ $(FUZZER) \ $(LIBCRYPTO_EXTRA_CFLAGS) # build with libtpms callback support common_CFLAGS += -DTPM_LIBTPMS_CALLBACKS # let the default NVRAM write to disk common_CFLAGS += -DTPM_NV_DISK if WITH_TPM1 # # TPM1.2 # noinst_LTLIBRARIES += libtpms_tpm12.la libtpms_la_LIBADD += libtpms_tpm12.la libtpms_tpm12_la_LIBADD = libtpms_tpm12_la_CFLAGS = $(common_CFLAGS) #Build 1.2 TPM libtpms_tpm12_la_CFLAGS += -DTPM_V12 # build a PC Client TPM libtpms_tpm12_la_CFLAGS += -DTPM_PCCLIENT # upon initialization have the TPM load the volatile state libtpms_tpm12_la_CFLAGS += -DTPM_VOLATILE_LOAD # build the TPM enabled and activated libtpms_tpm12_la_CFLAGS += -DTPM_ENABLE_ACTIVATE # build with AES support for symmetric crypto libtpms_tpm12_la_CFLAGS += -DTPM_AES # build a POSIX type of TPM libtpms_tpm12_la_CFLAGS += -DTPM_POSIX # build without maintenance commands libtpms_tpm12_la_CFLAGS += -DTPM_NOMAINTENANCE_COMMANDS libtpms_tpm12_la_CFLAGS += @DEBUG_DEFINES@ CRYPTO_OBJFILES = libtpms_tpm12_la_SOURCES = \ tpm12/tpm_admin.c \ tpm12/tpm_audit.c \ tpm12/tpm_auth.c \ tpm12/tpm_cryptoh.c \ tpm12/tpm_counter.c \ tpm12/tpm_daa.c \ tpm12/tpm_delegate.c \ tpm12/tpm_digest.c \ tpm12/tpm_error.c \ tpm12/tpm_global.c \ tpm12/tpm_identity.c \ tpm12/tpm_init.c \ tpm12/tpm_libtpms_io.c \ tpm12/tpm_key.c \ tpm12/tpm_load.c \ tpm12/tpm_maint.c \ tpm12/tpm_migration.c \ tpm12/tpm_nonce.c \ tpm12/tpm_nvram.c \ tpm12/tpm_openssl_helpers.c \ tpm12/tpm_owner.c \ tpm12/tpm_pcr.c \ tpm12/tpm_permanent.c \ tpm12/tpm_platform.c \ tpm12/tpm_process.c \ tpm12/tpm_secret.c \ tpm12/tpm_session.c \ tpm12/tpm_sizedbuffer.c \ tpm12/tpm_startup.c \ tpm12/tpm_store.c \ tpm12/tpm_storage.c \ tpm12/tpm_ticks.c \ tpm12/tpm_time.c \ tpm12/tpm_transport.c \ tpm12/tpm_ver.c \ tpm12/tpm_svnrevision.c \ tpm_tpm12_interface.c \ tpm_tpm12_tis.c noinst_HEADERS += \ tpm12/tpm_admin.h \ tpm12/tpm_audit.h \ tpm12/tpm_auth.h \ tpm12/tpm_commands.h \ tpm12/tpm_constants.h \ tpm12/tpm_counter.h \ tpm12/tpm_crypto.h \ tpm12/tpm_cryptoh.h \ tpm12/tpm_daa.h \ tpm_debug.h \ tpm12/tpm_delegate.h \ tpm12/tpm_digest.h \ tpm12/tpm_global.h \ tpm12/tpm_identity.h \ tpm12/tpm_init.h \ tpm12/tpm_io.h \ tpm12/tpm_key.h \ tpm_library_conf.h \ tpm_library_intern.h \ tpm12/tpm_load.h \ tpm12/tpm_maint.h \ tpm12/tpm_migration.h \ tpm12/tpm_nonce.h \ tpm_nvfile.h \ tpm12/tpm_nvram_const.h \ tpm12/tpm_nvram.h \ tpm12/tpm_openssl_helpers.h \ tpm12/tpm_owner.h \ tpm12/tpm_pcr.h \ tpm12/tpm_permanent.h \ tpm12/tpm_platform.h \ tpm12/tpm_process.h \ tpm12/tpm_secret.h \ tpm12/tpm_session.h \ tpm12/tpm_sizedbuffer.h \ tpm12/tpm_startup.h \ tpm12/tpm_storage.h \ tpm12/tpm_store.h \ tpm12/tpm_structures.h \ tpm12/tpm_svnrevision.h \ tpm12/tpm_ticks.h \ tpm12/tpm_time.h \ tpm12/tpm_transport.h \ tpm12/tpm_ver.h if LIBTPMS_USE_FREEBL libtpms_tpm12_la_SOURCES += tpm12/tpm_crypto_freebl.c libtpms_tpm12_la_LIBADD += -lfreebl -lgmp -lnspr4 -lnssutil3 -lnss3 #work-around broken freebl includes libtpms_tpm12_la_CFLAGS += $(shell [ ! -r /usr/include/nss3/alghmac.h ] && \ touch alghmac.h && \ echo -I./) # tpm12/tpm_crypto_freebl.c: work around #include "blapi.h" : should be libtpms_tpm12_la_CFLAGS += $(shell nss-config --cflags) #including nss3/blapi.h requires a look into nspr4 dir libtpms_tpm12_la_CFLAGS += $(shell nspr-config --cflags) else if LIBTPMS_USE_OPENSSL libtpms_tpm12_la_SOURCES += tpm12/tpm_crypto.c libtpms_tpm12_la_LIBADD += -lcrypto endif # LIBTPMS_USE_OPENSSL endif # LIBTPMS_USE_FREEBL endif # WITH_TPM1 # TPM2 # if WITH_TPM2 noinst_LTLIBRARIES += libtpms_tpm2.la libtpms_la_LIBADD += libtpms_tpm2.la libtpms_tpm2_la_LIBADD = $(LIBRT_LIBS) libtpms_tpm2_la_CFLAGS = $(common_CFLAGS) libtpms_tpm2_la_CFLAGS += -D_POSIX_ libtpms_tpm2_la_CFLAGS += -DTPM_POSIX libtpms_tpm2_la_SOURCES = \ tpm2/ACT_spt.c \ tpm2/ACTCommands.c \ tpm2/AlgorithmCap.c \ tpm2/AlgorithmTests.c \ tpm2/AsymmetricCommands.c \ tpm2/AttestationCommands.c \ tpm2/Attest_spt.c \ tpm2/AuditCommands.c \ tpm2/Bits.c \ tpm2/BnConvert.c \ tpm2/BnMath.c \ tpm2/BnMemory.c \ tpm2/Cancel.c \ tpm2/CapabilityCommands.c \ tpm2/Clock.c \ tpm2/ClockCommands.c \ tpm2/CommandAudit.c \ tpm2/CommandCodeAttributes.c \ tpm2/CommandDispatcher.c \ tpm2/ContextCommands.c \ tpm2/Context_spt.c \ tpm2/CryptEccData.c \ tpm2/CryptSelfTest.c \ tpm2/CryptUtil.c \ tpm2/DA.c \ tpm2/DebugHelpers.c \ tpm2/DictionaryCommands.c \ tpm2/DuplicationCommands.c \ tpm2/EACommands.c \ tpm2/EncryptDecrypt_spt.c \ tpm2/Entity.c \ tpm2/Entropy.c \ tpm2/EphemeralCommands.c \ tpm2/ExecCommand.c \ tpm2/Global.c \ tpm2/Handle.c \ tpm2/HashCommands.c \ tpm2/Hierarchy.c \ tpm2/HierarchyCommands.c \ tpm2/IntegrityCommands.c \ tpm2/IoBuffers.c \ tpm2/Locality.c \ tpm2/LocalityPlat.c \ tpm2/ManagementCommands.c \ tpm2/Manufacture.c \ tpm2/Marshal.c \ tpm2/MathOnByteBuffers.c \ tpm2/Memory.c \ tpm2/NVCommands.c \ tpm2/NVDynamic.c \ tpm2/NVMem.c \ tpm2/NVReserved.c \ tpm2/NV_spt.c \ tpm2/Object.c \ tpm2/ObjectCommands.c \ tpm2/Object_spt.c \ tpm2/PCR.c \ tpm2/PlatformACT.c \ tpm2/PlatformData.c \ tpm2/Policy_spt.c \ tpm2/Power.c \ tpm2/PowerPlat.c \ tpm2/PP.c \ tpm2/PPPlat.c \ tpm2/PrimeData.c \ tpm2/PropertyCap.c \ tpm2/RandomCommands.c \ tpm2/Response.c \ tpm2/ResponseCodeProcessing.c \ tpm2/RunCommand.c \ tpm2/Session.c \ tpm2/SessionCommands.c \ tpm2/SessionProcess.c \ tpm2/SigningCommands.c \ tpm2/StartupCommands.c \ tpm2/SymmetricCommands.c \ tpm2/TestingCommands.c \ tpm2/Ticket.c \ tpm2/Time.c \ tpm2/TpmAsn1.c \ tpm2/TpmSizeChecks.c \ tpm2/TPMCmdp.c \ tpm2/TpmFail.c \ tpm2/Unique.c \ tpm2/Unmarshal.c \ tpm2/Vendor_TCG_Test.c \ tpm2/X509_ECC.c \ tpm2/X509_RSA.c \ tpm2/X509_spt.c \ tpm_tpm2_interface.c \ tpm_tpm2_tis.c \ \ tpm2/BackwardsCompatibilityObject.c \ tpm2/LibtpmsCallbacks.c \ tpm2/NVMarshal.c \ tpm2/StateMarshal.c \ tpm2/Volatile.c noinst_HEADERS += \ compiler.h \ tpm2/crypto/CryptCmac_fp.h \ tpm2/crypto/CryptDes_fp.h \ tpm2/crypto/CryptEcc.h \ tpm2/crypto/CryptEccCrypt_fp.h \ tpm2/crypto/CryptEccKeyExchange_fp.h \ tpm2/crypto/CryptEccMain_fp.h \ tpm2/crypto/CryptEccSignature_fp.h \ tpm2/crypto/CryptHash_fp.h \ tpm2/crypto/CryptHash.h \ tpm2/crypto/CryptPrime_fp.h \ tpm2/crypto/CryptPrimeSieve_fp.h \ tpm2/crypto/CryptRand_fp.h \ tpm2/crypto/CryptRand.h \ tpm2/crypto/CryptRsa_fp.h \ tpm2/crypto/CryptRsa.h \ tpm2/crypto/CryptSelfTest_fp.h \ tpm2/crypto/CryptSmac_fp.h \ tpm2/crypto/CryptSym.h \ tpm2/crypto/CryptSym_fp.h \ tpm2/crypto/CryptTest.h \ tpm2/crypto/CryptUtil_fp.h \ tpm2/ACT.h \ tpm2/ACT_spt_fp.h \ tpm2/ACT_SetTimeout_fp.h \ tpm2/ActivateCredential_fp.h \ tpm2/AlgorithmCap_fp.h \ tpm2/AlgorithmTests_fp.h \ tpm2/Attest_spt_fp.h \ tpm2/BaseTypes.h \ tpm2/Bits_fp.h \ tpm2/Capabilities.h \ tpm2/CertifyCreation_fp.h \ tpm2/CertifyX509_fp.h \ tpm2/Certify_fp.h \ tpm2/ChangeEPS_fp.h \ tpm2/ChangePPS_fp.h \ tpm2/ClearControl_fp.h \ tpm2/Clear_fp.h \ tpm2/ClockRateAdjust_fp.h \ tpm2/ClockSet_fp.h \ tpm2/CommandAttributeData.h \ tpm2/CommandAttributes.h \ tpm2/CommandAudit_fp.h \ tpm2/CommandCodeAttributes_fp.h \ tpm2/CommandDispatchData.h \ tpm2/CommandDispatcher_fp.h \ tpm2/Commit_fp.h \ tpm2/CompilerDependencies.h \ tpm2/ContextLoad_fp.h \ tpm2/ContextSave_fp.h \ tpm2/Context_spt_fp.h \ tpm2/Create_fp.h \ tpm2/CreateLoaded_fp.h \ tpm2/CreatePrimary_fp.h \ tpm2/CryptSelfTest_fp.h \ tpm2/DA_fp.h \ tpm2/DebugHelpers_fp.h \ tpm2/DictionaryAttackLockReset_fp.h \ tpm2/DictionaryAttackParameters_fp.h \ tpm2/Duplicate_fp.h \ tpm2/EccTestData.h \ tpm2/ECC_Parameters_fp.h \ tpm2/ECDH_KeyGen_fp.h \ tpm2/ECDH_ZGen_fp.h \ tpm2/EC_Ephemeral_fp.h \ tpm2/EncryptDecrypt2_fp.h \ tpm2/EncryptDecrypt_fp.h \ tpm2/EncryptDecrypt_spt_fp.h \ tpm2/Entity_fp.h \ tpm2/EventSequenceComplete_fp.h \ tpm2/EvictControl_fp.h \ tpm2/ExecCommand_fp.h \ tpm2/FlushContext_fp.h \ tpm2/GetCapability_fp.h \ tpm2/GetCommandAuditDigest_fp.h \ tpm2/GetRandom_fp.h \ tpm2/GetSessionAuditDigest_fp.h \ tpm2/GetTestResult_fp.h \ tpm2/GetTime_fp.h \ tpm2/Global.h \ tpm2/GpMacros.h \ tpm2/Handle_fp.h \ tpm2/Hash_fp.h \ tpm2/HashSequenceStart_fp.h \ tpm2/HashTestData.h \ tpm2/HierarchyChangeAuth_fp.h \ tpm2/HierarchyControl_fp.h \ tpm2/Hierarchy_fp.h \ tpm2/HMAC_fp.h \ tpm2/HMAC_Start_fp.h \ tpm2/Import_fp.h \ tpm2/IncrementalSelfTest_fp.h \ tpm2/InternalRoutines.h \ tpm2/IoBuffers_fp.h \ tpm2/KdfTestData.h \ tpm2/LoadExternal_fp.h \ tpm2/Load_fp.h \ tpm2/Locality_fp.h \ tpm2/MAC_fp.h \ tpm2/MAC_Start_fp.h \ tpm2/MakeCredential_fp.h \ tpm2/Manufacture_fp.h \ tpm2/Marshal_fp.h \ tpm2/MathOnByteBuffers_fp.h \ tpm2/Memory_fp.h \ tpm2/MinMax.h \ tpm2/NV_Certify_fp.h \ tpm2/NV_ChangeAuth_fp.h \ tpm2/NV_DefineSpace_fp.h \ tpm2/NVDynamic_fp.h \ tpm2/NV_Extend_fp.h \ tpm2/NV_GlobalWriteLock_fp.h \ tpm2/NV.h \ tpm2/NV_Increment_fp.h \ tpm2/NV_Read_fp.h \ tpm2/NV_ReadLock_fp.h \ tpm2/NV_ReadPublic_fp.h \ tpm2/NVReserved_fp.h \ tpm2/NV_SetBits_fp.h \ tpm2/NV_spt_fp.h \ tpm2/NV_UndefineSpace_fp.h \ tpm2/NV_UndefineSpaceSpecial_fp.h \ tpm2/NV_Write_fp.h \ tpm2/NV_WriteLock_fp.h \ tpm2/OIDs.h \ tpm2/ObjectChangeAuth_fp.h \ tpm2/Object_fp.h \ tpm2/Object_spt_fp.h \ tpm2/PCR_Allocate_fp.h \ tpm2/PCR_Event_fp.h \ tpm2/PCR_Extend_fp.h \ tpm2/PCR_fp.h \ tpm2/PCR_Read_fp.h \ tpm2/PCR_Reset_fp.h \ tpm2/PCR_SetAuthPolicy_fp.h \ tpm2/PCR_SetAuthValue_fp.h \ tpm2/Platform.h \ tpm2/PlatformACT.h \ tpm2/PlatformACT_fp.h \ tpm2/PlatformClock.h \ tpm2/PlatformData.h \ tpm2/Platform_fp.h \ tpm2/PolicyAuthorize_fp.h \ tpm2/PolicyAuthorizeNV_fp.h \ tpm2/PolicyAuthValue_fp.h \ tpm2/PolicyCommandCode_fp.h \ tpm2/PolicyCounterTimer_fp.h \ tpm2/PolicyCpHash_fp.h \ tpm2/PolicyDuplicationSelect_fp.h \ tpm2/PolicyGetDigest_fp.h \ tpm2/PolicyLocality_fp.h \ tpm2/PolicyNameHash_fp.h \ tpm2/PolicyNV_fp.h \ tpm2/PolicyNvWritten_fp.h \ tpm2/PolicyOR_fp.h \ tpm2/PolicyPassword_fp.h \ tpm2/PolicyPCR_fp.h \ tpm2/PolicyPhysicalPresence_fp.h \ tpm2/PolicyRestart_fp.h \ tpm2/PolicySecret_fp.h \ tpm2/PolicySigned_fp.h \ tpm2/Policy_spt_fp.h \ tpm2/PolicyTemplate_fp.h \ tpm2/PolicyTicket_fp.h \ tpm2/Power_fp.h \ tpm2/PP_Commands_fp.h \ tpm2/PP_fp.h \ tpm2/PRNG_TestVectors.h \ tpm2/PropertyCap_fp.h \ tpm2/Quote_fp.h \ tpm2/ReadClock_fp.h \ tpm2/ReadPublic_fp.h \ tpm2/ResponseCodeProcessing_fp.h \ tpm2/Response_fp.h \ tpm2/Rewrap_fp.h \ tpm2/RsaTestData.h \ tpm2/RSA_Decrypt_fp.h \ tpm2/RSA_Encrypt_fp.h \ tpm2/SelfTest.h \ tpm2/SelfTest_fp.h \ tpm2/SequenceComplete_fp.h \ tpm2/SequenceUpdate_fp.h \ tpm2/Session_fp.h \ tpm2/SessionProcess_fp.h \ tpm2/SetAlgorithmSet_fp.h \ tpm2/SetCommandCodeAuditStatus_fp.h \ tpm2/SetPrimaryPolicy_fp.h \ tpm2/Shutdown_fp.h \ tpm2/Sign_fp.h \ tpm2/Simulator_fp.h \ tpm2/StartAuthSession_fp.h \ tpm2/Startup_fp.h \ tpm2/StirRandom_fp.h \ tpm2/SupportLibraryFunctionPrototypes_fp.h \ tpm2/SymmetricTest.h \ tpm2/SymmetricTestData.h \ tpm2/swap.h \ tpm2/TcpServerPosix_fp.h \ tpm2/TestParms_fp.h \ tpm2/Ticket_fp.h \ tpm2/Time_fp.h \ tpm2/TPMB.h \ tpm2/TpmAlgorithmDefines.h \ tpm2/TpmAsn1.h \ tpm2/TpmAsn1_fp.h \ tpm2/TpmBuildSwitches.h \ tpm2/TpmError.h \ tpm2/TpmFail_fp.h \ tpm2/TpmProfile.h \ tpm2/Tpm.h \ tpm2/_TPM_Hash_Data_fp.h \ tpm2/_TPM_Hash_End_fp.h \ tpm2/_TPM_Hash_Start_fp.h \ tpm2/_TPM_Init_fp.h \ tpm2/TpmSizeChecks_fp.h \ tpm2/TpmTcpProtocol.h \ tpm2/TpmTypes.h \ tpm2/Unmarshal_fp.h \ tpm2/Unseal_fp.h \ tpm2/VendorString.h \ tpm2/Vendor_TCG_Test_fp.h \ tpm2/VerifySignature_fp.h \ tpm2/X509.h \ tpm2/X509_ECC_fp.h \ tpm2/X509_RSA_fp.h \ tpm2/X509_spt_fp.h \ tpm2/ZGen_2Phase_fp.h \ \ tpm2/BackwardsCompatibility.h \ tpm2/BackwardsCompatibilityObject.h \ tpm2/LibtpmsCallbacks.h \ tpm2/NVMarshal.h \ tpm2/StateMarshal.h \ tpm2/Utils.h \ tpm2/Volatile.h if LIBTPMS_USE_OPENSSL libtpms_tpm2_la_SOURCES += \ tpm2/crypto/openssl/CryptCmac.c \ tpm2/crypto/openssl/CryptDes.c \ tpm2/crypto/openssl/CryptEccKeyExchange.c \ tpm2/crypto/openssl/CryptEccMain.c \ tpm2/crypto/openssl/CryptEccSignature.c \ tpm2/crypto/openssl/CryptHash.c \ tpm2/crypto/openssl/CryptPrime.c \ tpm2/crypto/openssl/CryptPrimeSieve.c \ tpm2/crypto/openssl/CryptRand.c \ tpm2/crypto/openssl/CryptRsa.c \ tpm2/crypto/openssl/CryptSmac.c \ tpm2/crypto/openssl/CryptSym.c \ tpm2/crypto/openssl/ExpDCache.c \ tpm2/crypto/openssl/Helpers.c \ tpm2/crypto/openssl/TpmToOsslDesSupport.c \ tpm2/crypto/openssl/TpmToOsslMath.c \ tpm2/crypto/openssl/TpmToOsslSupport.c noinst_HEADERS += \ tpm2/crypto/openssl/ConsttimeUtils.h \ tpm2/crypto/openssl/BnConvert_fp.h \ tpm2/crypto/openssl/BnMath_fp.h \ tpm2/crypto/openssl/BnMemory_fp.h \ tpm2/crypto/openssl/BnValues.h \ tpm2/crypto/openssl/ExpDCache_fp.h \ tpm2/crypto/openssl/Helpers_fp.h \ tpm2/crypto/openssl/LibSupport.h \ tpm2/crypto/openssl/TpmToOsslDesSupport_fp.h \ tpm2/crypto/openssl/TpmToOsslHash.h \ tpm2/crypto/openssl/TpmToOsslMath_fp.h \ tpm2/crypto/openssl/TpmToOsslMath.h \ tpm2/crypto/openssl/TpmToOsslSupport_fp.h \ tpm2/crypto/openssl/TpmToOsslSym.h libtpms_tpm2_la_CFLAGS += \ -I $(srcdir)/tpm2 \ -I $(srcdir)/tpm2/crypto \ -I $(srcdir)/tpm2/crypto/openssl libtpms_tpm2_la_LIBADD += -lcrypto endif # LIBTPMS_USE_OPENSSL endif # WITH_TPM2 # # Library API layer # libtpms_la_SOURCES = \ disabled_interface.c \ tpm_debug.c \ tpm_library.c \ tpm_memory.c \ tpm_nvfile.c libtpms_la_CFLAGS = $(common_CFLAGS) libtpms_la_LDFLAGS = -version-info $(LIBTPMS_VERSION_INFO) \ -no-undefined $(AM_LDFLAGS) if HAVE_VERSION_SCRIPT libtpms_la_LDFLAGS += -Wl,--version-script=$(srcdir)/libtpms.syms endif LDFLAGS_ARCH = $(findstring -m32, $(AM_CFLAGS)) LDFLAGS_ARCH += $(findstring -m64, $(AM_CFLAGS)) LDFLAGS_ARCH += $(findstring -m32, $(AM_LDFLAGS)) LDFLAGS_ARCH += $(findstring -m64, $(AM_LDFLAGS)) check-local: SHELL?="/usr/bin/env bash" check-local: @case $(host_os) in \ openbsd*) ADDLIBS="-lc" ;; \ darwin*|freebsd*) LDFLAGS_OS="-shared" ;; \ *) ADDLIBS="" ;; \ esac; \ ($(CC) $$LDFLAGS_OS $(LDFLAGS_ARCH) -nostdlib -L./.libs -ltpms $$ADDLIBS 2>/dev/null || \ (echo "There are undefined symbols in libtpms ($$LDFLAGS_OS $(LDFLAGS_ARCH))";\ $(CC) $$LDFLAGS_OS $(LDFLAGS_ARCH) -nostdlib -L./.libs -ltpms $$ADDLIBS 2>&1 | grep libtpms)) @case $(host_os) in \ openbsd*) ADDLIBS="-lc" ;; \ darwin*|freebsd*) LDFLAGS_OS="-shared" ;; \ *) ADDLIBS="" ;; \ esac; \ $(CC) $$LDFLAGS_OS $(LDFLAGS_ARCH) -nostdlib -L./.libs -ltpms $$ADDLIBS 2>/dev/null rm a.out || true EXTRA_DIST = \ tpm12/tpm_crypto_freebl.c \ tpm12/tpm_crypto.c \ libtpms.syms \ test.syms CLEANFILES = \ a.out \ *.gcov \ *.gcda \ *.gcno \ tpm12/*.gcov \ tpm12/*.gcda \ tpm12/*.gcno \ tpm2/*.gcov \ tpm2/*.gcda \ tpm2/*.gcno \ tpm2/crypto/openssl/*.gcov \ tpm2/crypto/openssl/*.gcda \ tpm2/crypto/openssl/*.gcno libtpms-0.9.3/src/compiler.h000066400000000000000000000046361421143571500157630ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Compiler-specific macros */ /* Written by Stefan Berger */ /* IBM Thomas J. Watson Research Center */ /* */ /* (c) Copyright IBM Corporation 2018. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPMLIB_COMPILER_H #define TPMLIB_COMPILER_H #ifndef __clang__ # define ATTRIBUTE_FORMAT(STRING_IDX, FIRST_TO_CHECK) \ __attribute__((format (printf, STRING_IDX, FIRST_TO_CHECK))) #else # define ATTRIBUTE_FORMAT(STRING_IDX, FIRST_TO_CHECK) \ __attribute__((__format__ (__printf__, STRING_IDX, FIRST_TO_CHECK))) #endif #endif /* TPMLIB_COMPILER_H */ libtpms-0.9.3/src/disabled_interface.c000066400000000000000000000053121421143571500177230ustar00rootroot00000000000000#include #include "tpm_error.h" #include "tpm_library_intern.h" static TPM_RESULT Disabled_MainInit(void) { return TPM_FAIL; } static void Disabled_Terminate(void) { } static TPM_RESULT Disabled_Process(unsigned char **respbuffer, uint32_t *resp_size, uint32_t *respbufsize, unsigned char *command, uint32_t command_size) { return TPM_FAIL; } static TPM_RESULT Disabled_VolatileAllStore(unsigned char **buffer, uint32_t *buflen) { return TPM_FAIL; } static TPM_RESULT Disabled_CancelCommand(void) { return TPM_FAIL; } static TPM_RESULT Disabled_GetTPMProperty(enum TPMLIB_TPMProperty prop, int *result) { return TPM_FAIL; } static char *Disabled_GetInfo(enum TPMLIB_InfoFlags flags) { return NULL; } static uint32_t Disabled_SetBufferSize(uint32_t wanted_size, uint32_t *min_size, uint32_t *max_size) { return 0; } static TPM_RESULT Disabled_ValidateState(enum TPMLIB_StateType st, unsigned int flags) { return TPM_FAIL; } static TPM_RESULT Disabled_GetState(enum TPMLIB_StateType st, unsigned char **buffer, uint32_t *buflen) { return TPM_FAIL; } static TPM_RESULT Disabled_SetState(enum TPMLIB_StateType st, const unsigned char *buffer, uint32_t buflen) { return TPM_FAIL; } static TPM_RESULT Disabled_IO_Hash_Start(void) { return TPM_FAIL; } static TPM_RESULT Disabled_IO_Hash_Data(const unsigned char *data, uint32_t data_length) { return TPM_FAIL; } static TPM_RESULT Disabled_IO_Hash_End(void) { return TPM_FAIL; } static TPM_RESULT Disabled_IO_TpmEstablished_Get(TPM_BOOL *tpmEstablished) { return TPM_FAIL; } static TPM_RESULT Disabled_IO_TpmEstablished_Reset(void) { return TPM_FAIL; } const struct tpm_interface DisabledInterface = { .MainInit = Disabled_MainInit, .Terminate = Disabled_Terminate, .Process = Disabled_Process, .VolatileAllStore = Disabled_VolatileAllStore, .CancelCommand = Disabled_CancelCommand, .GetTPMProperty = Disabled_GetTPMProperty, .GetInfo = Disabled_GetInfo, .TpmEstablishedGet = Disabled_IO_TpmEstablished_Get, .TpmEstablishedReset = Disabled_IO_TpmEstablished_Reset, .HashStart = Disabled_IO_Hash_Start, .HashData = Disabled_IO_Hash_Data, .HashEnd = Disabled_IO_Hash_End, .SetBufferSize = Disabled_SetBufferSize, .ValidateState = Disabled_ValidateState, .SetState = Disabled_SetState, .GetState = Disabled_GetState, }; libtpms-0.9.3/src/libtpms.syms000066400000000000000000000013131421143571500163540ustar00rootroot00000000000000# Symbol file for the linker. For newer versions add new sections. LIBTPMS_0.5.1 { global: TPM_IO_Hash_Data; TPM_IO_Hash_End; TPM_IO_Hash_Start; TPM_IO_TpmEstablished_Get; TPMLIB_DecodeBlob; TPMLIB_GetTPMProperty; TPMLIB_GetVersion; TPMLIB_MainInit; TPMLIB_Process; TPMLIB_RegisterCallbacks; TPMLIB_Terminate; TPMLIB_VolatileAll_Store; TPM_Free; TPM_Malloc; TPM_Realloc; local: *; }; LIBTPMS_0.6.0 { global: TPM_IO_TpmEstablished_Reset; TPMLIB_CancelCommand; TPMLIB_ChooseTPMVersion; TPMLIB_GetInfo; TPMLIB_GetState; TPMLIB_SetBufferSize; TPMLIB_SetDebugFD; TPMLIB_SetDebugLevel; TPMLIB_SetDebugPrefix; TPMLIB_SetState; TPMLIB_ValidateState; local: *; } LIBTPMS_0.5.1; libtpms-0.9.3/src/test.syms000066400000000000000000000002401421143571500156570ustar00rootroot00000000000000# Symbol file for the linker. For testing in configure.ac only TEST { global: # two work-around for a broken link environ; __progname; local: *; }; libtpms-0.9.3/src/tpm12/000077500000000000000000000000001421143571500147325ustar00rootroot00000000000000libtpms-0.9.3/src/tpm12/tpm_admin.c000066400000000000000000002161431421143571500170550ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM Admin Test and Opt-in */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_admin.c 4505 2011-03-20 17:43:27Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include #include "tpm_auth.h" #include "tpm_cryptoh.h" #include "tpm_digest.h" #include "tpm_debug.h" #include "tpm_error.h" #include "tpm_key.h" #include "tpm_nonce.h" #include "tpm_permanent.h" #include "tpm_process.h" #include "tpm_secret.h" #include "tpm_ticks.h" #include "tpm_time.h" #include "tpm_admin.h" /* The Software TPM Self Test works as follows: TPM_LimitedSelfTestCommon(void) - self tests which affect all TPM's TPM_LimitedSelfTestTPM(tpm_state) - self test per virtual TPM TPM_ContinueSelfTestCmd(tpm_state) - currently does nothing on failure, sets tpm_state->testState to failure for the virtual TPM TPM_SelfTestFullCmd(tpm_state) calls TPM_LimitedSelfTestTPM() TPM_ContinueSelfTestCmd(tpm_state) on failure, sets tpm_state->testState to failure for the virtual TPM TPM_MainInit(void) calls TPM_LimitedSelfTestCommon(void) TPM_LimitedSelfTestTPM(tpm_state) TPM_Process_ContinueSelfTest(tpm_state) calls either (depending on FIPS mode) TPM_SelfTestFullCmd(tpm_state) TPM_ContinueSelfTestCmd(tpm_state) TPM_Process_SelfTestFull(tpm_state) calls TPM_SelfTestFullCmd(tpm_state) The Software TPM assumes that the coprocessor has run self tests before the application code even begins. So this code doesn't do any real testing of the underlying hardware. This simplifies the state machine, since TPM_Process_ContinueSelfTest doesn't require a separate thread. */ /* TPM_LimitedSelfTestCommon() provides the assurance that a selected subset of TPM commands will perform properly. The limited nature of the self-test allows the TPM to be functional in as short of time as possible. all the TPM tests. The caller is responsible for setting the shutdown state on error. */ TPM_RESULT TPM_LimitedSelfTestCommon(void) { TPM_RESULT rc = 0; uint32_t tv_sec; uint32_t tv_usec; printf(" TPM_LimitedSelfTestCommon:\n"); #if 0 if (rc == 0) { rc = TPM_Sbuffer_Test(); } #endif if (rc == 0) { rc = TPM_Uint64_Test(); } if (rc == 0) { rc = TPM_CryptoTest(); } /* test time of day clock */ if (rc == 0) { rc = TPM_GetTimeOfDay(&tv_sec, &tv_usec); } if (rc != 0) { rc = TPM_FAILEDSELFTEST; } return rc; } TPM_RESULT TPM_LimitedSelfTestTPM(tpm_state_t *tpm_state) { TPM_RESULT rc = 0; TPM_NONCE clrData; TPM_SIZED_BUFFER encData; TPM_NONCE decData; uint32_t decLength; printf(" TPM_LimitedSelfTestTPM:\n"); TPM_SizedBuffer_Init(&encData); /* freed @1 */ /* 8. The TPM MUST check the following: */ /* a. RNG functionality */ /* NOTE Tested by coprocessor boot */ /* b. Reading and extending the integrity registers. The self-test for the integrity registers will leave the integrity registers in a known state. */ /* NOTE Since there is nothing special about the PCR's, the common TPM_CryptoTest() is sufficient */ /* c. Testing the EK integrity, if it exists */ /* i. This requirement specifies that the TPM will verify that the endorsement key pair can encrypt and decrypt a known value. This tests the RSA engine. If the EK has not yet been generated the TPM action is manufacturer specific. */ if ((rc == 0) && (tpm_state->tpm_permanent_data.endorsementKey.keyUsage != TPM_KEY_UNINITIALIZED)) { /* check the key integrity */ if (rc == 0) { rc = TPM_Key_CheckPubDataDigest(&(tpm_state->tpm_permanent_data.endorsementKey)); } /* encrypt */ if (rc == 0) { TPM_Nonce_Generate(clrData); rc = TPM_RSAPublicEncrypt_Key(&encData, /* output */ clrData, /* input */ TPM_NONCE_SIZE, /* input */ &(tpm_state->tpm_permanent_data.endorsementKey)); } /* decrypt */ if (rc == 0) { rc = TPM_RSAPrivateDecryptH(decData, /* decrypted data */ &decLength, /* length of data put into decrypt_data */ TPM_NONCE_SIZE, /* size of decrypt_data buffer */ encData.buffer, encData.size, &(tpm_state->tpm_permanent_data.endorsementKey)); } /* verify */ if (rc == 0) { if (decLength != TPM_NONCE_SIZE) { printf("TPM_LimitedSelfTestTPM: Error, decrypt length %u should be %u\n", decLength, TPM_NONCE_SIZE); rc = TPM_FAILEDSELFTEST; } } if (rc == 0) { rc = TPM_Nonce_Compare(clrData, decData); } } /* d. The integrity of the protected capabilities of the TPM */ /* i. This means that the TPM must ensure that its "microcode" has not changed, and not that a test must be run on each function. */ /* e. Any tamper-resistance markers */ /* i. The tests on the tamper-resistance or tamper-evident markers are under programmable control. */ /* There is no requirement to check tamper-evident tape or the status of epoxy surrounding the case. */ /* NOTE: Done by coprocessor POST */ /* 9. The TPM SHOULD check the following: */ /* a. The hash functionality */ /* i. This check will hash a known value and compare it to an expected result. There is no requirement to accept external data to perform the check. */ /* ii. The TPM MAY support a test using external data. */ /* NOTE: Done by TPM_CryptoTest() */ /* b. Any symmetric algorithms */ /* i. This check will use known data with a random key to encrypt and decrypt the data */ /* NOTE: Done by TPM_CryptoTest() */ /* c. Any additional asymmetric algorithms */ /* i. This check will use known data to encrypt and decrypt. */ /* NOTE: So far only RSA is supported */ /* d. The key-wrapping mechanism */ /* i. The TPM should wrap and unwrap a key. The TPM MUST NOT use the endorsement key pair for this test. */ /* NOTE: There is nothing special about serializing a TPM_STORE_ASYMKEY */ /* e. Any other internal mechanisms */ TPM_SizedBuffer_Delete(&encData); /* @1 */ if (rc != 0) { rc = TPM_FAILEDSELFTEST; } /* set the TPM test state */ if ((rc == 0) && (tpm_state->testState != TPM_TEST_STATE_FAILURE)) { printf(" TPM_LimitedSelfTestTPM: Set testState to %u \n", TPM_TEST_STATE_LIMITED); tpm_state->testState = TPM_TEST_STATE_LIMITED; } else { printf(" TPM_LimitedSelfTestTPM: Set testState to %u \n", TPM_TEST_STATE_FAILURE); tpm_state->testState = TPM_TEST_STATE_FAILURE; } return rc; } /* TPM_ContinueSelfTestCmd() runs the continue self test actions */ TPM_RESULT TPM_ContinueSelfTestCmd(tpm_state_t *tpm_state) { TPM_RESULT rc = 0; /* NOTE all done by limited self test */ printf(" TPM_ContinueSelfTestCmd:\n"); if (rc != 0) { rc = TPM_FAILEDSELFTEST; } /* set the TPM test state */ if (rc == 0) { printf(" TPM_ContinueSelfTestCmd: Set testState to %u \n", TPM_TEST_STATE_FULL); tpm_state->testState = TPM_TEST_STATE_FULL; } else { printf(" TPM_ContinueSelfTestCmd: Set testState to %u \n", TPM_TEST_STATE_FAILURE); tpm_state->testState = TPM_TEST_STATE_FAILURE; } return rc; } /* TPM_SelfTestFullCmd is a request to have the TPM perform another complete self-test. This test will take some time but provides an accurate assessment of the TPM's ability to perform all operations. Runs the actions of self test full. */ TPM_RESULT TPM_SelfTestFullCmd(tpm_state_t *tpm_state) { TPM_RESULT rc = 0; printf(" TPM_SelfTestFullCmd\n"); if (rc == 0) { rc = TPM_LimitedSelfTestTPM(tpm_state); } if (rc == 0) { rc = TPM_ContinueSelfTestCmd(tpm_state); } return rc; } /* 4.1 TPM_SelfTestFull rev 88 SelfTestFull tests all of the TPM capabilities. Unlike TPM_ContinueSelfTest, which may optionally return immediately and then perform the tests, TPM_SelfTestFull always performs the tests and then returns success or failure. */ TPM_RESULT TPM_Process_SelfTestFull(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_SelfTestFull: Ordinal Entry\n"); /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | TPM_CHECK_NO_LOCKOUT)); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_SelfTestFull: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ /* 1. TPM_SelfTestFull SHALL cause a TPM to perform self-test of each TPM internal function. */ /* a. If the self-test succeeds, return TPM_SUCCESS. */ /* b. If the self-test fails, return TPM_FAILEDSELFTEST. */ /* 2. Failure of any test results in overall failure, and the TPM goes into failure mode. */ /* 3. If the TPM has not executed the action of TPM_ContinueSelfTest, the TPM */ /* a. MAY perform the full self-test. */ /* b. MAY return TPM_NEEDS_SELFTEST. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SelfTestFullCmd(tpm_state); } /* response */ if (rcf == 0) { printf("TPM_Process_SelfTestFull: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } return rcf; } /* 4.2 TPM_ContinueSelfTest rev 88 TPM_Process_ContinueSelfTest informs the TPM that it may complete the self test of all TPM functions. The TPM may return success immediately and then perform the self-test, or it may perform the self-test and then return success or failure. 1. Prior to executing the actions of TPM_ContinueSelfTest, if the TPM receives a command C1 that uses an untested TPM function, the TPM MUST take one of these actions: a. The TPM MAY return TPM_NEEDS_SELFTEST i. This indicates that the TPM has not tested the internal resources required to execute C1. ii. The TPM does not execute C1. iii. The caller MUST issue TPM_ContinueSelfTest before re-issuing the command C1. (1) If the TPM permits TPM_SelfTestFull prior to completing the actions of TPM_ContinueSelfTest, the caller MAY issue TPM_SelfTestFull rather than TPM_ContinueSelfTest. b. The TPM MAY return TPM_DOING_SELFTEST i. This indicates that the TPM is doing the actions of TPM_ContinueSelfTest implicitly, as if the TPM_ContinueSelfTest command had been issued. ii. The TPM does not execute C1. iii. The caller MUST wait for the actions of TPM_ContinueSelfTest to complete before reissuing the command C1. c. The TPM MAY return TPM_SUCCESS or an error code associated with C1. i. This indicates that the TPM has completed the actions of TPM_ContinueSelfTest and has completed the command C1. ii. The error code MAY be TPM_FAILEDSELFTEST. */ TPM_RESULT TPM_Process_ContinueSelfTest(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_ContinueSelfTest: Ordinal Entry\n"); /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | TPM_CHECK_NO_LOCKOUT)); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_ContinueSelfTest: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ if (returnCode == TPM_SUCCESS) { /* 1. If TPM_PERMANENT_FLAGS -> FIPS is TRUE or TPM_PERMANENT_FLAGS -> TPMpost is TRUE */ if ((tpm_state->tpm_permanent_flags.FIPS) || (tpm_state->tpm_permanent_flags.TPMpost)) { /* a. The TPM MUST run ALL self-tests */ returnCode = TPM_SelfTestFullCmd(tpm_state); } /* 2. Else */ else { /* a. The TPM MUST complete all self-tests that are outstanding */ /* i. Instead of completing all outstanding self-tests the TPM MAY run all self-tests */ returnCode = TPM_ContinueSelfTestCmd(tpm_state); } } /* 3. The TPM either a. MAY immediately return TPM_SUCCESS i. When TPM_ContinueSelfTest finishes execution, it MUST NOT respond to the caller with a return code. b. MAY complete the self-test and then return TPM_SUCCESS or TPM_FAILEDSELFTEST. NOTE Option 3.b. implemented */ /* response */ if (rcf == 0) { printf("TPM_Process_ContinueSelfTest: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } return rcf; } /* 4.3 TPM_GetTestResult rev 96 TPM_GetTestResult provides manufacturer specific information regarding the results of the self test. This command will work when the TPM is in self test failure mode. The reason for allowing this command to operate in the failure mode is to allow TPM manufacturers to obtain diagnostic information. */ TPM_RESULT TPM_Process_GetTestResult(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_SIZED_BUFFER outData; /* The outData this is manufacturer specific */ printf("TPM_Process_GetTestResult: Ordinal Entry\n"); TPM_SizedBuffer_Init(&outData); /* freed @1 */ /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ /* This command will work when the TPM is in self test failure or limited operation mode. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_NO_LOCKOUT); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_GetTestResult: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ /* 1. The TPM SHALL respond to this command with a manufacturer specific block of information that describes the result of the latest self test. */ /* 2. The information MUST NOT contain any data that uniquely identifies an individual TPM. */ /* allocate some reasonable area */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_Allocate(&outData, 128); } /* for now, just return the state of shutdown as a printable string */ if (returnCode == TPM_SUCCESS) { size_t len = outData.size; /* cast because TPM_SIZED_BUFFER is typically unsigned (binary) but snprintf expects char */ outData.size = snprintf((char *)(outData.buffer), len, "Shutdown %08x\n", tpm_state->testState); if (outData.size >= len) { printf("TPM_Process_GetTestResult: Error (fatal), buffer too small\n"); returnCode = TPM_FAIL; } } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_GetTestResult: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* return outData */ returnCode = TPM_SizedBuffer_Store(response, &outData); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* cleanup */ TPM_SizedBuffer_Delete(&outData); /* @1 */ return rcf; } /* 5.1 TPM_SetOwnerInstall rev 100 When enabled but without an owner this command sets the PERMANENT flag that allows or disallows the ability to insert an owner. */ TPM_RESULT TPM_Process_SetOwnerInstall(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_BOOL state; /* State to which ownership flag is to be set. */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL writeAllNV = FALSE; /* flag to write back NV */ TPM_BOOL physicalPresence; /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_SetOwnerInstall: Ordinal Entry\n"); /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_LoadBool(&state, &command, ¶mSize); } /* save the ending point of inParam's for authorization */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_SetOwnerInstall: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ if (returnCode == TPM_SUCCESS) { /* 1. If the TPM has a current owner, this command immediately returns with TPM_SUCCESS. */ if (tpm_state->tpm_permanent_data.ownerInstalled) { printf("TPM_Process_SetOwnerInstall: Already current owner\n"); } /* If the TPM does not have a current owner */ else { if (returnCode == TPM_SUCCESS) { printf("TPM_Process_SetOwnerInstall: No current owner\n"); /* 2. The TPM validates the assertion of physical presence. The TPM then sets the value of TPM_PERMANENT_FLAGS -> ownership to the value in state. */ returnCode = TPM_Global_GetPhysicalPresence(&physicalPresence, tpm_state); } if (returnCode == TPM_SUCCESS) { if (!physicalPresence) { printf("TPM_Process_SetOwnerInstall: Error, physicalPresence is FALSE\n"); returnCode = TPM_BAD_PRESENCE; } } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_SetOwnerInstall: Setting ownership to %02x\n", state); TPM_SetCapability_Flag(&writeAllNV, /* altered */ &(tpm_state->tpm_permanent_flags.ownership), /* flag */ state); /* value */ /* Store the permanent flags back to NVRAM */ returnCode = TPM_PermanentAll_NVStore(tpm_state, writeAllNV, returnCode); } } } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_SetOwnerInstall: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } return rcf; } /* 5.2 TPM_OwnerSetDisable rev 107 The TPM owner sets the PERMANENT disable flag to TRUE or FALSE. */ TPM_RESULT TPM_Process_OwnerSetDisable(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_BOOL disableState; /* Value for disable state */ TPM_AUTHHANDLE authHandle; /* The authorization handle used for owner authorization. */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization handle */ TPM_AUTHDATA ownerAuth; /* The authorization digest for inputs and owner authorization. HMAC key: ownerAuth. */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_AUTH_SESSION_DATA *auth_session_data; /* session data for authHandle */ TPM_SECRET *hmacKey; TPM_BOOL writeAllNV = FALSE; /* flag to write back NV */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_OwnerSetDisable: Ordinal Entry\n"); /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get disableState parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_LoadBool(&disableState, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | TPM_CHECK_OWNER | TPM_CHECK_NO_LOCKOUT)); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag1(tag); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, ownerAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_OwnerSetDisable: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* 1. The TPM SHALL authenticate the command as coming from the TPM Owner. If unsuccessful, the TPM SHALL return TPM_AUTHFAIL. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_OWNER, ordinal, NULL, &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ } if (returnCode == TPM_SUCCESS) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* owner HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, ownerAuth); /* Authorization digest for input */ } /* 2. The TPM SHALL set the TPM_PERMANENT_FLAGS -> disable flag to the value in the disableState parameter. */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_OwnerSetDisable: Setting disable to %u\n", disableState); TPM_SetCapability_Flag(&writeAllNV, /* altered */ &(tpm_state->tpm_permanent_flags.disable), /* flag */ disableState); /* value */ /* Store the permanent flags back to NVRAM */ returnCode = TPM_PermanentAll_NVStore(tpm_state, writeAllNV, returnCode); } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_OwnerSetDisable: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* owner HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, terminate the session. */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } return rcf; } /* 5.3 TPM_PhysicalEnable rev 87 Sets the PERMANENT disable flag to FALSE using physical presence as authorization. */ TPM_RESULT TPM_Process_PhysicalEnable(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL writeAllNV = FALSE; /* flag to write back NV */ TPM_BOOL physicalPresence; /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_PhysicalEnable: Ordinal Entry\n"); /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | TPM_CHECK_NO_LOCKOUT)); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_PhysicalEnable: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ /* 1. Validate that physical presence is being asserted, if not return TPM_BAD_PRESENCE */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Global_GetPhysicalPresence(&physicalPresence, tpm_state); } if (returnCode == TPM_SUCCESS) { if (!physicalPresence) { printf("TPM_Process_PhysicalEnable: Error, physicalPresence is FALSE\n"); returnCode = TPM_BAD_PRESENCE; } } /* 2. The TPM SHALL set the TPM_PERMANENT_FLAGS.disable value to FALSE. */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_PhysicalEnable: Setting disable to FALSE\n"); TPM_SetCapability_Flag(&writeAllNV, /* altered */ &(tpm_state->tpm_permanent_flags.disable), /* flag */ FALSE); /* value */ /* Store the permanent flags back to NVRAM */ returnCode = TPM_PermanentAll_NVStore(tpm_state, writeAllNV, returnCode); } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_PhysicalEnable: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } return rcf; } /* 5.4 TPM_PhysicalDisable rev 87 Sets the PERMANENT disable flag to TRUE using physical presence as authorization */ TPM_RESULT TPM_Process_PhysicalDisable(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL writeAllNV = FALSE; /* flag to write back NV */ TPM_BOOL physicalPresence; /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_PhysicalDisable: Ordinal Entry\n"); /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | TPM_CHECK_ENABLED | TPM_CHECK_NO_LOCKOUT)); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_PhysicalDisable: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ /* 1. Validate that physical presence is being asserted, if not return TPM_BAD_PRESENCE */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Global_GetPhysicalPresence(&physicalPresence, tpm_state); } if (returnCode == TPM_SUCCESS) { if (!physicalPresence) { printf("TPM_Process_PhysicalDisable: Error, physicalPresence is FALSE\n"); returnCode = TPM_BAD_PRESENCE; } } /* 2. The TPM SHALL set the TPM_PERMANENT_FLAGS.disable value to TRUE. */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_PhysicalDisable: Setting disable to TRUE\n"); TPM_SetCapability_Flag(&writeAllNV, /* altered */ &(tpm_state->tpm_permanent_flags.disable ), /* flag */ TRUE); /* value */ /* Store the permanent flags back to NVRAM */ returnCode = TPM_PermanentAll_NVStore(tpm_state, writeAllNV, returnCode); } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_PhysicalDisable: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } return rcf; } /* 5.5 TPM_PhysicalSetDeactivated rev 105 Changes the TPM persistent deactivated flag using physical presence as authorization. */ TPM_RESULT TPM_Process_PhysicalSetDeactivated(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_BOOL state; /* State to which deactivated flag is to be set. */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL writeAllNV = FALSE; /* flag to write back NV */ TPM_BOOL physicalPresence; /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_PhysicalSetDeactivated: Ordinal Entry\n"); /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get state parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_LoadBool(&state, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_PhysicalSetDeactivated: state %02x\n", state); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | TPM_CHECK_ENABLED | TPM_CHECK_NO_LOCKOUT)); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_PhysicalSetDeactivated: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ /* 1. Validate that physical presence is being asserted, if not return TPM_BAD_PRESENCE */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Global_GetPhysicalPresence(&physicalPresence, tpm_state); } if (returnCode == TPM_SUCCESS) { if (!physicalPresence) { printf("TPM_Process_PhysicalSetDeactivated: Error, physicalPresence is FALSE\n"); returnCode = TPM_BAD_PRESENCE; } } /* 2. The TPM SHALL set the TPM_PERMANENT_FLAGS.deactivated flag to the value in the state parameter. */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_PhysicalSetDeactivated: Setting deactivated to %u\n", state); TPM_SetCapability_Flag(&writeAllNV, /* altered */ &(tpm_state->tpm_permanent_flags.deactivated), /* flag */ state); /* value */ /* Store the permanent flags back to NVRAM */ returnCode = TPM_PermanentAll_NVStore(tpm_state, writeAllNV, returnCode); } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_PhysicalSetDeactivated: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } return rcf; } /* 5.6 TPM_SetTempDeactivated rev 87 This command allows the operator of the platform to deactivate the TPM until the next boot of the platform. This command requires operator authorization. The operator can provide the authorization by either the assertion of physical presence or presenting the operation authorization value. */ TPM_RESULT TPM_Process_SetTempDeactivated(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_AUTHHANDLE authHandle; /* auth handle for operation validation. Session type must be OIAP. */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization handle */ TPM_AUTHDATA operatorAuth; /* HMAC key: operatorAuth */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ TPM_SECRET *hmacKey; #if TPM_V12 TPM_BOOL physicalPresence; #endif /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_SetTempDeactivated: Ordinal Entry\n"); /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | TPM_CHECK_ACTIVATED | TPM_CHECK_NO_LOCKOUT)); } /* check tag */ if (returnCode == TPM_SUCCESS) { #if TPM_V12 returnCode = TPM_CheckRequestTag10(tag); #else /* v1.1 is always auth0. This check implicitly bypasses the operatorAuth Actions below. */ returnCode = TPM_CheckRequestTag0(tag); #endif } /* get the optional 'below the line' authorization parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, operatorAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_SetTempDeactivated: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* 1. If tag = TPM_TAG_REQ_AUTH1_COMMAND */ /* a. If TPM_PERMANENT_FLAGS -> operator is FALSE return TPM_NOOPERATOR */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { if (!tpm_state->tpm_permanent_flags.tpmOperator) { printf("TPM_Process_SetTempDeactivated: Error, no operator\n"); returnCode = TPM_NOOPERATOR; } } /* b. Validate command and parameters using operatorAuth, on error return TPM_AUTHFAIL */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { printf(" TPM_Process_SetTempDeactivated: authHandle %08x\n", authHandle); /* get the session data */ returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_OIAP, 0, /* OSAP entity type */ ordinal, NULL, &(tpm_state->tpm_permanent_data.operatorAuth), /* OIAP */ NULL); /* OSAP */ } if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* operator HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, operatorAuth); /* Authorization digest for input */ } #if TPM_V12 /* v1.1 does not require physical presence */ /* 2. Else */ /* a. If physical presence is not asserted the TPM MUST return TPM_BAD_PRESENCE */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)) { returnCode = TPM_Global_GetPhysicalPresence(&physicalPresence, tpm_state); } if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)) { if (!physicalPresence) { printf("TPM_Process_SetTempDeactivated: Error, physicalPresence is FALSE\n"); returnCode = TPM_BAD_PRESENCE; } } #endif /* 3. The TPM SHALL set the TPM_STCLEAR_FLAGS.deactivated flag to the value TRUE. */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_SetTempDeactivated: Setting deactivated to TRUE\n"); tpm_state->tpm_stclear_flags.deactivated = TRUE; } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_SetTempDeactivated: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* operator HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ return rcf; } /* 5.7 TPM_SetOperatorAuth rev 87 This command allows the setting of the operator authorization value. There is no confidentiality applied to the operator authorization as the value is sent under the assumption of being local to the platform. If there is a concern regarding the path between the TPM and the keyboard then unless the keyboard is using encryption and a secure channel an attacker can read the values. */ TPM_RESULT TPM_Process_SetOperatorAuth(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_SECRET operatorAuth; /* The operator authorization */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL writeAllNV = FALSE; /* flag to write back NV */ TPM_BOOL physicalPresence; /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_SetOperatorAuth: Ordinal Entry\n"); /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get operatorAuth parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Secret_Load(operatorAuth, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_SetOperatorAuth: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ /* 1. If physical presence is not asserted the TPM MUST return TPM_BAD_PRESENCE */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Global_GetPhysicalPresence(&physicalPresence, tpm_state); } if (returnCode == TPM_SUCCESS) { if (!physicalPresence) { printf("TPM_Process_SetOperatorAuth: Error, physicalPresence is FALSE\n"); returnCode = TPM_BAD_PRESENCE; } } if (returnCode == TPM_SUCCESS) { /* 2. The TPM SHALL set the TPM_PERSISTENT_DATA -> operatorAuth */ TPM_Digest_Copy(tpm_state->tpm_permanent_data.operatorAuth, operatorAuth); /* 3. The TPM SHALL set TPM_PERMANENT_FLAGS -> operator to TRUE */ printf("TPM_Process_SetOperatorAuth: Setting operator to TRUE\n"); TPM_SetCapability_Flag(&writeAllNV, /* altered */ &(tpm_state->tpm_permanent_flags.tpmOperator), /* flag */ TRUE); /* value */ /* Store the permanent data and flags back to NVRAM */ returnCode = TPM_PermanentAll_NVStore(tpm_state, TRUE, returnCode); } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_SetOperatorAuth: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } return rcf; } /* 9.3 TPM_ResetLockValue rev 96 Command that resets the TPM dictionary attack mitigation values This allows the TPM owner to cancel the effect of a number of successive authorization failures. If this command itself has an authorization failure, it is blocked for the remainder of the lock out period. This prevents a dictionary attack on the owner authorization using this command. It is understood that this command allows the TPM owner to perform a dictionary attack on other authorization values by alternating a trial and this command. Similarly, delegating this command allows the owner's delegate to perform a dictionary attack. */ TPM_RESULT TPM_Process_ResetLockValue(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_AUTHHANDLE authHandle; /* The authorization session handle used for TPM Owner authorization */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization session handle */ TPM_AUTHDATA ownerAuth; /* HMAC key TPM Owner auth */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_AUTH_SESSION_DATA *auth_session_data; /* session data for authHandle */ TPM_SECRET *hmacKey; /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_ResetLockValue: Ordinal Entry\n"); /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { /* Update disableResetLock. Ignore the return code since this command is not locked out */ TPM_Authdata_CheckState(tpm_state); /* NOTE No TPM_CHECK_NO_LOCKOUT, since this command proceeds anyway */ returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | TPM_CHECK_ENABLED | TPM_CHECK_ACTIVATED | TPM_CHECK_OWNER)); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag1(tag); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, ownerAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_ResetLockValue: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* 1. If TPM_STCLEAR_DATA -> disableResetLock is TRUE return TPM_AUTHFAIL */ if (returnCode == TPM_SUCCESS) { if (tpm_state->tpm_stclear_data.disableResetLock) { printf("TPM_Process_ResetLockValue: Error, command locked out\n"); returnCode = TPM_AUTHFAIL; } } /* a. The internal dictionary attack mechanism will set TPM_STCLEAR_DATA -> disableResetLock to FALSE when the timeout period expires */ /* NOTE Done by TPM_Authdata_CheckState() */ /* Validate the parameters and owner authorization for this command */ if (returnCode == TPM_SUCCESS) { if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_OWNER, ordinal, NULL, &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ } if (returnCode == TPM_SUCCESS) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* owner HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, ownerAuth); /* Authorization digest for input */ } /* 2. If the the command and parameters validation using ownerAuth fails */ if (returnCode != TPM_SUCCESS) { printf("TPM_Process_ResetLockValue: Error, disabling ordinal\n"); /* a. Set TPM_STCLEAR_DATA -> disableResetLock to TRUE */ tpm_state->tpm_stclear_data.disableResetLock = TRUE; /* b. Restart the TPM dictionary attack lock out period */ /* A failure restarts it anyway with double the period.*/ /* c. Return TPM_AUTHFAIL */ } } /* 3. Reset the internal TPM dictionary attack mitigation mechanism */ /* a. The mechanism is vendor specific and can include time outs, reboots, and other mitigation strategies */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_ResetLockValue: Resetting the failure counter\n"); /* clear the authorization failure counter */ tpm_state->tpm_stclear_data.authFailCount = 0; } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_ResetLockValue: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* owner HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, terminate the session. */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } return rcf; } libtpms-0.9.3/src/tpm12/tpm_admin.h000066400000000000000000000172551421143571500170650ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM Admin Test and Opt-in */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_admin.h 4403 2011-02-08 18:28:22Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_ADMIN_H #define TPM_ADMIN_H #include "tpm_types.h" #include "tpm_global.h" #include "tpm_store.h" TPM_RESULT TPM_LimitedSelfTestCommon(void); TPM_RESULT TPM_LimitedSelfTestTPM(tpm_state_t *tpm_state); TPM_RESULT TPM_ContinueSelfTestCmd(tpm_state_t *tpm_state); TPM_RESULT TPM_SelfTestFullCmd(tpm_state_t *tpm_state); TPM_RESULT TPM_Process_ContinueSelfTest(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_SelfTestFull(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_GetTestResult(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_SetOwnerInstall(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_OwnerSetDisable(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_PhysicalDisable(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_PhysicalEnable(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_PhysicalSetDeactivated(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_SetTempDeactivated(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_SetOperatorAuth(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_ResetLockValue(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); #endif libtpms-0.9.3/src/tpm12/tpm_audit.c000066400000000000000000001327761421143571500171040ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Audit Handler */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_audit.c 4438 2011-02-13 23:03:56Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include #include #include "tpm_auth.h" #include "tpm_counter.h" #include "tpm_cryptoh.h" #include "tpm_debug.h" #include "tpm_digest.h" #include "tpm_error.h" #include "tpm_global.h" #include "tpm_key.h" #include "tpm_nonce.h" #include "tpm_permanent.h" #include "tpm_process.h" #include "tpm_audit.h" /* TPM_AUDIT_EVENT_IN */ /* TPM_AuditEventIn_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_AuditEventIn_Init(TPM_AUDIT_EVENT_IN *tpm_audit_event_in) { printf(" TPM_AuditEventIn_Init:\n"); TPM_Digest_Init(tpm_audit_event_in->inputParms); TPM_CounterValue_Init(&(tpm_audit_event_in->auditCount)); return; } /* TPM_AuditEventIn_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_AuditEventIn_Store(TPM_STORE_BUFFER *sbuffer, const TPM_AUDIT_EVENT_IN *tpm_audit_event_in) { TPM_RESULT rc = 0; printf(" TPM_AuditEventIn_Store:\n"); /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_AUDIT_EVENT_IN); } /* store inputParms */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_audit_event_in->inputParms); } /* store auditCount */ if (rc == 0) { rc = TPM_CounterValue_StorePublic(sbuffer, &(tpm_audit_event_in->auditCount)); } return rc; } /* TPM_AuditEventIn_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_AuditEventIn_Init to set members back to default values The object itself is not freed */ void TPM_AuditEventIn_Delete(TPM_AUDIT_EVENT_IN *tpm_audit_event_in) { printf(" TPM_AuditEventIn_Delete:\n"); if (tpm_audit_event_in != NULL) { TPM_AuditEventIn_Init(tpm_audit_event_in); } return; } /* TPM_AUDIT_EVENT_OUT */ /* TPM_AuditEventOut_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_AuditEventOut_Init(TPM_AUDIT_EVENT_OUT *tpm_audit_event_out) { printf(" TPM_AuditEventOut_Init:\n"); TPM_Digest_Init(tpm_audit_event_out->outputParms); TPM_CounterValue_Init(&(tpm_audit_event_out->auditCount)); return; } /* TPM_AuditEventOut_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_AuditEventOut_Store(TPM_STORE_BUFFER *sbuffer, const TPM_AUDIT_EVENT_OUT *tpm_audit_event_out) { TPM_RESULT rc = 0; printf(" TPM_AuditEventOut_Store:\n"); /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_AUDIT_EVENT_OUT); } /* store outputParms */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_audit_event_out->outputParms); } /* store auditCount */ if (rc == 0) { rc = TPM_CounterValue_StorePublic(sbuffer, &(tpm_audit_event_out->auditCount)); } return rc; } /* TPM_AuditEventOut_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_AuditEventOut_Init to set members back to default values The object itself is not freed */ void TPM_AuditEventOut_Delete(TPM_AUDIT_EVENT_OUT *tpm_audit_event_out) { printf(" TPM_AuditEventOut_Delete:\n"); if (tpm_audit_event_out != NULL) { TPM_AuditEventOut_Init(tpm_audit_event_out); } return; } /* ordinalAuditStatus Processing */ /* TPM_OrdinalAuditStatus_Init() initializes the TPM_PERMANENT_DATA 'ordinalAuditStatus' to the default The flags are stored as a bit map to conserve NVRAM. The array is not written back to NVRAM. */ TPM_RESULT TPM_OrdinalAuditStatus_Init(TPM_PERMANENT_DATA *tpm_permanent_data) { TPM_RESULT rc = 0; TPM_COMMAND_CODE ord; /* iterate through all ordinals */ TPM_BOOL auditDefault; /* result for an ordinal */ TPM_BOOL altered; printf(" TPM_OrdinalAuditStatus_Init:\n"); for (ord = 0 ; (rc == 0) && (ord < TPM_ORDINALS_MAX) ; ord++) { /* get the default audit state from the ordinals table */ TPM_OrdinalTable_GetAuditDefault(&auditDefault, ord); /* write to the TPM_PERMANENT_DATA bit map */ rc = TPM_OrdinalAuditStatus_SetAuditStatus(&altered, tpm_permanent_data, auditDefault, ord); } /* hack for TSC ordinals */ if (rc == 0) { TPM_OrdinalTable_GetAuditDefault(&auditDefault, TSC_ORD_PhysicalPresence); rc = TPM_OrdinalAuditStatus_SetAuditStatus(&altered, tpm_permanent_data, auditDefault, TSC_ORD_PhysicalPresence); } if (rc == 0) { TPM_OrdinalTable_GetAuditDefault(&auditDefault, TSC_ORD_ResetEstablishmentBit); rc = TPM_OrdinalAuditStatus_SetAuditStatus(&altered, tpm_permanent_data, auditDefault, TSC_ORD_ResetEstablishmentBit); } return rc; } /* TPM_OrdinalAuditStatus_Store() stores a list of all ordinals being audited */ TPM_RESULT TPM_OrdinalAuditStatus_Store(TPM_SIZED_BUFFER *ordinalList, TPM_PERMANENT_DATA *tpm_permanent_data, TPM_COMMAND_CODE startOrdinal) { TPM_RESULT rc = 0; TPM_STORE_BUFFER sbuffer; TPM_COMMAND_CODE ord; TPM_BOOL auditStatus; printf(" TPM_OrdinalAuditStatus_Store\n"); TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ /* scan through the ordinals array */ for (ord = startOrdinal ; (rc == 0) && (ord < TPM_ORDINALS_MAX) ; ord++ ) { /* determine if the ordinal being audited */ if (rc == 0) { rc = TPM_OrdinalAuditStatus_GetAuditStatus(&auditStatus, ord, tpm_permanent_data); } /* if being audited */ if ((rc == 0) && auditStatus) { rc = TPM_Sbuffer_Append32(&sbuffer, ord); /* append ordinal to the list */ } } /* scan the TSC ordinals */ if (rc == 0) { if (rc == 0) { rc = TPM_OrdinalAuditStatus_GetAuditStatus(&auditStatus, TSC_ORD_PhysicalPresence, tpm_permanent_data); } if ((rc == 0) && auditStatus) { rc = TPM_Sbuffer_Append32(&sbuffer, TSC_ORD_PhysicalPresence); } if (rc == 0) { rc = TPM_OrdinalAuditStatus_GetAuditStatus(&auditStatus, TSC_ORD_ResetEstablishmentBit, tpm_permanent_data); } /* if being audited */ if ((rc == 0) && auditStatus) { rc = TPM_Sbuffer_Append32(&sbuffer, TSC_ORD_ResetEstablishmentBit); } } /* convert the list to a TPM_SIZED_BUFFER */ if (rc == 0) { rc = TPM_SizedBuffer_SetFromStore(ordinalList, &sbuffer); } TPM_Sbuffer_Delete(&sbuffer); /* @1 */ return rc; } /* TPM_OrdinalAuditStatus_GetAuditState() gets the audit state for the ordinal */ TPM_RESULT TPM_OrdinalAuditStatus_GetAuditStatus(TPM_BOOL *auditStatus, TPM_COMMAND_CODE ordinal, TPM_PERMANENT_DATA *tpm_permanent_data) { TPM_RESULT rc = 0; size_t index; /* index of ordinal in array */ unsigned int offset; /* bit position of ordinal in array */ unsigned char bit; if (rc == 0) { /* handle the TPM ordinals */ if (ordinal < TPM_ORDINALS_MAX) { index = ordinal/CHAR_BIT; offset = ordinal % CHAR_BIT; bit = 0x01 << offset; *auditStatus = tpm_permanent_data->ordinalAuditStatus[index] & bit; } /* handle the TSC ordinals */ else if (ordinal == TSC_ORD_PhysicalPresence) { *auditStatus = tpm_permanent_data->tscOrdinalAuditStatus & TSC_PHYS_PRES_AUDIT; } else if (ordinal == TSC_ORD_ResetEstablishmentBit) { *auditStatus = tpm_permanent_data->tscOrdinalAuditStatus & TSC_RESET_ESTAB_AUDIT; } else { printf("TPM_OrdinalAuditStatus_GetAuditStatus: Error (fatal) " "ordinal %08x out of range\n", ordinal); rc = TPM_FAIL; /* should never occur, always called with ordinal processing */ } } /* trace the ordinals with auditing enabled */ if ((rc == 0) && *auditStatus) { printf(" TPM_OrdinalAuditStatus_GetAuditStatus: ordinal %08x status %02x\n", ordinal, *auditStatus); } return rc; } /* TPM_OrdinalAuditStatus_SetAuditStatus() sets the TPM_PERMANENT_DATA -> ordinalAuditStatus for the ordinal The flags are stored as a bit map to conserve NVRAM. The array is not written back to NVRAM. On error, TPM_PERMANENT_DATA is not changed. altered is TRUE if the bit was changed, */ TPM_RESULT TPM_OrdinalAuditStatus_SetAuditStatus(TPM_BOOL *altered, TPM_PERMANENT_DATA *tpm_permanent_data, TPM_BOOL auditStatus, TPM_COMMAND_CODE ordinal) { TPM_RESULT rc = 0; TPM_BOOL auditable; /* TRUE if the ordinal is auditable by this TPM implementation */ size_t index; /* index of ordinal in array */ unsigned int offset; /* bit position of ordinal in array */ unsigned char bit; *altered = FALSE; /* default, returned on error */ #if 0 printf(" TPM_OrdinalAuditStatus_SetAuditStatus: ordinal %08x status %02x\n", ordinal, auditStatus); #endif /* If trying to set, screen against the 'never audit' ordinal table */ if ((rc == 0) && auditStatus) { TPM_OrdinalTable_GetAuditable(&auditable, ordinal); /* if it is a 'never audit' ordinal, it can not be set */ if (!auditable) { printf("TPM_OrdinalAuditStatus_SetAuditStatus: " "Error, cannot audit ordinal %08x\n", ordinal); rc = TPM_BAD_PARAMETER; } } if (rc == 0) { /* handle the TPM ordinals */ if (ordinal < TPM_ORDINALS_MAX) { index = ordinal/CHAR_BIT; offset = ordinal % CHAR_BIT; bit = 0x01 << offset; /* determine if the bit is to be altered */ if (((tpm_permanent_data->ordinalAuditStatus[index] & bit) && !auditStatus) || (!(tpm_permanent_data->ordinalAuditStatus[index] & bit) && auditStatus)) { *altered = TRUE; } if (auditStatus) { /* set the bit */ tpm_permanent_data->ordinalAuditStatus[index] |= bit; } else { /* clear the bit */ tpm_permanent_data->ordinalAuditStatus[index] &= ~bit; } } /* handle the TSC ordinals */ else if (ordinal == TSC_ORD_PhysicalPresence) { /* determine if the bit is to be altered */ if (((tpm_permanent_data->tscOrdinalAuditStatus & TSC_PHYS_PRES_AUDIT) && !auditStatus) || (!(tpm_permanent_data->tscOrdinalAuditStatus & TSC_PHYS_PRES_AUDIT) && auditStatus)) { *altered = TRUE; } if (auditStatus) { tpm_permanent_data->tscOrdinalAuditStatus |= TSC_PHYS_PRES_AUDIT; } else { tpm_permanent_data->tscOrdinalAuditStatus &= ~TSC_PHYS_PRES_AUDIT; } } else if (ordinal == TSC_ORD_ResetEstablishmentBit) { if (auditStatus) { /* determine if the bit is to be altered */ if (((tpm_permanent_data->tscOrdinalAuditStatus & TSC_RESET_ESTAB_AUDIT) && !auditStatus) || (!(tpm_permanent_data->tscOrdinalAuditStatus & TSC_RESET_ESTAB_AUDIT) && auditStatus)) { *altered = TRUE; } tpm_permanent_data->tscOrdinalAuditStatus |= TSC_RESET_ESTAB_AUDIT; } else { tpm_permanent_data->tscOrdinalAuditStatus &= ~TSC_RESET_ESTAB_AUDIT; } } else { printf("TPM_OrdinalAuditStatus_SetAuditStatus: Error ordinal %08x out of range\n", ordinal); rc = TPM_BADINDEX; } } return rc; } /* Common Processing Functions */ /* 8.1 Audit Generation rev 109 TPM_AuditDigest_ExtendIn() extends the audit digest with a digest of input parameters */ TPM_RESULT TPM_AuditDigest_ExtendIn(tpm_state_t *tpm_state, TPM_DIGEST inParamDigest) { TPM_RESULT rc = 0; TPM_AUDIT_EVENT_IN tpm_audit_event_in; TPM_STORE_BUFFER eventIn_sbuffer; const unsigned char *eventIn_buffer; /* serialized buffer */ uint32_t eventIn_length; /* serialization length */ printf(" TPM_AuditDigest_ExtendIn:\n"); TPM_AuditEventIn_Init(&tpm_audit_event_in); /* freed @1 */ TPM_Sbuffer_Init(&eventIn_sbuffer); /* freed @2 */ if (rc == 0) { /* b. Create A1 a TPM_AUDIT_EVENT_IN structure */ /* NOTE Done by TPM_AuditEventIn_Init() */ /* i. Set A1 -> inputParms to the digest of the input parameters from the command */ /* (1) Digest value according to the HMAC digest rules of the "above the line" parameters (i.e. the first HMAC digest calculation). */ TPM_Digest_Copy(tpm_audit_event_in.inputParms, inParamDigest); /* ii. Set A1 -> auditCount to TPM_PERMANENT_DATA -> auditMonotonicCounter */ TPM_CounterValue_CopyPublic(&(tpm_audit_event_in.auditCount), &(tpm_state->tpm_permanent_data.auditMonotonicCounter)); /* serialize the A1 TPM_AUDIT_EVENT_IN object */ rc = TPM_AuditEventIn_Store(&eventIn_sbuffer, &tpm_audit_event_in); } if (rc == 0) { /* get the serialization results */ TPM_Sbuffer_Get(&eventIn_sbuffer, &eventIn_buffer, &eventIn_length); /* c. Set TPM_STANY_DATA -> auditDigest to SHA-1 (TPM_STANY_DATA -> auditDigest || A1) */ TPM_PrintFour(" TPM_AuditDigest_ExtendIn: Previous digest", tpm_state->tpm_stclear_data.auditDigest); TPM_PrintAll(" TPM_AuditDigest_ExtendIn: TPM_AUDIT_EVENT_IN", eventIn_buffer, eventIn_length); rc = TPM_SHA1(tpm_state->tpm_stclear_data.auditDigest, TPM_DIGEST_SIZE, tpm_state->tpm_stclear_data.auditDigest, eventIn_length, eventIn_buffer, 0, NULL); TPM_PrintFour(" TPM_AuditDigest_ExtendIn: Current digest (in)", tpm_state->tpm_stclear_data.auditDigest); } TPM_AuditEventIn_Delete(&tpm_audit_event_in); /* @1 */ TPM_Sbuffer_Delete(&eventIn_sbuffer); /* @2 */ return rc; } /* 8.1 Audit Generation rev 109 TPM_AuditDigest_ExtendOut() extends the audit digest with a digest of output parameters */ TPM_RESULT TPM_AuditDigest_ExtendOut(tpm_state_t *tpm_state, TPM_DIGEST outParamDigest) { TPM_RESULT rc = 0; TPM_AUDIT_EVENT_OUT tpm_audit_event_out; TPM_STORE_BUFFER eventOut_sbuffer; const unsigned char *eventOut_buffer; /* serialized buffer */ uint32_t eventOut_length; /* serialization length */ printf(" TPM_AuditDigest_ExtendOut:\n"); TPM_AuditEventOut_Init(&tpm_audit_event_out); /* freed @1 */ TPM_Sbuffer_Init(&eventOut_sbuffer); /* freed @2 */ if (rc == 0) { /* d. Create A2 a TPM_AUDIT_EVENT_OUT structure */ /* NOTE Done by TPM_AuditEventOut_Init() */ /* i. Set A2 -> outputParms to the digest of the output parameters from the command */ /* (1). Digest value according to the HMAC digest rules of the "above the line" parameters (i.e. the first HMAC digest calculation). */ TPM_Digest_Copy(tpm_audit_event_out.outputParms, outParamDigest); /* ii. Set A2 -> auditCount to TPM_PERMANENT_DATA -> auditMonotonicCounter */ TPM_CounterValue_CopyPublic(&(tpm_audit_event_out.auditCount), &(tpm_state->tpm_permanent_data.auditMonotonicCounter)); /* serialize the A2 TPM_AUDIT_EVENT_OUT object */ rc = TPM_AuditEventOut_Store(&eventOut_sbuffer, &tpm_audit_event_out); } if (rc == 0) { /* get the serialization results */ TPM_Sbuffer_Get(&eventOut_sbuffer, &eventOut_buffer, &eventOut_length); /* e. Set TPM_STANY_DATA -> auditDigest to SHA-1 (TPM_STANY_DATA -> auditDigest || A2) */ TPM_PrintFour(" TPM_AuditDigest_ExtendOut: Previous digest", tpm_state->tpm_stclear_data.auditDigest); TPM_PrintAll(" TPM_AuditDigest_ExtendOut: TPM_AUDIT_EVENT_OUT", eventOut_buffer, eventOut_length); rc = TPM_SHA1(tpm_state->tpm_stclear_data.auditDigest, TPM_DIGEST_SIZE, tpm_state->tpm_stclear_data.auditDigest, eventOut_length, eventOut_buffer, 0, NULL); TPM_PrintFour(" TPM_AuditDigest_ExtendOut: Current digest (out)", tpm_state->tpm_stclear_data.auditDigest); } TPM_AuditEventOut_Delete(&tpm_audit_event_out); /* @1 */ TPM_Sbuffer_Delete(&eventOut_sbuffer); /* @2 */ return rc; } /* Processing Functions */ /* The TPM generates an audit event in response to the TPM executing a command that has the audit flag set to TRUE for that command. The TPM maintains an extended value for all audited operations. */ /* 8.3 TPM_GetAuditDigest rev 87 This returns the current audit digest. The external audit log has the responsibility to track the parameters that constitute the audit digest. This value may be unique to an individual TPM. The value however will be changing at a rate set by the TPM Owner. Those attempting to use this value may find it changing without their knowledge. This value represents a very poor source of tracking uniqueness. */ TPM_RESULT TPM_Process_GetAuditDigest(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ uint32_t startOrdinal; /* The starting ordinal for the list of audited ordinals */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_DIGEST auditDigest; /* Log of all audited events */ TPM_BOOL more; /* TRUE if the output does not contain a full list of audited ordinals */ TPM_SIZED_BUFFER ordList; /* List of ordinals that are audited. */ printf("TPM_Process_GetAuditDigest: Ordinal Entry\n"); TPM_SizedBuffer_Init(&ordList); /* freed @1 */ /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get startOrdinal parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&startOrdinal, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_GetAuditDigest: startOrdinal %08x\n", startOrdinal); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_GetAuditDigest: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ if (returnCode == TPM_SUCCESS) { /* 1. The TPM sets auditDigest to TPM_STANY_DATA -> auditDigest */ TPM_Digest_Copy(auditDigest, tpm_state->tpm_stclear_data.auditDigest); /* 2. The TPM sets counterValue to TPM_PERMANENT_DATA -> auditMonotonicCounter */ /* NOTE Since there is only one, use it directly on the output */ printf("TPM_Process_GetAuditDigest: Counter value %08x\n", tpm_state->tpm_permanent_data.auditMonotonicCounter.counter); /* 3. The TPM creates an ordered list of audited ordinals. The list starts at startOrdinal listing each ordinal that is audited. */ /* a. If startOrdinal is 0 then the first ordinal that could be audited would be TPM_OIAP (ordinal 0x0000000A) */ /* b. The next ordinal would be TPM_OSAP (ordinal 0x0000000B) */ returnCode = TPM_OrdinalAuditStatus_Store(&ordList, &(tpm_state->tpm_permanent_data), startOrdinal); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_GetAuditDigest: ordSize %u\n", ordList.size); /* 4. If the ordered list does not fit in the output buffer the TPM sets more to TRUE */ more = FALSE; } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_GetAuditDigest: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { /* append counterValue */ if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* append counterValue */ returnCode = TPM_CounterValue_StorePublic (response, &(tpm_state->tpm_permanent_data.auditMonotonicCounter)); } /* 5. Return TPM_STANY_DATA -> auditDigest as auditDigest */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Digest_Store(response, auditDigest); } /* append more */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Sbuffer_Append(response, &more, sizeof(TPM_BOOL)); } /* append ordList */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_Store(response, &ordList); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* cleanup */ TPM_SizedBuffer_Delete(&ordList); /* @1 */ return rcf; } /* 8.4 TPM_GetAuditDigestSigned rev 101 The signing of the audit log returns the entire digest value and the list of currently audited commands. The inclusion of the list of audited commands as an atomic operation is to tie the current digest value with the list of commands that are being audited. Note to future architects When auditing functionality is active in a TPM, it may seem logical to remove this ordinal from the active set of ordinals as the signing functionality of this command could be handled in a signed transport session. While true this command has a secondary affect also, resetting the audit log digest. As the reset requires TPM Owner authentication there must be some way in this command to reflect the TPM Owner wishes. By requiring that a TPM Identity key be the only key that can sign and reset the TPM Owners authentication is implicit in the execution of the command (TPM Identity Keys are created and controlled by the TPM Owner only). Hence while one might want to remove an ordinal this is not one that can be removed if auditing is functional. */ TPM_RESULT TPM_Process_GetAuditDigestSigned(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_KEY_HANDLE keyHandle; /* The handle of a loaded key that can perform digital signatures. */ TPM_BOOL closeAudit; /* Indication if audit session should be closed */ TPM_NONCE antiReplay; /* A nonce to prevent replay attacks */ TPM_AUTHHANDLE authHandle; /* The authorization session handle used for key authentication. */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession; /* The continue use flag for the authorization session handle */ TPM_AUTHDATA keyAuth; /* Authorization. HMAC key: key.usageAuth. */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_SECRET *hmacKey; TPM_KEY *sigKey = NULL; /* the key specified by keyHandle */ TPM_SECRET *keyUsageAuth; TPM_BOOL parentPCRStatus; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ TPM_SIGN_INFO d1SignInfo; TPM_SIZED_BUFFER d3SizedBuffer; /* List of ordinals that are audited. */ TPM_STORE_BUFFER d2Sbuffer; /* data to be signed */ TPM_DIGEST h1; /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_DIGEST ordinalDigest; /* Digest of all audited ordinals */ TPM_SIZED_BUFFER sig; /* The signature of the area */ printf("TPM_Process_GetAuditDigestSigned: Ordinal Entry\n"); TPM_SignInfo_Init(&d1SignInfo); /* freed @1 */ TPM_SizedBuffer_Init(&d3SizedBuffer); /* freed @2 */ TPM_Sbuffer_Init(&d2Sbuffer); /* freed @3 */ TPM_SizedBuffer_Init(&sig); /* freed @4 */ /* get inputs */ /* get keyHandle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&keyHandle, &command, ¶mSize); } /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get closeAudit parameter */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_GetAuditDigestSigned: keyHandle %08x\n", keyHandle); returnCode = TPM_LoadBool(&closeAudit, &command, ¶mSize); } /* get antiReplay parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Digest_Load(antiReplay, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag10(tag); } /* get the optional 'below the line' authorization parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, keyAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_GetAuditDigestSigned: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* 1. Validate the AuthData and parameters using keyAuth, return TPM_AUTHFAIL on error */ /* get the key corresponding to the keyHandle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyHandleEntries_GetKey(&sigKey, &parentPCRStatus, tpm_state, keyHandle, FALSE, /* not read-only */ FALSE, /* do not ignore PCRs */ FALSE); /* cannot use EK */ } if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)){ if (sigKey->authDataUsage != TPM_AUTH_NEVER) { printf("TPM_Process_GetAuditDigestSigned: Error, authorization required\n"); returnCode = TPM_AUTHFAIL; } } /* get keyHandle -> usageAuth */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_Key_GetUsageAuth(&keyUsageAuth, sigKey); } /* get the session data */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_KEYHANDLE, ordinal, sigKey, keyUsageAuth, /* OIAP */ sigKey->tpm_store_asymkey->pubDataDigest); /* OSAP */ } /* validate the authorization to use the key pointed to by keyHandle */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, keyAuth); /* Authorization digest for input */ } /* 2.Validate that keyHandle -> keyUsage is TPM_KEY_SIGNING, TPM_KEY_IDENTITY or TPM_KEY_LEGACY, if not return TPM_INVALID_KEYUSAGE */ if (returnCode == TPM_SUCCESS) { if ((sigKey->keyUsage != TPM_KEY_SIGNING) && (sigKey->keyUsage != TPM_KEY_IDENTITY) && (sigKey->keyUsage != TPM_KEY_LEGACY)) { printf("TPM_Process_GetAuditDigestSigned: Error, keyUsage %04hx is invalid\n", sigKey->keyUsage); returnCode = TPM_INVALID_KEYUSAGE; } } /* 3. The TPM validates that the key pointed to by keyHandle has a signature scheme of TPM_SS_RSASSAPKCS1v15_SHA1 or TPM_SS_RSASSAPKCS1v15_INFO, return TPM_INVALID_KEYUSAGE on error */ if (returnCode == TPM_SUCCESS) { if ((sigKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1) && (sigKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_INFO)) { printf("TPM_Process_GetAuditDigestSigned: Error, invalid sigScheme %04hx\n", sigKey->algorithmParms.sigScheme); returnCode = TPM_INVALID_KEYUSAGE; } } if (returnCode == TPM_SUCCESS) { /* 4. Create D1 a TPM_SIGN_INFO structure and set the structure defaults */ /* NOTE Done by TPM_SignInfo_Init() */ /* a. Set D1 -> fixed to "ADIG" */ memcpy(d1SignInfo.fixed, "ADIG", TPM_SIGN_INFO_FIXED_SIZE); /* b. Set D1 -> replay to antiReplay */ TPM_Nonce_Copy(d1SignInfo.replay, antiReplay); /* c. Create D3 a list of all audited ordinals as defined in the TPM_GetAuditDigest uint32_t[] ordList outgoing parameter */ returnCode = TPM_OrdinalAuditStatus_Store(&d3SizedBuffer, &(tpm_state->tpm_permanent_data), 0); } /* d. Create D4 (ordinalDigest outgoing parameter) the SHA-1 of D3 */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SHA1(ordinalDigest, d3SizedBuffer.size, d3SizedBuffer.buffer, 0, NULL); } if (returnCode == TPM_SUCCESS) { /* e. Set auditDigest to TPM_STANY_DATA -> auditDigest */ /* NOTE: Use it directly on the output */ /* f. Set counterValue to TPM_PERMANENT_DATA -> auditMonotonicCounter */ /* NOTE Since there is only one, use it directly on the output */ /* g. Create D2 the concatenation of auditDigest || counterValue || D4 */ returnCode = TPM_Sbuffer_Append(&d2Sbuffer, tpm_state->tpm_stclear_data.auditDigest, TPM_DIGEST_SIZE); } if (returnCode == TPM_SUCCESS) { returnCode = TPM_CounterValue_StorePublic(&d2Sbuffer, &(tpm_state->tpm_permanent_data.auditMonotonicCounter)); } if (returnCode == TPM_SUCCESS) { returnCode = TPM_Sbuffer_Append(&d2Sbuffer, ordinalDigest, TPM_DIGEST_SIZE); } /* h. Set D1 -> data to D2 */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_SetFromStore(&(d1SignInfo.data), &d2Sbuffer); } /* i. Create a digital signature of the SHA-1 of D1 by using the signature scheme for keyHandle */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SHA1_GenerateStructure(h1, &d1SignInfo, (TPM_STORE_FUNCTION_T)TPM_SignInfo_Store); } if (returnCode == TPM_SUCCESS) { returnCode = TPM_RSASignToSizedBuffer(&sig, /* signature */ h1, /* message */ TPM_DIGEST_SIZE, /* message size */ sigKey); /* input, signing key */ } if (returnCode == TPM_SUCCESS) { TPM_PrintFour("TPM_Process_GetAuditDigestSigned: auditDigest", tpm_state->tpm_stclear_data.auditDigest); TPM_PrintFour("TPM_Process_GetAuditDigestSigned: ordinalDigest", ordinalDigest); } /* j. Set ordinalDigest to D4 */ /* NOTE Created directly in ordinalDigest */ /* 5. If closeAudit == TRUE */ if ((returnCode == TPM_SUCCESS) && closeAudit) { /* a. If keyHandle->keyUsage is TPM_KEY_IDENTITY */ if (sigKey->keyUsage == TPM_KEY_IDENTITY) { /* i. TPM_STANY_DATA -> auditDigest MUST be set to all zeros. */ TPM_Digest_Init(tpm_state->tpm_stclear_data.auditDigest); } /* b. Else */ else { /* i. Return TPM_INVALID_KEYUSAGE */ printf("TPM_Process_GetAuditDigestSigned: Error, " "cannot closeAudit with keyUsage %04hx\n", sigKey->keyUsage); returnCode = TPM_INVALID_KEYUSAGE; } } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_GetAuditDigestSigned: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* return counterValue */ returnCode = TPM_CounterValue_StorePublic (response, &(tpm_state->tpm_permanent_data.auditMonotonicCounter)); } /* return auditDigest */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Digest_Store(response, tpm_state->tpm_stclear_data.auditDigest); } /* return ordinalDigest */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Digest_Store(response, ordinalDigest); } /* return sig */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_Store(response, &sig); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* owner HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ TPM_SignInfo_Delete(&d1SignInfo); /* @1 */ TPM_SizedBuffer_Delete(&d3SizedBuffer); /* @2 */ TPM_Sbuffer_Delete(&d2Sbuffer); /* @3 */ TPM_SizedBuffer_Delete(&sig); /* @4 */ return rcf; } /* 8.5 TPM_SetOrdinalAuditStatus rev 109 Set the audit flag for a given ordinal. This command requires the authentication of the TPM Owner. */ TPM_RESULT TPM_Process_SetOrdinalAuditStatus(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_COMMAND_CODE ordinalToAudit; /* The ordinal whose audit flag is to be set */ TPM_BOOL auditState; /* Value for audit flag */ TPM_AUTHHANDLE authHandle; /* The authorization session handle used for owner authentication. */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization session handle */ TPM_AUTHDATA ownerAuth; /* The authorization session digest for inputs and owner authentication. HMAC key: ownerAuth. */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL altered; /* status is changing */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_SECRET *hmacKey; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_SetOrdinalAuditStatus: Ordinal Entry\n"); /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get ordinalToAudit parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&ordinalToAudit, &command, ¶mSize); } /* get auditState parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_LoadBool(&auditState, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_SetOrdinalAuditStatus: ordinalToAudit %08x auditState %02x\n", ordinalToAudit, auditState); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag1(tag); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, ownerAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_SetOrdinalAuditStatus: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* 1. Validate the AuthData to execute the command and the parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_OWNER, ordinal, NULL, &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ } /* calculate and set the below the line parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, ownerAuth); /* Authorization digest for input */ } /* 2. Validate that the ordinal points to a valid TPM ordinal, return TPM_BADINDEX on error */ /* a. Valid TPM ordinal means an ordinal that the TPM implementation supports */ /* Done by TPM_OrdinalAuditStatus_SetAuditState() */ /* 3. Set the non-volatile flag associated with ordinalToAudit to the value in auditState */ /* NOTE: On error, TPM_PERMANENT_DATA is not changed */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_OrdinalAuditStatus_SetAuditStatus(&altered, &(tpm_state->tpm_permanent_data), auditState, /* uninitialized */ ordinalToAudit); /* It's not really uninitialized, but beam doesn't understand that TPM_GetInParamDigest() can't turn a FALSE into a TRUE */ } /* Store the permanent data back to NVRAM */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_PermanentAll_NVStore(tpm_state, altered, returnCode); } /* Audit Generation 3.b. Corner Cases: TPM_SetOrdinalAuditStatus: In the case where the ordinalToAudit is TPM_ORD_SetOrdinalAuditStatus, audit is based on the initial state, not the final state. */ /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_SetOrdinalAuditStatus: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* owner HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, terminate the session. */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } return rcf; } libtpms-0.9.3/src/tpm12/tpm_audit.h000066400000000000000000000132261421143571500170750ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Audit Handler */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_audit.h 4071 2010-04-29 19:26:45Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_AUDIT_H #define TPM_AUDIT_H #include "tpm_global.h" #include "tpm_store.h" #include "tpm_structures.h" /* TPM_AUDIT_EVENT_IN */ void TPM_AuditEventIn_Init(TPM_AUDIT_EVENT_IN *tpm_audit_event_in); TPM_RESULT TPM_AuditEventIn_Store(TPM_STORE_BUFFER *sbuffer, const TPM_AUDIT_EVENT_IN *tpm_audit_event_in); void TPM_AuditEventIn_Delete(TPM_AUDIT_EVENT_IN *tpm_audit_event_in); /* TPM_AUDIT_EVENT_OUT */ void TPM_AuditEventOut_Init(TPM_AUDIT_EVENT_OUT *tpm_audit_event_out); TPM_RESULT TPM_AuditEventOut_Store(TPM_STORE_BUFFER *sbuffer, const TPM_AUDIT_EVENT_OUT *tpm_audit_event_out); void TPM_AuditEventOut_Delete(TPM_AUDIT_EVENT_OUT *tpm_audit_event_out); /* ordinalAuditStatus Processing */ TPM_RESULT TPM_OrdinalAuditStatus_Init(TPM_PERMANENT_DATA *tpm_permanent_data); TPM_RESULT TPM_OrdinalAuditStatus_Store(TPM_SIZED_BUFFER *ordinalList, TPM_PERMANENT_DATA *tpm_permanent_data, TPM_COMMAND_CODE startOrdinal); TPM_RESULT TPM_OrdinalAuditStatus_GetAuditStatus(TPM_BOOL *auditStatus, TPM_COMMAND_CODE ordinal, TPM_PERMANENT_DATA *tpm_permanent_data); TPM_RESULT TPM_OrdinalAuditStatus_SetAuditStatus(TPM_BOOL *altered, TPM_PERMANENT_DATA *tpm_permanent_data, TPM_BOOL auditStatus, TPM_COMMAND_CODE ordinal); /* Common Processing Functions */ TPM_RESULT TPM_AuditDigest_ExtendIn(tpm_state_t *tpm_state, TPM_DIGEST inParamDigest); TPM_RESULT TPM_AuditDigest_ExtendOut(tpm_state_t *tpm_state, TPM_DIGEST outParamDigest); /* Processing Functions */ TPM_RESULT TPM_Process_GetAuditDigest(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_GetAuditDigestSigned(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_SetOrdinalAuditStatus(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); #endif libtpms-0.9.3/src/tpm12/tpm_auth.c000066400000000000000000002516241421143571500167310ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Authorization */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_auth.c 4438 2011-02-13 23:03:56Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include #include #include #include "tpm_crypto.h" #include "tpm_cryptoh.h" #include "tpm_debug.h" #include "tpm_digest.h" #include "tpm_error.h" #include "tpm_init.h" #include "tpm_key.h" #include "tpm_memory.h" #include "tpm_nonce.h" #include "tpm_permanent.h" #include "tpm_process.h" #include "tpm_secret.h" #include "tpm_storage.h" #include "tpm_time.h" #include "tpm_transport.h" #include "tpm_auth.h" /* Dictionary attack mitigation: TPM_Authdata_CheckState() - called at command entry if past limit, check authFailTime vs. current time if command allowed disableResetLock = FALSE TPM_Authdata_Check() - called during the command to validate authorization data TPM_Authdata_Fail() - called on failure authFailCount++ if past limit, authFailTime = current time TPM_ResetLockValue TPM_Authdata_CheckState() disableResetLock = FALSE if no lockout if disableResetLock, return error if authorization failure disableResetLock = TRUE authFailCount = 0 */ #if 0 /* TPM_Authdata_Init() zeros the tpm_authdata */ void TPM_Authdata_Init(TPM_AUTHDATA tpm_authdata) { printf(" TPM_Authdata_Init:\n"); memset(tpm_authdata, 0, TPM_AUTHDATA_SIZE); return; } #endif /* TPM_Authdata_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes */ TPM_RESULT TPM_Authdata_Load(TPM_AUTHDATA tpm_authdata, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_Authdata_Load:\n"); /* check stream_size */ if (rc == 0) { if (*stream_size < TPM_AUTHDATA_SIZE) { printf("TPM_Authdata_Load: Error, stream_size %u less than %u\n", *stream_size, TPM_DIGEST_SIZE); rc = TPM_BAD_PARAM_SIZE; } } if (rc == 0) { memcpy(tpm_authdata, *stream, TPM_AUTHDATA_SIZE); *stream += TPM_AUTHDATA_SIZE; *stream_size -= TPM_AUTHDATA_SIZE; } return rc; } /* TPM_Authdata_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes After use, call TPM_Sbuffer_Delete() to free memory */ TPM_RESULT TPM_Authdata_Store(TPM_STORE_BUFFER *sbuffer, const TPM_AUTHDATA tpm_authdata) { TPM_RESULT rc = 0; printf(" TPM_Authdata_Store:\n"); if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, tpm_authdata, TPM_AUTHDATA_SIZE); } return rc; } /* TPM_AuthParams_Get() is common code to load a set of "below the double line" request parameters from the input stream. */ TPM_RESULT TPM_AuthParams_Get(TPM_AUTHHANDLE *authHandle, /* The authorization handle used for this command */ TPM_BOOL *authHandleValid, TPM_NONCE nonceOdd, /* Nonce generated by system associated with authHandle */ TPM_BOOL *continueAuthSession, /* The continue use flag for the authorization handle */ TPM_AUTHDATA authData, /* Authorization digest for input params. */ unsigned char **command, /* parameter stream */ uint32_t *paramSize) /* bytes left in command */ { TPM_RESULT rc = 0; printf(" TPM_AuthParams_Get:\n"); /* get authHandle parameter */ if (rc == 0) { rc = TPM_Load32(authHandle, command, paramSize); } /* get nonceOdd parameter */ if (rc == 0) { rc = TPM_Nonce_Load(nonceOdd, command, paramSize); } /* get continueAuthSession parameter */ if (rc == 0) { rc = TPM_LoadBool(continueAuthSession, command, paramSize); } /* get authData parameter */ if (rc == 0) { rc = TPM_Authdata_Load(authData, command, paramSize); } if (rc == 0) { *authHandleValid = TRUE; /* so handle can be terminated */ } return rc; } /* TPM_SetAuthParams is common code to set a set of "below the double line" response parameters. */ TPM_RESULT TPM_AuthParams_Set(TPM_STORE_BUFFER *response, TPM_SECRET hmacKey, /* HMAC key */ TPM_AUTH_SESSION_DATA *auth_session_data, /* session data for authHandle */ TPM_DIGEST outParamDigest, TPM_NONCE nonceOdd, /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession) /* session continue use flag */ { TPM_RESULT rc = 0; TPM_AUTHDATA resAuth; /* The authorization digest for the returned parameters */ printf(" TPM_AuthParams_Set:\n"); /* generate new nonceEven */ if (rc == 0) { rc = TPM_Nonce_Generate(auth_session_data->nonceEven); } /* append nonceEven */ if (rc == 0) { rc = TPM_Nonce_Store(response, auth_session_data->nonceEven); } /* append continueAuthSession */ if (rc == 0) { rc = TPM_Sbuffer_Append(response, &continueAuthSession, sizeof(TPM_BOOL)); } /* Calculate resAuth using the hmac key */ if (rc == 0) { rc = TPM_Authdata_Generate(resAuth, /* result */ hmacKey, /* HMAC key */ outParamDigest, /* params */ auth_session_data->nonceEven, nonceOdd, continueAuthSession); } /* append resAuth */ if (rc == 0) { rc = TPM_Authdata_Store(response, resAuth); } return rc; } TPM_RESULT TPM_Authdata_Generate(TPM_AUTHDATA resAuth, /* result */ TPM_SECRET usageAuth, /* HMAC key */ TPM_DIGEST outParamDigest, /* digest of outputs above double line */ TPM_NONCE nonceEven, TPM_NONCE nonceOdd, TPM_BOOL continueSession) { TPM_RESULT rc = 0; printf(" TPM_Authdata_Generate:\n"); if (rc == 0) { TPM_PrintFour(" TPM_Authdata_Generate: outParamDigest", outParamDigest); TPM_PrintFour(" TPM_Authdata_Generate: usageAuth (key)", usageAuth); TPM_PrintFour(" TPM_Authdata_Generate: nonceEven", nonceEven); TPM_PrintFour(" TPM_Authdata_Generate: nonceOdd", nonceOdd); printf (" TPM_Authdata_Generate: continueSession %02x\n", continueSession); rc = TPM_HMAC_Generate(resAuth, usageAuth, /* key */ TPM_DIGEST_SIZE, outParamDigest, /* response digest */ TPM_NONCE_SIZE, nonceEven, /* 2H */ TPM_NONCE_SIZE, nonceOdd, /* 3H */ sizeof(TPM_BOOL), &continueSession, /* 4H */ 0, NULL); TPM_PrintFour(" TPM_Authdata_Generate: resAuth", resAuth); } return rc; } /* TPM_Authdata_Check() checks the authorization of a command. Handles the protection against dictionary attacks. Returns TPM_AUTHFAIL if the TPM_AUTHDATA does not match. */ TPM_RESULT TPM_Authdata_Check(tpm_state_t *tpm_state, TPM_SECRET hmacKey, /* HMAC key */ TPM_DIGEST inParamDigest, /* digest of inputs above line */ TPM_AUTH_SESSION_DATA *tpm_auth_session_data, /* auth session */ TPM_NONCE nonceOdd, /* Nonce generated by system associated with authHandle */ TPM_BOOL continueSession, TPM_AUTHDATA usageAuth) /* Authorization digest for input */ { TPM_RESULT rc = 0; TPM_BOOL valid; printf(" TPM_Authdata_Check:\n"); if (rc == 0) { TPM_PrintFour(" TPM_Authdata_Check: inParamDigest", inParamDigest); TPM_PrintFour(" TPM_Authdata_Check: usageAuth (key)", hmacKey); TPM_PrintFour(" TPM_Authdata_Check: nonceEven", tpm_auth_session_data->nonceEven); TPM_PrintFour(" TPM_Authdata_Check: nonceOdd", nonceOdd); printf (" TPM_Authdata_Check: continueSession %02x\n", continueSession); /* HMAC the inParamDigest, authLastNonceEven, nonceOdd, continue */ /* authLastNonceEven is retrieved from internal authorization session storage */ rc = TPM_HMAC_Check(&valid, usageAuth, /* expected, from command */ hmacKey, /* key */ sizeof(TPM_DIGEST), inParamDigest, /* command digest */ sizeof(TPM_NONCE), tpm_auth_session_data->nonceEven, /* 2H */ sizeof(TPM_NONCE), nonceOdd, /* 3H */ sizeof(TPM_BOOL), &continueSession, /* 4H */ 0, NULL); } if (rc == 0) { if (!valid) { printf("TPM_Authdata_Check: Error, authorization failed\n"); /* record the authorization failure */ rc = TPM_Authdata_Fail(tpm_state); /* TPM_Authdata_Fail() fatal TPM_FAIL error takes precedence, else TPM_AUTHFAIL */ if (rc == 0) { rc = TPM_AUTHFAIL; } } } return rc; } /* TPM_Auth2data_Check() is a wrapper around TPM_Authdata_Check() that returns TPM_AUTH2FAIL in place of TPM_AUTHFAIL. */ TPM_RESULT TPM_Auth2data_Check(tpm_state_t *tpm_state, TPM_SECRET hmacKey, /* HMAC key */ TPM_DIGEST inParamDigest, /* digest of inputs above line */ TPM_AUTH_SESSION_DATA *tpm_auth_session_data, /* auth session */ TPM_NONCE nonceOdd, /* Nonce generated by system associated with authHandle */ TPM_BOOL continueSession, TPM_AUTHDATA usageAuth) /* Authorization digest for input */ { TPM_RESULT rc = 0; rc = TPM_Authdata_Check(tpm_state, hmacKey, inParamDigest, tpm_auth_session_data, nonceOdd, continueSession, usageAuth); if (rc == TPM_AUTHFAIL) { rc = TPM_AUTH2FAIL; } return rc; } /* TPM_Authdata_Fail() processes an authorization failure event, to mitigate dictionary attacks. Returns TPM_FAIL on error, so that the caller can shut down the TPM */ TPM_RESULT TPM_Authdata_Fail(tpm_state_t *tpm_state) { TPM_RESULT rc = 0; uint32_t tv_usec; /* dummy, discard usec */ if (rc == 0) { /* Each failure increments the counter. No need to check for overflow. Unless TPM_LOCKOUT_THRESHOLD is absurdly large, the left shift overflows first. */ tpm_state->tpm_stclear_data.authFailCount++; printf(" TPM_Authdata_Fail: New authFailCount %u\n", tpm_state->tpm_stclear_data.authFailCount); /* Test if past the failure threshold. Each time authorization fails, this test is made. Once in dictionary attack mitigation, there will be no authdata check until the mitigation period is exceeded. After that, if there is another failure, the fail count increases and mitigation begins again. Note that a successful authorization does NOT reset authFailCount, as this would allow a dictionary attack by an attacker that knew ANY good authorization value. The count is only reset by the owner using TPM_ResetLockValue. */ if (tpm_state->tpm_stclear_data.authFailCount > TPM_LOCKOUT_THRESHOLD) { /* the current authorization failure time is the start time */ rc = TPM_GetTimeOfDay(&(tpm_state->tpm_stclear_data.authFailTime), &tv_usec); printf(" TPM_Authdata_Fail: Past limit, authFailTime %u\n", tpm_state->tpm_stclear_data.authFailTime); } } return rc; } /* TPM_Authdata_GetState() gets the boolean dictionary attack mitigation state. */ TPM_RESULT TPM_Authdata_GetState(TPM_DA_STATE *state, uint32_t *timeLeft, tpm_state_t *tpm_state) { TPM_RESULT rc = 0; uint32_t currentTime; /* in seconds */ uint32_t tv_usec; /* dummy, discarded */ uint32_t threshold_diff; /* in failure counts */ uint32_t waitTime; /* in seconds, timeout based on threshold_diff */ uint32_t timeDiff; /* in seconds, how far along is timeout */ printf(" TPM_Authdata_GetState:\n"); *state = TPM_DA_STATE_INACTIVE; /* default value */ /* if there is an attack in progress */ if (tpm_state->tpm_stclear_data.authFailCount > TPM_LOCKOUT_THRESHOLD) { printf(" TPM_Authdata_GetState: In timeout, authFailCount %u threshold %u\n", tpm_state->tpm_stclear_data.authFailCount, TPM_LOCKOUT_THRESHOLD); /* get the current time */ if (rc == 0) { /* throw away usec. This means that the time difference could be 1 sec off. But the lockout mechanism is somewhat arbitrary anyway */ rc = TPM_GetTimeOfDay(¤tTime, &tv_usec); } /* calculate how much time to wait */ if (rc == 0) { printf(" TPM_Authdata_GetState: currentTime %u authFailTime %u\n", currentTime, tpm_state->tpm_stclear_data.authFailTime); /* how many failures over the threshold. The -1 makes threshold_diff 0 based, so the first waitTime is 1 sec. */ threshold_diff = tpm_state->tpm_stclear_data.authFailCount - TPM_LOCKOUT_THRESHOLD - 1; /* Wait time depends on how far over threshold, wait 1 sec and double each time. Ignore shift overflow, since the previous timeout 0x80000000 sec is 68 years. */ waitTime = 0x01 << threshold_diff; /* how far along is timeout. */ if (currentTime >= tpm_state->tpm_stclear_data.authFailTime) { timeDiff = currentTime - tpm_state->tpm_stclear_data.authFailTime; } /* handle unlikely currentTime wrap around */ else { timeDiff = ((0xffffffff - tpm_state->tpm_stclear_data.authFailTime) + currentTime) + 1; } /* if not past the timeout, return an error */ printf(" TPM_Authdata_GetState: waitTime %u timeDiff %u\n", waitTime, timeDiff); if (waitTime > timeDiff) { printf("TPM_Authdata_GetState: Error, timeout not complete\n"); *state = TPM_DA_STATE_ACTIVE; *timeLeft = waitTime - timeDiff; } } } return rc; } /* TPM_Authdata_CheckState() checks the dictionary attack mitigation state. This function is typically called at the beginning of each command. If an attack is in progress, and the lockout timeout has not expired, an error is returned. */ TPM_RESULT TPM_Authdata_CheckState(tpm_state_t *tpm_state) { TPM_RESULT rc = 0; TPM_DA_STATE state; uint32_t timeLeft; printf(" TPM_Authdata_CheckState:\n"); /* Get the dictionary attack mitigation state */ if (rc == 0) { rc = TPM_Authdata_GetState(&state, &timeLeft, tpm_state); } /* If not during the timeout period, allow the TPM_ResetLockValue ordinal */ if (rc == 0) { if (state == TPM_DA_STATE_INACTIVE) { tpm_state->tpm_stclear_data.disableResetLock = FALSE; } else { /* TPM_DA_STATE_ACTIVE */ rc = TPM_DEFEND_LOCK_RUNNING; } } return rc; } /* TPM_CHANGEAUTH_VALIDATE */ /* TPM_ChangeauthValidate_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_ChangeauthValidate_Init(TPM_CHANGEAUTH_VALIDATE *tpm_changeauth_validate) { printf(" TPM_ChangeauthValidate_Init:\n"); TPM_Secret_Init(tpm_changeauth_validate->newAuthSecret); TPM_Nonce_Init(tpm_changeauth_validate->n1); return; } /* TPM_ChangeauthValidate_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_ChangeauthValidate_Init() After use, call TPM_ChangeauthValidate_Delete() to free memory */ TPM_RESULT TPM_ChangeauthValidate_Load(TPM_CHANGEAUTH_VALIDATE *tpm_changeauth_validate, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_ChangeauthValidate_Load:\n"); /* load newAuthSecret */ if (rc == 0) { rc = TPM_Secret_Load(tpm_changeauth_validate->newAuthSecret, stream, stream_size); } /* load n1 */ if (rc == 0) { rc = TPM_Nonce_Load(tpm_changeauth_validate->n1, stream, stream_size); } return rc; } #if 0 /* TPM_ChangeauthValidate_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_ChangeauthValidate_Store(TPM_STORE_BUFFER *sbuffer, const TPM_CHANGEAUTH_VALIDATE *tpm_changeauth_validate) { TPM_RESULT rc = 0; printf(" TPM_ChangeauthValidate_Store:\n"); /* store newAuthSecret */ if (rc == 0) { rc = TPM_Secret_Store(sbuffer, tpm_changeauth_validate->newAuthSecret); } /* store n1 */ if (rc == 0) { rc = TPM_Secret_Store(sbuffer, tpm_changeauth_validate->n1); } return rc; } #endif /* TPM_ChangeauthValidate_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_ChangeauthValidate_Init to set members back to default values The object itself is not freed */ void TPM_ChangeauthValidate_Delete(TPM_CHANGEAUTH_VALIDATE *tpm_changeauth_validate) { printf(" TPM_ChangeauthValidate_Delete:\n"); if (tpm_changeauth_validate != NULL) { TPM_ChangeauthValidate_Init(tpm_changeauth_validate); } return; } /* TPM_DA_INFO */ /* TPM_DaInfo_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_DaInfo_Init(TPM_DA_INFO *tpm_da_info) { printf(" TPM_DaInfo_Init:\n"); /* tpm_da_info->tag = TPM_TAG_DA_INFO; */ tpm_da_info->state = TPM_DA_STATE_INACTIVE; tpm_da_info->currentCount = 0; tpm_da_info->thresholdCount = TPM_LOCKOUT_THRESHOLD; /* TPM_DA_ACTION_TYPE is a trivial structure, in-line here */ tpm_da_info->actionAtThreshold.tag = TPM_TAG_DA_ACTION_TYPE; tpm_da_info->actionAtThreshold.actions = TPM_DA_ACTION_TIMEOUT; tpm_da_info->actionDependValue = 0; TPM_SizedBuffer_Init(&tpm_da_info->vendorData); return; } /* TPM_DaInfo_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_DaInfo_Store(TPM_STORE_BUFFER *sbuffer, const TPM_DA_INFO *tpm_da_info) { TPM_RESULT rc = 0; printf(" TPM_DaInfo_Store:\n"); /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_DA_INFO); } /* store state */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_da_info->state), sizeof(TPM_DA_STATE)); } /* store currentCount */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, tpm_da_info->currentCount); } /* store thresholdCount */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, tpm_da_info->thresholdCount); } /* store actionAtThreshold */ /* TPM_DA_ACTION_TYPE is a trivial structure, in-line here */ /* store TPM_DA_ACTION_TYPE tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_DA_ACTION_TYPE); } /* store TPM_DA_ACTION_TYPE actions */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_da_info->actionAtThreshold.actions); } /* store actionDependValue */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_da_info->actionDependValue); } /* store vendorData */ if (rc == 0) { rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_da_info->vendorData)); } return rc; } /* TPM_DaInfo_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_DaInfo_Init to set members back to default values The object itself is not freed */ void TPM_DaInfo_Delete(TPM_DA_INFO *tpm_da_info) { printf(" TPM_DaInfo_Delete:\n"); if (tpm_da_info != NULL) { TPM_SizedBuffer_Delete(&(tpm_da_info->vendorData)); TPM_DaInfo_Init(tpm_da_info); } return; } /* TPM_DaInfoLimited_Set() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_DaInfo_Set(TPM_DA_INFO *tpm_da_info, tpm_state_t *tpm_state) { TPM_RESULT rc = 0; printf(" TPM_DaInfo_Set:\n"); /* state: Dynamic. The actual state of the dictionary attack mitigation logic. */ /* actionDependValue: Dynamic. Action being taken when the dictionary attack mitigation logic is active. E.g., when actionAtThreshold is TPM_DA_ACTION_TIMEOUT, this is the lockout time remaining in seconds. */ if (rc == 0) { rc = TPM_Authdata_GetState(&(tpm_da_info->state), &(tpm_da_info->actionDependValue), tpm_state); } /* Dynamic. The actual count of the authorization failure counter for the selected entity type */ if (rc == 0) { if (tpm_state->tpm_stclear_data.authFailCount <= 0xffff) { tpm_da_info->currentCount = tpm_state->tpm_stclear_data.authFailCount; } /* with the doubling, this should never overflow. So overflow indicates a serious error */ else { printf("TPM_DaInfo_Set: Error (fatal), authFailCount overflow %08x\n", tpm_state->tpm_stclear_data.authFailCount); rc = TPM_FAIL; } } return rc; } /* TPM_DA_INFO_LIMITED */ /* TPM_DaInfoLimited_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_DaInfoLimited_Init(TPM_DA_INFO_LIMITED *tpm_da_info_limited) { printf(" TPM_DaInfoLimited_Init:\n"); /* tpm_da_info_limited->tag = TPM_TAG_DA_INFO_LIMITED; */ tpm_da_info_limited->state = TPM_DA_STATE_INACTIVE; /* TPM_DA_ACTION_TYPE is a trivial structure, in-line here */ tpm_da_info_limited->actionAtThreshold.tag = TPM_TAG_DA_ACTION_TYPE; tpm_da_info_limited->actionAtThreshold.actions = TPM_DA_ACTION_TIMEOUT; TPM_SizedBuffer_Init(&tpm_da_info_limited->vendorData); return; } /* TPM_DaInfoLimited_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_DaInfoLimited_Store(TPM_STORE_BUFFER *sbuffer, const TPM_DA_INFO_LIMITED *tpm_da_info_limited) { TPM_RESULT rc = 0; printf(" TPM_DaInfoLimited_Store:\n"); /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_DA_INFO_LIMITED); } /* store state */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_da_info_limited->state), sizeof (TPM_DA_STATE)); } /* store actionAtThreshold */ /* TPM_DA_ACTION_TYPE is a trivial structure, in-line here */ /* store TPM_DA_ACTION_TYPE tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_DA_ACTION_TYPE); } /* store TPM_DA_ACTION_TYPE actions */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_da_info_limited->actionAtThreshold.actions); } /* store vendorData */ if (rc == 0) { rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_da_info_limited->vendorData)); } return rc; } /* TPM_DaInfoLimited_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_DaInfoLimited_Init to set members back to default values The object itself is not freed */ void TPM_DaInfoLimited_Delete(TPM_DA_INFO_LIMITED *tpm_da_info_limited) { printf(" TPM_DaInfoLimited_Delete:\n"); if (tpm_da_info_limited != NULL) { TPM_SizedBuffer_Delete(&(tpm_da_info_limited->vendorData)); TPM_DaInfoLimited_Init(tpm_da_info_limited); } return; } /* TPM_DaInfoLimited_Set() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_DaInfoLimited_Set(TPM_DA_INFO_LIMITED *tpm_da_info_limited, tpm_state_t *tpm_state) { TPM_RESULT rc = 0; uint32_t timeLeft; printf(" TPM_DaInfoLimited_Set:\n"); /* Dynamic. The actual state of the dictionary attack mitigation logic. */ if (rc == 0) { rc = TPM_Authdata_GetState(&(tpm_da_info_limited->state), &timeLeft, tpm_state); } return rc; } /* Processing Functions */ /* 17.1 TPM_ChangeAuth rev 107 The TPM_ChangeAuth command allows the owner of an entity to change the authorization data for the entity. This command cannot invalidate the old entity. Therefore, the authorization change is only effective if the application can guarantee that the old entity can be securely destroyed. If not, two valid entities will exist, one with the old and one with the new authorization secret. If this command is delegated, the delegated party can expand its key use privileges. That party can create a copy of the key with known authorization, and it can then use the key without any ordinal restrictions. TPM_ChangeAuth requires the encryption of one parameter ("NewAuth"). For the sake of uniformity with other commands that require the encryption of more than one parameter, the string used for XOR encryption is generated by concatenating the evenNonce (created during the OSAP session) with the session shared secret and then hashing the result. The parameter list to this command must always include two authorization sessions, regardless of the state of authDataUsage for the respective keys. */ TPM_RESULT TPM_Process_ChangeAuth(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_KEY_HANDLE parentHandle; /* Handle of the parent key to the entity. */ TPM_PROTOCOL_ID protocolID = 0; /* The protocol in use. */ TPM_ENCAUTH newAuth; /* The encrypted new authorization data for the entity */ TPM_ENTITY_TYPE entityType = 0; /* The type of entity to be modified */ TPM_SIZED_BUFFER encData; /* The encrypted entity that is to be modified. */ TPM_AUTHHANDLE parentAuthHandle; /* The authorization handle used for the parent key. */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with parentAuthHandle */ TPM_BOOL continueAuthSession; /* Ignored, parentAuthHandle is always terminated. */ TPM_AUTHDATA parentAuth; /* The authorization digest for inputs and parentHandle. HMAC key: parentKey.usageAuth. */ TPM_AUTHHANDLE entityAuthHandle; /* The authorization handle used for the encrypted entity. The session type MUST be OIAP */ TPM_NONCE entitynonceOdd; /* Nonce generated by system associated with entityAuthHandle */ TPM_BOOL continueEntitySession; /* Ignored, entityAuthHandle is always terminated. */ TPM_AUTHDATA entityAuth; /* The authorization digest for the inputs and encrypted entity. HMAC key: entity.usageAuth. */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL parentAuthHandleValid = FALSE; TPM_BOOL entityAuthHandleValid = FALSE; TPM_AUTH_SESSION_DATA *parent_auth_session_data = NULL; /* session data for parentAuthHandle */ TPM_AUTH_SESSION_DATA *entity_auth_session_data = NULL; /* session data for entityAuthHandle */ TPM_KEY *parentKey = NULL; TPM_SECRET *parentHmacKey; TPM_SECRET *entityHmacKey; TPM_SECRET saveKey; /* copy of entity HMAC key for response */ TPM_BOOL parentPCRStatus; TPM_AUTHDATA decryptAuth; unsigned char *b1DecryptData; uint32_t b1DecryptDataLength = 0; /* actual valid data */ unsigned char *stream; /* for deserializing decrypted encData */ uint32_t stream_size; TPM_STORE_ASYMKEY keyEntity; /* entity structure when it's a TPM_ET_KEY */ TPM_SEALED_DATA sealEntity; /* entity structure when it's a TPM_ET_DATA */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_SIZED_BUFFER outData; /* The modified, encrypted entity. */ printf("TPM_Process_ChangeAuth: Ordinal Entry\n"); TPM_SizedBuffer_Init(&encData); /* freed @1 */ TPM_SizedBuffer_Init(&outData); /* freed @2 */ b1DecryptData = NULL; /* freed @3 */ TPM_StoreAsymkey_Init(&keyEntity); /* freed @4 */ TPM_SealedData_Init(&sealEntity); /* freed @5 */ /* get inputs */ /* get parentHandle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&parentHandle, &command, ¶mSize); } /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get protocolID parameter */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_ChangeAuth: parentHandle %08x\n", parentHandle); returnCode = TPM_Load16(&protocolID, &command, ¶mSize); } /* get newAuth parameter */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_ChangeAuth: protocolID %04hx\n", protocolID); returnCode = TPM_Authdata_Load(newAuth, &command, ¶mSize); } /* get entityType parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load16(&entityType, &command, ¶mSize); } /* get encData parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_Load(&encData, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_ChangeAuth: encDataSize %u\n", encData.size); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag2(tag); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Get(&parentAuthHandle, &parentAuthHandleValid, nonceOdd, &continueAuthSession, parentAuth, &command, ¶mSize); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_ChangeAuth: parentAuthHandle %08x\n", parentAuthHandle); returnCode = TPM_AuthParams_Get(&entityAuthHandle, &entityAuthHandleValid, entitynonceOdd, &continueEntitySession, entityAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_ChangeAuth: entityAuthHandle %08x\n", entityAuthHandle); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_ChangeAuth: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { parentAuthHandleValid = FALSE; entityAuthHandleValid = FALSE; } /* Processing */ /* Description 1. The parentAuthHandle session type MUST be TPM_PID_OSAP. 2. In this capability, the SRK cannot be accessed as entityType TPM_ET_KEY, since the SRK is not wrapped by a parent key. */ /* 1. Verify that entityType is one of TPM_ET_DATA, TPM_ET_KEY and return the error TPM_WRONG_ENTITYTYPE if not. */ if (returnCode == TPM_SUCCESS) { if ((entityType != TPM_ET_DATA) && (entityType != TPM_ET_KEY)) { printf("TPM_Process_ChangeAuth: Error, bad entityType %04x\n", entityType); returnCode = TPM_WRONG_ENTITYTYPE; } } /* 2. Verify that parentAuthHandle session type is TPM_PID_OSAP return TPM_BAD_MODE on error */ /* get the key corresponding to the keyHandle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyHandleEntries_GetKey(&parentKey, &parentPCRStatus, tpm_state, parentHandle, FALSE, /* not r/o, using to authenticate */ FALSE, /* do not ignore PCRs */ FALSE); /* cannot use EK */ } /* get the OSAP session data */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetData(&parent_auth_session_data, &parentHmacKey, tpm_state, parentAuthHandle, TPM_PID_OSAP, TPM_ET_KEYHANDLE, ordinal, parentKey, NULL, /* OIAP */ parentKey->tpm_store_asymkey->pubDataDigest); /*OSAP*/ } /* 3. Verify that entityAuthHandle session type is TPM_PID_OIAP return TPM_BAD_MODE on error */ /* keyEntity and sealEntity are not valid yet, so pass in NULL and ignore the returned entityHmacKey */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetData(&entity_auth_session_data, &entityHmacKey, tpm_state, entityAuthHandle, TPM_PID_OIAP, 0, /* OSAP entity type */ ordinal, NULL, NULL, NULL); } /* 4.If protocolID is not TPM_PID_ADCP, the TPM MUST return TPM_BAD_PARAMETER. */ if (returnCode == TPM_SUCCESS) { if (protocolID != TPM_PID_ADCP) { printf("TPM_Process_ChangeAuth: Error, bad protocolID\n"); returnCode = TPM_BAD_PARAMETER; } } /* 5. The encData field MUST be the encData field from either the TPM_STORED_DATA or TPM_KEY structures. */ /* NOTE Seems the same as Action 1. */ /* 6. Create decryptAuth by decrypting newAuth according to the ADIP indicated by parentHandle. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessionData_Decrypt(decryptAuth, NULL, newAuth, parent_auth_session_data, NULL, NULL, FALSE); /* odd and even */ } /* 7. The TPM MUST validate the command using the authorization data in the parentAuth parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Authdata_Check(tpm_state, *parentHmacKey, /* HMAC key */ inParamDigest, parent_auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, parentAuth); /* Authorization digest for input */ } /* 8. Validate that parentHandle -> keyUsage is TPM_KEY_STORAGE, if not return TPM_INVALID_KEYUSAGE */ if (returnCode == TPM_SUCCESS) { if (parentKey->keyUsage != TPM_KEY_STORAGE) { printf("TPM_Process_ChangeAuth: Error, keyUsage %04hx is invalid\n", parentKey->keyUsage); returnCode = TPM_INVALID_KEYUSAGE; } } /* 9. After parameter validation the TPM creates b1 by decrypting encData using the key pointed to by parentHandle. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_RSAPrivateDecryptMalloc(&b1DecryptData, /* decrypted data */ &b1DecryptDataLength, /* actual size of decrypted data */ encData.buffer,/* encrypted data */ encData.size, /* encrypted data size */ parentKey); } if ((returnCode == TPM_SUCCESS) && (entityType == TPM_ET_KEY)) { printf("TPM_Process_ChangeAuth: entityType is TPM_ET_KEY\n"); /* 10. The TPM MUST validate that b1 is a valid TPM structure, either a TPM_STORE_ASYMKEY or a TPM_SEALED_DATA */ if (returnCode == TPM_SUCCESS) { stream = b1DecryptData; stream_size = b1DecryptDataLength; returnCode = TPM_StoreAsymkey_Load(&keyEntity, FALSE, &stream, &stream_size, NULL, /* TPM_KEY_PARMS */ NULL); /* TPM_SIZED_BUFFER pubKey */ } /* a. Check the length and payload, return TPM_INVALID_STRUCTURE on any mismatch. */ /* NOTE: Done by TPM_StoreAsymkey_Load() */ if (returnCode == TPM_SUCCESS) { /* save a copy of the HMAC key for the response before changing */ TPM_Secret_Copy(saveKey, keyEntity.usageAuth); /* a.The TPM must validate the command using the authorization data entityAuth parameter. The HMAC key is TPM_STORE_ASYMKEY -> usageAuth or TPM_SEALED_DATA -> authData. */ returnCode = TPM_Auth2data_Check(tpm_state, keyEntity.usageAuth, /* HMAC key */ inParamDigest, entity_auth_session_data, /* authorization session */ entitynonceOdd, /* Nonce generated by system associated with authHandle */ continueEntitySession, entityAuth); /* Authorization digest for input */ } /* 11. The TPM replaces the authorization data for b1 with decryptAuth created above. */ if (returnCode == TPM_SUCCESS) { TPM_PrintFour("TPM_Process_ChangeAuth: usageAuth was", keyEntity.usageAuth); TPM_PrintFour("TPM_Process_ChangeAuth: usageAuth now", decryptAuth); TPM_Secret_Copy(keyEntity.usageAuth, decryptAuth); } /* 12. The TPM encrypts b1 using the appropriate mechanism for the type using the parentKeyHandle to provide the key information. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_StoreAsymkey_GenerateEncData(&outData, &keyEntity, parentKey); } } else if ((returnCode == TPM_SUCCESS) && (entityType == TPM_ET_DATA)) { printf("TPM_Process_ChangeAuth: entityType is TPM_ET_DATA\n"); /* 10. The TPM MUST validate that b1 is a valid TPM structure, either a TPM_STORE_ASYMKEY or a TPM_SEALED_DATA */ if (returnCode == TPM_SUCCESS) { stream = b1DecryptData; stream_size = b1DecryptDataLength; returnCode = TPM_SealedData_Load(&sealEntity, &stream, &stream_size); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_ChangeAuth: Checking tpmProof\n"); returnCode = TPM_Secret_Compare(sealEntity.tpmProof, tpm_state->tpm_permanent_data.tpmProof); } /* a. Check the length and payload, return TPM_INVALID_STRUCTURE on any mismatch. */ /* NOTE: Done by TPM_SealedData_Load() */ if (returnCode == TPM_SUCCESS) { /* save a copy of the HMAC key for the response before changing */ TPM_Secret_Copy(saveKey, sealEntity.authData); /* a.The TPM must validate the command using the authorization data entityAuth parameter. The HMAC key is TPM_STORE_ASYMKEY -> usageAuth or TPM_SEALED_DATA -> authData. */ returnCode = TPM_Auth2data_Check(tpm_state, sealEntity.authData, /* HMAC key */ inParamDigest, entity_auth_session_data, /* authorization session */ entitynonceOdd, /* Nonce generated by system associated with authHandle */ continueEntitySession, entityAuth); /* Authorization digest for input */ } /* 11. The TPM replaces the authorization data for b1 with decryptAuth created above. */ if (returnCode == TPM_SUCCESS) { TPM_PrintFour("TPM_Process_ChangeAuth: authData was", sealEntity.authData); TPM_PrintFour("TPM_Process_ChangeAuth: authData now", decryptAuth); TPM_Secret_Copy(sealEntity.authData, decryptAuth); } /* 12. The TPM encrypts b1 using the appropriate mechanism for the type using the parentKeyHandle to provide the key information. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SealedData_GenerateEncData(&outData, &sealEntity, parentKey); } } /* 13. The TPM MUST enforce the destruction of both the parentAuthHandle and entityAuthHandle sessions. */ if (returnCode == TPM_SUCCESS) { continueAuthSession = FALSE; continueEntitySession = FALSE; } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_ChangeAuth: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* 14. The new blob is returned in outData when appropriate. */ returnCode = TPM_SizedBuffer_Store(response, &outData); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Set(response, *parentHmacKey, /* HMAC key */ parent_auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Set(response, saveKey, /* the original and not the new auth value */ entity_auth_session_data, outParamDigest, entitynonceOdd, continueEntitySession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* 15. The TPM MUST enforce the destruction of both the parentAuthHandle and entityAuthHandle sessions. */ if (parentAuthHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, parentAuthHandle); } if (entityAuthHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, entityAuthHandle); } /* cleanup */ TPM_SizedBuffer_Delete(&encData); /* @1 */ TPM_SizedBuffer_Delete(&outData); /* @2 */ free(b1DecryptData); /* @3 */ TPM_StoreAsymkey_Delete(&keyEntity); /* @4 */ TPM_SealedData_Delete(&sealEntity); /* @5 */ return rcf; } /* 17.2 TPM_ChangeAuthOwner rev 98 The TPM_ChangeAuthOwner command allows the owner of an entity to change the authorization data for the TPM Owner or the SRK. This command requires authorization from the current TPM Owner to execute. TPM's targeted for an environment (e.g. a server) with long lasting sessions should not invalidate all sessions. */ TPM_RESULT TPM_Process_ChangeAuthOwner(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_PROTOCOL_ID protocolID; /* The protocol in use. */ TPM_ENCAUTH newAuth; /* The encrypted new authorization data for the entity */ TPM_ENTITY_TYPE entityType = 0; /* The type of entity to be modified */ TPM_AUTHHANDLE ownerAuthHandle; /* The authorization handle used for the TPM Owner. */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with ownerAuthHandle */ TPM_BOOL continueAuthSession = TRUE; /* Continue use flag the TPM ignores this value */ TPM_AUTHDATA ownerAuth; /* The authorization digest for inputs and ownerHandle. HMAC key: tpmOwnerAuth. */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL ownerAuthHandleValid = FALSE; TPM_AUTH_SESSION_DATA *owner_auth_session_data = NULL; /* session data for ownerAuthHandle */ TPM_SECRET *hmacKey; TPM_SECRET saveKey; /* copy of HMAC key, since sessions invalidated */ TPM_AUTHDATA decryptAuth; TPM_AUTHDATA *entityAuth; /* pointer to either owner or SRK auth */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_ChangeAuthOwner: Ordinal Entry\n"); /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get protocolID parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load16(&protocolID, &command, ¶mSize); } /* get newAuth parameter */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_ChangeAuthOwner: protocolID %04hx\n", protocolID); returnCode = TPM_Authdata_Load(newAuth, &command, ¶mSize); } /* get entityType parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load16(&entityType, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag1(tag); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Get(&ownerAuthHandle, &ownerAuthHandleValid, nonceOdd, &continueAuthSession, ownerAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_ChangeAuthOwner: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { ownerAuthHandleValid = FALSE; } /* Processing */ /* 1. The TPM MUST validate the command using the AuthData in the ownerAuth parameter */ /* 2. The ownerAuthHandle session type MUST be TPM_PID_OSAP */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetData(&owner_auth_session_data, &hmacKey, tpm_state, ownerAuthHandle, TPM_PID_OSAP, TPM_ET_OWNER, ordinal, NULL, NULL, tpm_state->tpm_permanent_data.ownerAuth); } if (returnCode == TPM_SUCCESS) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* HMAC key */ inParamDigest, owner_auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, ownerAuth); /* Authorization digest for input */ } /* 3. If protocolID is not TPM_PID_ADCP, the TPM MUST return TPM_BAD_PARAMETER. */ if (returnCode == TPM_SUCCESS) { if (protocolID != TPM_PID_ADCP) { printf("TPM_Process_ChangeAuthOwner: Error, bad protocolID\n"); returnCode = TPM_BAD_PARAMETER; } } /* 4. Verify that entityType is either TPM_ET_OWNER or TPM_ET_SRK, and return the error TPM_WRONG_ENTITYTYPE if not. */ if (returnCode == TPM_SUCCESS) { if (entityType == TPM_ET_OWNER) { printf("TPM_Process_ChangeAuthOwner: entityType TPM_ET_OWNER\n"); entityAuth = &(tpm_state->tpm_permanent_data.ownerAuth); } else if (entityType == TPM_ET_SRK) { printf("TPM_Process_ChangeAuthOwner: entityType TPM_ET_SRK\n"); entityAuth = &(tpm_state->tpm_permanent_data.srk.tpm_store_asymkey->usageAuth); } else { entityAuth = NULL; /* just to quiet the compiler */ printf("TPM_Process_ChangeAuthOwner: Error, wrong entityType %04x\n", entityType); returnCode = TPM_WRONG_ENTITYTYPE; } } /* 5. Create decryptAuth by decrypting newAuth according to the ADIP indicated by ownerAuthHandle. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessionData_Decrypt(decryptAuth, NULL, newAuth, owner_auth_session_data, NULL, NULL, FALSE); /* even and odd */ } if (returnCode == TPM_SUCCESS) { TPM_PrintFour("TPM_Process_ChangeAuthOwner: From entityAuth", *entityAuth); TPM_PrintFour("TPM_Process_ChangeAuthOwner: To decryptAuth", decryptAuth); /* 6. The TPM MUST enforce the destruction of the ownerAuthHandle session upon completion of this command (successful or unsuccessful). This includes setting continueAuthSession to FALSE */ continueAuthSession = FALSE; /* 7. Set the authorization data for the indicated entity to decryptAuth */ TPM_Secret_Copy(*entityAuth, decryptAuth); /* save a copy of the HMAC key for the response before invalidating */ TPM_Secret_Copy(saveKey, *hmacKey); /* 8. The TPM MUST invalidate all owner authorized OSAP and DSAP sessions, active or saved. */ TPM_AuthSessions_TerminateEntity(&continueAuthSession, ownerAuthHandle, tpm_state->tpm_stclear_data.authSessions, TPM_ET_OWNER, /* TPM_ENTITY_TYPE */ NULL); /* ignore entityDigest */ /* 9. The TPM MAY invalidate all sessions, active or saved */ /* Store the permanent data back to NVRAM */ returnCode = TPM_PermanentAll_NVStore(tpm_state, TRUE, returnCode); } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_ChangeAuthOwner: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Set(response, saveKey, /* HMAC key */ owner_auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && ownerAuthHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, ownerAuthHandle); } /* cleanup */ return rcf; } /* 27.4.1 TPM_ChangeAuthAsymStart rev 87 The TPM_ChangeAuthAsymStart starts the process of changing AuthData for an entity. It sets up an OIAP session that must be retained for use by its twin TPM_ChangeAuthAsymFinish command. TPM_ChangeAuthAsymStart creates a temporary asymmetric public key "tempkey" to provide confidentiality for new AuthData to be sent to the TPM. TPM_ChangeAuthAsymStart certifies that tempkey was generated by a genuine TPM, by generating a certifyInfo structure that is signed by a TPM identity. The owner of that TPM identity must cooperate to produce this command, because TPM_ChangeAuthAsymStart requires authorization to use that identity. It is envisaged that tempkey and certifyInfo are given to the owner of the entity whose authorization is to be changed. That owner uses certifyInfo and a TPM_IDENTITY_CREDENTIAL to verify that tempkey was generated by a genuine TPM. This is done by verifying the TPM_IDENTITY_CREDENTIAL using the public key of a CA, verifying the signature on the certifyInfo structure with the public key of the identity in TPM_IDENTITY_CREDENTIAL, and verifying tempkey by comparing its digest with the value inside certifyInfo. The owner uses tempkey to encrypt the desired new AuthData and inserts that encrypted data in a TPM_ChangeAuthAsymFinish command, in the knowledge that only a TPM with a specific identity can interpret the new AuthData. */ TPM_RESULT TPM_Process_ChangeAuthAsymStart(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_KEY_HANDLE idHandle; /* The keyHandle identifier of a loaded identity ID key */ TPM_NONCE antiReplay; /* The nonce to be inserted into the certifyInfo structure */ TPM_KEY_PARMS tempKeyParms; /* Structure contains all parameters of ephemeral key. */ TPM_AUTHHANDLE authHandle; /* The authorization session handle used for idHandle authorization. */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession; /* The continue use flag for the authorization session handle */ TPM_AUTHDATA idAuth; /* Authorization. HMAC key: idKey.usageAuth. */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ TPM_SECRET *hmacKey; TPM_KEY *idKey = NULL; TPM_SECRET *idKeyUsageAuth; TPM_BOOL idPCRStatus; TPM_RSA_KEY_PARMS *temp_rsa_key_parms; /* tempKey is RSA */ TPM_BOOL key_added = FALSE; /* added to key handle entries */ TPM_DIGEST h1Digest; /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_CERTIFY_INFO certifyInfo; /* The certifyInfo structure that is to be signed. */ TPM_SIZED_BUFFER sig; /* The signature of the certifyInfo parameter. */ TPM_KEY_HANDLE ephHandle; /* The keyHandle identifier to be used by ChangeAuthAsymFinish for the ephemeral key */ TPM_KEY *tempKey; /* Structure containing all parameters and public part of ephemeral key. TPM_KEY.encSize is set to 0. NOTE Actually tempKey and k1 are the same. The encData is present but not returned in the response. */ printf("TPM_Process_ChangeAuthAsymStart: Ordinal Entry\n"); TPM_KeyParms_Init(&tempKeyParms); /* freed @1 */ TPM_CertifyInfo_Init(&certifyInfo); /* freed @2 */ TPM_SizedBuffer_Init(&sig); /* freed @3 */ tempKey = NULL; /* freed @4 */ /* get inputs */ /* get idHandle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&idHandle, &command, ¶mSize); } /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; if (returnCode == TPM_SUCCESS) { printf("TPM_Process_ChangeAuthAsymStart: idHandle %08x\n", idHandle); /* get antiReplay parameter */ returnCode = TPM_Nonce_Load(antiReplay, &command, ¶mSize); } /* get tempKey (actually tempKeyParms) parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyParms_Load(&tempKeyParms, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag10(tag); } /* get the optional 'below the line' authorization parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, idAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_ChangeAuthAsymStart: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* 1. The TPM SHALL verify the AuthData to use the TPM identity key held in idHandle. The TPM MUST verify that the key is a TPM identity key.*/ if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyHandleEntries_GetKey(&idKey, &idPCRStatus, tpm_state, idHandle, FALSE, /* not read-only */ FALSE, /* do not ignore PCRs */ FALSE); /* cannot use EK */ } if (returnCode == TPM_SUCCESS) { if (idKey->keyUsage != TPM_KEY_IDENTITY) { printf("TPM_Process_ChangeAuthAsymStart: Error, keyUsage %04hx is invalid\n", idKey->keyUsage); returnCode = TPM_INVALID_KEYUSAGE; } } if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)){ if (idKey->authDataUsage != TPM_AUTH_NEVER) { printf("TPM_Process_ChangeAuthAsymStart: Error, authorization required\n"); returnCode = TPM_AUTHFAIL; } } /* get idHandle -> usageAuth */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_Key_GetUsageAuth(&idKeyUsageAuth, idKey); } /* get the session data */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_KEYHANDLE, ordinal, idKey, idKeyUsageAuth, /* OIAP */ idKey->tpm_store_asymkey->pubDataDigest); /* OSAP */ } if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, idAuth); /* Authorization digest for input */ } /* 2. The TPM SHALL validate the algorithm parameters for the key to create from the tempKey parameter. */ if (returnCode == TPM_SUCCESS) { /* get the TPM_RSA_KEY_PARMS structure from the TPM_KEY_PARMS structure */ /* 3. Recommended key type is RSA */ returnCode = TPM_KeyParms_GetRSAKeyParms(&temp_rsa_key_parms, &tempKeyParms); } /* 4. Minimum RSA key size MUST is 512 bits, recommended RSA key size is 1024 */ /* 5. For other key types the minimum key size strength MUST be comparable to RSA 512 */ /* 6. If the TPM is not designed to create a key of the requested type, return the error code TPM_BAD_KEY_PROPERTY */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyParms_CheckProperties(&tempKeyParms, TPM_KEY_AUTHCHANGE, 0, /* required key length in bits */ tpm_state->tpm_permanent_flags.FIPS); } /* 7. The TPM SHALL create a new key (k1) in accordance with the algorithm parameter. The newly created key is pointed to by ephHandle. */ /* NOTE tempKey is used as k1 */ /* Allocate space for k1. The key cannot be a local variable, since it persists in key storage after the command completes. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Malloc((unsigned char **)&tempKey, sizeof(TPM_KEY)); } /* Field Descriptions for certifyInfo parameter Type Name Description TPM_VERSION Version TPM version structure; Part 2 TPM_VERSION keyFlags Redirection This SHALL be set to FALSE Migratable This SHALL be set to FALSE Volatile This SHALL be set to TRUE TPM_AUTH_DATA_USAGE authDataUsage This SHALL be set to TPM_AUTH_NEVER TPM_KEY_USAGE KeyUsage This SHALL be set to TPM_KEY_AUTHCHANGE uint32_t PCRInfoSize This SHALL be set to 0 TPM_DIGEST pubDigest This SHALL be the hash of the public key being certified. TPM_NONCE Data This SHALL be set to antiReplay TPM_KEY_PARMS info This specifies the type of key and its parameters. TPM_BOOL parentPCRStatus This SHALL be set to FALSE. */ /* generate a TPM_KEY using TPM_KEY_PARMS. encData is stored as clear text since there is no parent key for the ephemeral key */ if (returnCode == TPM_SUCCESS) { /* This must immediately follow the successful malloc, so the _Delete / free work */ TPM_Key_Init(tempKey); printf(" TPM_Process_ChangeAuthAsymStart: Creating ephemeral key\n"); returnCode = TPM_Key_GenerateRSA(tempKey, tpm_state, NULL, /* encData cleartext */ tpm_state->tpm_stclear_data.PCRS, /* PCR array */ 1, /* TPM_KEY */ TPM_KEY_AUTHCHANGE, /* keyUsage */ TPM_ISVOLATILE, /* keyFlags */ TPM_AUTH_NEVER, /* authDataUsage */ &tempKeyParms, /* TPM_KEY_PARMS */ NULL, /* TPM_PCR_INFO */ NULL); /* TPM_PCR_INFO_LONG */ } if (returnCode == TPM_SUCCESS) { ephHandle = 0; /* no preferred value */ returnCode = TPM_KeyHandleEntries_AddKeyEntry(&ephHandle, /* output */ tpm_state->tpm_key_handle_entries, /* input */ tempKey, /* input */ 0, /* parentPCRStatus not used */ 0); /* keyControl not used */ } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_ChangeAuthAsymStart: Ephemeral key handle %08x\n", ephHandle); /* remember that the handle has been added to handle list, so it can be deleted on error */ key_added = TRUE; } /* 8. The TPM SHALL fill in all fields in tempKey using k1 for the information. The TPM_KEY -> encSize MUST be 0. */ /* NOTE Not required. k1 and tempKey are the same */ /* 9. The TPM SHALL fill in certifyInfo using k1 for the information. The certifyInfo -> data field is supplied by the antiReplay. */ if (returnCode == TPM_SUCCESS) { printf(" TPM_Process_ChangeAuthAsymStart: Creating certifyInfo\n"); TPM_Nonce_Copy(certifyInfo.data, antiReplay); returnCode = TPM_CertifyInfo_Set(&certifyInfo, tempKey); } /* 10. The TPM then signs the certifyInfo parameter using the key pointed to by idHandle. The resulting signed blob is returned in sig parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SHA1_GenerateStructure(h1Digest, &certifyInfo, (TPM_STORE_FUNCTION_T)TPM_CertifyInfo_Store); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_ChangeAuthAsymStart: Signing certifyInfo digest\n"); returnCode = TPM_RSASignToSizedBuffer(&sig, /* signature */ h1Digest, /* message */ TPM_DIGEST_SIZE, /* message size */ idKey); /* input, signing key */ } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_ChangeAuthAsymStart: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* return certifyInfo */ returnCode = TPM_CertifyInfo_Store(response, &certifyInfo); } /* return sig */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_Store(response, &sig); } /* return ephHandle */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Sbuffer_Append32(response, ephHandle); } /* return tempKey. TPM_Key_StorePubData() does not store any encData. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Key_StorePubData(response, FALSE, tempKey); } if (returnCode == TPM_SUCCESS) { /* TPM_KEY.encSize is set to 0 */ returnCode = TPM_Sbuffer_Append32(response, 0); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* owner HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ TPM_KeyParms_Delete(&tempKeyParms); /* @1 */ TPM_CertifyInfo_Delete(&certifyInfo); /* @2 */ TPM_SizedBuffer_Delete(&sig); /* @3 */ /* if there was a failure, delete inKey */ if ((rcf != 0) || (returnCode != TPM_SUCCESS)) { TPM_Key_Delete(tempKey); /* @4 */ free(tempKey); /* @4 */ if (key_added) { /* if there was a failure and tempKey was stored in the handle list, free the handle. Ignore errors, since only one error code can be returned. */ TPM_KeyHandleEntries_DeleteHandle(tpm_state->tpm_key_handle_entries, ephHandle); } } return rcf; } /* 27.4.2 TPM_ChangeAuthAsymFinish rev 110 The TPM_ChangeAuthAsymFinish command allows the owner of an entity to change the AuthData for the entity. The command requires the cooperation of the owner of the parent of the entity, since AuthData must be provided to use that parent entity. The command requires knowledge of the existing AuthData information and passes the new AuthData information. The newAuthLink parameter proves knowledge of existing AuthData information and new AuthData information. The new AuthData information "encNewAuth" is encrypted using the "tempKey" variable obtained via TPM_ChangeAuthAsymStart. A parent therefore retains control over a change in the AuthData of a child, but is prevented from knowing the new AuthData for that child. The changeProof parameter provides a proof that the new AuthData value was properly inserted into the entity. The inclusion of a nonce from the TPM provides an entropy source in the case where the AuthData value may be in itself be a low entropy value (hash of a password etc). */ TPM_RESULT TPM_Process_ChangeAuthAsymFinish(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_KEY_HANDLE parentHandle; /* The keyHandle of the parent key for the input data */ TPM_KEY_HANDLE ephHandle; /* The keyHandle identifier for the ephemeral key */ TPM_ENTITY_TYPE entityType = 0; /* The type of entity to be modified */ TPM_HMAC newAuthLink; /* HMAC calculation that links the old and new AuthData values together */ TPM_SIZED_BUFFER encNewAuth; /* New AuthData encrypted with ephemeral key. */ TPM_SIZED_BUFFER encData; /* The encrypted entity that is to be modified. */ TPM_AUTHHANDLE authHandle; /* Authorization for parent key. */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession; /* The continue use flag for the authorization session handle */ TPM_AUTHDATA privAuth; /* The authorization session digest for inputs and parentHandle. HMAC key: parentKey.usageAuth. */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ TPM_SECRET *hmacKey; TPM_KEY *parentKey = NULL; TPM_SECRET *parentKeyUsageAuth; TPM_BOOL parentPCRStatus; TPM_KEY *ephKey = NULL; TPM_BOOL ephPCRStatus; unsigned char *stream; /* for deserializing decrypted encData */ uint32_t stream_size; TPM_STORE_ASYMKEY keyEntity; /* entity structure when it's a TPM_ET_KEY */ unsigned char *e1DecryptData; uint32_t e1DecryptDataLength = 0; /* actual valid data */ unsigned char *a1Auth; uint32_t a1AuthLength = 0; /* actual valid data */ TPM_CHANGEAUTH_VALIDATE changeauthValidate; TPM_BOOL valid; /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_SIZED_BUFFER outData; /* The modified, encrypted entity. */ TPM_NONCE saltNonce; /* A nonce value from the TPM RNG to add entropy to the changeProof value */ TPM_DIGEST changeProof; /* Proof that AuthData has changed. */ printf("TPM_Process_ChangeAuthAsymFinish: Ordinal Entry\n"); TPM_SizedBuffer_Init(&encNewAuth); /* freed @1 */ TPM_SizedBuffer_Init(&encData); /* freed @2 */ TPM_SizedBuffer_Init(&outData); /* freed @3 */ TPM_StoreAsymkey_Init(&keyEntity); /* freed @4 */ e1DecryptData = NULL; /* freed @5 */ a1Auth = NULL; /* freed @6 */ TPM_ChangeauthValidate_Init(&changeauthValidate); /* freed @7 */ /* get inputs */ /* get parentHandle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&parentHandle, &command, ¶mSize); } /* get ephHandle parameter */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_ChangeAuthAsymFinish: parentHandle %08x\n", parentHandle); returnCode = TPM_Load32(&ephHandle, &command, ¶mSize); } /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; if (returnCode == TPM_SUCCESS) { printf("TPM_Process_ChangeAuthAsymFinish: ephHandle %08x\n", ephHandle); /* get entityType parameter */ returnCode = TPM_Load16(&entityType, &command, ¶mSize); } /* get newAuthLink parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Digest_Load(newAuthLink, &command, ¶mSize); } /* get encNewAuth parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_Load(&encNewAuth, &command, ¶mSize); } /* get encData parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_Load(&encData, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_ChangeAuthAsymFinish: encDataSize %u\n", encData.size); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag10(tag); } /* get the optional 'below the line' authorization parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, privAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_ChangeAuthAsymFinish: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* 1. The TPM SHALL validate that the authHandle parameter authorizes use of the key in parentHandle.*/ if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyHandleEntries_GetKey(&parentKey, &parentPCRStatus, tpm_state, parentHandle, FALSE, /* not read-only */ FALSE, /* do not ignore PCRs */ FALSE); /* cannot use EK */ } if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)){ if (parentKey->authDataUsage != TPM_AUTH_NEVER) { printf("TPM_Process_ChangeAuthAsymFinish: Error, authorization required\n"); returnCode = TPM_AUTHFAIL; } } /* get idHandle -> usageAuth */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { if (parentHandle != TPM_KH_SRK) { returnCode = TPM_Key_GetUsageAuth(&parentKeyUsageAuth, parentKey); } /* If the parentHandle points to the SRK then the HMAC key MUST be built using the TPM Owner authorization. */ else { parentKeyUsageAuth = &(tpm_state->tpm_permanent_data.ownerAuth); } } /* get the session data */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { if (parentHandle != TPM_KH_SRK) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_KEYHANDLE, ordinal, parentKey, parentKeyUsageAuth, /* OIAP */ parentKey->tpm_store_asymkey->pubDataDigest); /*OSAP*/ } /* If the parentHandle points to the SRK then the HMAC key MUST be built using the TPM Owner authorization. */ else { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_OWNER, ordinal, parentKey, parentKeyUsageAuth, /* OIAP */ tpm_state->tpm_permanent_data.ownerAuth); /*OSAP*/ } } if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, privAuth); /* Authorization digest for input */ } /* 2. The encData field MUST be the encData field from TPM_STORED_DATA or TPM_KEY. */ if (returnCode == TPM_SUCCESS) { /* FIXME currently only TPM_KEY supported */ if (entityType != TPM_ET_KEY) { printf("TPM_Process_ChangeAuthAsymFinish: Error, bad entityType %04x\n", entityType); returnCode = TPM_WRONG_ENTITYTYPE; } } /* Validate that parentHandle -> keyUsage is TPM_KEY_STORAGE, if not return the error code TPM_INVALID_KEYUSAGE */ if (returnCode == TPM_SUCCESS) { if (parentKey->keyUsage != TPM_KEY_STORAGE) { printf("TPM_Process_ChangeAuthAsymFinish: Error, keyUsage %04hx is invalid\n", parentKey->keyUsage); returnCode = TPM_INVALID_KEYUSAGE; } } /* 3. The TPM SHALL create e1 by decrypting the entity held in the encData parameter. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_RSAPrivateDecryptMalloc(&e1DecryptData, /* decrypted data */ &e1DecryptDataLength, /* actual size of decrypted data */ encData.buffer,/* encrypted data */ encData.size, /* encrypted data size */ parentKey); } if (returnCode == TPM_SUCCESS) { stream = e1DecryptData; stream_size = e1DecryptDataLength; returnCode = TPM_StoreAsymkey_Load(&keyEntity, FALSE, &stream, &stream_size, NULL, /* TPM_KEY_PARMS */ NULL); /* TPM_SIZED_BUFFER pubKey */ } /* 4. The TPM SHALL create a1 by decrypting encNewAuth using the ephHandle -> TPM_KEY_AUTHCHANGE private key. a1 is a structure of type TPM_CHANGEAUTH_VALIDATE. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyHandleEntries_GetKey(&ephKey, &ephPCRStatus, tpm_state, ephHandle, FALSE, /* not read-only */ FALSE, /* do not ignore PCRs */ FALSE); /* cannot use EK */ } if (returnCode == TPM_SUCCESS) { if (ephKey->keyUsage != TPM_KEY_AUTHCHANGE) { printf("TPM_Process_ChangeAuthAsymFinish: Error: " "ephHandle does not point to TPM_KEY_AUTHCHANGE\n"); returnCode = TPM_BAD_PARAMETER; } } if (returnCode == TPM_SUCCESS) { returnCode = TPM_RSAPrivateDecryptMalloc(&a1Auth, /* decrypted data */ &a1AuthLength, /* actual size of decrypted data */ encNewAuth.buffer, /* encrypted data */ encNewAuth.size, /* encrypted data size */ ephKey); } if (returnCode == TPM_SUCCESS) { stream = a1Auth; stream_size = a1AuthLength; returnCode = TPM_ChangeauthValidate_Load(&changeauthValidate, &stream, &stream_size); } /* 5. The TPM SHALL create b1 by performing the following HMAC calculation: b1 = HMAC (a1 -> newAuthSecret). The secret for this calculation is encData -> currentAuth. This means that b1 is a value built from the current AuthData value (encData -> currentAuth) and the new AuthData value (a1 -> newAuthSecret). */ /* 6. The TPM SHALL compare b1 with newAuthLink. The TPM SHALL indicate a failure if the values do not match. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_HMAC_Check(&valid, newAuthLink, /* expect */ keyEntity.usageAuth, /* HMAC key is current auth */ TPM_SECRET_SIZE, changeauthValidate.newAuthSecret, 0, NULL); } if (returnCode == TPM_SUCCESS) { if (!valid) { printf("TPM_Process_ChangeAuthAsymFinish: Error, authenticating newAuthLink\n"); returnCode = TPM_AUTHFAIL; } } if (returnCode == TPM_SUCCESS) { /* 7. The TPM SHALL replace e1 -> authData with a1 -> newAuthSecret */ TPM_Secret_Copy(keyEntity.usageAuth, changeauthValidate.newAuthSecret); /* 8. The TPM SHALL encrypt e1 using the appropriate functions for the entity type. The key to encrypt with is parentHandle. */ returnCode = TPM_StoreAsymkey_GenerateEncData(&outData, &keyEntity, parentKey); } /* 9. The TPM SHALL create salt-Nonce by taking the next 20 bytes from the TPM RNG. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Random(saltNonce, TPM_NONCE_SIZE); } /* 10. The TPM SHALL create changeProof a HMAC of (saltNonce concatenated with a1 -> n1) using a1 -> newAuthSecret as the HMAC secret. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_HMAC_Generate(changeProof, /* hmac output */ changeauthValidate.newAuthSecret, /* hmac key */ TPM_NONCE_SIZE, saltNonce, TPM_NONCE_SIZE, changeauthValidate.n1, 0, NULL); } /* 11. The TPM MUST destroy the TPM_KEY_AUTHCHANGE key associated with the authorization session. */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_ChangeAuthAsymFinish: Deleting ephemeral key\n"); TPM_Key_Delete(ephKey); /* free the key resources */ free(ephKey); /* free the key itself */ /* remove entry from the key handle entries list */ returnCode = TPM_KeyHandleEntries_DeleteHandle(tpm_state->tpm_key_handle_entries, ephHandle); } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_ChangeAuthAsymFinish: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* return outData */ returnCode = TPM_SizedBuffer_Store(response, &outData); } /* return saltNonce */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Nonce_Store(response, saltNonce); } /* return changeProof */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Digest_Store(response, changeProof); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* owner HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ TPM_SizedBuffer_Delete(&encNewAuth); /* @1 */ TPM_SizedBuffer_Delete(&encData); /* @2 */ TPM_SizedBuffer_Delete(&outData); /* @3 */ TPM_StoreAsymkey_Delete(&keyEntity); /* @4 */ free(e1DecryptData); /* @5 */ free(a1Auth); /* @6 */ TPM_ChangeauthValidate_Delete(&changeauthValidate); /* @7 */ return rcf; } libtpms-0.9.3/src/tpm12/tpm_auth.h000066400000000000000000000205641421143571500167330ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Authorization */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_auth.h 4071 2010-04-29 19:26:45Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_AUTH_H #define TPM_AUTH_H #include "tpm_global.h" #include "tpm_session.h" #include "tpm_store.h" #include "tpm_structures.h" #include "tpm_types.h" /* TPM_AUTHDATA */ #if 0 void TPM_Authdata_Init(TPM_AUTHDATA tpm_authdata); #endif TPM_RESULT TPM_Authdata_Load(TPM_AUTHDATA tpm_authdata, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_Authdata_Store(TPM_STORE_BUFFER *sbuffer, const TPM_AUTHDATA tpm_authdata); TPM_RESULT TPM_Authdata_Generate(TPM_AUTHDATA resAuth, TPM_SECRET usageAuth, TPM_DIGEST outParamDigest, TPM_NONCE nonceEven, TPM_NONCE nonceOdd, TPM_BOOL continueSession); TPM_RESULT TPM_Authdata_Check(tpm_state_t *tpm_state, TPM_SECRET hmacKey, TPM_DIGEST inParamDigest, TPM_AUTH_SESSION_DATA *tpm_auth_session_data, TPM_NONCE nonceOdd, TPM_BOOL continueSession, TPM_AUTHDATA usageAuth); TPM_RESULT TPM_Auth2data_Check(tpm_state_t *tpm_state, TPM_SECRET hmacKey, TPM_DIGEST inParamDigest, TPM_AUTH_SESSION_DATA *tpm_auth_session_data, TPM_NONCE nonceOdd, TPM_BOOL continueSession, TPM_AUTHDATA usageAuth); TPM_RESULT TPM_Authdata_Fail(tpm_state_t *tpm_state); TPM_RESULT TPM_Authdata_GetState(TPM_DA_STATE *state, uint32_t *timeLeft, tpm_state_t *tpm_state); TPM_RESULT TPM_Authdata_CheckState(tpm_state_t *tpm_state); /* Utilities for command input and output parameter load and store */ TPM_RESULT TPM_AuthParams_Get(TPM_AUTHHANDLE *authHandle, TPM_BOOL *authHandleValid, TPM_NONCE nonceOdd, TPM_BOOL *continueAuthSession, TPM_AUTHDATA authData, unsigned char **command, uint32_t *paramSize); TPM_RESULT TPM_AuthParams_Set(TPM_STORE_BUFFER *response, TPM_SECRET hmacKey, TPM_AUTH_SESSION_DATA *auth_session_data, TPM_DIGEST outParamDigest, TPM_NONCE nonceOdd, TPM_BOOL continueAuthSession); /* TPM_CHANGEAUTH_VALIDATE */ void TPM_ChangeauthValidate_Init(TPM_CHANGEAUTH_VALIDATE *tpm_changeauth_validate); TPM_RESULT TPM_ChangeauthValidate_Load(TPM_CHANGEAUTH_VALIDATE *tpm_changeauth_validate, unsigned char **stream, uint32_t *stream_size); #if 0 TPM_RESULT TPM_ChangeauthValidate_Store(TPM_STORE_BUFFER *sbuffer, const TPM_CHANGEAUTH_VALIDATE *tpm_changeauth_validate); #endif void TPM_ChangeauthValidate_Delete(TPM_CHANGEAUTH_VALIDATE *tpm_changeauth_validate); /* TPM_DA_INFO */ void TPM_DaInfo_Init(TPM_DA_INFO *tpm_da_info); TPM_RESULT TPM_DaInfo_Store(TPM_STORE_BUFFER *sbuffer, const TPM_DA_INFO *tpm_da_info); void TPM_DaInfo_Delete(TPM_DA_INFO *tpm_da_info); TPM_RESULT TPM_DaInfo_Set(TPM_DA_INFO *tpm_da_info, tpm_state_t *tpm_state); /* TPM_DA_INFO_LIMITED */ void TPM_DaInfoLimited_Init(TPM_DA_INFO_LIMITED *tpm_da_info_limited); TPM_RESULT TPM_DaInfoLimited_Store(TPM_STORE_BUFFER *sbuffer, const TPM_DA_INFO_LIMITED *tpm_da_info_limited); void TPM_DaInfoLimited_Delete(TPM_DA_INFO_LIMITED *tpm_da_info_limited); TPM_RESULT TPM_DaInfoLimited_Set(TPM_DA_INFO_LIMITED *tpm_da_info_limited, tpm_state_t *tpm_state); /* Processing functions */ TPM_RESULT TPM_Process_ChangeAuth(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_ChangeAuthOwner(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_ChangeAuthAsymStart(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_ChangeAuthAsymFinish(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); #endif libtpms-0.9.3/src/tpm12/tpm_commands.h000066400000000000000000000052331421143571500175670ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM Command Structure */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_commands.h 4071 2010-04-29 19:26:45Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_COMMANDS_H #define TPM_COMMANDS_H #include "tpm_types.h" /* general structure for all commands */ #define TPM_TAG_OFFSET 0 #define TPM_PARAMSIZE_OFFSET (sizeof(TPM_TAG) + TPM_TAG_OFFSET) #define TPM_ORDINAL_OFFSET (sizeof(uint32_t) + TPM_PARAMSIZE_OFFSET) #endif libtpms-0.9.3/src/tpm12/tpm_constants.h000066400000000000000000002554021421143571500200070ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM Constants */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_constants.h 4603 2011-08-16 20:40:26Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_CONSTANTS_H #define TPM_CONSTANTS_H #include #include /* NOTE implementation Specific */ /* version, revision, specLevel, errataRev */ /* current for released specification revision 103 */ #define TPM_REVISION_MAX 9999 #ifndef TPM_REVISION #define TPM_REVISION TPM_REVISION_MAX #endif #if (TPM_REVISION >= 116) #define TPM_SPEC_LEVEL 0x0002 /* uint16_t The level of ordinals supported */ #define TPM_ERRATA_REV 0x03 /* specification errata level */ #elif (TPM_REVISION >= 103) #define TPM_SPEC_LEVEL 0x0002 /* uint16_t The level of ordinals supported */ #define TPM_ERRATA_REV 0x02 /* specification errata level */ #elif (TPM_REVISION >= 94) #define TPM_SPEC_LEVEL 0x0002 /* uint16_t The level of ordinals supported */ #define TPM_ERRATA_REV 0x01 /* specification errata level */ #elif (TPM_REVISION >= 85) #define TPM_SPEC_LEVEL 0x0002 /* uint16_t The level of ordinals supported */ #define TPM_ERRATA_REV 0x00 /* specification errata level */ #else #define TPM_SPEC_LEVEL 0x0001 /* uint16_t The level of ordinals supported */ #define TPM_ERRATA_REV 0x00 /* specification errata level */ #endif /* IBM specific */ #if 0 /* at one time vendorID was the PCI vendor ID, this is the IBM code */ #define TPM_VENDOR_ID "\x00\x00\x10\x14" /* BYTE[4], the vendor ID, obtained from the TCG, typically PCI vendor ID */ #endif #define TPM_VENDOR_ID "IBM" /* 4 bytes, as of rev 99 vendorID and TPM_CAP_PROP_MANUFACTURER return the same value */ #define TPM_MANUFACTURER "IBM" /* 4 characters, assigned by TCG, typically stock ticker symbol */ /* Timeouts in microseconds. These are for the platform specific interface (e.g. the LPC bus registers in the PC Client TPM). They are most likely not applicable to a software TPM. */ #define TPM_TIMEOUT_A 1000000 #define TPM_TIMEOUT_B 1000000 #define TPM_TIMEOUT_C 1000000 #define TPM_TIMEOUT_D 1000000 /* dictionary attack mitigation */ #define TPM_LOCKOUT_THRESHOLD 5 /* successive failures to trigger lockout, must be greater than 0 */ /* Denotes the duration value in microseconds of the duration of the three classes of commands: Small, Medium and Long. The command types are in the Part 2 Ordinal Table. Essentially: Long - creating an RSA key pair Medium - using an RSA key Short - anything else */ #ifndef TPM_SMALL_DURATION #define TPM_SMALL_DURATION 2000000 #endif #ifndef TPM_MEDIUM_DURATION #define TPM_MEDIUM_DURATION 5000000 #endif #ifndef TPM_LONG_DURATION #define TPM_LONG_DURATION 60000000 #endif /* startup effects */ #define TPM_STARTUP_EFFECTS_VALUE \ (TPM_STARTUP_EFFECTS_ST_ANY_RT_KEY | /* key resources init by TPM_Startup(ST_ANY) */ \ TPM_STARTUP_EFFECTS_ST_STATE_RT_HASH | /* hash resources are init by TPM_Startup(ST_STATE) */ \ TPM_STARTUP_EFFECTS_ST_CLEAR_AUDITDIGEST) /* auditDigest nulled on TPM_Startup(ST_CLEAR) */ /* TPM buffer limits */ /* This is the increment by which the TPM_STORE_BUFFER grows. A larger number saves realloc's. A smaller number saves memory. TPM_ALLOC_MAX must be a multiple of this value. */ #define TPM_STORE_BUFFER_INCREMENT (TPM_ALLOC_MAX / 64) /* This is the maximum value of the TPM input and output packet buffer. It should be large enough to accommodate the largest TPM command or response, currently about 1200 bytes. It should be small enough to accommodate whatever software is driving the TPM. NOTE: Some commands are somewhat open ended, and related to this parmater. E.g., The input size for the TPM_SHA1Init. The output size for TPM_GetRandom. It is returned by TPM_GetCapability -> TPM_CAP_PROP_INPUT_BUFFER */ #ifndef TPM_BUFFER_MAX #define TPM_BUFFER_MAX 0x1000 /* 4k bytes */ #endif #ifndef TPM_BUFFER_MIN #define TPM_BUFFER_MIN 0x0c00 /* 3k bytes */ #endif /* Random number generator */ /* maximum bytes in one TPM_GetRandom() call Use maximum input buffer size minus tag, paramSize, returnCode, randomBytesSize. */ #define TPM_RANDOM_MAX (TPM12_GetBufferSize() \ - sizeof(TPM_TAG) - sizeof(uint32_t) \ - sizeof(TPM_RESULT) - sizeof(uint32_t)) /* Maximum number of bytes that can be sent to TPM_SHA1Update. Must be a multiple of 64 bytes. Use maximum input buffer size minus tag, paramSize, ordinal, numBytes. */ #define TPM_SHA1_MAXNUMBYTES (TPM12_GetBufferSize() - 64) /* extra audit status bits for TSC commands outside the normal ordinal range */ #define TSC_PHYS_PRES_AUDIT 0x01 #define TSC_RESET_ESTAB_AUDIT 0x02 /* TPM_CAP_MFR capabilities */ #define TPM_CAP_PROCESS_ID 0x00000020 /* define a value for an illegal instance handle */ #define TPM_ILLEGAL_INSTANCE_HANDLE 0xffffffff /* NOTE End Implementation Specific */ /* 3. Structure Tags rev 105 There have been some indications that knowing what structure is in use would be valuable information in each structure. This new tag will be in each new structure that the TPM defines. The upper nibble of the value designates the purview of the structure tag. 0 is used for TPM structures, 1 for platforms, and 2-F are reserved. */ /* 3.1 TPM_STRUCTURE_TAG */ /* Structure */ #define TPM_TAG_CONTEXTBLOB 0x0001 /* TPM_CONTEXT_BLOB */ #define TPM_TAG_CONTEXT_SENSITIVE 0x0002 /* TPM_CONTEXT_SENSITIVE */ #define TPM_TAG_CONTEXTPOINTER 0x0003 /* TPM_CONTEXT_POINTER */ #define TPM_TAG_CONTEXTLIST 0x0004 /* TPM_CONTEXT_LIST */ #define TPM_TAG_SIGNINFO 0x0005 /* TPM_SIGN_INFO */ #define TPM_TAG_PCR_INFO_LONG 0x0006 /* TPM_PCR_INFO_LONG */ #define TPM_TAG_PERSISTENT_FLAGS 0x0007 /* TPM_PERSISTENT_FLAGS (deprecated 1.1 struct) */ #define TPM_TAG_VOLATILE_FLAGS 0x0008 /* TPM_VOLATILE_FLAGS (deprecated 1.1 struct) */ #define TPM_TAG_PERSISTENT_DATA 0x0009 /* TPM_PERSISTENT_DATA (deprecated 1.1 struct) */ #define TPM_TAG_VOLATILE_DATA 0x000A /* TPM_VOLATILE_DATA (deprecated 1.1 struct) */ #define TPM_TAG_SV_DATA 0x000B /* TPM_SV_DATA */ #define TPM_TAG_EK_BLOB 0x000C /* TPM_EK_BLOB */ #define TPM_TAG_EK_BLOB_AUTH 0x000D /* TPM_EK_BLOB_AUTH */ #define TPM_TAG_COUNTER_VALUE 0x000E /* TPM_COUNTER_VALUE */ #define TPM_TAG_TRANSPORT_INTERNAL 0x000F /* TPM_TRANSPORT_INTERNAL */ #define TPM_TAG_TRANSPORT_LOG_IN 0x0010 /* TPM_TRANSPORT_LOG_IN */ #define TPM_TAG_TRANSPORT_LOG_OUT 0x0011 /* TPM_TRANSPORT_LOG_OUT */ #define TPM_TAG_AUDIT_EVENT_IN 0x0012 /* TPM_AUDIT_EVENT_IN */ #define TPM_TAG_AUDIT_EVENT_OUT 0X0013 /* TPM_AUDIT_EVENT_OUT */ #define TPM_TAG_CURRENT_TICKS 0x0014 /* TPM_CURRENT_TICKS */ #define TPM_TAG_KEY 0x0015 /* TPM_KEY */ #define TPM_TAG_STORED_DATA12 0x0016 /* TPM_STORED_DATA12 */ #define TPM_TAG_NV_ATTRIBUTES 0x0017 /* TPM_NV_ATTRIBUTES */ #define TPM_TAG_NV_DATA_PUBLIC 0x0018 /* TPM_NV_DATA_PUBLIC */ #define TPM_TAG_NV_DATA_SENSITIVE 0x0019 /* TPM_NV_DATA_SENSITIVE */ #define TPM_TAG_DELEGATIONS 0x001A /* TPM DELEGATIONS */ #define TPM_TAG_DELEGATE_PUBLIC 0x001B /* TPM_DELEGATE_PUBLIC */ #define TPM_TAG_DELEGATE_TABLE_ROW 0x001C /* TPM_DELEGATE_TABLE_ROW */ #define TPM_TAG_TRANSPORT_AUTH 0x001D /* TPM_TRANSPORT_AUTH */ #define TPM_TAG_TRANSPORT_PUBLIC 0X001E /* TPM_TRANSPORT_PUBLIC */ #define TPM_TAG_PERMANENT_FLAGS 0X001F /* TPM_PERMANENT_FLAGS */ #define TPM_TAG_STCLEAR_FLAGS 0X0020 /* TPM_STCLEAR_FLAGS */ #define TPM_TAG_STANY_FLAGS 0X0021 /* TPM_STANY_FLAGS */ #define TPM_TAG_PERMANENT_DATA 0X0022 /* TPM_PERMANENT_DATA */ #define TPM_TAG_STCLEAR_DATA 0X0023 /* TPM_STCLEAR_DATA */ #define TPM_TAG_STANY_DATA 0X0024 /* TPM_STANY_DATA */ #define TPM_TAG_FAMILY_TABLE_ENTRY 0X0025 /* TPM_FAMILY_TABLE_ENTRY */ #define TPM_TAG_DELEGATE_SENSITIVE 0X0026 /* TPM_DELEGATE_SENSITIVE */ #define TPM_TAG_DELG_KEY_BLOB 0X0027 /* TPM_DELG_KEY_BLOB */ #define TPM_TAG_KEY12 0x0028 /* TPM_KEY12 */ #define TPM_TAG_CERTIFY_INFO2 0X0029 /* TPM_CERTIFY_INFO2 */ #define TPM_TAG_DELEGATE_OWNER_BLOB 0X002A /* TPM_DELEGATE_OWNER_BLOB */ #define TPM_TAG_EK_BLOB_ACTIVATE 0X002B /* TPM_EK_BLOB_ACTIVATE */ #define TPM_TAG_DAA_BLOB 0X002C /* TPM_DAA_BLOB */ #define TPM_TAG_DAA_CONTEXT 0X002D /* TPM_DAA_CONTEXT */ #define TPM_TAG_DAA_ENFORCE 0X002E /* TPM_DAA_ENFORCE */ #define TPM_TAG_DAA_ISSUER 0X002F /* TPM_DAA_ISSUER */ #define TPM_TAG_CAP_VERSION_INFO 0X0030 /* TPM_CAP_VERSION_INFO */ #define TPM_TAG_DAA_SENSITIVE 0X0031 /* TPM_DAA_SENSITIVE */ #define TPM_TAG_DAA_TPM 0X0032 /* TPM_DAA_TPM */ #define TPM_TAG_CMK_MIGAUTH 0X0033 /* TPM_CMK_MIGAUTH */ #define TPM_TAG_CMK_SIGTICKET 0X0034 /* TPM_CMK_SIGTICKET */ #define TPM_TAG_CMK_MA_APPROVAL 0X0035 /* TPM_CMK_MA_APPROVAL */ #define TPM_TAG_QUOTE_INFO2 0X0036 /* TPM_QUOTE_INFO2 */ #define TPM_TAG_DA_INFO 0x0037 /* TPM_DA_INFO */ #define TPM_TAG_DA_INFO_LIMITED 0x0038 /* TPM_DA_INFO_LIMITED */ #define TPM_TAG_DA_ACTION_TYPE 0x0039 /* TPM_DA_ACTION_TYPE */ /* SW TPM Tags */ /* These tags are used to describe the format of serialized TPM non-volatile state */ /* These describe the overall format */ /* V1 state is the sequence permanent data, permanent flags, owner evict keys, NV defined space */ #define TPM_TAG_NVSTATE_V1 0x0001 /* svn revision 4078 */ /* These tags describe the TPM_PERMANENT_DATA format */ /* For the first release, use the standard TPM_TAG_PERMANENT_DATA tag. Since this tag is never visible outside the TPM, the tag value can be changed if the format changes. */ /* These tags describe the TPM_PERMANENT_FLAGS format */ /* The TPM_PERMANENT_FLAGS structure changed from rev 94 to 103. Unfortunately, the standard TPM tag did not change. Define distinguishing values here. */ #define TPM_TAG_NVSTATE_PF94 0x0001 #define TPM_TAG_NVSTATE_PF103 0x0002 /* This tag describes the owner evict key format */ #define TPM_TAG_NVSTATE_OE_V1 0x0001 /* This tag describes the NV defined space format */ #define TPM_TAG_NVSTATE_NV_V1 0x0001 /* V2 added the NV public optimization */ #define TPM_TAG_NVSTATE_NV_V2 0x0002 /* These tags are used to describe the format of serialized TPM volatile state */ /* These describe the overall format */ /* V1 state is the sequence TPM Parameters, TPM_STCLEAR_FLAGS, TPM_STANY_FLAGS, TPM_STCLEAR_DATA, TPM_STANY_DATA, TPM_KEY_HANDLE_ENTRY, SHA1 context(s), TPM_TRANSHANDLE, testState, NV volatile flags */ #define TPM_TAG_VSTATE_V1 0x0001 /* This tag defines the TPM Parameters format */ #define TPM_TAG_TPM_PARAMETERS_V1 0x0001 /* This tag defines the TPM_STCLEAR_FLAGS format */ /* V1 is the TCG standard returned by the getcap. It's unlikely that this will change */ #define TPM_TAG_STCLEAR_FLAGS_V1 0x0001 /* These tags describe the TPM_STANY_FLAGS format */ /* For the first release, use the standard TPM_TAG_STANY_FLAGS tag. Since this tag is never visible outside the TPM, the tag value can be changed if the format changes. */ /* This tag defines the TPM_STCLEAR_DATA format */ /* V2 deleted the ordinalResponse, responseCount */ #define TPM_TAG_STCLEAR_DATA_V2 0X0024 /* These tags describe the TPM_STANY_DATA format */ /* For the first release, use the standard TPM_TAG_STANY_DATA tag. Since this tag is never visible outside the TPM, the tag value can be changed if the format changes. */ /* This tag defines the key handle entries format */ #define TPM_TAG_KEY_HANDLE_ENTRIES_V1 0x0001 /* This tag defines the SHA-1 context format */ #define TPM_TAG_SHA1CONTEXT_OSSL_V1 0x0001 /* for openssl */ #define TPM_TAG_SHA1CONTEXT_FREEBL_V1 0x0101 /* for freebl */ /* This tag defines the NV index entries volatile format */ #define TPM_TAG_NV_INDEX_ENTRIES_VOLATILE_V1 0x0001 /* 4. Types */ /* 4.1 TPM_RESOURCE_TYPE rev 87 */ #define TPM_RT_KEY 0x00000001 /* The handle is a key handle and is the result of a LoadKey type operation */ #define TPM_RT_AUTH 0x00000002 /* The handle is an authorization handle. Auth handles come from TPM_OIAP, TPM_OSAP and TPM_DSAP */ #define TPM_RT_HASH 0X00000003 /* Reserved for hashes */ #define TPM_RT_TRANS 0x00000004 /* The handle is for a transport session. Transport handles come from TPM_EstablishTransport */ #define TPM_RT_CONTEXT 0x00000005 /* Resource wrapped and held outside the TPM using the context save/restore commands */ #define TPM_RT_COUNTER 0x00000006 /* Reserved for counters */ #define TPM_RT_DELEGATE 0x00000007 /* The handle is for a delegate row. These are the internal rows held in NV storage by the TPM */ #define TPM_RT_DAA_TPM 0x00000008 /* The value is a DAA TPM specific blob */ #define TPM_RT_DAA_V0 0x00000009 /* The value is a DAA V0 parameter */ #define TPM_RT_DAA_V1 0x0000000A /* The value is a DAA V1 parameter */ /* 4.2 TPM_PAYLOAD_TYPE rev 87 This structure specifies the type of payload in various messages. */ #define TPM_PT_ASYM 0x01 /* The entity is an asymmetric key */ #define TPM_PT_BIND 0x02 /* The entity is bound data */ #define TPM_PT_MIGRATE 0x03 /* The entity is a migration blob */ #define TPM_PT_MAINT 0x04 /* The entity is a maintenance blob */ #define TPM_PT_SEAL 0x05 /* The entity is sealed data */ #define TPM_PT_MIGRATE_RESTRICTED 0x06 /* The entity is a restricted-migration asymmetric key */ #define TPM_PT_MIGRATE_EXTERNAL 0x07 /* The entity is a external migratable key */ #define TPM_PT_CMK_MIGRATE 0x08 /* The entity is a CMK migratable blob */ /* 0x09 - 0x7F Reserved for future use by TPM */ /* 0x80 - 0xFF Vendor specific payloads */ /* 4.3 TPM_ENTITY_TYPE rev 100 This specifies the types of entity that are supported by the TPM. The LSB is used to indicate the entity type. The MSB is used to indicate the ADIP encryption scheme when applicable. For compatibility with TPM 1.1, this mapping is maintained: 0x0001 specifies a keyHandle entity with XOR encryption 0x0002 specifies an owner entity with XOR encryption 0x0003 specifies some data entity with XOR encryption 0x0004 specifies the SRK entity with XOR encryption 0x0005 specifies a key entity with XOR encryption When the entity is not being used for ADIP encryption, the MSB MUST be 0x00. */ /* TPM_ENTITY_TYPE LSB Values (entity type) */ #define TPM_ET_KEYHANDLE 0x01 /* The entity is a keyHandle or key */ #define TPM_ET_OWNER 0x02 /*0x40000001 The entity is the TPM Owner */ #define TPM_ET_DATA 0x03 /* The entity is some data */ #define TPM_ET_SRK 0x04 /*0x40000000 The entity is the SRK */ #define TPM_ET_KEY 0x05 /* The entity is a key or keyHandle */ #define TPM_ET_REVOKE 0x06 /*0x40000002 The entity is the RevokeTrust value */ #define TPM_ET_DEL_OWNER_BLOB 0x07 /* The entity is a delegate owner blob */ #define TPM_ET_DEL_ROW 0x08 /* The entity is a delegate row */ #define TPM_ET_DEL_KEY_BLOB 0x09 /* The entity is a delegate key blob */ #define TPM_ET_COUNTER 0x0A /* The entity is a counter */ #define TPM_ET_NV 0x0B /* The entity is a NV index */ #define TPM_ET_OPERATOR 0x0C /* The entity is the operator */ #define TPM_ET_RESERVED_HANDLE 0x40 /* Reserved. This value avoids collisions with the handle MSB setting.*/ /* TPM_ENTITY_TYPE MSB Values (ADIP encryption scheme) */ #define TPM_ET_XOR 0x00 /* XOR */ #define TPM_ET_AES128_CTR 0x06 /* AES 128 bits in CTR mode */ /* 4.4 Handles rev 88 Handles provides pointers to TPM internal resources. Handles should provide the ability to locate a value without collision. 1. The TPM MAY order and set a handle to any value the TPM determines is appropriate 2. The handle value SHALL provide assurance that collisions SHOULD not occur in 2^24 handles 4.4.1 Reserved Key Handles The reserved key handles. These values specify specific keys or specific actions for the TPM. */ /* 4.4.1 Reserved Key Handles rev 87 The reserved key handles. These values specify specific keys or specific actions for the TPM. TPM_KH_TRANSPORT indicates to TPM_EstablishTransport that there is no encryption key, and that the "secret" wrapped parameters are actually passed unencrypted. */ #define TPM_KH_SRK 0x40000000 /* The handle points to the SRK */ #define TPM_KH_OWNER 0x40000001 /* The handle points to the TPM Owner */ #define TPM_KH_REVOKE 0x40000002 /* The handle points to the RevokeTrust value */ #define TPM_KH_TRANSPORT 0x40000003 /* The handle points to the TPM_EstablishTransport static authorization */ #define TPM_KH_OPERATOR 0x40000004 /* The handle points to the Operator auth */ #define TPM_KH_ADMIN 0x40000005 /* The handle points to the delegation administration auth */ #define TPM_KH_EK 0x40000006 /* The handle points to the PUBEK, only usable with TPM_OwnerReadInternalPub */ /* 4.5 TPM_STARTUP_TYPE rev 87 To specify what type of startup is occurring. */ #define TPM_ST_CLEAR 0x0001 /* The TPM is starting up from a clean state */ #define TPM_ST_STATE 0x0002 /* The TPM is starting up from a saved state */ #define TPM_ST_DEACTIVATED 0x0003 /* The TPM is to startup and set the deactivated flag to TRUE */ /* 4.6 TPM_STARTUP_EFFECTS rev 101 This structure lists for the various resources and sessions on a TPM the affect that TPM_Startup has on the values. There are three ST_STATE options for keys (restore all, restore non-volatile, or restore none) and two ST_CLEAR options (restore non-volatile or restore none). As bit 4 was insufficient to describe the possibilities, it is deprecated. Software should use TPM_CAP_KEY_HANDLE to determine which keys are loaded after TPM_Startup. 31-9 No information and MUST be FALSE 8 TPM_RT_DAA_TPM resources are initialized by TPM_Startup(ST_STATE) 7 TPM_Startup has no effect on auditDigest 6 auditDigest is set to all zeros on TPM_Startup(ST_CLEAR) but not on other types of TPM_Startup 5 auditDigest is set to all zeros on TPM_Startup(any) 4 TPM_RT_KEY Deprecated, as the meaning was subject to interpretation. (Was:TPM_RT_KEY resources are initialized by TPM_Startup(ST_ANY)) 3 TPM_RT_AUTH resources are initialized by TPM_Startup(ST_STATE) 2 TPM_RT_HASH resources are initialized by TPM_Startup(ST_STATE) 1 TPM_RT_TRANS resources are initialized by TPM_Startup(ST_STATE) 0 TPM_RT_CONTEXT session (but not key) resources are initialized by TPM_Startup(ST_STATE) */ #define TPM_STARTUP_EFFECTS_ST_STATE_RT_DAA 0x00000100 /* bit 8 */ #define TPM_STARTUP_EFFECTS_STARTUP_NO_AUDITDIGEST 0x00000080 /* bit 7 */ #define TPM_STARTUP_EFFECTS_ST_CLEAR_AUDITDIGEST 0x00000040 /* bit 6 */ #define TPM_STARTUP_EFFECTS_STARTUP_AUDITDIGEST 0x00000020 /* bit 5 */ #define TPM_STARTUP_EFFECTS_ST_ANY_RT_KEY 0x00000010 /* bit 4 */ #define TPM_STARTUP_EFFECTS_ST_STATE_RT_AUTH 0x00000008 /* bit 3 */ #define TPM_STARTUP_EFFECTS_ST_STATE_RT_HASH 0x00000004 /* bit 2 */ #define TPM_STARTUP_EFFECTS_ST_STATE_RT_TRANS 0x00000002 /* bit 1 */ #define TPM_STARTUP_EFFECTS_ST_STATE_RT_CONTEXT 0x00000001 /* bit 0 */ /* 4.7 TPM_PROTOCOL_ID rev 87 This value identifies the protocol in use. */ #define TPM_PID_NONE 0x0000 /* kgold - added */ #define TPM_PID_OIAP 0x0001 /* The OIAP protocol. */ #define TPM_PID_OSAP 0x0002 /* The OSAP protocol. */ #define TPM_PID_ADIP 0x0003 /* The ADIP protocol. */ #define TPM_PID_ADCP 0X0004 /* The ADCP protocol. */ #define TPM_PID_OWNER 0X0005 /* The protocol for taking ownership of a TPM. */ #define TPM_PID_DSAP 0x0006 /* The DSAP protocol */ #define TPM_PID_TRANSPORT 0x0007 /*The transport protocol */ /* 4.8 TPM_ALGORITHM_ID rev 99 This table defines the types of algorithms that may be supported by the TPM. The TPM MUST support the algorithms TPM_ALG_RSA, TPM_ALG_SHA, TPM_ALG_HMAC, and TPM_ALG_MGF1 */ #define TPM_ALG_RSA 0x00000001 /* The RSA algorithm. */ /* #define TPM_ALG_DES 0x00000002 (was the DES algorithm) */ /* #define TPM_ALG_3DES 0X00000003 (was the 3DES algorithm in EDE mode) */ #define TPM_ALG_SHA 0x00000004 /* The SHA1 algorithm */ #define TPM_ALG_HMAC 0x00000005 /* The RFC 2104 HMAC algorithm */ #define TPM_ALG_AES128 0x00000006 /* The AES algorithm, key size 128 */ #define TPM_ALG_MGF1 0x00000007 /* The XOR algorithm using MGF1 to create a string the size of the encrypted block */ #define TPM_ALG_AES192 0x00000008 /* AES, key size 192 */ #define TPM_ALG_AES256 0x00000009 /* AES, key size 256 */ #define TPM_ALG_XOR 0x0000000A /* XOR using the rolling nonces */ /* 4.9 TPM_PHYSICAL_PRESENCE rev 87 */ #define TPM_PHYSICAL_PRESENCE_HW_DISABLE 0x0200 /* Sets the physicalPresenceHWEnable to FALSE */ #define TPM_PHYSICAL_PRESENCE_CMD_DISABLE 0x0100 /* Sets the physicalPresenceCMDEnable to FALSE */ #define TPM_PHYSICAL_PRESENCE_LIFETIME_LOCK 0x0080 /* Sets the physicalPresenceLifetimeLock to TRUE */ #define TPM_PHYSICAL_PRESENCE_HW_ENABLE 0x0040 /* Sets the physicalPresenceHWEnable to TRUE */ #define TPM_PHYSICAL_PRESENCE_CMD_ENABLE 0x0020 /* Sets the physicalPresenceCMDEnable to TRUE */ #define TPM_PHYSICAL_PRESENCE_NOTPRESENT 0x0010 /* Sets PhysicalPresence = FALSE */ #define TPM_PHYSICAL_PRESENCE_PRESENT 0x0008 /* Sets PhysicalPresence = TRUE */ #define TPM_PHYSICAL_PRESENCE_LOCK 0x0004 /* Sets PhysicalPresenceLock = TRUE */ #define TPM_PHYSICAL_PRESENCE_MASK 0xfc03 /* ~ OR of all above bits */ /* 4.10 TPM_MIGRATE_SCHEME rev 103 The scheme indicates how the StartMigrate command should handle the migration of the encrypted blob. */ #define TPM_MS_MIGRATE 0x0001 /* A public key that can be used with all TPM migration commands other than 'ReWrap' mode. */ #define TPM_MS_REWRAP 0x0002 /* A public key that can be used for the ReWrap mode of TPM_CreateMigrationBlob. */ #define TPM_MS_MAINT 0x0003 /* A public key that can be used for the Maintenance commands */ #define TPM_MS_RESTRICT_MIGRATE 0x0004 /* The key is to be migrated to a Migration Authority. */ #define TPM_MS_RESTRICT_APPROVE 0x0005 /* The key is to be migrated to an entity approved by a Migration Authority using double wrapping */ /* 4.11 TPM_EK_TYPE rev 87 This structure indicates what type of information that the EK is dealing with. */ #define TPM_EK_TYPE_ACTIVATE 0x0001 /* The blob MUST be TPM_EK_BLOB_ACTIVATE */ #define TPM_EK_TYPE_AUTH 0x0002 /* The blob MUST be TPM_EK_BLOB_AUTH */ /* 4.12 TPM_PLATFORM_SPECIFIC rev 87 This enumerated type indicates the platform specific spec that the information relates to. */ #define TPM_PS_PC_11 0x0001 /* PC Specific version 1.1 */ #define TPM_PS_PC_12 0x0002 /* PC Specific version 1.2 */ #define TPM_PS_PDA_12 0x0003 /* PDA Specific version 1.2 */ #define TPM_PS_Server_12 0x0004 /* Server Specific version 1.2 */ #define TPM_PS_Mobile_12 0x0005 /* Mobil Specific version 1.2 */ /* 5.8 TPM_KEY_USAGE rev 101 This table defines the types of keys that are possible. Each value defines for what operation the key can be used. Most key usages can be CMKs. See 4.2, TPM_PAYLOAD_TYPE. Each key has a setting defining the encryption and signature scheme to use. The selection of a key usage value limits the choices of encryption and signature schemes. */ #define TPM_KEY_UNINITIALIZED 0x0000 /* NOTE: Added. This seems like a good place to indicate that a TPM_KEY structure has not been initialized */ #define TPM_KEY_SIGNING 0x0010 /* This SHALL indicate a signing key. The [private] key SHALL be used for signing operations, only. This means that it MUST be a leaf of the Protected Storage key hierarchy. */ #define TPM_KEY_STORAGE 0x0011 /* This SHALL indicate a storage key. The key SHALL be used to wrap and unwrap other keys in the Protected Storage hierarchy */ #define TPM_KEY_IDENTITY 0x0012 /* This SHALL indicate an identity key. The key SHALL be used for operations that require a TPM identity, only. */ #define TPM_KEY_AUTHCHANGE 0X0013 /* This SHALL indicate an ephemeral key that is in use during the ChangeAuthAsym process, only. */ #define TPM_KEY_BIND 0x0014 /* This SHALL indicate a key that can be used for TPM_Bind and TPM_Unbind operations only. */ #define TPM_KEY_LEGACY 0x0015 /* This SHALL indicate a key that can perform signing and binding operations. The key MAY be used for both signing and binding operations. The TPM_KEY_LEGACY key type is to allow for use by applications where both signing and encryption operations occur with the same key. */ #define TPM_KEY_MIGRATE 0x0016 /* This SHALL indicate a key in use for TPM_MigrateKey */ /* 5.8.1 TPM_ENC_SCHEME Mandatory Key Usage Schemes rev 99 The TPM MUST check that the encryption scheme defined for use with the key is a valid scheme for the key type, as follows: */ #define TPM_ES_NONE 0x0001 #define TPM_ES_RSAESPKCSv15 0x0002 #define TPM_ES_RSAESOAEP_SHA1_MGF1 0x0003 #define TPM_ES_SYM_CTR 0x0004 #define TPM_ES_SYM_OFB 0x0005 /* 5.8.1 TPM_SIG_SCHEME Mandatory Key Usage Schemes rev 99 The TPM MUST check that the signature scheme defined for use with the key is a valid scheme for the key type, as follows: */ #define TPM_SS_NONE 0x0001 #define TPM_SS_RSASSAPKCS1v15_SHA1 0x0002 #define TPM_SS_RSASSAPKCS1v15_DER 0x0003 #define TPM_SS_RSASSAPKCS1v15_INFO 0x0004 /* 5.9 TPM_AUTH_DATA_USAGE rev 110 The indication to the TPM when authorization sessions for an entity are required. Future versions may allow for more complex decisions regarding AuthData checking. */ #define TPM_AUTH_NEVER 0x00 /* This SHALL indicate that usage of the key without authorization is permitted. */ #define TPM_AUTH_ALWAYS 0x01 /* This SHALL indicate that on each usage of the key the authorization MUST be performed. */ #define TPM_NO_READ_PUBKEY_AUTH 0x03 /* This SHALL indicate that on commands that require the TPM to use the the key, the authorization MUST be performed. For commands that cause the TPM to read the public portion of the key, but not to use the key (e.g. TPM_GetPubKey), the authorization may be omitted. */ /* 5.10 TPM_KEY_FLAGS rev 110 This table defines the meanings of the bits in a TPM_KEY_FLAGS structure, used in TPM_STORE_ASYMKEY and TPM_CERTIFY_INFO. The value of TPM_KEY_FLAGS MUST be decomposed into individual mask values. The presence of a mask value SHALL have the effect described in the above table On input, all undefined bits MUST be zero. The TPM MUST return an error if any undefined bit is set. On output, the TPM MUST set all undefined bits to zero. */ #ifdef TPM_V12 #define TPM_KEY_FLAGS_MASK 0x0000001f #else #define TPM_KEY_FLAGS_MASK 0x00000007 #endif #define TPM_REDIRECTION 0x00000001 /* This mask value SHALL indicate the use of redirected output. */ #define TPM_MIGRATABLE 0x00000002 /* This mask value SHALL indicate that the key is migratable. */ #define TPM_ISVOLATILE 0x00000004 /* This mask value SHALL indicate that the key MUST be unloaded upon execution of the TPM_Startup(ST_Clear). This does not indicate that a non-volatile key will remain loaded across TPM_Startup(ST_Clear) events. */ #define TPM_PCRIGNOREDONREAD 0x00000008 /* When TRUE the TPM MUST NOT check digestAtRelease or localityAtRelease for commands that read the public portion of the key (e.g., TPM_GetPubKey) and MAY NOT check digestAtRelease or localityAtRelease for commands that use the public portion of the key (e.g. TPM_Seal) When FALSE the TPM MUST check digestAtRelease and localityAtRelease for commands that read or use the public portion of the key */ #define TPM_MIGRATEAUTHORITY 0x00000010 /* When set indicates that the key is under control of a migration authority. The TPM MUST only allow the creation of a key with this flag in TPM_MA_CreateKey */ /* 5.17 TPM_CMK_DELEGATE values rev 89 The bits of TPM_CMK_DELEGATE are flags that determine how the TPM responds to delegated requests to manipulate a certified-migration-key, a loaded key with payload type TPM_PT_MIGRATE_RESTRICTED or TPM_PT_MIGRATE_EXTERNAL.. 26:0 reserved MUST be 0 The default value of TPM_CMK_Delegate is zero (0) */ #define TPM_CMK_DELEGATE_SIGNING 0x80000000 /* When set to 1, this bit SHALL indicate that a delegated command may manipulate a CMK of TPM_KEY_USAGE == TPM_KEY_SIGNING */ #define TPM_CMK_DELEGATE_STORAGE 0x40000000 /* When set to 1, this bit SHALL indicate that a delegated command may manipulate a CMK of TPM_KEY_USAGE == TPM_KEY_STORAGE */ #define TPM_CMK_DELEGATE_BIND 0x20000000 /* When set to 1, this bit SHALL indicate that a delegated command may manipulate a CMK of TPM_KEY_USAGE == TPM_KEY_BIND */ #define TPM_CMK_DELEGATE_LEGACY 0x10000000 /* When set to 1, this bit SHALL indicate that a delegated command may manipulate a CMK of TPM_KEY_USAGE == TPM_KEY_LEGACY */ #define TPM_CMK_DELEGATE_MIGRATE 0x08000000 /* When set to 1, this bit SHALL indicate that a delegated command may manipulate a CMK of TPM_KEY_USAGE == TPM_KEY_MIGRATE */ /* 6. TPM_TAG (Command and Response Tags) rev 100 These tags indicate to the TPM the construction of the command either as input or as output. The AUTH indicates that there are one or more AuthData values that follow the command parameters. */ #define TPM_TAG_RQU_COMMAND 0x00C1 /* A command with no authentication. */ #define TPM_TAG_RQU_AUTH1_COMMAND 0x00C2 /* An authenticated command with one authentication handle */ #define TPM_TAG_RQU_AUTH2_COMMAND 0x00C3 /* An authenticated command with two authentication handles */ #define TPM_TAG_RSP_COMMAND 0x00C4 /* A response from a command with no authentication */ #define TPM_TAG_RSP_AUTH1_COMMAND 0x00C5 /* An authenticated response with one authentication handle */ #define TPM_TAG_RSP_AUTH2_COMMAND 0x00C6 /* An authenticated response with two authentication handles */ /* TIS 7.2 PCR Attributes */ #define TPM_DEBUG_PCR 16 #define TPM_LOCALITY_4_PCR 17 #define TPM_LOCALITY_3_PCR 18 #define TPM_LOCALITY_2_PCR 19 #define TPM_LOCALITY_1_PCR 20 /* 10.9 TPM_KEY_CONTROL rev 87 Attributes that can control various aspects of key usage and manipulation. Allows for controlling of the key when loaded and how to handle TPM_Startup issues. */ #define TPM_KEY_CONTROL_OWNER_EVICT 0x00000001 /* Owner controls when the key is evicted from the TPM. When set the TPM MUST preserve key the key across all TPM_Init invocations. */ /* 13.1.1 TPM_TRANSPORT_ATTRIBUTES Definitions */ #define TPM_TRANSPORT_ENCRYPT 0x00000001 /* The session will provide encryption using the internal encryption algorithm */ #define TPM_TRANSPORT_LOG 0x00000002 /* The session will provide a log of all operations that occur in the session */ #define TPM_TRANSPORT_EXCLUSIVE 0X00000004 /* The transport session is exclusive and any command executed outside the transport session causes the invalidation of the session */ /* 21.1 TPM_CAPABILITY_AREA rev 115 To identify a capability to be queried. */ #define TPM_CAP_ORD 0x00000001 /* Boolean value. TRUE indicates that the TPM supports the ordinal. FALSE indicates that the TPM does not support the ordinal. Unimplemented optional ordinals and unused (unassigned) ordinals return FALSE. */ #define TPM_CAP_ALG 0x00000002 /* Boolean value. TRUE means that the TPM supports the asymmetric algorithm for TPM_Sign, TPM_Seal, TPM_UnSeal and TPM_UnBind and related commands. FALSE indicates that the asymmetric algorithm is not supported for these types of commands. The TPM MAY return TRUE or FALSE for other than asymmetric algorithms that it supports. Unassigned and unsupported algorithm IDs return FALSE.*/ #define TPM_CAP_PID 0x00000003 /* Boolean value. TRUE indicates that the TPM supports the protocol, FALSE indicates that the TPM does not support the protocol. */ #define TPM_CAP_FLAG 0x00000004 /* Return the TPM_PERMANENT_FLAGS structure or Return the TPM_STCLEAR_FLAGS structure */ #define TPM_CAP_PROPERTY 0x00000005 /* See following table for the subcaps */ #define TPM_CAP_VERSION 0x00000006 /* TPM_STRUCT_VER structure. The Major and Minor must indicate 1.1. The firmware revision MUST indicate 0.0 */ #define TPM_CAP_KEY_HANDLE 0x00000007 /* A TPM_KEY_HANDLE_LIST structure that enumerates all key handles loaded on the TPM. */ #define TPM_CAP_CHECK_LOADED 0x00000008 /* A Boolean value. TRUE indicates that the TPM has enough memory available to load a key of the type specified by TPM_KEY_PARMS. FALSE indicates that the TPM does not have enough memory. */ #define TPM_CAP_SYM_MODE 0x00000009 /* Subcap TPM_SYM_MODE A Boolean value. TRUE indicates that the TPM supports the TPM_SYM_MODE, FALSE indicates the TPM does not support the mode. */ #define TPM_CAP_KEY_STATUS 0x0000000C /* Boolean value of ownerEvict. The handle MUST point to a valid key handle.*/ #define TPM_CAP_NV_LIST 0x0000000D /* A list of TPM_NV_INDEX values that are currently allocated NV storage through TPM_NV_DefineSpace. */ #define TPM_CAP_MFR 0x00000010 /* Manufacturer specific. The manufacturer may provide any additional information regarding the TPM and the TPM state but MUST not expose any sensitive information. */ #define TPM_CAP_NV_INDEX 0x00000011 /* A TPM_NV_DATA_PUBLIC structure that indicates the values for the TPM_NV_INDEX. Returns TPM_BADINDEX if the index is not in the TPM_CAP_NV_LIST list. */ #define TPM_CAP_TRANS_ALG 0x00000012 /* Boolean value. TRUE means that the TPM supports the algorithm for TPM_EstablishTransport, TPM_ExecuteTransport and TPM_ReleaseTransportSigned. FALSE indicates that for these three commands the algorithm is not supported." */ #define TPM_CAP_HANDLE 0x00000014 /* A TPM_KEY_HANDLE_LIST structure that enumerates all handles currently loaded in the TPM for the given resource type. */ #define TPM_CAP_TRANS_ES 0x00000015 /* Boolean value. TRUE means the TPM supports the encryption scheme in a transport session for at least one algorithm.. */ #define TPM_CAP_AUTH_ENCRYPT 0x00000017 /* Boolean value. TRUE indicates that the TPM supports the encryption algorithm in OSAP encryption of AuthData values */ #define TPM_CAP_SELECT_SIZE 0x00000018 /* Boolean value. TRUE indicates that the TPM supports the size for the given version. For instance a request could ask for version 1.1 size 2 and the TPM would indicate TRUE. For 1.1 size 3 the TPM would indicate FALSE. For 1.2 size 3 the TPM would indicate TRUE. */ #define TPM_CAP_DA_LOGIC 0x00000019 /* (OPTIONAL) A TPM_DA_INFO or TPM_DA_INFO_LIMITED structure that returns data according to the selected entity type (e.g., TPM_ET_KEYHANDLE, TPM_ET_OWNER, TPM_ET_SRK, TPM_ET_COUNTER, TPM_ET_OPERATOR, etc.). If the implemented dictionary attack logic does not support different secret types, the entity type can be ignored. */ #define TPM_CAP_VERSION_VAL 0x0000001A /* TPM_CAP_VERSION_INFO structure. The TPM fills in the structure and returns the information indicating what the TPM currently supports. */ #define TPM_CAP_FLAG_PERMANENT 0x00000108 /* Return the TPM_PERMANENT_FLAGS structure */ #define TPM_CAP_FLAG_VOLATILE 0x00000109 /* Return the TPM_STCLEAR_FLAGS structure */ /* 21.2 CAP_PROPERTY Subcap values for CAP_PROPERTY rev 105 The TPM_CAP_PROPERTY capability has numerous subcap values. The definition for all subcap values occurs in this table. TPM_CAP_PROP_MANUFACTURER returns a vendor ID unique to each manufacturer. The same value is returned as the TPM_CAP_VERSION_INFO -> tpmVendorID. A company abbreviation such as a null terminated stock ticker is a typical choice. However, there is no requirement that the value contain printable characters. The document "TCG Vendor Naming" lists the vendor ID values. TPM_CAP_PROP_MAX_xxxSESS is a constant. At TPM_Startup(ST_CLEAR) TPM_CAP_PROP_xxxSESS == TPM_CAP_PROP_MAX_xxxSESS. As sessions are created on the TPM, TPM_CAP_PROP_xxxSESS decreases toward zero. As sessions are terminated, TPM_CAP_PROP_xxxSESS increases toward TPM_CAP_PROP_MAX_xxxSESS. There is a similar relationship between the constants TPM_CAP_PROP_MAX_COUNTERS and TPM_CAP_PROP_MAX_CONTEXT and the varying TPM_CAP_PROP_COUNTERS and TPM_CAP_PROP_CONTEXT. In one typical implementation where authorization and transport sessions reside in separate pools, TPM_CAP_PROP_SESSIONS will be the sum of TPM_CAP_PROP_AUTHSESS and TPM_CAP_PROP_TRANSESS. In another typical implementation where authorization and transport sessions share the same pool, TPM_CAP_PROP_SESSIONS, TPM_CAP_PROP_AUTHSESS, and TPM_CAP_PROP_TRANSESS will all be equal. */ #define TPM_CAP_PROP_PCR 0x00000101 /* uint32_t value. Returns the number of PCR registers supported by the TPM */ #define TPM_CAP_PROP_DIR 0x00000102 /* uint32_t. Deprecated. Returns the number of DIR, which is now fixed at 1 */ #define TPM_CAP_PROP_MANUFACTURER 0x00000103 /* uint32_t value. Returns the vendor ID unique to each TPM manufacturer. */ #define TPM_CAP_PROP_KEYS 0x00000104 /* uint32_t value. Returns the number of 2048- bit RSA keys that can be loaded. This may vary with time and circumstances. */ #define TPM_CAP_PROP_MIN_COUNTER 0x00000107 /* uint32_t. The minimum amount of time in 10ths of a second that must pass between invocations of incrementing the monotonic counter. */ #define TPM_CAP_PROP_AUTHSESS 0x0000010A /* uint32_t. The number of available authorization sessions. This may vary with time and circumstances. */ #define TPM_CAP_PROP_TRANSESS 0x0000010B /* uint32_t. The number of available transport sessions. This may vary with time and circumstances. */ #define TPM_CAP_PROP_COUNTERS 0x0000010C /* uint32_t. The number of available monotonic counters. This may vary with time and circumstances. */ #define TPM_CAP_PROP_MAX_AUTHSESS 0x0000010D /* uint32_t. The maximum number of loaded authorization sessions the TPM supports */ #define TPM_CAP_PROP_MAX_TRANSESS 0x0000010E /* uint32_t. The maximum number of loaded transport sessions the TPM supports. */ #define TPM_CAP_PROP_MAX_COUNTERS 0x0000010F /* uint32_t. The maximum number of monotonic counters under control of TPM_CreateCounter */ #define TPM_CAP_PROP_MAX_KEYS 0x00000110 /* uint32_t. The maximum number of 2048 RSA keys that the TPM can support. The number does not include the EK or SRK. */ #define TPM_CAP_PROP_OWNER 0x00000111 /* BOOL. A value of TRUE indicates that the TPM has successfully installed an owner. */ #define TPM_CAP_PROP_CONTEXT 0x00000112 /* uint32_t. The number of available saved session slots. This may vary with time and circumstances. */ #define TPM_CAP_PROP_MAX_CONTEXT 0x00000113 /* uint32_t. The maximum number of saved session slots. */ #define TPM_CAP_PROP_FAMILYROWS 0x00000114 /* uint32_t. The maximum number of rows in the family table */ #define TPM_CAP_PROP_TIS_TIMEOUT 0x00000115 /* A 4 element array of uint32_t values each denoting the timeout value in microseconds for the following in this order: TIMEOUT_A, TIMEOUT_B, TIMEOUT_C, TIMEOUT_D Where these timeouts are to be used is determined by the platform specific TPM Interface Specification. */ #define TPM_CAP_PROP_STARTUP_EFFECT 0x00000116 /* The TPM_STARTUP_EFFECTS structure */ #define TPM_CAP_PROP_DELEGATE_ROW 0x00000117 /* uint32_t. The maximum size of the delegate table in rows. */ #define TPM_CAP_PROP_MAX_DAASESS 0x00000119 /* uint32_t. The maximum number of loaded DAA sessions (join or sign) that the TPM supports */ #define TPM_CAP_PROP_DAASESS 0x0000011A /* uint32_t. The number of available DAA sessions. This may vary with time and circumstances */ #define TPM_CAP_PROP_CONTEXT_DIST 0x0000011B /* uint32_t. The maximum distance between context count values. This MUST be at least 2^16-1. */ #define TPM_CAP_PROP_DAA_INTERRUPT 0x0000011C /* BOOL. A value of TRUE indicates that the TPM will accept ANY command while executing a DAA Join or Sign. A value of FALSE indicates that the TPM will invalidate the DAA Join or Sign upon the receipt of any command other than the next join/sign in the session or a TPM_SaveContext */ #define TPM_CAP_PROP_SESSIONS 0X0000011D /* uint32_t. The number of available sessions from the pool. This MAY vary with time and circumstances. Pool sessions include authorization and transport sessions. */ #define TPM_CAP_PROP_MAX_SESSIONS 0x0000011E /* uint32_t. The maximum number of sessions the TPM supports. */ #define TPM_CAP_PROP_CMK_RESTRICTION 0x0000011F /* uint32_t TPM_Permanent_Data -> restrictDelegate */ #define TPM_CAP_PROP_DURATION 0x00000120 /* A 3 element array of uint32_t values each denoting the duration value in microseconds of the duration of the three classes of commands: Small, Medium and Long in the following in this order: SMALL_DURATION, MEDIUM_DURATION, LONG_DURATION */ #define TPM_CAP_PROP_ACTIVE_COUNTER 0x00000122 /* TPM_COUNT_ID. The id of the current counter. 0xff..ff if no counter is active */ #define TPM_CAP_PROP_MAX_NV_AVAILABLE 0x00000123 /*uint32_t. Deprecated. The maximum number of NV space that can be allocated, MAY vary with time and circumstances. This capability was not implemented consistently, and is replaced by TPM_NV_INDEX_TRIAL. */ #define TPM_CAP_PROP_INPUT_BUFFER 0x00000124 /* uint32_t. The maximum size of the TPM input buffer or output buffer in bytes. */ /* 21.4 Set_Capability Values rev 107 */ #define TPM_SET_PERM_FLAGS 0x00000001 /* The ability to set a value is field specific and a review of the structure will disclose the ability and requirements to set a value */ #define TPM_SET_PERM_DATA 0x00000002 /* The ability to set a value is field specific and a review of the structure will disclose the ability and requirements to set a value */ #define TPM_SET_STCLEAR_FLAGS 0x00000003 /* The ability to set a value is field specific and a review of the structure will disclose the ability and requirements to set a value */ #define TPM_SET_STCLEAR_DATA 0x00000004 /* The ability to set a value is field specific and a review of the structure will disclose the ability and requirements to set a value */ #define TPM_SET_STANY_FLAGS 0x00000005 /* The ability to set a value is field specific and a review of the structure will disclose the ability and requirements to set a value */ #define TPM_SET_STANY_DATA 0x00000006 /* The ability to set a value is field specific and a review of the structure will disclose the ability and requirements to set a value */ #define TPM_SET_VENDOR 0x00000007 /* This area allows the vendor to set specific areas in the TPM according to the normal shielded location requirements */ /* Set Capability sub caps */ /* TPM_PERMANENT_FLAGS */ #define TPM_PF_DISABLE 1 #define TPM_PF_OWNERSHIP 2 #define TPM_PF_DEACTIVATED 3 #define TPM_PF_READPUBEK 4 #define TPM_PF_DISABLEOWNERCLEAR 5 #define TPM_PF_ALLOWMAINTENANCE 6 #define TPM_PF_PHYSICALPRESENCELIFETIMELOCK 7 #define TPM_PF_PHYSICALPRESENCEHWENABLE 8 #define TPM_PF_PHYSICALPRESENCECMDENABLE 9 #define TPM_PF_CEKPUSED 10 #define TPM_PF_TPMPOST 11 #define TPM_PF_TPMPOSTLOCK 12 #define TPM_PF_FIPS 13 #define TPM_PF_OPERATOR 14 #define TPM_PF_ENABLEREVOKEEK 15 #define TPM_PF_NV_LOCKED 16 #define TPM_PF_READSRKPUB 17 #define TPM_PF_TPMESTABLISHED 18 #define TPM_PF_MAINTENANCEDONE 19 #define TPM_PF_DISABLEFULLDALOGICINFO 20 /* TPM_STCLEAR_FLAGS */ #define TPM_SF_DEACTIVATED 1 #define TPM_SF_DISABLEFORCECLEAR 2 #define TPM_SF_PHYSICALPRESENCE 3 #define TPM_SF_PHYSICALPRESENCELOCK 4 #define TPM_SF_BGLOBALLOCK 5 /* TPM_STANY_FLAGS */ #define TPM_AF_POSTINITIALISE 1 #define TPM_AF_LOCALITYMODIFIER 2 #define TPM_AF_TRANSPORTEXCLUSIVE 3 #define TPM_AF_TOSPRESENT 4 /* TPM_PERMANENT_DATA */ #define TPM_PD_REVMAJOR 1 #define TPM_PD_REVMINOR 2 #define TPM_PD_TPMPROOF 3 #define TPM_PD_OWNERAUTH 4 #define TPM_PD_OPERATORAUTH 5 #define TPM_PD_MANUMAINTPUB 6 #define TPM_PD_ENDORSEMENTKEY 7 #define TPM_PD_SRK 8 #define TPM_PD_DELEGATEKEY 9 #define TPM_PD_CONTEXTKEY 10 #define TPM_PD_AUDITMONOTONICCOUNTER 11 #define TPM_PD_MONOTONICCOUNTER 12 #define TPM_PD_PCRATTRIB 13 #define TPM_PD_ORDINALAUDITSTATUS 14 #define TPM_PD_AUTHDIR 15 #define TPM_PD_RNGSTATE 16 #define TPM_PD_FAMILYTABLE 17 #define TPM_DELEGATETABLE 18 #define TPM_PD_EKRESET 19 #define TPM_PD_LASTFAMILYID 21 #define TPM_PD_NOOWNERNVWRITE 22 #define TPM_PD_RESTRICTDELEGATE 23 #define TPM_PD_TPMDAASEED 24 #define TPM_PD_DAAPROOF 25 /* TPM_STCLEAR_DATA */ #define TPM_SD_CONTEXTNONCEKEY 1 #define TPM_SD_COUNTID 2 #define TPM_SD_OWNERREFERENCE 3 #define TPM_SD_DISABLERESETLOCK 4 #define TPM_SD_PCR 5 #define TPM_SD_DEFERREDPHYSICALPRESENCE 6 /* TPM_STCLEAR_DATA -> deferredPhysicalPresence bits */ #define TPM_DPP_UNOWNED_FIELD_UPGRADE 0x00000001 /* bit 0 TPM_FieldUpgrade */ /* TPM_STANY_DATA */ #define TPM_AD_CONTEXTNONCESESSION 1 #define TPM_AD_AUDITDIGEST 2 #define TPM_AD_CURRENTTICKS 3 #define TPM_AD_CONTEXTCOUNT 4 #define TPM_AD_CONTEXTLIST 5 #define TPM_AD_SESSIONS 6 /* 17. Ordinals rev 110 Ordinals are 32 bit values of type TPM_COMMAND_CODE. The upper byte contains values that serve as flag indicators, the next byte contains values indicating what committee designated the ordinal, and the final two bytes contain the Command Ordinal Index. 3 2 1 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P|C|V| Reserved| Purview | Command Ordinal Index | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Where: P is Protected/Unprotected command. When 0 the command is a Protected command, when 1 the command is an Unprotected command. C is Non-Connection/Connection related command. When 0 this command passes through to either the protected (TPM) or unprotected (TSS) components. V is TPM/Vendor command. When 0 the command is TPM defined, when 1 the command is vendor defined. All reserved area bits are set to 0. */ /* The following masks are created to allow for the quick definition of the commands */ #define TPM_PROTECTED_COMMAND 0x00000000 /* TPM protected command, specified in main specification */ #define TPM_UNPROTECTED_COMMAND 0x80000000 /* TSS command, specified in the TSS specification */ #define TPM_CONNECTION_COMMAND 0x40000000 /* TSC command, protected connection commands are specified in the main specification Unprotected connection commands are specified in the TSS */ #define TPM_VENDOR_COMMAND 0x20000000 /* Command that is vendor specific for a given TPM or TSS. */ /* The following Purviews have been defined: */ #define TPM_MAIN 0x00 /* Command is from the main specification */ #define TPM_PC 0x01 /* Command is specific to the PC */ #define TPM_PDA 0x02 /* Command is specific to a PDA */ #define TPM_CELL_PHONE 0x03 /* Command is specific to a cell phone */ #define TPM_SERVER 0x04 /* Command is specific to servers */ #define TPM_PERIPHERAL 0x05 /* Command is specific to peripherals */ #define TPM_TSS 0x06 /* Command is specific to TSS */ /* Combinations for the main specification would be: */ #define TPM_PROTECTED_ORDINAL (TPM_PROTECTED_COMMAND | TPM_MAIN) #define TPM_UNPROTECTED_ORDINAL (TPM_UNPROTECTED_COMMAND | TPM_MAIN) #define TPM_CONNECTION_ORDINAL (TPM_CONNECTION_COMMAND | TPM_MAIN) /* Command ordinals */ #define TPM_ORD_ActivateIdentity 0x0000007A #define TPM_ORD_AuthorizeMigrationKey 0x0000002B #define TPM_ORD_CertifyKey 0x00000032 #define TPM_ORD_CertifyKey2 0x00000033 #define TPM_ORD_CertifySelfTest 0x00000052 #define TPM_ORD_ChangeAuth 0x0000000C #define TPM_ORD_ChangeAuthAsymFinish 0x0000000F #define TPM_ORD_ChangeAuthAsymStart 0x0000000E #define TPM_ORD_ChangeAuthOwner 0x00000010 #define TPM_ORD_CMK_ApproveMA 0x0000001D #define TPM_ORD_CMK_ConvertMigration 0x00000024 #define TPM_ORD_CMK_CreateBlob 0x0000001B #define TPM_ORD_CMK_CreateKey 0x00000013 #define TPM_ORD_CMK_CreateTicket 0x00000012 #define TPM_ORD_CMK_SetRestrictions 0x0000001C #define TPM_ORD_ContinueSelfTest 0x00000053 #define TPM_ORD_ConvertMigrationBlob 0x0000002A #define TPM_ORD_CreateCounter 0x000000DC #define TPM_ORD_CreateEndorsementKeyPair 0x00000078 #define TPM_ORD_CreateMaintenanceArchive 0x0000002C #define TPM_ORD_CreateMigrationBlob 0x00000028 #define TPM_ORD_CreateRevocableEK 0x0000007F #define TPM_ORD_CreateWrapKey 0x0000001F #define TPM_ORD_DAA_Join 0x00000029 #define TPM_ORD_DAA_Sign 0x00000031 #define TPM_ORD_Delegate_CreateKeyDelegation 0x000000D4 #define TPM_ORD_Delegate_CreateOwnerDelegation 0x000000D5 #define TPM_ORD_Delegate_LoadOwnerDelegation 0x000000D8 #define TPM_ORD_Delegate_Manage 0x000000D2 #define TPM_ORD_Delegate_ReadTable 0x000000DB #define TPM_ORD_Delegate_UpdateVerification 0x000000D1 #define TPM_ORD_Delegate_VerifyDelegation 0x000000D6 #define TPM_ORD_DirRead 0x0000001A #define TPM_ORD_DirWriteAuth 0x00000019 #define TPM_ORD_DisableForceClear 0x0000005E #define TPM_ORD_DisableOwnerClear 0x0000005C #define TPM_ORD_DisablePubekRead 0x0000007E #define TPM_ORD_DSAP 0x00000011 #define TPM_ORD_EstablishTransport 0x000000E6 #define TPM_ORD_EvictKey 0x00000022 #define TPM_ORD_ExecuteTransport 0x000000E7 #define TPM_ORD_Extend 0x00000014 #define TPM_ORD_FieldUpgrade 0x000000AA #define TPM_ORD_FlushSpecific 0x000000BA #define TPM_ORD_ForceClear 0x0000005D #define TPM_ORD_GetAuditDigest 0x00000085 #define TPM_ORD_GetAuditDigestSigned 0x00000086 #define TPM_ORD_GetAuditEvent 0x00000082 #define TPM_ORD_GetAuditEventSigned 0x00000083 #define TPM_ORD_GetCapability 0x00000065 #define TPM_ORD_GetCapabilityOwner 0x00000066 #define TPM_ORD_GetCapabilitySigned 0x00000064 #define TPM_ORD_GetOrdinalAuditStatus 0x0000008C #define TPM_ORD_GetPubKey 0x00000021 #define TPM_ORD_GetRandom 0x00000046 #define TPM_ORD_GetTestResult 0x00000054 #define TPM_ORD_GetTicks 0x000000F1 #define TPM_ORD_IncrementCounter 0x000000DD #define TPM_ORD_Init 0x00000097 #define TPM_ORD_KeyControlOwner 0x00000023 #define TPM_ORD_KillMaintenanceFeature 0x0000002E #define TPM_ORD_LoadAuthContext 0x000000B7 #define TPM_ORD_LoadContext 0x000000B9 #define TPM_ORD_LoadKey 0x00000020 #define TPM_ORD_LoadKey2 0x00000041 #define TPM_ORD_LoadKeyContext 0x000000B5 #define TPM_ORD_LoadMaintenanceArchive 0x0000002D #define TPM_ORD_LoadManuMaintPub 0x0000002F #define TPM_ORD_MakeIdentity 0x00000079 #define TPM_ORD_MigrateKey 0x00000025 #define TPM_ORD_NV_DefineSpace 0x000000CC #define TPM_ORD_NV_ReadValue 0x000000CF #define TPM_ORD_NV_ReadValueAuth 0x000000D0 #define TPM_ORD_NV_WriteValue 0x000000CD #define TPM_ORD_NV_WriteValueAuth 0x000000CE #define TPM_ORD_OIAP 0x0000000A #define TPM_ORD_OSAP 0x0000000B #define TPM_ORD_OwnerClear 0x0000005B #define TPM_ORD_OwnerReadInternalPub 0x00000081 #define TPM_ORD_OwnerReadPubek 0x0000007D #define TPM_ORD_OwnerSetDisable 0x0000006E #define TPM_ORD_PCR_Reset 0x000000C8 #define TPM_ORD_PcrRead 0x00000015 #define TPM_ORD_PhysicalDisable 0x00000070 #define TPM_ORD_PhysicalEnable 0x0000006F #define TPM_ORD_PhysicalSetDeactivated 0x00000072 #define TPM_ORD_Quote 0x00000016 #define TPM_ORD_Quote2 0x0000003E #define TPM_ORD_ReadCounter 0x000000DE #define TPM_ORD_ReadManuMaintPub 0x00000030 #define TPM_ORD_ReadPubek 0x0000007C #define TPM_ORD_ReleaseCounter 0x000000DF #define TPM_ORD_ReleaseCounterOwner 0x000000E0 #define TPM_ORD_ReleaseTransportSigned 0x000000E8 #define TPM_ORD_Reset 0x0000005A #define TPM_ORD_ResetLockValue 0x00000040 #define TPM_ORD_RevokeTrust 0x00000080 #define TPM_ORD_SaveAuthContext 0x000000B6 #define TPM_ORD_SaveContext 0x000000B8 #define TPM_ORD_SaveKeyContext 0x000000B4 #define TPM_ORD_SaveState 0x00000098 #define TPM_ORD_Seal 0x00000017 #define TPM_ORD_Sealx 0x0000003D #define TPM_ORD_SelfTestFull 0x00000050 #define TPM_ORD_SetCapability 0x0000003F #define TPM_ORD_SetOperatorAuth 0x00000074 #define TPM_ORD_SetOrdinalAuditStatus 0x0000008D #define TPM_ORD_SetOwnerInstall 0x00000071 #define TPM_ORD_SetOwnerPointer 0x00000075 #define TPM_ORD_SetRedirection 0x0000009A #define TPM_ORD_SetTempDeactivated 0x00000073 #define TPM_ORD_SHA1Complete 0x000000A2 #define TPM_ORD_SHA1CompleteExtend 0x000000A3 #define TPM_ORD_SHA1Start 0x000000A0 #define TPM_ORD_SHA1Update 0x000000A1 #define TPM_ORD_Sign 0x0000003C #define TPM_ORD_Startup 0x00000099 #define TPM_ORD_StirRandom 0x00000047 #define TPM_ORD_TakeOwnership 0x0000000D #define TPM_ORD_Terminate_Handle 0x00000096 #define TPM_ORD_TickStampBlob 0x000000F2 #define TPM_ORD_UnBind 0x0000001E #define TPM_ORD_Unseal 0x00000018 #define TSC_ORD_PhysicalPresence 0x4000000A #define TSC_ORD_ResetEstablishmentBit 0x4000000B /* 19. NV storage structures */ /* 19.1 TPM_NV_INDEX rev 110 The index provides the handle to identify the area of storage. The reserved bits allow for a segregation of the index name space to avoid name collisions. The TPM may check the resvd bits for zero. Thus, applications should set the bits to zero. The TCG defines the space where the high order bits (T, P, U) are 0. The other spaces are controlled by the indicated entity. T is the TPM manufacturer reserved bit. 0 indicates a TCG defined value. 1 indicates a TPM manufacturer specific value. P is the platform manufacturer reserved bit. 0 indicates a TCG defined value. 1 indicates that the index is controlled by the platform manufacturer. U is for the platform user. 0 indicates a TCG defined value. 1 indicates that the index is controlled by the platform user. The TPM_NV_INDEX is a 32-bit value. 3 2 1 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |T|P|U|D| resvd | Purview | Index | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Where: 1. The TPM MAY return an error if the reserved area bits are not set to 0. 2. The TPM MUST accept all values for T, P, and U 3. D indicates defined. 1 indicates that the index is permanently defined and that any TPM_NV_DefineSpace operation will fail after nvLocked is set TRUE. a. TCG reserved areas MAY have D set to 0 or 1 4. Purview is the value used to indicate the platform specific area. This value is the same as used for command ordinals. a. The TPM MUST reject purview values that the TPM cannot support. This means that an index value for a PDA MUST be rejected by a TPM designed to work only on the PC Client. */ #define TPM_NV_INDEX_T_BIT 0x80000000 #define TPM_NV_INDEX_P_BIT 0x40000000 #define TPM_NV_INDEX_U_BIT 0x20000000 #define TPM_NV_INDEX_D_BIT 0x10000000 /* added kgold */ #define TPM_NV_INDEX_RESVD 0x0f000000 #define TPM_NV_INDEX_PURVIEW_BIT 16 #define TPM_NV_INDEX_PURVIEW_MASK 0x00ff0000 /* 19.1.1 Required TPM_NV_INDEX values rev 97 The required index values must be found on each TPM regardless of platform. These areas are always present and do not require a TPM_DefineSpace command to allocate. A platform specific specification may add additional required index values for the platform. The TPM MUST reserve the space as indicated for the required index values */ #define TPM_NV_INDEX_LOCK 0xFFFFFFFF /* This value turns on the NV authorization protections. Once executed all NV areas use the protections as defined. This value never resets. Attempting to execute TPM_NV_DefineSpace on this value with non-zero size MAY result in a TPM_BADINDEX response. */ #define TPM_NV_INDEX0 0x00000000 /* This value allows for the setting of the bGlobalLock flag, which is only reset on TPM_Startup(ST_Clear) Attempting to execute TPM_NV_WriteValue with a size other than zero MAY result in the TPM_BADINDEX error code. */ #define TPM_NV_INDEX_DIR 0x10000001 /* Size MUST be 20. This index points to the deprecated DIR command area from 1.1. The TPM MUST map this reserved space to be the area operated on by the 1.1 DIR commands. */ /* 19.1.2 Reserved Index values rev 116 The reserved values are defined to avoid index collisions. These values are not in each and every TPM. 1. The reserved index values are to avoid index value collisions. 2. These index values require a TPM_DefineSpace to have the area for the index allocated 3. A platform specific specification MAY indicate that reserved values are required. 4. The reserved index values MAY have their D bit set by the TPM vendor to permanently */ #define TPM_NV_INDEX_TPM 0x0000Fxxx /* Reserved for TPM use */ #define TPM_NV_INDEX_EKCert 0x0000F000 /* The Endorsement credential */ #define TPM_NV_INDEX_TPM_CC 0x0000F001 /* The TPM Conformance credential */ #define TPM_NV_INDEX_PlatformCert 0x0000F002 /* The platform credential */ #define TPM_NV_INDEX_Platform_CC 0x0000F003 /* The Platform conformance credential */ #define TPM_NV_INDEX_TRIAL 0x0000F004 /* To try TPM_NV_DefineSpace without actually allocating NV space */ #if 0 #define TPM_NV_INDEX_PC 0x0001xxxx /* Reserved for PC Client use */ #define TPM_NV_INDEX_GPIO_xx 0x000116xx /* Reserved for GPIO pins */ #define TPM_NV_INDEX_PDA 0x0002xxxx /* Reserved for PDA use */ #define TPM_NV_INDEX_MOBILE 0x0003xxxx /* Reserved for mobile use */ #define TPM_NV_INDEX_SERVER 0x0004xxxx /* Reserved for Server use */ #define TPM_NV_INDEX_PERIPHERAL 0x0005xxxx /* Reserved for peripheral use */ #define TPM_NV_INDEX_TSS 0x0006xxxx /* Reserved for TSS use */ #define TPM_NV_INDEX_GROUP_RESV 0x00xxxxxx /* Reserved for TCG WG use */ #endif #define TPM_NV_INDEX_GPIO_00 0x00011600 /* GPIO-Express-00 */ #define TPM_NV_INDEX_GPIO_START 0x00011600 /* Reserved for GPIO pins */ #define TPM_NV_INDEX_GPIO_END 0x000116ff /* Reserved for GPIO pins */ /* 19.2 TPM_NV_ATTRIBUTES rev 99 The attributes TPM_NV_PER_AUTHREAD and TPM_NV_PER_OWNERREAD cannot both be set to TRUE. Similarly, the attributes TPM_NV_PER_AUTHWRITE and TPM_NV_PER_OWNERWRITE cannot both be set to TRUE. */ #define TPM_NV_PER_READ_STCLEAR 0x80000000 /* 31: The value can be read until locked by a read with a data size of 0. It can only be unlocked by TPM_Startup(ST_Clear) or a successful write. Lock held for each area in bReadSTClear. */ /* #define 30:19 Reserved */ #define TPM_NV_PER_AUTHREAD 0x00040000 /* 18: The value requires authorization to read */ #define TPM_NV_PER_OWNERREAD 0x00020000 /* 17: The value requires TPM Owner authorization to read. */ #define TPM_NV_PER_PPREAD 0x00010000 /* 16: The value requires physical presence to read */ #define TPM_NV_PER_GLOBALLOCK 0x00008000 /* 15: The value is writable until a write to index 0 is successful. The lock of this attribute is reset by TPM_Startup(ST_CLEAR). Lock held by SF -> bGlobalLock */ #define TPM_NV_PER_WRITE_STCLEAR 0x00004000 /* 14: The value is writable until a write to the specified index with a datasize of 0 is successful. The lock of this attribute is reset by TPM_Startup(ST_CLEAR). Lock held for each area in bWriteSTClear. */ #define TPM_NV_PER_WRITEDEFINE 0x00002000 /* 13: Lock set by writing to the index with a datasize of 0. Lock held for each area in bWriteDefine. This is a persistent lock. */ #define TPM_NV_PER_WRITEALL 0x00001000 /* 12: The value must be written in a single operation */ /* #define 11:3 Reserved for write additions */ #define TPM_NV_PER_AUTHWRITE 0x00000004 /* 2: The value requires authorization to write */ #define TPM_NV_PER_OWNERWRITE 0x00000002 /* 1: The value requires TPM Owner authorization to write */ #define TPM_NV_PER_PPWRITE 0x00000001 /* 0: The value requires physical presence to write */ /* 20.2.1 Owner Permission Settings rev 87 */ /* Per1 bits */ #define TPM_DELEGATE_PER1_MASK 0xffffffff /* mask of legal bits */ #define TPM_DELEGATE_KeyControlOwner 31 #define TPM_DELEGATE_SetOrdinalAuditStatus 30 #define TPM_DELEGATE_DirWriteAuth 29 #define TPM_DELEGATE_CMK_ApproveMA 28 #define TPM_DELEGATE_NV_WriteValue 27 #define TPM_DELEGATE_CMK_CreateTicket 26 #define TPM_DELEGATE_NV_ReadValue 25 #define TPM_DELEGATE_Delegate_LoadOwnerDelegation 24 #define TPM_DELEGATE_DAA_Join 23 #define TPM_DELEGATE_AuthorizeMigrationKey 22 #define TPM_DELEGATE_CreateMaintenanceArchive 21 #define TPM_DELEGATE_LoadMaintenanceArchive 20 #define TPM_DELEGATE_KillMaintenanceFeature 19 #define TPM_DELEGATE_OwnerReadInternalPub 18 #define TPM_DELEGATE_ResetLockValue 17 #define TPM_DELEGATE_OwnerClear 16 #define TPM_DELEGATE_DisableOwnerClear 15 #define TPM_DELEGATE_NV_DefineSpace 14 #define TPM_DELEGATE_OwnerSetDisable 13 #define TPM_DELEGATE_SetCapability 12 #define TPM_DELEGATE_MakeIdentity 11 #define TPM_DELEGATE_ActivateIdentity 10 #define TPM_DELEGATE_OwnerReadPubek 9 #define TPM_DELEGATE_DisablePubekRead 8 #define TPM_DELEGATE_SetRedirection 7 #define TPM_DELEGATE_FieldUpgrade 6 #define TPM_DELEGATE_Delegate_UpdateVerification 5 #define TPM_DELEGATE_CreateCounter 4 #define TPM_DELEGATE_ReleaseCounterOwner 3 #define TPM_DELEGATE_Delegate_Manage 2 #define TPM_DELEGATE_Delegate_CreateOwnerDelegation 1 #define TPM_DELEGATE_DAA_Sign 0 /* Per2 bits */ #define TPM_DELEGATE_PER2_MASK 0x00000000 /* mask of legal bits */ /* All reserved */ /* 20.2.3 Key Permission settings rev 85 */ /* Per1 bits */ #define TPM_KEY_DELEGATE_PER1_MASK 0x1fffffff /* mask of legal bits */ #define TPM_KEY_DELEGATE_CMK_ConvertMigration 28 #define TPM_KEY_DELEGATE_TickStampBlob 27 #define TPM_KEY_DELEGATE_ChangeAuthAsymStart 26 #define TPM_KEY_DELEGATE_ChangeAuthAsymFinish 25 #define TPM_KEY_DELEGATE_CMK_CreateKey 24 #define TPM_KEY_DELEGATE_MigrateKey 23 #define TPM_KEY_DELEGATE_LoadKey2 22 #define TPM_KEY_DELEGATE_EstablishTransport 21 #define TPM_KEY_DELEGATE_ReleaseTransportSigned 20 #define TPM_KEY_DELEGATE_Quote2 19 #define TPM_KEY_DELEGATE_Sealx 18 #define TPM_KEY_DELEGATE_MakeIdentity 17 #define TPM_KEY_DELEGATE_ActivateIdentity 16 #define TPM_KEY_DELEGATE_GetAuditDigestSigned 15 #define TPM_KEY_DELEGATE_Sign 14 #define TPM_KEY_DELEGATE_CertifyKey2 13 #define TPM_KEY_DELEGATE_CertifyKey 12 #define TPM_KEY_DELEGATE_CreateWrapKey 11 #define TPM_KEY_DELEGATE_CMK_CreateBlob 10 #define TPM_KEY_DELEGATE_CreateMigrationBlob 9 #define TPM_KEY_DELEGATE_ConvertMigrationBlob 8 #define TPM_KEY_DELEGATE_Delegate_CreateKeyDelegation 7 #define TPM_KEY_DELEGATE_ChangeAuth 6 #define TPM_KEY_DELEGATE_GetPubKey 5 #define TPM_KEY_DELEGATE_UnBind 4 #define TPM_KEY_DELEGATE_Quote 3 #define TPM_KEY_DELEGATE_Unseal 2 #define TPM_KEY_DELEGATE_Seal 1 #define TPM_KEY_DELEGATE_LoadKey 0 /* Per2 bits */ #define TPM_KEY_DELEGATE_PER2_MASK 0x00000000 /* mask of legal bits */ /* All reserved */ /* 20.3 TPM_FAMILY_FLAGS rev 87 These flags indicate the operational state of the delegation and family table. These flags are additions to TPM_PERMANENT_FLAGS and are not stand alone values. */ #define TPM_DELEGATE_ADMIN_LOCK 0x00000002 /* TRUE: Some TPM_Delegate_XXX commands are locked and return TPM_DELEGATE_LOCK FALSE: TPM_Delegate_XXX commands are available Default is FALSE */ #define TPM_FAMFLAG_ENABLED 0x00000001 /* When TRUE the table is enabled. The default value is FALSE. */ /* 20.14 TPM_FAMILY_OPERATION Values rev 87 These are the opFlag values used by TPM_Delegate_Manage. */ #define TPM_FAMILY_CREATE 0x00000001 /* Create a new family */ #define TPM_FAMILY_ENABLE 0x00000002 /* Set or reset the enable flag for this family. */ #define TPM_FAMILY_ADMIN 0x00000003 /* Prevent administration of this family. */ #define TPM_FAMILY_INVALIDATE 0x00000004 /* Invalidate a specific family row. */ /* 21.9 TPM_DA_STATE rev 100 TPM_DA_STATE enumerates the possible states of the dictionary attack mitigation logic. */ #define TPM_DA_STATE_INACTIVE 0x00 /* The dictionary attack mitigation logic is currently inactive */ #define TPM_DA_STATE_ACTIVE 0x01 /* The dictionary attack mitigation logic is active. TPM_DA_ACTION_TYPE (21.10) is in progress. */ /* 21.10 TPM_DA_ACTION_TYPE rev 100 */ /* 31-4 Reserved No information and MUST be FALSE */ #define TPM_DA_ACTION_FAILURE_MODE 0x00000008 /* bit 3: The TPM is in failure mode. */ #define TPM_DA_ACTION_DEACTIVATE 0x00000004 /* bit 2: The TPM is in the deactivated state. */ #define TPM_DA_ACTION_DISABLE 0x00000002 /* bit 1: The TPM is in the disabled state. */ #define TPM_DA_ACTION_TIMEOUT 0x00000001 /* bit 0: The TPM will be in a locked state for TPM_DA_INFO -> actionDependValue seconds. This value is dynamic, depending on the time the lock has been active. */ /* 22. DAA Structures rev 91 All byte and bit areas are byte arrays treated as large integers */ #define DAA_SIZE_r0 43 #define DAA_SIZE_r1 43 #define DAA_SIZE_r2 128 #define DAA_SIZE_r3 168 #define DAA_SIZE_r4 219 #define DAA_SIZE_NT 20 #define DAA_SIZE_v0 128 #define DAA_SIZE_v1 192 #define DAA_SIZE_NE 256 #define DAA_SIZE_w 256 #define DAA_SIZE_issuerModulus 256 /* check that DAA_SIZE_issuerModulus will fit in DAA_scratch */ #if (DAA_SIZE_issuerModulus != 256) #error "DAA_SIZE_issuerModulus must be 256" #endif /* 22.2 Constant definitions rev 91 */ #define DAA_power0 104 #define DAA_power1 1024 #endif libtpms-0.9.3/src/tpm12/tpm_counter.c000066400000000000000000001511161421143571500174420ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Counter Handler */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_counter.c 4539 2011-04-04 21:44:22Z kgoldman $ */ /* */ //* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include #include #include "tpm_auth.h" #include "tpm_cryptoh.h" #include "tpm_debug.h" #include "tpm_digest.h" #include "tpm_error.h" #include "tpm_io.h" #include "tpm_permanent.h" #include "tpm_process.h" #include "tpm_secret.h" #include "tpm_counter.h" /* Monotonic Counter Resource Handling */ /* TPM_Counters_Init() initializes the monotonic counters */ void TPM_Counters_Init(TPM_COUNTER_VALUE *monotonicCounters) { uint32_t i; for (i = 0 ; i < TPM_MIN_COUNTERS ; i++) { TPM_CounterValue_Init(&(monotonicCounters[i])); } return; } /* TPM_Counters_Load() loads the monotonic counters deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes */ TPM_RESULT TPM_Counters_Load(TPM_COUNTER_VALUE *monotonicCounters, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; uint32_t i; /* load the counters */ for (i = 0 ; (rc == 0) && (i < TPM_MIN_COUNTERS) ; i++) { rc = TPM_CounterValue_Load(&(monotonicCounters[i]), stream, stream_size); } return rc; } TPM_RESULT TPM_Counters_Store(TPM_STORE_BUFFER *sbuffer, TPM_COUNTER_VALUE *monotonicCounters) { TPM_RESULT rc = 0; uint32_t i; /* store the counters */ for (i = 0 ; (rc == 0) && (i < TPM_MIN_COUNTERS) ; i++) { rc = TPM_CounterValue_Store(sbuffer, &(monotonicCounters[i])); } return rc; } /* TPM_Counters_StoreHandles() stores a count of the created counters and a list of created counter handles. */ TPM_RESULT TPM_Counters_StoreHandles(TPM_STORE_BUFFER *sbuffer, TPM_COUNTER_VALUE *monotonicCounters) { TPM_RESULT rc = 0; uint16_t loaded; uint32_t i; printf(" TPM_Counters_StoreHandles:\n"); if (rc == 0) { loaded = 0; /* count the number of loaded counters */ for (i = 0 ; i < TPM_MIN_COUNTERS ; i++) { if ((monotonicCounters[i]).valid) { loaded++; } } /* store created handle count */ rc = TPM_Sbuffer_Append16(sbuffer, loaded); } for (i = 0 ; (rc == 0) && (i < TPM_MIN_COUNTERS) ; i++) { if ((monotonicCounters[i]).valid) { /* the handle is just the index */ rc = TPM_Sbuffer_Append32(sbuffer, i); /* store it */ } } return rc; } /* TPM_Counters_GetSpace() returns the number of unused monotonicCounters. */ void TPM_Counters_GetSpace(uint32_t *space, TPM_COUNTER_VALUE *monotonicCounters) { uint32_t i; printf(" TPM_Counters_GetSpace:\n"); for (*space = 0 , i = 0 ; i < TPM_MIN_COUNTERS ; i++) { if (!(monotonicCounters[i]).valid) { (*space)++; } } return; } /* TPM_Counters_GetNewHandle() checks for space in the monotonicCounters table. If there is space, it returns a TPM_COUNTER_VALUE entry in 'tpm_counter_value' and its handle in 'countID'. The entry is marked 'valid'. Returns TPM_RESOURCES if there is no space in the sessions table. monotonicCounters is not altered on error. */ TPM_RESULT TPM_Counters_GetNewHandle(TPM_COUNTER_VALUE **tpm_counter_value, TPM_COUNT_ID *countID, TPM_COUNTER_VALUE *monotonicCounters) { TPM_RESULT rc = 0; TPM_BOOL is_space; printf(" TPM_Counters_GetNewHandle:\n"); for (*countID = 0, is_space = FALSE ; *countID < TPM_MIN_COUNTERS ; (*countID)++) { if (!(monotonicCounters[*countID]).valid) { is_space = TRUE; break; } } /* NOTE: According to TPMWG email, TPM_COUNT_ID can be an index */ if (is_space) { printf(" TPM_Counters_GetNewHandle: Assigned handle %u\n", *countID); *tpm_counter_value = &(monotonicCounters[*countID]); (*tpm_counter_value)->valid = TRUE; /* mark it occupied */ } else { printf("TPM_Counters_GetNewHandle: Error, no space in monotonicCounters table\n"); rc = TPM_RESOURCES; } return rc; } /* TPM_Counters_GetNextCount() searches the monotonicCounters for the maximum count, and returns nextCount equal to the incremented maximum count. The counter does not have to be valid (created). It can be invalid (released). */ void TPM_Counters_GetNextCount(TPM_ACTUAL_COUNT *nextCount, TPM_COUNTER_VALUE *monotonicCounters) { TPM_COUNT_ID countID; TPM_ACTUAL_COUNT maxCount = 0; printf(" TPM_Counters_GetNextCount:\n"); for (countID = 0 ; countID < TPM_MIN_COUNTERS ; countID++) { if (monotonicCounters[countID].counter > maxCount) { maxCount = monotonicCounters[countID].counter; } } *nextCount = maxCount + 1; printf(" TPM_Counters_GetNextCount: Next count %u\n", *nextCount); return; } /* TPM_Counters_IsValidId() verifies that countID is in range and a created counter */ TPM_RESULT TPM_Counters_IsValidId(TPM_COUNTER_VALUE *monotonicCounters, TPM_COUNT_ID countID) { TPM_RESULT rc = 0; printf(" TPM_Counters_IsValidId: countID %u\n", countID); /* range check */ if (rc == 0) { if (countID >= TPM_MIN_COUNTERS) { printf("TPM_Counters_IsValidId: Error countID %u out of range\n", countID); rc = TPM_BAD_COUNTER ; } } /* validity (creation) check */ if (rc == 0) { if (!(monotonicCounters[countID].valid)) { printf("TPM_Counters_IsValidId: Error countID %u invalid\n", countID); rc = TPM_BAD_COUNTER ; } } return rc; } /* TPM_Counters_GetCounterValue() gets the TPM_COUNTER_VALUE associated with the countID. */ TPM_RESULT TPM_Counters_GetCounterValue(TPM_COUNTER_VALUE **tpm_counter_value, TPM_COUNTER_VALUE *monotonicCounters, TPM_COUNT_ID countID) { TPM_RESULT rc = 0; printf(" TPM_Counters_GetCounterValue: countID %u\n", countID); /* valid counter check */ if (rc == 0) { rc = TPM_Counters_IsValidId(monotonicCounters, countID); } if (rc == 0) { *tpm_counter_value = &(monotonicCounters[countID]); } return rc; } /* TPM_Counters_Release() iterates through all monotonicCounter's, and releases those that are created. The resource is set invalid, and the authorization data and digest are cleared. a. This includes invalidating all currently allocated counters. The result will be no currently allocated counters and the new owner will need to allocate counters. The actual count value will continue to increase. */ TPM_RESULT TPM_Counters_Release(TPM_COUNTER_VALUE *monotonicCounters) { TPM_RESULT rc = 0; TPM_COUNT_ID i; printf(" TPM_Counters_Release:\n"); for (i = 0 ; i < TPM_MIN_COUNTERS ; i++) { if (monotonicCounters[i].valid) { /* the actual count value does not reset to zero */ printf(" TPM_Counters_Release: Releasing %u\n", i); TPM_Secret_Init(monotonicCounters[i].authData); TPM_Digest_Init(monotonicCounters[i].digest); monotonicCounters[i].valid = FALSE; } } return rc; } /* TPM_Counters_GetActiveCounter() gets the active counter based on the value in TPM_STCLEAR_DATA -> countID */ void TPM_Counters_GetActiveCounter(TPM_COUNT_ID *activeCounter, TPM_COUNT_ID countID) { if (countID < TPM_MIN_COUNTERS) { *activeCounter = countID; } else { *activeCounter = TPM_COUNT_ID_NULL; } } /* TPM_COUNTER_VALUE */ /* TPM_CounterValue_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_CounterValue_Init(TPM_COUNTER_VALUE *tpm_counter_value) { printf(" TPM_CounterValue_Init:\n"); memset(tpm_counter_value->label, 0, TPM_COUNTER_LABEL_SIZE); tpm_counter_value->counter = 0; TPM_Secret_Init(tpm_counter_value->authData); tpm_counter_value->valid = FALSE; return; } /* TPM_CounterValue_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes */ TPM_RESULT TPM_CounterValue_Load(TPM_COUNTER_VALUE *tpm_counter_value, /* result */ unsigned char **stream, /* pointer to next parameter */ uint32_t *stream_size) /* stream size left */ { TPM_RESULT rc = 0; printf(" TPM_CounterValue_Load:\n"); /* check tag */ if (rc == 0) { rc = TPM_CheckTag(TPM_TAG_COUNTER_VALUE, stream, stream_size); } /* load label */ if (rc == 0) { rc = TPM_Loadn(tpm_counter_value->label, TPM_COUNTER_LABEL_SIZE, stream, stream_size); } /* load counter */ if (rc == 0) { rc = TPM_Load32(&(tpm_counter_value->counter), stream, stream_size); } /* load authData */ if (rc == 0) { rc = TPM_Secret_Load(tpm_counter_value->authData, stream, stream_size); } /* load valid */ if (rc == 0) { rc = TPM_LoadBool(&(tpm_counter_value->valid), stream, stream_size); } return rc; } /* TPM_CounterValue_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes It is typically used to store the structure in the permanent data file. */ TPM_RESULT TPM_CounterValue_Store(TPM_STORE_BUFFER *sbuffer, const TPM_COUNTER_VALUE *tpm_counter_value) { TPM_RESULT rc = 0; printf(" TPM_CounterValue_Store:\n"); /* store tag, label, counter */ if (rc == 0) { rc = TPM_CounterValue_StorePublic(sbuffer, tpm_counter_value); } /* store authData */ if (rc == 0) { rc = TPM_Secret_Store(sbuffer, tpm_counter_value->authData); } /* store valid */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_counter_value->valid), sizeof(TPM_BOOL)); } return rc; } /* TPM_CounterValue_StorePublic() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes This version only stores the public, externally visible fields: tag, label, counter. It is typically used to return outgoing parameters. */ TPM_RESULT TPM_CounterValue_StorePublic(TPM_STORE_BUFFER *sbuffer, const TPM_COUNTER_VALUE *tpm_counter_value) { TPM_RESULT rc = 0; printf(" TPM_CounterValue_StorePublic:\n"); /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_COUNTER_VALUE); } /* store label */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, tpm_counter_value->label, TPM_COUNTER_LABEL_SIZE); } /* store counter */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_counter_value->counter); } return rc; } /* TPM_CounterValue_CopyPublic() copies the public, externally visible fields: tag, label, counter. */ void TPM_CounterValue_CopyPublic(TPM_COUNTER_VALUE *dst_tpm_counter_value, TPM_COUNTER_VALUE *src_tpm_counter_value) { memcpy(dst_tpm_counter_value->label, src_tpm_counter_value->label, TPM_COUNTER_LABEL_SIZE); dst_tpm_counter_value->counter = src_tpm_counter_value->counter; return; } /* TPM_CounterValue_Set() Sets the label, counter, and authData members from input parameters, and sets the digest from members. */ TPM_RESULT TPM_CounterValue_Set(TPM_COUNTER_VALUE *tpm_counter_value, TPM_COUNT_ID countID, BYTE *label, TPM_ACTUAL_COUNT counter, TPM_SECRET authData) { TPM_RESULT rc = 0; printf(" TPM_CounterValue_Set:\n"); tpm_counter_value->counter = counter; memcpy(tpm_counter_value->label, label, TPM_COUNTER_LABEL_SIZE); TPM_Secret_Copy(tpm_counter_value->authData, authData); /* create a hopefully unique digest of the object for the OSAP setup. The cast is OK here since the actual value of the digest is never verified. */ rc = TPM_SHA1(tpm_counter_value->digest, sizeof(TPM_COUNT_ID), (unsigned char *)&countID, TPM_COUNTER_LABEL_SIZE, label, TPM_SECRET_SIZE, authData, 0, NULL); return rc; } /* TPM_CounterValue_Release() releases a counter. The resource is set invalid, and the authorization data and digest are cleared. */ TPM_RESULT TPM_CounterValue_Release(TPM_COUNTER_VALUE *tpm_counter_value, TPM_COUNT_ID countID) { TPM_RESULT rc = 0; printf(" TPM_CounterValue_Release: countID %u\n", countID); /* sanity check */ if (rc == 0) { if (!tpm_counter_value->valid) { printf("TPM_CounterValue_Release: Error (fatal), countID %u not valid\n", countID); rc = TPM_FAIL; /* should never occur */ } } if (rc == 0) { TPM_Secret_Init(tpm_counter_value->authData); TPM_Digest_Init(tpm_counter_value->digest); tpm_counter_value->valid = FALSE; } return rc; } /* Processing Functions */ /* 25.1 TPM_CreateCounter rev 98 This command creates the counter but does not select the counter. Counter creation assigns an AuthData value to the counter and sets the counters original start value. The original start value is the current internal base value plus one. Setting the new counter to the internal base avoids attacks on the system that are attempting to use old counter values. This command creates a new monotonic counter. The TPM MUST support a minimum of 4 concurrent counters. */ TPM_RESULT TPM_Process_CreateCounter(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_ENCAUTH encAuth; /* The encrypted auth data for the new counter */ BYTE label[TPM_COUNTER_LABEL_SIZE]; /* Label to associate with counter */ TPM_AUTHHANDLE authHandle; /* The authorization session handle used for owner authentication. */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* Ignored */ TPM_AUTHDATA ownerAuth; /* Authorization ownerAuth. */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus = FALSE; /* audit the ordinal */ TPM_BOOL transportEncrypt = FALSE; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_SECRET *hmacKey = NULL; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ TPM_SECRET a1Auth; TPM_ACTUAL_COUNT nextCount; TPM_BOOL writeAllNV= FALSE; /* flag to write back NV */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_COUNT_ID countID = 0; /* The handle for the counter */ TPM_COUNTER_VALUE *counterValue = NULL; /* The starting counter value */ printf("TPM_Process_CreateCounter: Ordinal Entry\n"); /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get authData */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Authdata_Load(encAuth, &command, ¶mSize); } /* get label */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Loadn(label, TPM_COUNTER_LABEL_SIZE, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { TPM_PrintFour("TPM_Process_CreateCounter: label", label); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag1(tag); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, ownerAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_CreateCounter: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* 1. Using the authHandle field, validate the owner's AuthData to execute the command and all of the incoming parameters. The authorization session MUST be OSAP or DSAP. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_OSAP, TPM_ET_OWNER, ordinal, NULL, NULL, tpm_state->tpm_permanent_data.ownerAuth); } if (returnCode == TPM_SUCCESS) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, ownerAuth); /* Authorization digest for input */ } /* 2. Ignore continueAuthSession on input and set continueAuthSession to FALSE on output */ if (returnCode == TPM_SUCCESS) { continueAuthSession = FALSE; } /* 3. Create a1 by decrypting encAuth according to the ADIP indicated by authHandle. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessionData_Decrypt(a1Auth, NULL, encAuth, auth_session_data, NULL, NULL, FALSE); /* even and odd */ } /* 4. Validate that there is sufficient internal space in the TPM to create a new counter. If there is insufficient space the command returns an error. */ /* a. The TPM MUST provide storage for a1, TPM_COUNTER_VALUE, countID, and any other internal data the TPM needs to associate with the counter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Counters_GetNewHandle(&counterValue, /* structure */ &countID, /* index */ tpm_state->tpm_permanent_data.monotonicCounter); } if (returnCode == TPM_SUCCESS) { writeAllNV = TRUE; /* 5. Increment the max counter value */ TPM_Counters_GetNextCount(&nextCount, tpm_state->tpm_permanent_data.monotonicCounter); /* 6. Set the counter to the max counter value */ /* 7. Set the counter label to label */ returnCode = TPM_CounterValue_Set(counterValue, countID, label, nextCount, a1Auth); /* 8. Create a countID */ /* NOTE Done in TPM_Counters_GetNewHandle() */ } /* save the permanent data structure in NVRAM */ returnCode = TPM_PermanentAll_NVStore(tpm_state, writeAllNV, returnCode); /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_CreateCounter: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* return the countID */ returnCode = TPM_Sbuffer_Append32(response, countID); } if (returnCode == TPM_SUCCESS) { /* Return the TPM_COUNTER_VALUE publicly visible members */ returnCode = TPM_CounterValue_StorePublic(response, counterValue); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ return rcf; } /* 25.2 TPM_IncrementCounter rev 87 This authorized command increments the indicated counter by one. Once a counter has been incremented then all subsequent increments must be for the same handle until a successful TPM_Startup(ST_CLEAR) is executed. The order for checking validation of the command parameters when no counter is active, keeps an attacker from creating a denial-of-service attack. This function increments the counter by 1. The TPM MAY implement increment throttling to avoid burn problems */ TPM_RESULT TPM_Process_IncrementCounter(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_COUNT_ID countID; /* The handle of a valid counter */ TPM_AUTHHANDLE authHandle; /* The authorization session handle used for counter authorization */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization session handle */ TPM_AUTHDATA counterAuth; /* The authorization session digest that authorizes the use of countID. HMAC key: countID -> authData */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_SECRET *hmacKey; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_COUNTER_VALUE *counterValue = NULL; /* The counter value */ printf("TPM_Process_IncrementCounter: Ordinal Entry\n"); /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get countID */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&countID, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_IncrementCounter: countID %u\n", countID); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag1(tag); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, counterAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_IncrementCounter: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* The first check is that either there is no active counter and the countID has been created or that the countID is the active counter */ if (returnCode == TPM_SUCCESS) { /* 1. If TPM_STCLEAR_DATA -> countID is NULL */ if (tpm_state->tpm_stclear_data.countID == TPM_COUNT_ID_NULL) { /* a. Validate that countID is a valid counter, return TPM_BAD_COUNTER on mismatch */ returnCode = TPM_Counters_IsValidId(tpm_state->tpm_permanent_data.monotonicCounter, countID); } /* 2. else (TPM_STCLEAR_DATA -> countID is not NULL */ else { /* a. If TPM_STCLEAR_DATA -> countID does not equal countID */ if (tpm_state->tpm_stclear_data.countID != countID) { if (tpm_state->tpm_stclear_data.countID == TPM_COUNT_ID_ILLEGAL) { printf("TPM_Process_IncrementCounter: Error, counter has been released\n"); } else { printf("TPM_Process_IncrementCounter: Error, %u is already active\n", tpm_state->tpm_stclear_data.countID); } /* i. Return TPM_BAD_COUNTER */ returnCode = TPM_BAD_COUNTER; } } } /* b. Validate the command parameters using counterAuth */ /* Get the TPM_COUNTER_VALUE associated with the countID */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Counters_GetCounterValue(&counterValue, tpm_state->tpm_permanent_data.monotonicCounter, countID); } /* get the session data */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_COUNTER, ordinal, NULL, &(counterValue->authData), /* OIAP */ counterValue->digest); /* OSAP */ } /* Validate the authorization to use the key pointed to by keyHandle */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, counterAuth); /* Authorization digest for input */ } if (returnCode == TPM_SUCCESS) { /* 1. If TPM_STCLEAR_DATA -> countID is NULL */ if (tpm_state->tpm_stclear_data.countID == TPM_COUNT_ID_NULL) { /* c. Set TPM_STCLEAR_DATA -> countID to countID */ tpm_state->tpm_stclear_data.countID = countID; printf("TPM_Process_IncrementCounter: Setting %u as active counter\n", countID); } } if (returnCode == TPM_SUCCESS) { /* 3. Increments the counter by 1 */ counterValue->counter++; /* in TPM_PERMANENT_DATA */ /* save the permanent data structure in NVRAM */ returnCode = TPM_PermanentAll_NVStore(tpm_state, TRUE, returnCode); } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_IncrementCounter: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* 4. Return new count value in count */ returnCode = TPM_CounterValue_StorePublic(response, counterValue); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* owner HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ return rcf; } /* 25.3 TPM_ReadCounter rev 87 Reading the counter provides the caller with the current number in the sequence. This returns the current value for the counter indicated. The counter MAY be any valid counter. */ TPM_RESULT TPM_Process_ReadCounter(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_COUNT_ID countID; /* ID value of the counter */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_ReadCounter: Ordinal Entry\n"); /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get countID */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&countID, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_ReadCounter: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ /* 1. Validate that countID points to a valid counter. Return TPM_BAD_COUNTER on error. */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_ReadCounter: countID %u\n", countID); returnCode = TPM_Counters_IsValidId(tpm_state->tpm_permanent_data.monotonicCounter, countID); } /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_ReadCounter: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* 2. Return count (directly from TPM_PERMANENT_DATA) */ returnCode = TPM_CounterValue_StorePublic (response, &(tpm_state->tpm_permanent_data.monotonicCounter[countID])); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* cleanup */ return rcf; } /* 25.4 TPM_ReleaseCounter rev 87 This command releases a counter such that no reads or increments of the indicated counter will succeed. The TPM uses countID to locate a valid counter. */ TPM_RESULT TPM_Process_ReleaseCounter(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_COUNT_ID countID; /* ID value of the counter */ TPM_AUTHHANDLE authHandle; /* The authorization session handle used for countID authorization */ TPM_NONCE nonceOdd; /* Nonce associated with countID */ TPM_BOOL continueAuthSession = TRUE; /* Ignored */ TPM_AUTHDATA counterAuth; /* The authorization session digest that authorizes the use of countID. HMAC key: countID -> authData */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus = FALSE; /* audit the ordinal */ TPM_BOOL transportEncrypt = FALSE; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_SECRET *hmacKey; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ TPM_COUNTER_VALUE *counterValue; /* associated with countID */ TPM_SECRET savedAuth; /* saved copy for response */ TPM_BOOL writeAllNV = FALSE; /* flag to write back NV*/ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_ReleaseCounter: Ordinal Entry\n"); /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get countID */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&countID, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_ReleaseCounter: countID %u\n", countID); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag1(tag); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, counterAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_ReleaseCounter: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* 1. Authenticate the command and the parameters using the AuthData pointed to by countID. Return TPM_AUTHFAIL on error */ /* Get the TPM_COUNTER_VALUE associated with the countID */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Counters_GetCounterValue(&counterValue, tpm_state->tpm_permanent_data.monotonicCounter, countID); } /* get the session data */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_COUNTER, ordinal, NULL, &(counterValue->authData), /* OIAP */ counterValue->digest); /* OSAP */ } if (returnCode == TPM_SUCCESS) { /* make a copy of the HMAC key for the response, since it gets invalidated */ TPM_Secret_Copy(savedAuth, *hmacKey); /* Validate the authorization to use the key pointed to by countID */ returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, counterAuth); /* Authorization digest for input */ } /* 3. The TPM invalidates sessions */ /* a. MUST invalidate all OSAP sessions associated with the counter */ /* b. MAY invalidate any other session */ /* NOTE: Actions reversed because the sessions can't be found after the digest is initialized */ if (returnCode == TPM_SUCCESS) { TPM_AuthSessions_TerminateEntity(&continueAuthSession, authHandle, tpm_state->tpm_stclear_data.authSessions, TPM_ET_COUNTER, /* TPM_ENTITY_TYPE */ &(counterValue->digest)); /* entityDigest */ } /* 2. The TPM invalidates all internal information regarding the counter. This includes releasing countID such that any subsequent attempts to use countID will fail. */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_ReleaseCounter: Releasing counter %u\n", countID); returnCode = TPM_CounterValue_Release(counterValue, countID); } if (returnCode == TPM_SUCCESS) { writeAllNV= TRUE; /* 4. If TPM_STCLEAR_DATA -> countID equals countID, */ if (tpm_state->tpm_stclear_data.countID == countID ) { printf("TPM_Process_ReleaseCounter: Deactivating counter %u\n", countID); /* a. Set TPM_STCLEAR_DATA -> countID to an illegal value (not the NULL value) */ tpm_state->tpm_stclear_data.countID = TPM_COUNT_ID_ILLEGAL; } } /* save the permanent data structure in NVRAM */ returnCode = TPM_PermanentAll_NVStore(tpm_state, writeAllNV, returnCode); /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_ReleaseCounter: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Set(response, savedAuth, /* saved countID HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, terminate the session. */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ return rcf; } /* 25.5 TPM_ReleaseCounterOwner rev 101 This command releases a counter such that no reads or increments of the indicated counter will succeed. This invalidates all information regarding a counter. */ TPM_RESULT TPM_Process_ReleaseCounterOwner(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ TPM_COUNT_ID countID; /* ID value of the counter */ TPM_AUTHHANDLE authHandle; /* The authorization session handle used for owner authentication */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = FALSE; /* The continue use flag for the authorization session handle */ TPM_AUTHDATA ownerAuth; /* The authorization session digest that authorizes the inputs. HMAC key: ownerAuth */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus = FALSE; /* audit the ordinal */ TPM_BOOL transportEncrypt = TRUE; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_SECRET *hmacKey = NULL; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ TPM_COUNTER_VALUE *counterValue; /* associated with countID */ TPM_BOOL writeAllNV = FALSE; /* flag to write back NV */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_ReleaseCounterOwner: Ordinal Entry\n"); /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get countID */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&countID, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_ReleaseCounterOwner: countID %u\n", countID); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag1(tag); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, ownerAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_ReleaseCounterOwner: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* 1. Validate that ownerAuth properly authorizes the command and parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_OWNER, ordinal, NULL, &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ } if (returnCode == TPM_SUCCESS) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* owner HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, ownerAuth); /* Authorization digest for input */ } /* 2. The TPM uses countID to locate a valid counter. Return TPM_BAD_COUNTER if not found. */ /* Get the TPM_COUNTER_VALUE associated with the countID */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Counters_GetCounterValue(&counterValue, tpm_state->tpm_permanent_data.monotonicCounter, countID); } /* NOTE: Actions reversed because the sessions can't be found after the digest is initialized */ if (returnCode == TPM_SUCCESS) { TPM_AuthSessions_TerminateEntity(&continueAuthSession, authHandle, tpm_state->tpm_stclear_data.authSessions, TPM_ET_COUNTER, /* TPM_ENTITY_TYPE */ &(counterValue->digest)); /* entityDigest */ } /* 3. The TPM invalidates all internal information regarding the counter. This includes releasing countID such that any subsequent attempts to use countID will fail. */ /* NOTE: This function can only return a TPM_FAIL error, so that the failure to store TPM_PERMANENT_DATA will already be reported as fatal. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CounterValue_Release(counterValue, countID); } /* 4. The TPM invalidates sessions */ /* a. MUST invalidate all OSAP sessions associated with the counter */ /* b. MAY invalidate any other session */ if (returnCode == TPM_SUCCESS) { writeAllNV = TRUE; /* 5. If TPM_STCLEAR_DATA -> countID equals countID, */ if (tpm_state->tpm_stclear_data.countID == countID ) { printf("TPM_Process_ReleaseCounterOwner: Deactivating counter %u\n", countID); /* a. Set TPM_STCLEAR_DATA -> countID to an illegal value (not the zero value) */ tpm_state->tpm_stclear_data.countID = TPM_COUNT_ID_ILLEGAL; } } /* save the permanent data structure in NVRAM */ returnCode = TPM_PermanentAll_NVStore(tpm_state, writeAllNV, returnCode); /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_ReleaseCounterOwner: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, terminate the session. */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ return rcf; } libtpms-0.9.3/src/tpm12/tpm_counter.h000066400000000000000000000166021421143571500174470ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Counter Handler */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_counter.h 4526 2011-03-24 21:14:42Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_COUNTER_H #define TPM_COUNTER_H #include "tpm_global.h" #include "tpm_store.h" #include "tpm_structures.h" /* Counter Resource Handling */ void TPM_Counters_Init(TPM_COUNTER_VALUE *monotonicCounters); TPM_RESULT TPM_Counters_Load(TPM_COUNTER_VALUE *monotonicCountersa, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_Counters_Store(TPM_STORE_BUFFER *sbuffer, TPM_COUNTER_VALUE *monotonicCounters); TPM_RESULT TPM_Counters_StoreHandles(TPM_STORE_BUFFER *sbuffer, TPM_COUNTER_VALUE *monotonicCounters); TPM_RESULT TPM_Counters_GetNewHandle(TPM_COUNTER_VALUE **tpm_counter_value, TPM_COUNT_ID *countID, TPM_COUNTER_VALUE *monotonicCounters); void TPM_Counters_GetSpace(uint32_t *space, TPM_COUNTER_VALUE *monotonicCounters); void TPM_Counters_GetNextCount(TPM_ACTUAL_COUNT *nextCount, TPM_COUNTER_VALUE *monotonicCounters); TPM_RESULT TPM_Counters_IsValidId(TPM_COUNTER_VALUE *monotonicCounters, TPM_COUNT_ID countID); TPM_RESULT TPM_Counters_GetCounterValue(TPM_COUNTER_VALUE **tpm_counter_value, TPM_COUNTER_VALUE *monotonicCounters, TPM_COUNT_ID countID); TPM_RESULT TPM_Counters_Release(TPM_COUNTER_VALUE *monotonicCounters); void TPM_Counters_GetActiveCounter(TPM_COUNT_ID *activeCounter, TPM_COUNT_ID countID); /* TPM_COUNTER_VALUE */ void TPM_CounterValue_Init(TPM_COUNTER_VALUE *tpm_counter_value); TPM_RESULT TPM_CounterValue_Load(TPM_COUNTER_VALUE *tpm_counter_value, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_CounterValue_Store(TPM_STORE_BUFFER *sbuffer, const TPM_COUNTER_VALUE *tpm_counter_value); TPM_RESULT TPM_CounterValue_StorePublic(TPM_STORE_BUFFER *sbuffer, const TPM_COUNTER_VALUE *tpm_counter_value); void TPM_CounterValue_CopyPublic(TPM_COUNTER_VALUE *dst_tpm_counter_value, TPM_COUNTER_VALUE *src_tpm_counter_value); TPM_RESULT TPM_CounterValue_Set(TPM_COUNTER_VALUE *tpm_counter_value, TPM_COUNT_ID countID, BYTE *label, TPM_ACTUAL_COUNT counter, TPM_SECRET authData); TPM_RESULT TPM_CounterValue_Release(TPM_COUNTER_VALUE *tpm_counter_value, TPM_COUNT_ID countID); /* Processing Functions */ TPM_RESULT TPM_Process_CreateCounter(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_IncrementCounter(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_ReadCounter(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_ReleaseCounter(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_ReleaseCounterOwner(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); #endif libtpms-0.9.3/src/tpm12/tpm_crypto.c000066400000000000000000003310421421143571500173010ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Platform Dependent Crypto */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_crypto.c 4767 2017-07-27 23:06:32Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ /* This is the openSSL implementation */ #include #include #include #include #include #include #include #include #include "tpm_cryptoh.h" #include "tpm_debug.h" #include "tpm_error.h" #include "tpm_key.h" #include "tpm_io.h" #include "tpm_load.h" #include "tpm_memory.h" #include "tpm_process.h" #include "tpm_types.h" #include "tpm_crypto.h" #include "tpm_openssl_helpers.h" // libtpms added /* The TPM OAEP encoding parameter */ static const unsigned char tpm_oaep_pad_str[] = { 'T', 'C', 'P', 'A' }; /* local prototypes */ static void TPM_OpenSSL_PrintError(void); static TPM_RESULT TPM_RSAGeneratePublicToken(RSA **rsa_pub_key, unsigned char *narr, uint32_t nbytes, unsigned char *earr, uint32_t ebytes); static TPM_RESULT TPM_RSAGeneratePrivateToken(RSA **rsa_pri_key, unsigned char *narr, uint32_t nbytes, unsigned char *earr, uint32_t ebytes, unsigned char *darr, uint32_t dbytes); static TPM_RESULT TPM_RSASignSHA1(unsigned char *signature, unsigned int *signature_length, const unsigned char *message, size_t message_size, RSA *rsa_pri_key); static TPM_RESULT TPM_RSASignDER(unsigned char *signature, unsigned int *signature_length, const unsigned char *message, size_t message_size, RSA *rsa_pri_key); static TPM_RESULT TPM_BN_CTX_new(BN_CTX **ctx); /* TPM_SYMMETRIC_KEY_DATA is a crypto library platform dependent symmetric key structure */ #ifdef TPM_DES /* local prototype and structure for DES */ #include /* DES requires data lengths that are a multiple of the block size */ #define TPM_DES_BLOCK_SIZE 8 typedef struct tdTPM_SYMMETRIC_KEY_DATA { TPM_TAG tag; TPM_BOOL valid; BYTE fill; DES_cblock des_cblock1; DES_cblock des_cblock2; DES_cblock des_cblock3; } TPM_SYMMETRIC_KEY_DATA; static TPM_RESULT TPM_SymmetricKeyData_Crypt(unsigned char *data_out, const unsigned char *data_in, uint32_t length, TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data, int enc, TPM_RESULT error); #endif #ifdef TPM_AES /* local prototype and structure for AES */ #include #if defined(__OpenBSD__) # define OPENSSL_OLD_API #else #if OPENSSL_VERSION_NUMBER < 0x10100000 #define OPENSSL_OLD_API #endif #endif /* AES requires data lengths that are a multiple of the block size */ #define TPM_AES_BITS 128 /* The AES block size is always 16 bytes */ #define TPM_AES_BLOCK_SIZE 16 /* Since the AES key is often derived by truncating the session shared secret, test that it's not too large */ #if (TPM_AES_BLOCK_SIZE > TPM_SECRET_SIZE) #error TPM_AES_BLOCK_SIZE larger than TPM_SECRET_SIZE #endif /* The AES initial CTR value is derived from a nonce. */ #if (TPM_AES_BLOCK_SIZE > TPM_NONCE_SIZE) #error TPM_AES_BLOCK_SIZE larger than TPM_NONCE_SIZE #endif typedef struct tdTPM_SYMMETRIC_KEY_DATA { TPM_TAG tag; TPM_BOOL valid; TPM_BOOL fill; unsigned char userKey[TPM_AES_BLOCK_SIZE]; /* For performance, generate these once from userKey */ AES_KEY aes_enc_key; AES_KEY aes_dec_key; } TPM_SYMMETRIC_KEY_DATA; static TPM_RESULT TPM_SymmetricKeyData_SetKeys(TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data); static TPM_RESULT TPM_SymmetricKeyData_SetKey(TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data, const unsigned char *key_data, uint32_t key_data_size); static TPM_RESULT TPM_AES_ctr128_encrypt(unsigned char *data_out, const unsigned char *data_in, uint32_t data_size, const AES_KEY *aes_enc_key, unsigned char ctr[TPM_AES_BLOCK_SIZE]); #endif /* Initialization function */ TPM_RESULT TPM_Crypto_Init() { TPM_RESULT rc = 0; printf("TPM_Crypto_Init: OpenSSL library %08lx\n", (unsigned long)OPENSSL_VERSION_NUMBER); /* sanity check that the SHA1 context handling remains portable */ if (rc == 0) { if ((sizeof(SHA_LONG) != sizeof(uint32_t)) || (sizeof(unsigned int) != sizeof(uint32_t)) || (sizeof(SHA_CTX) != (sizeof(uint32_t) * (8 + SHA_LBLOCK)))) { printf("TPM_Crypto_Init: Error(fatal), SHA_CTX has unexpected structure\n"); rc = TPM_FAIL; } } return rc; } /* TPM_Crypto_TestSpecific() performs any library specific tests For OpenSSL */ TPM_RESULT TPM_Crypto_TestSpecific() { TPM_RESULT rc = 0; /* Saving the SHA-1 context is fragile code, so test at startup */ void *context1; void *context2; unsigned char buffer1[] = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; unsigned char expect1[] = {0x84,0x98,0x3E,0x44,0x1C, 0x3B,0xD2,0x6E,0xBA,0xAE, 0x4A,0xA1,0xF9,0x51,0x29, 0xE5,0xE5,0x46,0x70,0xF1}; TPM_DIGEST actual; int not_equal; TPM_STORE_BUFFER sbuffer; const unsigned char *stream; uint32_t stream_size; printf(" TPM_Crypto_TestSpecific: Test 1 - SHA1 two parts\n"); context1 = NULL; /* freed @1 */ context2 = NULL; /* freed @2 */ TPM_Sbuffer_Init(&sbuffer); /* freed @3 */ if (rc== 0) { rc = TPM_Malloc((unsigned char **)&context1, sizeof(SHA_CTX)); /* freed @1 */ } /* digest the first part of the array */ if (rc== 0) { SHA1_Init(context1); SHA1_Update(context1, buffer1, 16); } /* store the SHA1 context */ if (rc== 0) { rc = TPM_Sha1Context_Store(&sbuffer, context1); } /* load the SHA1 context */ if (rc== 0) { TPM_Sbuffer_Get(&sbuffer, &stream, &stream_size); rc = TPM_Sha1Context_Load (&context2, (unsigned char **)&stream, &stream_size); /* freed @2 */ } /* digest the rest of the array */ if (rc== 0) { SHA1_Update(context2, buffer1 + 16, sizeof(buffer1) - 17); SHA1_Final(actual, context2); } if (rc == 0) { not_equal = memcmp(expect1, actual, TPM_DIGEST_SIZE); if (not_equal) { printf("TPM_Crypto_TestSpecific: Error in test 1\n"); TPM_PrintFour("\texpect", expect1); TPM_PrintFour("\tactual", actual); rc = TPM_FAILEDSELFTEST; } } free(context1); /* @1 */ free(context2); /* @2 */ TPM_Sbuffer_Delete(&sbuffer); /* @3 */ return rc; } /* Random Number Functions */ /* TPM_Random() fills 'buffer' with 'bytes' bytes. */ TPM_RESULT TPM_Random(BYTE *buffer, size_t bytes) { TPM_RESULT rc = 0; printf(" TPM_Random: Requesting %lu bytes\n", (unsigned long)bytes); if (rc == 0) { /* openSSL call */ rc = RAND_bytes(buffer, bytes); if (rc == 1) { /* OSSL success */ rc = 0; } else { /* OSSL failure */ printf("TPM_Random: Error (fatal) calling RAND_bytes()\n"); rc = TPM_FAIL; } } return rc; } TPM_RESULT TPM_StirRandomCmd(TPM_SIZED_BUFFER *inData) { TPM_RESULT rc = 0; printf(" TPM_StirRandomCmd:\n"); if (rc == 0) { /* NOTE: The TPM command does not give an entropy estimate. This assumes the best case */ /* openSSL call */ RAND_add(inData->buffer, /* buf mixed into PRNG state*/ inData->size, /* number of bytes */ inData->size); /* entropy, the lower bound of an estimate of how much randomness is contained in buf */ } return rc; } /* RSA Functions */ /* Generate an RSA key pair. 'n', 'p', 'q', 'd' must be freed by the caller */ TPM_RESULT TPM_RSAGenerateKeyPair(unsigned char **n, /* public key - modulus */ unsigned char **p, /* private key prime */ unsigned char **q, /* private key prime */ unsigned char **d, /* private key (private exponent) */ int num_bits, /* key size in bits */ const unsigned char *earr, /* public exponent as an array */ uint32_t e_size) { TPM_RESULT rc = 0; RSA *rsa = NULL; const BIGNUM *bnn = NULL; BIGNUM *bne = NULL; const BIGNUM *bnp = NULL; const BIGNUM *bnq = NULL; const BIGNUM *bnd = NULL; uint32_t nbytes; uint32_t pbytes; uint32_t qbytes; uint32_t dbytes; unsigned long e; /* initialize in case of error */ printf(" TPM_RSAGenerateKeyPair:\n"); *n = NULL; *p = NULL; *q = NULL; *d = NULL; /* check that num_bits is a multiple of 16. If not, the primes p and q will not be a multiple of 8 and will not fit well in a byte */ if (rc == 0) { if ((num_bits % 16) != 0) { printf("TPM_RSAGenerateKeyPair: Error, num_bits %d is not a multiple of 16\n", num_bits); rc = TPM_BAD_KEY_PROPERTY; } } /* convert the e array to an unsigned long */ if (rc == 0) { rc = TPM_LoadLong(&e, earr, e_size); } /* validate the public exponent against a list of legal values. Some values (e.g. even numbers) will hang the key generator. */ if (rc == 0) { rc = TPM_RSA_exponent_verify(e); } if (rc == 0) { rsa = RSA_new(); /* freed @1 */ if (rsa == NULL) { printf("TPM_RSAGenerateKeyPair: Error in RSA_new()\n"); rc = TPM_SIZE; } } if (rc == 0) { rc = TPM_bin2bn((TPM_BIGNUM *)&bne, earr, e_size); /* freed @2 */ } if (rc == 0) { printf(" TPM_RSAGenerateKeyPair: num_bits %d exponent %08lx\n", num_bits, e); int irc = RSA_generate_key_ex(rsa, num_bits, bne, NULL); if (irc != 1) { printf("TPM_RSAGenerateKeyPair: Error calling RSA_generate_key_ex()\n"); rc = TPM_BAD_KEY_PROPERTY; } } if (rc == 0) { #if defined OPENSSL_OLD_API bnn = rsa->n; bnp = rsa->p; bnq = rsa->q; bnd = rsa->d; #else /* currently, this function accepts NULL inputs, but it's not guaranteed by the documentation */ const BIGNUM *bnetmp = NULL; /* not needed */ RSA_get0_key(rsa, &bnn, &bnetmp, &bnd); RSA_get0_factors(rsa, &bnp, &bnq); #endif } /* load n */ if (rc == 0) { rc = TPM_bn2binMalloc(n, &nbytes, (TPM_BIGNUM)bnn, num_bits/8); /* freed by caller */ } /* load p */ if (rc == 0) { rc = TPM_bn2binMalloc(p, &pbytes, (TPM_BIGNUM)bnp, num_bits/16); /* freed by caller */ } /* load q */ if (rc == 0) { rc = TPM_bn2binMalloc(q, &qbytes, (TPM_BIGNUM)bnq, num_bits/16); /* freed by caller */ } /* load d */ if (rc == 0) { rc = TPM_bn2binMalloc(d, &dbytes, (TPM_BIGNUM)bnd, num_bits/8); /* freed by caller */ } if (rc == 0) { printf(" TPM_RSAGenerateKeyPair: length of n,p,q,d = %d / %d / %d / %d\n", nbytes, pbytes, qbytes, dbytes); } if (rc != 0) { free(*n); free(*p); free(*q); free(*d); *n = NULL; *p = NULL; *q = NULL; *d = NULL; } if (rsa != NULL) { RSA_free(rsa); /* @1 */ } if (bne != NULL) { BN_free(bne); /* @2 */ } return rc; } /* TPM_RSAGeneratePublicToken() generates an RSA key token from n and e */ static TPM_RESULT TPM_RSAGeneratePublicToken(RSA **rsa_pub_key, /* freed by caller */ unsigned char *narr, /* public modulus */ uint32_t nbytes, unsigned char *earr, /* public exponent */ uint32_t ebytes) { TPM_RESULT rc = 0; BIGNUM * n = NULL; BIGNUM * e = NULL; /* sanity check for the free */ if (rc == 0) { if (*rsa_pub_key != NULL) { printf("TPM_RSAGeneratePublicToken: Error (fatal), token %p should be NULL\n", *rsa_pub_key ); rc = TPM_FAIL; } } /* construct the OpenSSL private key object */ if (rc == 0) { *rsa_pub_key = RSA_new(); /* freed by caller */ if (*rsa_pub_key == NULL) { printf("TPM_RSAGeneratePublicToken: Error in RSA_new()\n"); rc = TPM_SIZE; } } if (rc == 0) { rc = TPM_bin2bn((TPM_BIGNUM *)&n, narr, nbytes); /* freed by caller */ } if (rc == 0) { rc = TPM_bin2bn((TPM_BIGNUM *)&e, earr, ebytes); /* freed by caller */ } if (rc == 0) { #if defined OPENSSL_OLD_API (*rsa_pub_key)->n = n; (*rsa_pub_key)->e = e; (*rsa_pub_key)->d = NULL; #else int irc = RSA_set0_key(*rsa_pub_key, n, e, NULL); if (irc != 1) { printf("TPM_RSAGeneratePublicToken: Error in RSA_set0_key()\n"); rc = TPM_SIZE; } #endif } return rc; } /* TPM_RSAGeneratePrivateToken() generates an RSA key token from n,e,d */ static TPM_RESULT TPM_RSAGeneratePrivateToken(RSA **rsa_pri_key, /* freed by caller */ unsigned char *narr, /* public modulus */ uint32_t nbytes, unsigned char *earr, /* public exponent */ uint32_t ebytes, unsigned char *darr, /* private exponent */ uint32_t dbytes) { TPM_RESULT rc = 0; BIGNUM * n = NULL; BIGNUM * e = NULL; BIGNUM * d = NULL; /* sanity check for the free */ if (rc == 0) { if (*rsa_pri_key != NULL) { printf("TPM_RSAGeneratePrivateToken: Error (fatal), token %p should be NULL\n", *rsa_pri_key ); rc = TPM_FAIL; } } /* construct the OpenSSL private key object */ if (rc == 0) { *rsa_pri_key = RSA_new(); /* freed by caller */ if (*rsa_pri_key == NULL) { printf("TPM_RSAGeneratePrivateToken: Error in RSA_new()\n"); rc = TPM_SIZE; } } if (rc == 0) { rc = TPM_bin2bn((TPM_BIGNUM *)&n, narr, nbytes); /* freed by caller */ } if (rc == 0) { rc = TPM_bin2bn((TPM_BIGNUM *)&e, earr, ebytes); /* freed by caller */ } if (rc == 0) { rc = TPM_bin2bn((TPM_BIGNUM *)&d, darr, dbytes); /* freed by caller */ } if (rc == 0) { #if defined OPENSSL_OLD_API (*rsa_pri_key)->n = n; (*rsa_pri_key)->e = e; (*rsa_pri_key)->d = d; BN_set_flags(d, BN_FLG_CONSTTIME); // d is private #else int irc = RSA_set0_key(*rsa_pri_key, n, e, d); if (irc != 1) { printf("TPM_RSAGeneratePrivateToken: Error in RSA_set0_key()\n"); rc = TPM_SIZE; } #endif } return rc; } #if !USE_OPENSSL_FUNCTIONS_RSA // libtpms added /* TPM_RSAPrivateDecrypt() decrypts 'encrypt_data' using the private key 'n, e, d'. The OAEP padding is removed and 'decrypt_data_length' bytes are moved to 'decrypt_data'. 'decrypt_data_length' is at most 'decrypt_data_size'. */ TPM_RESULT TPM_RSAPrivateDecrypt(unsigned char *decrypt_data, /* decrypted data */ uint32_t *decrypt_data_length, /* length of data put into decrypt_data */ size_t decrypt_data_size, /* size of decrypt_data buffer */ TPM_ENC_SCHEME encScheme, /* encryption scheme */ unsigned char *encrypt_data, /* encrypted data */ uint32_t encrypt_data_size, unsigned char *narr, /* public modulus */ uint32_t nbytes, unsigned char *earr, /* public exponent */ uint32_t ebytes, unsigned char *darr, /* private exponent */ uint32_t dbytes) { TPM_RESULT rc = 0; int irc; RSA * rsa_pri_key = NULL; /* freed @1 */ unsigned char *padded_data = NULL; int padded_data_size = 0; printf(" TPM_RSAPrivateDecrypt:\n"); /* construct the OpenSSL private key object */ if (rc == 0) { rc = TPM_RSAGeneratePrivateToken(&rsa_pri_key, /* freed @1 */ narr, /* public modulus */ nbytes, earr, /* public exponent */ ebytes, darr, /* private exponent */ dbytes); } /* intermediate buffer for the decrypted but still padded data */ if (rc == 0) { /* the size of the decrypted data is guaranteed to be less than this */ padded_data_size = RSA_size(rsa_pri_key); rc = TPM_Malloc(&padded_data, padded_data_size); } if (rc == 0) { /* decrypt with private key. Must decrypt first and then remove padding because the decrypt call cannot specify an encoding parameter */ /* returns the size of the encrypted data. On error, -1 is returned */ irc = RSA_private_decrypt(encrypt_data_size, /* length */ encrypt_data, /* from - the encrypted data */ padded_data, /* to - the decrypted but padded data */ rsa_pri_key, /* key */ RSA_NO_PADDING); /* padding */ if (irc < 0) { printf("TPM_RSAPrivateDecrypt: Error in RSA_private_decrypt()\n"); rc = TPM_DECRYPT_ERROR; } } if (rc == 0) { printf(" TPM_RSAPrivateDecrypt: RSA_private_decrypt() success\n"); printf(" TPM_RSAPrivateDecrypt: Padded data size %u\n", padded_data_size); TPM_PrintFour(" TPM_RSAPrivateDecrypt: Decrypt padded data", padded_data); if (encScheme == TPM_ES_RSAESOAEP_SHA1_MGF1) { /* openSSL expects the padded data to skip the first 0x00 byte, since it expects the padded data to come from a bignum via bn2bin. */ irc = RSA_padding_check_PKCS1_OAEP(decrypt_data, /* to */ decrypt_data_size, /* to length */ padded_data + 1, /* from */ padded_data_size - 1, /* from length */ encrypt_data_size, /* rsa_len */ tpm_oaep_pad_str, /* encoding parameter */ sizeof(tpm_oaep_pad_str) /* encoding parameter length */ ); if (irc < 0) { printf("TPM_RSAPrivateDecrypt: Error in RSA_padding_check_PKCS1_OAEP()\n"); rc = TPM_DECRYPT_ERROR; } } else if (encScheme == TPM_ES_RSAESPKCSv15) { irc = RSA_padding_check_PKCS1_type_2(decrypt_data, /* to */ decrypt_data_size, /* to length */ padded_data + 1, /* from */ padded_data_size - 1, /* from length */ encrypt_data_size /* rsa_len */ ); if (irc < 0) { printf("TPM_RSAPrivateDecrypt: Error in RSA_padding_check_PKCS1_type_2()\n"); rc = TPM_DECRYPT_ERROR; } } else { printf("TPM_RSAPrivateDecrypt: Error, unknown encryption scheme %04x\n", encScheme); rc = TPM_INAPPROPRIATE_ENC; } } if (rc == 0) { *decrypt_data_length = irc; printf(" TPM_RSAPrivateDecrypt: RSA_padding_check_PKCS1_OAEP() recovered %d bytes\n", irc); TPM_PrintFourLimit(" TPM_RSAPrivateDecrypt: Decrypt data", decrypt_data, *decrypt_data_length); } if (rsa_pri_key != NULL) { RSA_free(rsa_pri_key); /* @1 */ } free(padded_data); /* @2 */ return rc; } #else // libtpms added begin TPM_RESULT TPM_RSAPrivateDecrypt(unsigned char *decrypt_data, /* decrypted data */ uint32_t *decrypt_data_length, /* length of data put into decrypt_data */ size_t decrypt_data_size, /* size of decrypt_data buffer */ TPM_ENC_SCHEME encScheme, /* encryption scheme */ unsigned char *encrypt_data, /* encrypted data */ uint32_t encrypt_data_size, unsigned char *narr, /* public modulus */ uint32_t nbytes, unsigned char *earr, /* public exponent */ uint32_t ebytes, unsigned char *darr, /* private exponent */ uint32_t dbytes) { TPM_RESULT rc = 0; EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *ctx = NULL; const EVP_MD *md = NULL; unsigned char *label = NULL; size_t outlen; unsigned char buffer[(TPM_RSA_KEY_LENGTH_MAX + 7) / 8]; printf(" TPM_RSAPrivateDecrypt:\n"); /* construct the OpenSSL private key object */ if (rc == 0) { rc = TPM_RSAGenerateEVP_PKEY(&pkey, /* freed @1 */ narr, /* public modulus */ nbytes, earr, /* public exponent */ ebytes, darr, /* private exponent */ dbytes); } if (rc == 0) { ctx = EVP_PKEY_CTX_new(pkey, NULL); if (ctx == 0) { printf("TPM_RSAPrivateDecrypt: Error in EVP_PKEY_CTX_new()\n"); rc = TPM_FAIL; } } if (rc == 0) { if (EVP_PKEY_decrypt_init(ctx) <= 0) { printf("TPM_RSAPrivateDecrypt: Error in EVP_PKEY_decrypt_init()\n"); rc = TPM_FAIL; } } if (rc == 0) { switch (encScheme) { case TPM_ES_RSAESOAEP_SHA1_MGF1: if (rc == 0) { md = EVP_get_digestbyname("sha1"); if (md == NULL || EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0 || EVP_PKEY_CTX_set_rsa_oaep_md(ctx, md) <= 0) { printf("TPM_RSAPrivateDecrypt: Error in setting up decrypt context for TPM_ES_RSAESOAEP_SHA1_MGF\n"); rc = TPM_FAIL; } } if (rc == 0) { rc = TPM_Malloc(&label, sizeof(tpm_oaep_pad_str)); if (rc) { printf("TPM_RSAPrivateDecrypt: TPM_Malloc failed\n"); } } if (rc == 0) { memcpy(label, tpm_oaep_pad_str, sizeof(tpm_oaep_pad_str)); if (EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, label, sizeof(tpm_oaep_pad_str)) <= 0) { printf("TPM_RSAPrivateDecrypt: EVP_PKEY_CTX_set0_rsa_oaep_label() failed\n"); rc = TPM_FAIL; } if (rc == 0) { label = NULL; } } break; case TPM_ES_RSAESPKCSv15: if (rc == 0) { if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0) { printf("TPM_RSAPrivateDecrypt: Error in setting up decrypt context for TPM_ES_RSAESPKCSv15\n"); rc = TPM_FAIL; } } break; default: if (rc == 0) { printf("TPM_RSAPrivateDecrypt: Error, unknown encryption scheme %04x\n", encScheme); rc = TPM_INAPPROPRIATE_ENC; } } } if (rc == 0) { outlen = sizeof(buffer); if (EVP_PKEY_decrypt(ctx, buffer, &outlen, encrypt_data, encrypt_data_size) <= 0) { printf("TPM_RSAPrivateDecrypt: EVP_PKEY_decrypt failed\n"); rc = TPM_DECRYPT_ERROR; } if (rc == 0) { if (outlen > decrypt_data_size) { printf("TPM_RSAPrivateDecrypt: Error, decrypt_data_size %u too small for message size %u\n", decrypt_data_size, outlen); rc = TPM_DECRYPT_ERROR; } } if (rc == 0) { *decrypt_data_length = (uint32_t)outlen; memcpy(decrypt_data, buffer, outlen); TPM_PrintFourLimit(" TPM_RSAPrivateDecrypt: Decrypt data", decrypt_data, *decrypt_data_length); } } EVP_PKEY_free(pkey); EVP_PKEY_CTX_free(ctx); TPM_Free(label); return rc; } #endif // libtpms added end /* TPM_RSAPublicEncrypt() pads 'decrypt_data' to 'encrypt_data_size' and encrypts using the public key 'n, e'. */ #if !USE_OPENSSL_FUNCTIONS_RSA // libtpms added TPM_RESULT TPM_RSAPublicEncrypt(unsigned char* encrypt_data, /* encrypted data */ size_t encrypt_data_size, /* size of encrypted data buffer */ TPM_ENC_SCHEME encScheme, const unsigned char *decrypt_data, /* decrypted data */ size_t decrypt_data_size, unsigned char *narr, /* public modulus */ uint32_t nbytes, unsigned char *earr, /* public exponent */ uint32_t ebytes) { TPM_RESULT rc = 0; int irc; RSA *rsa_pub_key = NULL; unsigned char *padded_data = NULL; printf(" TPM_RSAPublicEncrypt: Input data size %lu\n", (unsigned long)decrypt_data_size); /* intermediate buffer for the decrypted but still padded data */ if (rc == 0) { rc = TPM_Malloc(&padded_data, encrypt_data_size); /* freed @2 */ } /* construct the OpenSSL public key object */ if (rc == 0) { rc = TPM_RSAGeneratePublicToken(&rsa_pub_key, /* freed @1 */ narr, /* public modulus */ nbytes, earr, /* public exponent */ ebytes); } if (rc == 0) { if (encScheme == TPM_ES_RSAESOAEP_SHA1_MGF1) { irc = RSA_padding_add_PKCS1_OAEP(padded_data, /* to */ encrypt_data_size, /* to length */ decrypt_data, /* from */ decrypt_data_size, /* from length */ tpm_oaep_pad_str, /* encoding parameter */ sizeof(tpm_oaep_pad_str) /* encoding parameter length */ ); if (irc != 1) { printf("TPM_RSAPublicEncrypt: Error in RSA_padding_add_PKCS1_OAEP()\n"); rc = TPM_ENCRYPT_ERROR; } else { printf(" TPM_RSAPublicEncrypt: RSA_padding_add_PKCS1_OAEP() success\n"); } } else if (encScheme == TPM_ES_RSAESPKCSv15) { irc = RSA_padding_add_PKCS1_type_2(padded_data, /* to */ encrypt_data_size, /* to length */ decrypt_data, /* from */ decrypt_data_size); /* from length */ if (irc != 1) { printf("TPM_RSAPublicEncrypt: Error in RSA_padding_add_PKCS1_type_2()\n"); rc = TPM_ENCRYPT_ERROR; } else { printf(" TPM_RSAPublicEncrypt: RSA_padding_add_PKCS1_type_2() success\n"); } } else { printf("TPM_RSAPublicEncrypt: Error, unknown encryption scheme %04x\n", encScheme); rc = TPM_INAPPROPRIATE_ENC; } } if (rc == 0) { printf(" TPM_RSAPublicEncrypt: Padded data size %lu\n", (unsigned long)encrypt_data_size); TPM_PrintFour(" TPM_RSAPublicEncrypt: Padded data", padded_data); /* encrypt with public key. Must pad first and then encrypt because the encrypt call cannot specify an encoding parameter */ /* returns the size of the encrypted data. On error, -1 is returned */ irc = RSA_public_encrypt(encrypt_data_size, /* from length */ padded_data, /* from - the clear text data */ encrypt_data, /* the padded and encrypted data */ rsa_pub_key, /* key */ RSA_NO_PADDING); /* padding */ if (irc < 0) { printf("TPM_RSAPublicEncrypt: Error in RSA_public_encrypt()\n"); rc = TPM_ENCRYPT_ERROR; } } if (rc == 0) { printf(" TPM_RSAPublicEncrypt: RSA_public_encrypt() success\n"); } if (rsa_pub_key != NULL) { RSA_free(rsa_pub_key); /* @1 */ } free(padded_data); /* @2 */ return rc; } #else // libtpms added begin TPM_RESULT TPM_RSAPublicEncrypt(unsigned char* encrypt_data, /* encrypted data */ size_t encrypt_data_size, /* size of encrypted data buffer */ TPM_ENC_SCHEME encScheme, const unsigned char *decrypt_data, /* decrypted data */ size_t decrypt_data_size, unsigned char *narr, /* public modulus */ uint32_t nbytes, unsigned char *earr, /* public exponent */ uint32_t ebytes) { TPM_RESULT rc = 0; EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *ctx = NULL; const EVP_MD *md = NULL; unsigned char *label = NULL; size_t outlen; printf(" TPM_RSAPublicEncrypt: Input data size %lu\n", (unsigned long)decrypt_data_size); /* construct the OpenSSL private key object */ if (rc == 0) { rc = TPM_RSAGenerateEVP_PKEY(&pkey, /* freed @1 */ narr, /* public modulus */ nbytes, earr, /* public exponent */ ebytes, NULL, /* private exponent */ 0); } if (rc == 0) { ctx = EVP_PKEY_CTX_new(pkey, NULL); if (ctx == 0) { printf("TPM_RSAqPrivateDecrypt: Error in EVP_PKEY_CTX_new()\n"); rc = TPM_FAIL; } } if (rc == 0) { if (EVP_PKEY_encrypt_init(ctx) <= 0) { printf("TPM_RSAPrivateDecrypt: Error in EVP_PKEY_decrypt_init()\n"); rc = TPM_FAIL; } } if (rc == 0) { switch (encScheme) { case TPM_ES_RSAESOAEP_SHA1_MGF1: if (rc == 0) { md = EVP_get_digestbyname("sha1"); if (md == NULL || EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0 || EVP_PKEY_CTX_set_rsa_oaep_md(ctx, md) <= 0) { printf("TPM_RSAPublicEncrypt: Error in setting up encrypt context for TPM_ES_RSAESOAEP_SHA1_MGF\n"); rc = TPM_FAIL; } } if (rc == 0) { rc = TPM_Malloc(&label, sizeof(tpm_oaep_pad_str)); if (rc) { printf("TPM_RSAPublicEncrypt: TPM_Malloc failed\n"); } } if (rc == 0) { memcpy(label, tpm_oaep_pad_str, sizeof(tpm_oaep_pad_str)); if (EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, label, sizeof(tpm_oaep_pad_str)) <= 0) { printf("TPM_RSAPublicEncrypt: EVP_PKEY_CTX_set0_rsa_oaep_label() failed\n"); rc = TPM_FAIL; } if (rc == 0) { label = NULL; } } break; case TPM_ES_RSAESPKCSv15: if (rc == 0) { if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0) { printf("TPM_RSAPublicEncrypt: Error in setting up encrypt context for TPM_ES_RSAESPKCSv15\n"); rc = TPM_FAIL; } } break; default: if (rc == 0) { printf("TPM_RSAPublicEncrypt: Error, unknown encryption scheme %04x\n", encScheme); rc = TPM_INAPPROPRIATE_ENC; } } } if (rc == 0) { outlen = encrypt_data_size; if (EVP_PKEY_encrypt(ctx, encrypt_data, &outlen, decrypt_data, decrypt_data_size) <= 0) { printf("TPM_RSAPublicEncrypt: EVP_PKEY_encrypt failed\n"); rc = TPM_ENCRYPT_ERROR; } } EVP_PKEY_free(pkey); EVP_PKEY_CTX_free(ctx); TPM_Free(label); return rc; } #endif // libtpms added end #if USE_FREEBL_CRYPTO_LIBRARY /* TPM_RSAPublicEncryptRaw() does a raw public key operation without any padding. */ TPM_RESULT TPM_RSAPublicEncryptRaw(unsigned char *encrypt_data, /* output */ uint32_t encrypt_data_size, /* input, size of message buffer */ unsigned char *decrypt_data, /* input */ uint32_t decrypt_data_size, /* input, size of sig buffer */ unsigned char *narr, /* public modulus */ uint32_t nbytes, unsigned char *earr, /* public exponent */ uint32_t ebytes) { TPM_RESULT rc = 0; int irc; RSA *rsa_pub_key = NULL; printf(" TPM_RSAPublicEncryptRaw:\n"); /* the input data size must equal the public key size */ if (rc == 0) { if (decrypt_data_size != nbytes) { printf("TPM_RSAPublicEncryptRaw: Error, decrypt data size is %u not %u\n", decrypt_data_size, nbytes); rc = TPM_ENCRYPT_ERROR; } } /* the output data size must equal the public key size */ if (rc == 0) { if (encrypt_data_size != nbytes) { printf("TPM_RSAPublicEncryptRaw: Error, Encrypted data size is %u not %u\n", encrypt_data_size, nbytes); rc = TPM_ENCRYPT_ERROR; } } /* construct the OpenSSL public key object */ if (rc == 0) { rc = TPM_RSAGeneratePublicToken(&rsa_pub_key, /* freed @1 */ narr, /* public modulus */ nbytes, earr, /* public exponent */ ebytes); } if (rc == 0) { TPM_PrintFour(" TPM_RSAPublicEncryptRaw: Public modulus", narr); TPM_PrintAll(" TPM_RSAPublicEncryptRaw: Public exponent", earr, ebytes); TPM_PrintFourLimit(" TPM_RSAPublicEncryptRaw: Decrypt data", decrypt_data, decrypt_data_size); /* encrypt the decrypt_data */ irc = RSA_public_encrypt(decrypt_data_size, /* from length */ decrypt_data, /* from - the clear text data */ encrypt_data, /* to - the padded and encrypted data */ rsa_pub_key, /* key */ RSA_NO_PADDING); /* padding */ if (irc < 0) { printf("TPM_RSAPublicEncryptRaw: Error in RSA_public_encrypt()\n"); rc = TPM_ENCRYPT_ERROR; } } if (rc == 0) { TPM_PrintFour(" TPM_RSAPublicEncryptRaw: Encrypt data", encrypt_data); #if 0 /* NOTE: Uncomment as a debug aid for signature verification */ TPM_PrintAll(" TPM_RSAPublicEncryptRaw: Padded signed data", encrypt_data, encrypt_data_size); #endif } if (rsa_pub_key != NULL) { RSA_free(rsa_pub_key); /* @1 */ } return rc; } #endif /* TPM_RSASign() signs 'message' of size 'message_size' using the private key n,e,d and the signature scheme 'sigScheme' as specified in PKCS #1 v2.0. 'signature_length' bytes are moved to 'signature'. 'signature_length' is at most 'signature_size'. signature must point to RSA_size(rsa) bytes of memory. */ /* Note regarding conversion to EVP_PKEY_sign for the purpose of constant-timeness: - TPM_SS_RSASSAPKCS1v15_SHA1: EVP_PKEY_sign() will call pkey_rsa_sign() which in turn will call RSA_sign() for RSA_PKCS1_PADDING. This is the same as we do here. - TPM_SS_RSASSAPKCS1v15_DER: EVP_PKEY_sign() must not have a message digest since none of the padding choices calls RSA_padding_add_PKCS1_type_1(), so we would have to do the padding again ourselves. */ TPM_RESULT TPM_RSASign(unsigned char *signature, /* output */ unsigned int *signature_length, /* output, size of signature */ unsigned int signature_size, /* input, size of signature buffer */ TPM_SIG_SCHEME sigScheme, /* input, type of signature */ const unsigned char *message, /* input */ size_t message_size, /* input */ unsigned char *narr, /* public modulus */ uint32_t nbytes, unsigned char *earr, /* public exponent */ uint32_t ebytes, unsigned char *darr, /* private exponent */ uint32_t dbytes) { TPM_RESULT rc = 0; RSA * rsa_pri_key = NULL; /* freed @1 */ unsigned int key_size; printf(" TPM_RSASign:\n"); /* construct the OpenSSL private key object */ if (rc == 0) { rc = TPM_RSAGeneratePrivateToken(&rsa_pri_key, /* freed @1 */ narr, /* public modulus */ nbytes, earr, /* public exponent */ ebytes, darr, /* private exponent */ dbytes); } /* check the size of the output signature buffer */ if (rc == 0) { key_size = (unsigned int)RSA_size(rsa_pri_key); /* openSSL returns an int, but never negative */ if (signature_size < key_size) { printf("TPM_RSASign: Error (fatal), buffer %u too small for signature %u\n", signature_size, key_size); rc = TPM_FAIL; /* internal error, should never occur */ } } /* determine the signature scheme for the key */ if (rc == 0) { switch(sigScheme) { case TPM_SS_NONE: printf("TPM_RSASign: Error, sigScheme TPM_SS_NONE\n"); rc = TPM_INVALID_KEYUSAGE; break; case TPM_SS_RSASSAPKCS1v15_SHA1: case TPM_SS_RSASSAPKCS1v15_INFO: rc = TPM_RSASignSHA1(signature, signature_length, message, message_size, rsa_pri_key); break; case TPM_SS_RSASSAPKCS1v15_DER: rc = TPM_RSASignDER(signature, signature_length, message, message_size, rsa_pri_key); break; default: printf("TPM_RSASign: Error, sigScheme %04hx unknown\n", sigScheme); rc = TPM_INVALID_KEYUSAGE; break; } } if (rsa_pri_key != NULL) { RSA_free(rsa_pri_key); /* @1 */ } return rc; } /* TPM_RSASignSHA1() performs the following: prepend a DER encoded algorithm ID prepend a type 1 pad encrypt with the private key */ static TPM_RESULT TPM_RSASignSHA1(unsigned char *signature, /* output */ unsigned int *signature_length, /* output, size of signature */ const unsigned char *message, /* input */ size_t message_size, /* input */ RSA *rsa_pri_key) /* signing private key */ { TPM_RESULT rc = 0; int irc; printf(" TPM_RSASignSHA1:\n"); /* sanity check, SHA1 messages must be 20 bytes */ if (rc == 0) { if (message_size != TPM_DIGEST_SIZE) { printf("TPM_RSASignSHA1: Error, message size %lu not TPM_DIGEST_SIZE\n", (unsigned long)message_size ); rc = TPM_DECRYPT_ERROR; } } if (rc == 0) { /* type NID_sha1, adds the algorithm identifier and type 1 pad */ irc = RSA_sign(NID_sha1, /* type */ message, message_size, signature, signature_length, rsa_pri_key); /* RSA_sign() returns 1 on success, 0 otherwise. */ if (irc != 1) { printf("TPM_RSASignSHA1: Error in RSA_sign()\n"); rc = TPM_DECRYPT_ERROR; } } return rc; } /* TPM_RSASignDER() performs the following: prepend a type 1 pad encrypt with the private key The caller must check that the signature buffer is >= the key size. */ static TPM_RESULT TPM_RSASignDER(unsigned char *signature, /* output */ unsigned int *signature_length, /* output, size of signature */ const unsigned char *message, /* input */ size_t message_size, /* input */ RSA *rsa_pri_key) /* signing private key */ { TPM_RESULT rc = 0; int irc; int key_size; unsigned char *message_pad; int int_sig_len; /* openSSL overloads RSA_private_decrypt return code */ printf(" TPM_RSASignDER:\n"); message_pad = NULL; /* freed @1 */ /* the padded message size is the same as the key size */ if (rc == 0) { key_size = RSA_size(rsa_pri_key); if (key_size < 0) { printf(" TPM_RSASignDER: Error (fatal), negative key size %d\n", key_size); rc = TPM_FAIL; /* should never occur */ } } /* allocate memory for the padded message */ if (rc == 0) { printf(" TPM_RSASignDER: key size %d\n", key_size); rc = TPM_Malloc(&message_pad, key_size); /* freed @1 */ } /* PKCS1 type 1 pad the message */ if (rc == 0) { printf(" TPM_RSASignDER: Applying PKCS1 type 1 padding, size from %lu to %u\n", (unsigned long)message_size, key_size); TPM_PrintFourLimit(" TPM_RSASignDER: Input message", message, message_size); /* This call checks that the message will fit with the padding */ irc = RSA_padding_add_PKCS1_type_1(message_pad, /* to */ key_size, message, /* from */ message_size); if (irc != 1) { printf("TPM_RSASignDER: Error padding message, size %lu key size %u\n", (unsigned long)message_size, key_size); rc = TPM_DECRYPT_ERROR; } } /* raw sign with private key */ if (rc == 0) { printf(" TPM_RSASignDER: Encrypting with private key, message size %d\n", key_size); TPM_PrintFour(" TPM_RSASignDER: Padded message", message_pad); /* returns the size of the encrypted data. On error, -1 is returned */ int_sig_len = RSA_private_encrypt(key_size, /* int flen */ message_pad, /* unsigned char *from, */ signature, /* unsigned char *to, */ rsa_pri_key, /* RSA *rsa, */ RSA_NO_PADDING); /* int padding); */ if (int_sig_len >= 0) { *signature_length = (unsigned int)int_sig_len; } else { printf("TPM_RSASignDER: Error in RSA_private_encrypt()\n"); rc = TPM_DECRYPT_ERROR; } } if (rc == 0) { TPM_PrintFour(" TPM_RSASignDER: signature", signature); } free(message_pad); /* @1 */ return rc; } /* TPM_RSAVerifySHA1() performs the following: decrypt the signature verify and remove type 1 pad verify and remove DER encoded algorithm ID verify the signature on the message */ TPM_RESULT TPM_RSAVerifySHA1(unsigned char *signature, /* input */ unsigned int signature_size, /* input, size of signature buffer */ const unsigned char *message, /* input */ uint32_t message_size, /* input */ unsigned char *narr, /* public modulus */ uint32_t nbytes, unsigned char *earr, /* public exponent */ uint32_t ebytes) { TPM_RESULT rc = 0; TPM_BOOL valid; RSA * rsa_pub_key = NULL; printf(" TPM_RSAVerifySHA1:\n"); /* construct the openSSL public key object from n and e */ if (rc == 0) { rc = TPM_RSAGeneratePublicToken(&rsa_pub_key, /* freed @1 */ narr, /* public modulus */ nbytes, earr, /* public exponent */ ebytes); } if (rc == 0) { /* RSA_verify() returns 1 on successful verification, 0 otherwise. */ valid = RSA_verify(NID_sha1, message, message_size, signature, signature_size, rsa_pub_key); if (valid != 1) { printf("TPM_RSAVerifySHA1: Error, bad signature\n"); rc = TPM_BAD_SIGNATURE; } } if (rsa_pub_key != NULL) { RSA_free(rsa_pub_key); /* @1 */ } return rc; } /* TPM_RSAGetPrivateKey recalculates q (2nd prime factor) and d (private key) from n (public key), e (public exponent), and p (1st prime factor) The private key is validated by dividing the RSA product n by the RSA prime p and verifying that the remainder is 0. 'qarr', darr' must be freed by the caller. */ TPM_RESULT TPM_RSAGetPrivateKey(uint32_t *qbytes, unsigned char **qarr, uint32_t *dbytes, unsigned char **darr, uint32_t nbytes, unsigned char *narr, uint32_t ebytes, unsigned char *earr, uint32_t pbytes, unsigned char *parr) { TPM_RESULT rc = 0; /* TPM return code */ int irc; /* openSSL return code */ BIGNUM *brc; /* BIGNUM return code */ BIGNUM *n = NULL; /* public modulus */ BIGNUM *e = NULL; /* public exponent */ BIGNUM *d = NULL; /* private exponent */ BIGNUM *p = NULL; /* secret prime factor */ BIGNUM *q = NULL; /* secret prime factor */ /* temporary variables */ BN_CTX *ctx = NULL; /* freed @5, @6 */ BIGNUM *r0 = NULL; /* n/p remainder */ BIGNUM *r1 = NULL; BIGNUM *r2 = NULL; /* set to NULL so caller can free after failure */ printf(" TPM_RSAGetPrivateKey:\n"); *qarr = NULL; *darr = NULL; /* check input parameters */ if (rc == 0) { if ((narr == NULL) || (nbytes == 0)) { printf("TPM_RSAGetPrivateKey: Error, missing n\n"); rc = TPM_BAD_PARAMETER; } } /* check input parameters */ if (rc == 0) { if ((earr == NULL) || (ebytes == 0)) { printf("TPM_RSAGetPrivateKey: Error, missing e\n"); rc = TPM_BAD_PARAMETER; } } /* check input parameters */ if (rc == 0) { if ((parr == NULL) || (pbytes == 0)) { printf("TPM_RSAGetPrivateKey: Error, missing p\n"); rc = TPM_BAD_PARAMETER; } } /* get some temporary BIGNUM's for use in the calculations */ if (rc == 0) { rc = TPM_BN_CTX_new(&ctx); } if (rc == 0) { BN_CTX_start(ctx); /* no return code */ r0 = BN_CTX_get(ctx); /* sufficient to test return of last 'get' call */ r1 = BN_CTX_get(ctx); r2 = BN_CTX_get(ctx); if (r2 == 0) { printf("TPM_RSAGetPrivateKey: Error in BN_CTX_get()\n"); TPM_OpenSSL_PrintError(); rc = TPM_SIZE; } } /* allocate BIGNUM's for q, d */ if (rc == 0) { rc = TPM_BN_new((TPM_BIGNUM *)&q); } if (rc == 0) { rc = TPM_BN_new((TPM_BIGNUM *)&d); } /* convert n, e, p to BIGNUM's */ if (rc == 0) { rc = TPM_bin2bn((TPM_BIGNUM *)&n, narr, nbytes); /* freed @1 */ } if (rc == 0) { rc = TPM_bin2bn((TPM_BIGNUM *)&e, earr, ebytes); /* freed @2 */ } if (rc == 0) { rc = TPM_bin2bn((TPM_BIGNUM *)&p, parr, pbytes); /* freed @3 */ if (p) BN_set_flags(p, BN_FLG_CONSTTIME); // p is private } /* calculate q = n/p */ if (rc == 0) { irc = BN_div(q, r0, n, p, ctx); /* q = n/p freed @4 */ if (irc != 1) { /* 1 is success */ printf("TPM_RSAGetPrivateKey: Error in BN_div()\n"); TPM_OpenSSL_PrintError(); rc = TPM_BAD_PARAMETER; } else BN_set_flags(q, BN_FLG_CONSTTIME); // q is private } /* remainder should be zero */ if (rc == 0) { irc = BN_is_zero(r0); if (irc != 1) { /* 1 is success */ printf("TPM_RSAGetPrivateKey: Error in BN_is_zero()\n"); rc = TPM_BAD_PARAMETER; } } /* calculate r0 = p-1 */ if (rc == 0) { irc = BN_sub(r0, p, BN_value_one()); /* r0 = p-1 freed @6 */ if (irc != 1) { /* 1 is success */ printf("TPM_RSAGetPrivateKey: Error in BN_sub()\n"); TPM_OpenSSL_PrintError(); rc = TPM_BAD_PARAMETER; } } /* calculate r1 = q-1 */ if (rc == 0) { irc = BN_sub(r1, q, BN_value_one()); /* freed @6 */ if (irc != 1) { /* 1 is success */ printf("TPM_RSAGetPrivateKey: Error in BN_sub()\n"); TPM_OpenSSL_PrintError(); rc = TPM_BAD_PARAMETER; } } /* calculate r2 = (p-1)(q-1) */ if (rc == 0) { irc = BN_mul(r2, r0, r1, ctx); /* freed @6 */ if (irc != 1) { /* 1 is success */ printf("TPM_RSAGetPrivateKey: Error in BN_mul()\n"); TPM_OpenSSL_PrintError(); rc = TPM_BAD_PARAMETER; } else BN_set_flags(r2, BN_FLG_CONSTTIME); // r2 is private } /* calculate d = multiplicative inverse e mod r0 */ if (rc == 0) { brc = BN_mod_inverse(d, e, r2, ctx); /* feed @5 */ if (brc == NULL) { printf("TPM_RSAGetPrivateKey: Error in BN_mod_inverse()\n"); TPM_OpenSSL_PrintError(); rc = TPM_BAD_PARAMETER; } } /* get q as an array */ if (rc == 0) { rc = TPM_bn2binMalloc(qarr, qbytes, (TPM_BIGNUM)q, pbytes); /* freed by caller */ } /* get d as an array */ if (rc == 0) { TPM_PrintFour(" TPM_RSAGetPrivateKey: Calculated q", *qarr); rc = TPM_bn2binMalloc(darr, dbytes, (TPM_BIGNUM)d, nbytes); /* freed by caller */ } if (rc == 0) { TPM_PrintFour(" TPM_RSAGetPrivateKey: Calculated d", *darr); printf(" TPM_RSAGetPrivateKey: length of n,p,q,d = %u / %u / %u / %u\n", nbytes, pbytes, *qbytes, *dbytes); } BN_free(n); /* @1 */ BN_free(e); /* @2 */ BN_free(p); /* @3 */ BN_free(q); /* @4 */ BN_free(d); /* @3 */ BN_CTX_end(ctx); /* @5 */ BN_CTX_free(ctx); /* @6 */ return rc; } /* openSSL wrappers do error logging and transformation of openSSL errors to TPM type errors */ /* TPM_OpenSSL_PrintError() prints a detailed openSSL error trace. */ static void TPM_OpenSSL_PrintError() { /* openssl error printing */ unsigned long error; const char *file; int line; const char *data; int flags; error = ERR_get_error_line_data(&file, &line, &data, &flags); printf("\terror %08lx file %s line %d data %s flags %08x\n", error, file, line, data, flags); return; } /* TPM_BN_num_bytes() wraps the openSSL function in a TPM error handler Returns number of bytes in the input */ TPM_RESULT TPM_BN_num_bytes(unsigned int *numBytes, TPM_BIGNUM bn_in) { TPM_RESULT rc = 0; int i; BIGNUM *bn = (BIGNUM *)bn_in; i = BN_num_bytes(bn); if (i >= 0) { *numBytes = (unsigned int)i; } else { printf("TPM_BN_num_bytes: Error (fatal), bytes in BIGNUM is negative\n"); TPM_OpenSSL_PrintError(); rc = TPM_FAIL; } return rc; } /* TPM_BN_is_one() wraps the openSSL function in a TPM error handler Returns success if input is 1 */ TPM_RESULT TPM_BN_is_one(TPM_BIGNUM bn_in) { TPM_RESULT rc = 0; int irc; BIGNUM *bn = (BIGNUM *)bn_in; /* int BN_is_one(BIGNUM *a); BN_is_one() tests if a equals 0, 1, BN_is_one() returns 1 if the condition is true, 0 otherwise. */ irc = BN_is_one(bn); if (irc != 1) { printf("TPM_BN_is_one: Error, result is not 1\n"); rc = TPM_DAA_WRONG_W; } return rc; } /* TPM_BN_mod() wraps the openSSL function in a TPM error handler r = a mod m */ TPM_RESULT TPM_BN_mod(TPM_BIGNUM rem_in, const TPM_BIGNUM a_in, const TPM_BIGNUM m_in) { TPM_RESULT rc = 0; int irc; BIGNUM *rem = (BIGNUM *)rem_in; BIGNUM *a = (BIGNUM *)a_in; BIGNUM *m = (BIGNUM *)m_in; BN_CTX *ctx = NULL; /* freed @1 */ if (rc == 0) { rc = TPM_BN_CTX_new(&ctx); /* freed @1 */ } /*int BN_mod(BIGNUM *rem, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx); BN_mod() corresponds to BN_div() with dv set to NULL. int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *a, const BIGNUM *d, BN_CTX *ctx); BN_div() divides a by d and places the result in dv and the remainder in rem (dv=a/d, rem=a%d). Either of dv and rem may be NULL, in which case the respective value is not returned. The result is rounded towards zero; thus if a is negative, the remainder will be zero or negative. For division by powers of 2, use BN_rshift(3). For all functions, 1 is returned for success, 0 on error. The return value should always be checked */ irc = BN_mod(rem, a, m, ctx); if (irc != 1) { printf("TPM_BN_mod: Error performing BN_mod()\n"); TPM_OpenSSL_PrintError(); rc = TPM_DAA_WRONG_W; } BN_CTX_free(ctx); /* @1 */ return rc; } /* TPM_BN_mask_bits() wraps the openSSL function in a TPM error handler erase all but the lowest n bits of bn bn = bn mod 2^^n */ TPM_RESULT TPM_BN_mask_bits(TPM_BIGNUM bn_in, unsigned int n) { TPM_RESULT rc = 0; int irc; unsigned int numBytes; BIGNUM *bn = (BIGNUM *)bn_in; if (rc == 0) { rc = TPM_BN_num_bytes(&numBytes, bn_in); } /* if the BIGNUM is already the correct number of bytes, no need to mask, and BN_mask_bits() will fail. */ if (rc == 0) { if (numBytes > (n / 8)) { /* BN_mask_bits() truncates a to an n bit number (a&=~((~0)>>;n)). An error occurs if a already is shorter than n bits. int BN_mask_bits(BIGNUM *a, int n); return 1 for success, 0 on error. */ irc = BN_mask_bits(bn, n); if (irc != 1) { printf("TPM_BN_mask_bits: Error performing BN_mask_bits()\n"); TPM_OpenSSL_PrintError(); rc = TPM_DAA_WRONG_W; } } } return rc; } /* TPM_BN_rshift() wraps the openSSL function in a TPM error handler Shift a right by n bits (discard the lowest n bits) and label the result r */ TPM_RESULT TPM_BN_rshift(TPM_BIGNUM *rBignum_in, /* freed by caller */ TPM_BIGNUM aBignum_in, int n) { TPM_RESULT rc = 0; int irc; BIGNUM **rBignum = (BIGNUM **)rBignum_in; BIGNUM *aBignum = (BIGNUM *)aBignum_in; printf(" TPM_BN_rshift: n %d\n", n); if (rc == 0) { rc = TPM_BN_new(rBignum_in); } if (rc == 0) { /* BN_rshift() shifts a right by n bits and places the result in r (r=a/2^n). int BN_rshift(BIGNUM *r, BIGNUM *a, int n); return 1 for success, 0 on error. */ irc = BN_rshift(*rBignum, aBignum, n); if (irc != 1) { printf("TPM_BN_rshift: Error performing BN_rshift()\n"); TPM_OpenSSL_PrintError(); rc = TPM_DAA_WRONG_W; } } return rc; } /* TPM_BN_lshift() wraps the openSSL function in a TPM error handler Shift a left by n bits and label the result r */ TPM_RESULT TPM_BN_lshift(TPM_BIGNUM *rBignum_in, /* freed by caller */ TPM_BIGNUM aBignum_in, int n) { TPM_RESULT rc = 0; int irc; BIGNUM **rBignum = (BIGNUM **)rBignum_in; BIGNUM *aBignum = (BIGNUM *)aBignum_in; printf(" TPM_BN_lshift: n %d\n", n); if (rc == 0) { rc = TPM_BN_new(rBignum_in); } if (rc == 0) { /* BN_lshift() shifts a left by n bits and places the result in r (r=a*2^n). int BN_lshift(BIGNUM *r, const BIGNUM *a, int n); return 1 for success, 0 on error. */ irc = BN_lshift(*rBignum, aBignum, n); if (irc != 1) { printf("TPM_lshift: Error performing BN_lshift()\n"); TPM_OpenSSL_PrintError(); rc = TPM_DAA_WRONG_W; } } return rc; } /* TPM_BN_add() wraps the openSSL function in a TPM error handler Performs R = A + B R may be the same as A or B */ TPM_RESULT TPM_BN_add(TPM_BIGNUM rBignum_in, TPM_BIGNUM aBignum_in, TPM_BIGNUM bBignum_in) { TPM_RESULT rc = 0; int irc; BIGNUM *rBignum = (BIGNUM *)rBignum_in; BIGNUM *aBignum = (BIGNUM *)aBignum_in; BIGNUM *bBignum = (BIGNUM *)bBignum_in; printf(" TPM_BN_add:\n"); /* int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); BN_add() adds a and b and places the result in r (r=a+b). r may be the same BIGNUM as a or b. 1 is returned for success, 0 on error. */ irc = BN_add(rBignum, aBignum, bBignum); if (irc != 1) { printf("TPM_BN_add: Error performing BN_add()\n"); TPM_OpenSSL_PrintError(); rc = TPM_DAA_WRONG_W; } return rc; } /* TPM_BN_mul() wraps the openSSL function in a TPM error handler r = a * b */ TPM_RESULT TPM_BN_mul(TPM_BIGNUM rBignum_in, TPM_BIGNUM aBignum_in, TPM_BIGNUM bBignum_in) { TPM_RESULT rc = 0; int irc; BN_CTX *ctx; BIGNUM *rBignum = (BIGNUM *)rBignum_in; BIGNUM *aBignum = (BIGNUM *)aBignum_in; BIGNUM *bBignum = (BIGNUM *)bBignum_in; printf(" TPM_BN_mul:\n"); ctx = NULL; /* freed @1 */ if (rc == 0) { rc = TPM_BN_CTX_new(&ctx); /* freed @1 */ } /* int BN_mul(BIGNUM *r, BIGNUM *a, BIGNUM *b, BN_CTX *ctx); BN_mul() multiplies a and b and places the result in r (r=a*b). r may be the same BIGNUM as a or b. 1 is returned for success, 0 on error. */ if (rc == 0) { irc = BN_mul(rBignum, aBignum, bBignum, ctx); if (irc != 1) { printf("TPM_BN_add: Error performing BN_mul()\n"); TPM_OpenSSL_PrintError(); rc = TPM_DAA_WRONG_W; } } BN_CTX_free(ctx); /* @1 */ return rc; } /* TPM_BN_mod_exp() wraps the openSSL function in a TPM error handler computes a to the p-th power modulo m (r=a^p % n) */ TPM_RESULT TPM_BN_mod_exp(TPM_BIGNUM rBignum_in, TPM_BIGNUM aBignum_in, TPM_BIGNUM pBignum_in, TPM_BIGNUM nBignum_in) { TPM_RESULT rc = 0; int irc; BN_CTX *ctx; BIGNUM *rBignum = (BIGNUM *)rBignum_in; BIGNUM *aBignum = (BIGNUM *)aBignum_in; BIGNUM *pBignum = (BIGNUM *)pBignum_in; BIGNUM *nBignum = (BIGNUM *)nBignum_in; printf(" TPM_BN_mod_exp:\n"); ctx = NULL; /* freed @1 */ if (rc == 0) { rc = TPM_BN_CTX_new(&ctx); } /* BIGNUM calculation */ /* int BN_mod_exp(BIGNUM *r, BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx); BN_mod_exp() computes a to the p-th power modulo m (r=a^p % m). This function uses less time and space than BN_exp(). 1 is returned for success, 0 on error. */ if (rc == 0) { printf(" TPM_BN_mod_exp: Calculate mod_exp\n"); BN_set_flags(pBignum, BN_FLG_CONSTTIME); // p may be private irc = BN_mod_exp(rBignum, aBignum, pBignum, nBignum, ctx); if (irc != 1) { printf("TPM_BN_mod_exp: Error performing BN_mod_exp()\n"); TPM_OpenSSL_PrintError(); rc = TPM_DAA_WRONG_W; } } BN_CTX_free(ctx); /* @1 */ return rc; } /* TPM_BN_Mod_add() wraps the openSSL function in a TPM error handler adds a to b modulo m */ TPM_RESULT TPM_BN_mod_add(TPM_BIGNUM rBignum_in, TPM_BIGNUM aBignum_in, TPM_BIGNUM bBignum_in, TPM_BIGNUM mBignum_in) { TPM_RESULT rc = 0; int irc; BN_CTX *ctx; BIGNUM *rBignum = (BIGNUM *)rBignum_in; BIGNUM *aBignum = (BIGNUM *)aBignum_in; BIGNUM *bBignum = (BIGNUM *)bBignum_in; BIGNUM *mBignum = (BIGNUM *)mBignum_in; printf(" TPM_BN_mod_add:\n"); ctx = NULL; /* freed @1 */ if (rc == 0) { rc = TPM_BN_CTX_new(&ctx); } /* int BN_mod_add(BIGNUM *r, BIGNUM *a, BIGNUM *b, const BIGNUM *m, BN_CTX *ctx); BN_mod_add() adds a to b modulo m and places the non-negative result in r. 1 is returned for success, 0 on error. */ if (rc == 0) { irc = BN_mod_add(rBignum, aBignum, bBignum, mBignum, ctx); if (irc != 1) { printf("TPM_BN_mod_add: Error performing BN_mod_add()\n"); TPM_OpenSSL_PrintError(); rc = TPM_DAA_WRONG_W; } } BN_CTX_free(ctx); /* @1 */ return rc; } /* TPM_BN_mod_mul() wraps the openSSL function in a TPM error handler r = (a * b) mod m */ TPM_RESULT TPM_BN_mod_mul(TPM_BIGNUM rBignum_in, TPM_BIGNUM aBignum_in, TPM_BIGNUM bBignum_in, TPM_BIGNUM mBignum_in) { TPM_RESULT rc = 0; int irc; BN_CTX *ctx; BIGNUM *rBignum = (BIGNUM *)rBignum_in; BIGNUM *aBignum = (BIGNUM *)aBignum_in; BIGNUM *bBignum = (BIGNUM *)bBignum_in; BIGNUM *mBignum = (BIGNUM *)mBignum_in; printf(" TPM_BN_mod_mul:\n"); ctx = NULL; /* freed @1 */ if (rc == 0) { rc = TPM_BN_CTX_new(&ctx); } /* int BN_mod_mul(BIGNUM *r, BIGNUM *a, BIGNUM *b, const BIGNUM *m, BN_CTX *ctx); BN_mod_mul() multiplies a by b and finds the non-negative remainder respective to modulus m (r=(a*b) mod m). r may be the same BIGNUM as a or b. 1 is returned for success, 0 on error. */ if (rc == 0) { irc = BN_mod_mul(rBignum, aBignum, bBignum, mBignum, ctx); if (irc != 1) { printf("TPM_BN_mod_mul: Error performing BN_mod_mul()\n"); TPM_OpenSSL_PrintError(); rc = TPM_DAA_WRONG_W; } } BN_CTX_free(ctx); /* @1 */ return rc; } /* TPM_BN_CTX_new() wraps the openSSL function in a TPM error handler */ static TPM_RESULT TPM_BN_CTX_new(BN_CTX **ctx) { TPM_RESULT rc = 0; if (rc == 0) { if (*ctx != NULL) { printf("TPM_BN_CTX_new: Error (fatal), *ctx %p should be NULL before BN_CTX_new \n", *ctx); rc = TPM_FAIL; } } if (rc == 0) { *ctx = BN_CTX_new(); if (*ctx == NULL) { printf("TPM_BN_CTX_new: Error, context is NULL\n"); TPM_OpenSSL_PrintError(); rc = TPM_SIZE; } } return rc; } /* TPM_BN_new() wraps the openSSL function in a TPM error handler Allocates a new bignum */ TPM_RESULT TPM_BN_new(TPM_BIGNUM *bn_in) { TPM_RESULT rc = 0; BIGNUM **bn = (BIGNUM **)bn_in; *bn = BN_new(); if (*bn == NULL) { printf("TPM_BN_new: Error, bn is NULL\n"); TPM_OpenSSL_PrintError(); rc = TPM_SIZE; } return rc; } /* TPM_BN_free() wraps the openSSL function Frees the bignum */ void TPM_BN_free(TPM_BIGNUM bn_in) { BIGNUM *bn = (BIGNUM *)bn_in; BN_free(bn); return; } /* TPM_bn2bin wraps the openSSL function in a TPM error handler. Converts a bignum to char array 'bin' must already be checked for sufficient size. int BN_bn2bin(const BIGNUM *a, unsigned char *to); BN_bn2bin() returns the length of the big-endian number placed at to */ TPM_RESULT TPM_bn2bin(unsigned char *bin, TPM_BIGNUM bn_in) { TPM_RESULT rc = 0; BN_bn2bin((BIGNUM *)bn_in, bin); return rc; } /* TPM_bin2bn() wraps the openSSL function in a TPM error handler Converts a char array to bignum bn must be freed by the caller. */ TPM_RESULT TPM_bin2bn(TPM_BIGNUM *bn_in, const unsigned char *bin, unsigned int bytes) { TPM_RESULT rc = 0; BIGNUM **bn = (BIGNUM **)bn_in; /* BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret); BN_bin2bn() converts the positive integer in big-endian form of length len at s into a BIGNUM and places it in ret. If ret is NULL, a new BIGNUM is created. BN_bin2bn() returns the BIGNUM, NULL on error. */ if (rc == 0) { *bn = BN_bin2bn(bin, bytes, *bn); if (*bn == NULL) { printf("TPM_bin2bn: Error in BN_bin2bn\n"); TPM_OpenSSL_PrintError(); rc = TPM_SIZE; } } return rc; } /* Hash Functions */ /* for the openSSL version, TPM_SHA1Context is a SHA_CTX structure */ /* TPM_SHA1InitCmd() initializes a platform dependent TPM_SHA1Context structure. The structure must be freed using TPM_SHA1Delete() */ TPM_RESULT TPM_SHA1InitCmd(void **context) { TPM_RESULT rc = 0; printf(" TPM_SHA1InitCmd:\n"); if (rc== 0) { rc = TPM_Malloc((unsigned char **)context, sizeof(SHA_CTX)); } if (rc== 0) { SHA1_Init(*context); } return rc; } /* TPM_SHA1UpdateCmd() adds 'data' of 'length' to the SHA-1 context */ TPM_RESULT TPM_SHA1UpdateCmd(void *context, const unsigned char *data, uint32_t length) { TPM_RESULT rc = 0; printf(" TPM_SHA1Update: length %u\n", length); if (context != NULL) { SHA1_Update(context, data, length); } else { printf("TPM_SHA1Update: Error, no existing SHA1 thread\n"); rc = TPM_SHA_THREAD; } return rc; } /* TPM_SHA1FinalCmd() extracts the SHA-1 digest 'md' from the context */ TPM_RESULT TPM_SHA1FinalCmd(unsigned char *md, void *context) { TPM_RESULT rc = 0; printf(" TPM_SHA1FinalCmd:\n"); if (context != NULL) { SHA1_Final(md, context); } else { printf("TPM_SHA1FinalCmd: Error, no existing SHA1 thread\n"); rc = TPM_SHA_THREAD; } return rc; } /* TPM_SHA1Delete() zeros and frees the SHA1 context */ void TPM_SHA1Delete(void **context) { if (*context != NULL) { printf(" TPM_SHA1Delete:\n"); /* zero because the SHA1 context might have data left from an HMAC */ memset(*context, 0, sizeof(SHA_CTX)); free(*context); *context = NULL; } return; } /* TPM_Sha1Context_Load() is non-portable code to deserialize the OpenSSL SHA1 context. If the contextPresent prepended by TPM_Sha1Context_Store() is FALSE, context remains NULL. If TRUE, context is allocated and loaded. */ TPM_RESULT TPM_Sha1Context_Load(void **context, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; size_t i; SHA_CTX *sha_ctx = NULL; /* initialize to silence hopefully bogus gcc 4.4.4 warning */ TPM_BOOL contextPresent; /* is there a context to be loaded */ printf(" TPM_Sha1Context_Load: OpenSSL\n"); /* TPM_Sha1Context_Store() stored a flag to indicate whether a context should be stored */ if (rc== 0) { rc = TPM_LoadBool(&contextPresent, stream, stream_size); printf(" TPM_Sha1Context_Load: contextPresent %u\n", contextPresent); } /* check format tag */ /* In the future, if multiple formats are supported, this check will be replaced by a 'switch' on the tag */ if ((rc== 0) && contextPresent) { rc = TPM_CheckTag(TPM_TAG_SHA1CONTEXT_OSSL_V1, stream, stream_size); } if ((rc== 0) && contextPresent) { rc = TPM_Malloc((unsigned char **)context, sizeof(SHA_CTX)); sha_ctx = (SHA_CTX *)*context; } /* load h0 */ if ((rc== 0) && contextPresent) { rc = TPM_Load32(&(sha_ctx->h0), stream, stream_size); } /* load h1 */ if ((rc== 0) && contextPresent) { rc = TPM_Load32(&(sha_ctx->h1), stream, stream_size); } /* load h2 */ if ((rc== 0) && contextPresent) { rc = TPM_Load32(&(sha_ctx->h2), stream, stream_size); } /* load h3 */ if ((rc== 0) && contextPresent) { rc = TPM_Load32(&(sha_ctx->h3), stream, stream_size); } /* load h4 */ if ((rc== 0) && contextPresent) { rc = TPM_Load32(&(sha_ctx->h4), stream, stream_size); } /* load Nl */ if ((rc== 0) && contextPresent) { rc = TPM_Load32(&(sha_ctx->Nl), stream, stream_size); } /* load Nh */ if ((rc== 0) && contextPresent) { rc = TPM_Load32(&(sha_ctx->Nh), stream, stream_size); } /* load data */ for (i = 0 ; (rc == 0) && contextPresent && (i < SHA_LBLOCK) ; i++) { rc = TPM_Load32(&(sha_ctx->data[i]), stream, stream_size); } /* load num */ if ((rc== 0) && contextPresent) { rc = TPM_Load32(&(sha_ctx->num), stream, stream_size); } return rc; } /* TPM_Sha1Context_Store() is non-portable code to serialize the OpenSSL SHA1 context. context is not altered. It prepends a contextPresent flag to the stream, FALSE if context is NULL, TRUE if not. */ TPM_RESULT TPM_Sha1Context_Store(TPM_STORE_BUFFER *sbuffer, void *context) { TPM_RESULT rc = 0; size_t i; SHA_CTX *sha_ctx = (SHA_CTX *)context; TPM_BOOL contextPresent; /* is there a context to be stored */ printf(" TPM_Sha1Context_Store: OpenSSL\n"); /* store contextPresent */ if (rc == 0) { if (sha_ctx != NULL) { printf(" TPM_Sha1Context_Store: Storing context\n"); contextPresent = TRUE; } else { printf(" TPM_Sha1Context_Store: No context to store\n"); contextPresent = FALSE; } rc = TPM_Sbuffer_Append(sbuffer, &contextPresent, sizeof(TPM_BOOL)); } /* overall format tag */ if ((rc== 0) && contextPresent) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_SHA1CONTEXT_OSSL_V1); } if ((rc== 0) && contextPresent) { rc = TPM_Sbuffer_Append32(sbuffer, sha_ctx->h0); } if ((rc== 0) && contextPresent) { rc = TPM_Sbuffer_Append32(sbuffer, sha_ctx->h1); } if ((rc== 0) && contextPresent) { rc = TPM_Sbuffer_Append32(sbuffer, sha_ctx->h2); } if ((rc== 0) && contextPresent) { rc = TPM_Sbuffer_Append32(sbuffer, sha_ctx->h3); } if ((rc== 0) && contextPresent) { rc = TPM_Sbuffer_Append32(sbuffer, sha_ctx->h4); } if ((rc== 0) && contextPresent) { rc = TPM_Sbuffer_Append32(sbuffer, sha_ctx->Nl); } if ((rc== 0) && contextPresent) { rc = TPM_Sbuffer_Append32(sbuffer, sha_ctx->Nh); } for (i = 0 ; (rc == 0) && contextPresent && (i < SHA_LBLOCK) ; i++) { rc = TPM_Sbuffer_Append32(sbuffer, sha_ctx->data[i]); } if ((rc== 0) && contextPresent) { rc = TPM_Sbuffer_Append32(sbuffer, sha_ctx->num); } return rc; } /* TPM_SYMMETRIC_KEY_DATA */ /* TPM_SymmetricKeyData_New() allocates memory for and initializes a TPM_SYMMETRIC_KEY_DATA token. */ TPM_RESULT TPM_SymmetricKeyData_New(TPM_SYMMETRIC_KEY_TOKEN *tpm_symmetric_key_data) { TPM_RESULT rc = 0; printf(" TPM_SymmetricKeyData_New:\n"); if (rc == 0) { rc = TPM_Malloc(tpm_symmetric_key_data, sizeof(TPM_SYMMETRIC_KEY_DATA)); } if (rc == 0) { TPM_SymmetricKeyData_Init(*tpm_symmetric_key_data); } return rc; } /* TPM_SymmetricKeyData_Free() initializes the key token to wipe secrets. It then frees the TPM_SYMMETRIC_KEY_DATA token and sets it to NULL. */ void TPM_SymmetricKeyData_Free(TPM_SYMMETRIC_KEY_TOKEN *tpm_symmetric_key_data) { printf(" TPM_SymmetricKeyData_Free:\n"); if (*tpm_symmetric_key_data != NULL) { TPM_SymmetricKeyData_Init(*tpm_symmetric_key_data); free(*tpm_symmetric_key_data); *tpm_symmetric_key_data = NULL; } return; } #ifdef TPM_DES /* TPM_SymmetricKeyData_Init() is DES non-portable code to initialize the TPM_SYMMETRIC_KEY_DATA It depends on the TPM_SYMMETRIC_KEY_DATA declaration. */ void TPM_SymmetricKeyData_Init(TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token) { TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; printf(" TPM_SymmetricKeyData_Init:\n"); tpm_symmetric_key_data->tag = TPM_TAG_KEY; tpm_symmetric_key_data->valid = FALSE; tpm_symmetric_key_data->fill = 0; memset(tpm_symmetric_key_data->des_cblock1, 0, sizeof(DES_cblock)); memset(tpm_symmetric_key_data->des_cblock2, 0, sizeof(DES_cblock)); memset(tpm_symmetric_key_data->des_cblock3, 0, sizeof(DES_cblock)); return; } /* TPM_SymmetricKeyData_Load() is DES non-portable code to deserialize the TPM_SYMMETRIC_KEY_DATA It depends on the TPM_SYMMETRIC_KEY_DATA declaration. */ TPM_RESULT TPM_SymmetricKeyData_Load(TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; printf(" TPM_SymmetricKeyData_Load:\n"); /* check tag */ if (rc == 0) { rc = TPM_CheckTag(TPM_TAG_KEY, stream, stream_size); } /* load valid */ if (rc == 0) { rc = TPM_LoadBool(&(tpm_symmetric_key_data->valid), stream, stream_size); } /* load fill */ if (rc == 0) { rc = TPM_Load8(&(tpm_symmetric_key_data->fill), stream, stream_size); } /* this assumes that DES_cblock is a consistently packed structure. It is in fact an array of 8 bytes for openSSL. */ if (rc == 0) { rc = TPM_Loadn(tpm_symmetric_key_data->des_cblock1, sizeof(DES_cblock), stream, stream_size); } if (rc == 0) { rc = TPM_Loadn(tpm_symmetric_key_data->des_cblock2, sizeof(DES_cblock), stream, stream_size); } if (rc == 0) { rc = TPM_Loadn(tpm_symmetric_key_data->des_cblock3, sizeof(DES_cblock), stream, stream_size); } if (rc == 0) { TPM_PrintFour(" TPM_SymmetricKeyData_Load: des1", tpm_symmetric_key_data->des_cblock1); TPM_PrintFour(" TPM_SymmetricKeyData_Load: des2", tpm_symmetric_key_data->des_cblock2); TPM_PrintFour(" TPM_SymmetricKeyData_Load: des3", tpm_symmetric_key_data->des_cblock3); } return rc; } /* TPM_SymmetricKeyData_Store() DES is non-portable code to serialize the TPM_SYMMETRIC_KEY_DATA It depends on the TPM_SYMMETRIC_KEY_DATA declaration. */ TPM_RESULT TPM_SymmetricKeyData_Store(TPM_STORE_BUFFER *sbuffer, const TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token) { TPM_RESULT rc = 0; TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; printf(" TPM_SymmetricKeyData_Store:\n"); if (rc == 0) { TPM_PrintFour(" TPM_SymmetricKeyData_Store: des1", tpm_symmetric_key_data->des_cblock1); TPM_PrintFour(" TPM_SymmetricKeyData_Store: des2", tpm_symmetric_key_data->des_cblock2); TPM_PrintFour(" TPM_SymmetricKeyData_Store: des3", tpm_symmetric_key_data->des_cblock3); } /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, tpm_symmetric_key_data->tag); } /* store valid */s if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_symmetric_key_data->valid), sizeof(TPM_BOOL)); } /* store fill */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_symmetric_key_data->fill), sizeof(TPM_BOOL)); } /* store DES key */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, tpm_symmetric_key_data->des_cblock1, sizeof(DES_cblock)); } if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, tpm_symmetric_key_data->des_cblock2, sizeof(DES_cblock)); } if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, tpm_symmetric_key_data->des_cblock3, sizeof(DES_cblock)); } return rc; } /* TPM_SymmetricKeyData_GenerateKey() is DES non-portable code to generate a symmetric key vsymmetric_key must be freed by the caller */ TPM_RESULT TPM_SymmetricKeyData_GenerateKey(TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token) { TPM_RESULT rc = 0; TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; printf(" TPM_SymmetricKeyData_GenerateKey:\n"); /* generate a random key */ if (rc == 0) { DES_random_key(&(tpm_symmetric_key_data->des_cblock1)); DES_random_key(&(tpm_symmetric_key_data->des_cblock2)); DES_random_key(&(tpm_symmetric_key_data->des_cblock3)); /* sets the parity of the passed key to odd. */ DES_set_odd_parity(&(tpm_symmetric_key_data->des_cblock1)); DES_set_odd_parity(&(tpm_symmetric_key_data->des_cblock2)); DES_set_odd_parity(&(tpm_symmetric_key_data->des_cblock3)); TPM_PrintFour(" TPM_SymmetricKeyData_GenerateKey: des1", tpm_symmetric_key_data->des_cblock1); TPM_PrintFour(" TPM_SymmetricKeyData_GenerateKey: des2", tpm_symmetric_key_data->des_cblock2); TPM_PrintFour(" TPM_SymmetricKeyData_GenerateKey: des3", tpm_symmetric_key_data->des_cblock3); tpm_symmetric_key_data->valid = TRUE; } return rc; } /* TPM_SymmetricKeyData_Encrypt() is DES non-portable code to encrypt 'decrypt_data' to 'encrypt_data' The stream is padded as per PKCS#7 / RFC2630 'encrypt_data' must be free by the caller */ TPM_RESULT TPM_SymmetricKeyData_Encrypt(unsigned char **encrypt_data, /* output, caller frees */ uint32_t *encrypt_length, /* output */ const unsigned char *decrypt_data, /* input */ uint32_t decrypt_length, /* input */ const TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token) /* input */ { TPM_RESULT rc = 0; uint32_t pad_length; unsigned char *decrypt_data_pad; TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; printf(" TPM_SymmetricKeyData_Encrypt: Length %u\n", decrypt_length); decrypt_data_pad = NULL; /* freed @1 */ if (rc == 0) { /* calculate the pad length and padded data length */ pad_length = TPM_DES_BLOCK_SIZE - (decrypt_length % TPM_DES_BLOCK_SIZE); *encrypt_length = decrypt_length + pad_length; printf(" TPM_SymmetricKeyData_Encrypt: Padded length %u pad length %u\n", *encrypt_length, pad_length); /* allocate memory for the encrypted response */ rc = TPM_Malloc(encrypt_data, *encrypt_length); } /* allocate memory for the padded decrypted data */ if (rc == 0) { rc = TPM_Malloc(&decrypt_data_pad, *encrypt_length); } /* pad the decrypted clear text data */ if (rc == 0) { /* unpadded original data */ memcpy(decrypt_data_pad, decrypt_data, decrypt_length); /* last gets pad = pad length */ memset(decrypt_data_pad + decrypt_length, pad_length, pad_length); /* encrypt the padded input to the output */ rc = TPM_SymmetricKeyData_Crypt(*encrypt_data, decrypt_data_pad, *encrypt_length, tpm_symmetric_key_data, DES_ENCRYPT, TPM_ENCRYPT_ERROR); } free(decrypt_data_pad); /* @1 */ return rc; } /* TPM_SymmetricKeyData_Decrypt() is DES non-portable code to decrypt 'encrypt_data' to 'decrypt_data' The stream must be padded as per PKCS#7 / RFC2630 decrypt_data must be free by the caller */ TPM_RESULT TPM_SymmetricKeyData_Decrypt(unsigned char **decrypt_data, /* output, caller frees */ uint32_t *decrypt_length, /* output */ const unsigned char *encrypt_data, /* input */ uint32_t encrypt_length, /* input */ const TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_data) /* input */ { TPM_RESULT rc = 0; uint32_t pad_length; uint32_t i; unsigned char *pad_data; printf(" TPM_SymmetricKeyData_Decrypt: Length %u\n", encrypt_length); /* sanity check encrypted length */ if (rc == 0) { if (encrypt_length < TPM_DES_BLOCK_SIZE) { printf("TPM_SymmetricKeyData_Decrypt: Error, bad length\n"); rc = TPM_DECRYPT_ERROR; } } /* allocate memory for the padded decrypted data */ if (rc == 0) { rc = TPM_Malloc(decrypt_data, encrypt_length); } /* decrypt the input to the padded output */ if (rc == 0) { rc = TPM_SymmetricKeyData_Crypt(*decrypt_data, encrypt_data, encrypt_length, tpm_symmetric_key_data, DES_DECRYPT, TPM_DECRYPT_ERROR); } /* get the pad length */ if (rc == 0) { /* get the pad length from the last byte */ pad_length = (uint32_t)*(*decrypt_data + encrypt_length - 1); /* sanity check the pad length */ printf(" TPM_SymmetricKeyData_Decrypt: Pad length %u\n", pad_length); if ((pad_length == 0) || (pad_length > TPM_DES_BLOCK_SIZE)) { printf("TPM_SymmetricKeyData_Decrypt: Error, illegal pad length\n"); rc = TPM_DECRYPT_ERROR; } } if (rc == 0) { /* get the unpadded length */ *decrypt_length = encrypt_length - pad_length; /* pad starting point */ pad_data = *decrypt_data + *decrypt_length; /* sanity check the pad */ for (i = 0 ; i < pad_length ; i++, pad_data++) { if (*pad_data != pad_length) { printf("TPM_SymmetricKeyData_Decrypt: Error, bad pad %02x at index %u\n", *pad_data, i); rc = TPM_DECRYPT_ERROR; } } } return rc; } /* TPM_SymmetricKeyData_Crypt() is DES common code for openSSL, since encrypt and decrypt use the same function with an 'enc' flag. 'data_in' and 'data_out' must be preallocated arrays of 'length' bytes. 'length' must be a multiple of TPM_DES_BLOCK_SIZE. Returns 'error' on error. */ /* openSSL prototype void DES_ede3_cbc_encrypt(const unsigned char *input, unsigned char *output, long length, DES_key_schedule *ks1, DES_key_schedule *ks2, DES_key_schedule *ks3, DES_cblock *ivec, int enc); */ static TPM_RESULT TPM_SymmetricKeyData_Crypt(unsigned char *data_out, /* output */ const unsigned char *data_in, /* input */ uint32_t length, /* input */ TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data, /*in*/ int enc, /* input */ TPM_RESULT error) /* input */ { TPM_RESULT rc = 0; int irc; DES_key_schedule des_key_schedule1; DES_key_schedule des_key_schedule2; DES_key_schedule des_key_schedule3; DES_cblock ivec; /* initial chaining vector */ if (rc == 0) { if ((length % TPM_DES_BLOCK_SIZE) != 0) { printf("TPM_SymmetricKeyData_Crypt: Error, illegal length %u\n", length); rc = error; /* should never occur */ } } if (rc == 0) { TPM_PrintFour(" TPM_SymmetricKeyData_Crypt: des1", tpm_symmetric_key_data->des_cblock1); TPM_PrintFour(" TPM_SymmetricKeyData_Crypt: des2", tpm_symmetric_key_data->des_cblock2); TPM_PrintFour(" TPM_SymmetricKeyData_Crypt: des3", tpm_symmetric_key_data->des_cblock3); } /* Before a DES key can be used, it must be converted into the architecture dependent DES_key_schedule via the DES_set_key_checked() or DES_set_key_unchecked() function. */ if (rc == 0) { irc = DES_set_key_checked(&(tpm_symmetric_key_data->des_cblock1), &des_key_schedule1); if (irc != 0) { printf("TPM_SymmetricKeyData_Crypt: Error, DES_set_key_checked rc %d\n", irc); rc = error; } } if (rc == 0) { irc = DES_set_key_checked(&(tpm_symmetric_key_data->des_cblock2), &des_key_schedule2); if (irc != 0) { printf("TPM_SymmetricKeyData_Crypt: Error, DES_set_key_checked rc %d\n", irc); rc = error; } } if (rc == 0) { irc = DES_set_key_checked(&(tpm_symmetric_key_data->des_cblock3), &des_key_schedule3); if (irc != 0) { printf("TPM_SymmetricKeyData_Crypt: Error, DES_set_key_checked rc %d\n", irc); rc = error; } } /* initialize initial chaining vector */ if (rc == 0) { TPM_PrintFourLimit(" TPM_SymmetricKeyData_Crypt: Input", data_in, length); /* encrypt operation */ memset(&ivec, 0, sizeof(DES_cblock)); DES_ede3_cbc_encrypt(data_in, data_out, length, &des_key_schedule1, &des_key_schedule2, &des_key_schedule3, &ivec, enc); TPM_PrintFour(" TPM_SymmetricKeyData_Crypt: Output", data_out); } return rc; } #endif #ifdef TPM_AES /* TPM_SymmetricKeyData_Init() is AES non-portable code to initialize the TPM_SYMMETRIC_KEY_DATA It depends on the TPM_SYMMETRIC_KEY_DATA declaration. */ void TPM_SymmetricKeyData_Init(TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token) { TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; printf(" TPM_SymmetricKeyData_Init:\n"); tpm_symmetric_key_data->tag = TPM_TAG_KEY; tpm_symmetric_key_data->valid = FALSE; tpm_symmetric_key_data->fill = 0; memset(tpm_symmetric_key_data->userKey, 0, sizeof(tpm_symmetric_key_data->userKey)); memset(&(tpm_symmetric_key_data->aes_enc_key), 0, sizeof(tpm_symmetric_key_data->aes_enc_key)); memset(&(tpm_symmetric_key_data->aes_dec_key), 0, sizeof(tpm_symmetric_key_data->aes_dec_key)); return; } /* TPM_SymmetricKeyData_Load() is AES non-portable code to deserialize the TPM_SYMMETRIC_KEY_DATA It depends on the above TPM_SYMMETRIC_KEY_DATA declaration. */ TPM_RESULT TPM_SymmetricKeyData_Load(TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; printf(" TPM_SymmetricKeyData_Load:\n"); /* check tag */ if (rc == 0) { rc = TPM_CheckTag(TPM_TAG_KEY, stream, stream_size); } /* load valid */ if (rc == 0) { rc = TPM_LoadBool(&(tpm_symmetric_key_data->valid), stream, stream_size); } /* load fill */ if (rc == 0) { rc = TPM_Load8(&(tpm_symmetric_key_data->fill), stream, stream_size); } /* The AES key is a simple array. */ if (rc == 0) { rc = TPM_Loadn(tpm_symmetric_key_data->userKey, sizeof(tpm_symmetric_key_data->userKey), stream, stream_size); } /* reconstruct the internal AES keys */ if (rc == 0) { rc = TPM_SymmetricKeyData_SetKeys(tpm_symmetric_key_data); } return rc; } /* TPM_SymmetricKeyData_Store() is AES non-portable code to serialize the TPM_SYMMETRIC_KEY_DATA It depends on the above TPM_SYMMETRIC_KEY_DATA declaration. */ TPM_RESULT TPM_SymmetricKeyData_Store(TPM_STORE_BUFFER *sbuffer, const TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token) { TPM_RESULT rc = 0; TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; printf(" TPM_SymmetricKeyData_Store:\n"); /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, tpm_symmetric_key_data->tag); } /* store valid */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_symmetric_key_data->valid), sizeof(TPM_BOOL)); } /* store fill */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_symmetric_key_data->fill), sizeof(TPM_BOOL)); } /* store AES key */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, tpm_symmetric_key_data->userKey, sizeof(tpm_symmetric_key_data->userKey)); } /* No need to store the internal AES keys. They are reconstructed on load */ return rc; } /* TPM_SymmetricKeyData_GenerateKey() is AES non-portable code to generate a random symmetric key tpm_symmetric_key_data should be initialized before and after use */ TPM_RESULT TPM_SymmetricKeyData_GenerateKey(TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token) { TPM_RESULT rc = 0; TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; printf(" TPM_SymmetricKeyData_GenerateKey:\n"); /* generate a random key */ if (rc == 0) { rc = TPM_Random(tpm_symmetric_key_data->userKey, sizeof(tpm_symmetric_key_data->userKey)); } /* construct the internal AES keys */ if (rc == 0) { rc = TPM_SymmetricKeyData_SetKeys(tpm_symmetric_key_data); } if (rc == 0) { tpm_symmetric_key_data->valid = TRUE; } return rc; } /* TPM_SymmetricKeyData_SetKey() is AES non-portable code to set a symmetric key from input data tpm_symmetric_key_data should be initialized before and after use */ TPM_RESULT TPM_SymmetricKeyData_SetKey(TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data, const unsigned char *key_data, uint32_t key_data_size) { TPM_RESULT rc = 0; printf(" TPM_SymmetricKeyData_SetKey:\n"); /* check the input data size, it can be truncated, but cannot be smaller than the AES key */ if (rc == 0) { if (sizeof(tpm_symmetric_key_data->userKey) > key_data_size) { printf("TPM_SymmetricKeyData_SetKey: Error (fatal), need %lu bytes, received %u\n", (unsigned long)sizeof(tpm_symmetric_key_data->userKey), key_data_size); rc = TPM_FAIL; /* should never occur */ } } if (rc == 0) { /* copy the input data into the AES key structure */ memcpy(tpm_symmetric_key_data->userKey, key_data, sizeof(tpm_symmetric_key_data->userKey)); /* construct the internal AES keys */ rc = TPM_SymmetricKeyData_SetKeys(tpm_symmetric_key_data); } if (rc == 0) { tpm_symmetric_key_data->valid = TRUE; } return rc; } /* TPM_SymmetricKeyData_SetKeys() is AES non-portable code to construct the internal AES keys from the userKey tpm_symmetric_key_data should be initialized before and after use */ static TPM_RESULT TPM_SymmetricKeyData_SetKeys(TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data) { TPM_RESULT rc = 0; int irc; printf(" TPM_SymmetricKeyData_SetKeys:\n"); if (rc == 0) { TPM_PrintFour(" TPM_SymmetricKeyData_SetKeys: userKey", tpm_symmetric_key_data->userKey); irc = AES_set_encrypt_key(tpm_symmetric_key_data->userKey, TPM_AES_BITS, &(tpm_symmetric_key_data->aes_enc_key)); if (irc != 0) { printf("TPM_SymmetricKeyData_SetKeys: Error (fatal) generating enc key\n"); TPM_OpenSSL_PrintError(); rc = TPM_FAIL; /* should never occur, null pointers or bad bit size */ } } if (rc == 0) { irc = AES_set_decrypt_key(tpm_symmetric_key_data->userKey, TPM_AES_BITS, &(tpm_symmetric_key_data->aes_dec_key)); if (irc != 0) { printf("TPM_SymmetricKeyData_SetKeys: Error (fatal) generating dec key\n"); TPM_OpenSSL_PrintError(); rc = TPM_FAIL; /* should never occur, null pointers or bad bit size */ } } return rc; } /* TPM_SymmetricKeyData_Encrypt() is AES non-portable code to encrypt 'decrypt_data' to 'encrypt_data' The stream is padded as per PKCS#7 / RFC2630 'encrypt_data' must be free by the caller */ TPM_RESULT TPM_SymmetricKeyData_Encrypt(unsigned char **encrypt_data, /* output, caller frees */ uint32_t *encrypt_length, /* output */ const unsigned char *decrypt_data, /* input */ uint32_t decrypt_length, /* input */ const TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token) /* input */ { TPM_RESULT rc = 0; uint32_t pad_length; unsigned char *decrypt_data_pad; unsigned char ivec[TPM_AES_BLOCK_SIZE]; /* initial chaining vector */ TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; printf(" TPM_SymmetricKeyData_Encrypt: Length %u\n", decrypt_length); decrypt_data_pad = NULL; /* freed @1 */ if (rc == 0) { /* calculate the pad length and padded data length */ pad_length = TPM_AES_BLOCK_SIZE - (decrypt_length % TPM_AES_BLOCK_SIZE); *encrypt_length = decrypt_length + pad_length; printf(" TPM_SymmetricKeyData_Encrypt: Padded length %u pad length %u\n", *encrypt_length, pad_length); /* allocate memory for the encrypted response */ rc = TPM_Malloc(encrypt_data, *encrypt_length); } /* allocate memory for the padded decrypted data */ if (rc == 0) { rc = TPM_Malloc(&decrypt_data_pad, *encrypt_length); } /* pad the decrypted clear text data */ if (rc == 0) { /* unpadded original data */ memcpy(decrypt_data_pad, decrypt_data, decrypt_length); /* last gets pad = pad length */ memset(decrypt_data_pad + decrypt_length, pad_length, pad_length); /* set the IV */ memset(ivec, 0, sizeof(ivec)); /* encrypt the padded input to the output */ TPM_PrintFour(" TPM_SymmetricKeyData_Encrypt: Input", decrypt_data_pad); AES_cbc_encrypt(decrypt_data_pad, *encrypt_data, *encrypt_length, &(tpm_symmetric_key_data->aes_enc_key), ivec, AES_ENCRYPT); TPM_PrintFour(" TPM_SymmetricKeyData_Encrypt: Output", *encrypt_data); } free(decrypt_data_pad); /* @1 */ return rc; } /* TPM_SymmetricKeyData_Decrypt() is AES non-portable code to decrypt 'encrypt_data' to 'decrypt_data' The stream must be padded as per PKCS#7 / RFC2630 decrypt_data must be free by the caller */ TPM_RESULT TPM_SymmetricKeyData_Decrypt(unsigned char **decrypt_data, /* output, caller frees */ uint32_t *decrypt_length, /* output */ const unsigned char *encrypt_data, /* input */ uint32_t encrypt_length, /* input */ const TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token) /* input */ { TPM_RESULT rc = 0; uint32_t pad_length; uint32_t i; unsigned char *pad_data; unsigned char ivec[TPM_AES_BLOCK_SIZE]; /* initial chaining vector */ TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; printf(" TPM_SymmetricKeyData_Decrypt: Length %u\n", encrypt_length); /* sanity check encrypted length */ if (rc == 0) { if (encrypt_length < TPM_AES_BLOCK_SIZE) { printf("TPM_SymmetricKeyData_Decrypt: Error, bad length\n"); rc = TPM_DECRYPT_ERROR; } } /* allocate memory for the padded decrypted data */ if (rc == 0) { rc = TPM_Malloc(decrypt_data, encrypt_length); } /* decrypt the input to the padded output */ if (rc == 0) { /* set the IV */ memset(ivec, 0, sizeof(ivec)); /* decrypt the padded input to the output */ TPM_PrintFour(" TPM_SymmetricKeyData_Decrypt: Input", encrypt_data); AES_cbc_encrypt(encrypt_data, *decrypt_data, encrypt_length, &(tpm_symmetric_key_data->aes_dec_key), ivec, AES_DECRYPT); TPM_PrintFour(" TPM_SymmetricKeyData_Decrypt: Output", *decrypt_data); } /* get the pad length */ if (rc == 0) { /* get the pad length from the last byte */ pad_length = (uint32_t)*(*decrypt_data + encrypt_length - 1); /* sanity check the pad length */ printf(" TPM_SymmetricKeyData_Decrypt: Pad length %u\n", pad_length); if ((pad_length == 0) || (pad_length > TPM_AES_BLOCK_SIZE)) { printf("TPM_SymmetricKeyData_Decrypt: Error, illegal pad length\n"); rc = TPM_DECRYPT_ERROR; } } if (rc == 0) { /* get the unpadded length */ *decrypt_length = encrypt_length - pad_length; /* pad starting point */ pad_data = *decrypt_data + *decrypt_length; /* sanity check the pad */ for (i = 0 ; i < pad_length ; i++, pad_data++) { if (*pad_data != pad_length) { printf("TPM_SymmetricKeyData_Decrypt: Error, bad pad %02x at index %u\n", *pad_data, i); rc = TPM_DECRYPT_ERROR; } } } return rc; } /* TPM_SymmetricKeyData_CtrCrypt() does an encrypt or decrypt (they are the same XOR operation with a CTR mode pad) of 'data_in' to 'data_out'. NOTE: This function looks general, but is currently hard coded to AES128. 'symmetric key' is the raw key, not converted to a non-portable form 'ctr_in' is the initial CTR value before possible truncation */ TPM_RESULT TPM_SymmetricKeyData_CtrCrypt(unsigned char *data_out, /* output */ const unsigned char *data_in, /* input */ uint32_t data_size, /* input */ const unsigned char *symmetric_key, /* input */ uint32_t symmetric_key_size, /* input */ const unsigned char *ctr_in, /* input */ uint32_t ctr_in_size) /* input */ { TPM_RESULT rc = 0; TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = NULL; /* freed @1 */ unsigned char ctr[TPM_AES_BLOCK_SIZE]; printf(" TPM_SymmetricKeyData_CtrCrypt: data_size %u\n", data_size); /* allocate memory for the key token. The token is opaque in the API, but at this low level, the code understands the TPM_SYMMETRIC_KEY_DATA structure */ if (rc == 0) { rc = TPM_SymmetricKeyData_New((TPM_SYMMETRIC_KEY_TOKEN *)&tpm_symmetric_key_data); } /* convert the raw key to the AES key, truncating as required */ if (rc == 0) { rc = TPM_SymmetricKeyData_SetKey(tpm_symmetric_key_data, symmetric_key, symmetric_key_size); } /* check the input CTR size, it can be truncated, but cannot be smaller than the AES key */ if (rc == 0) { if (ctr_in_size < sizeof(ctr)) { printf(" TPM_SymmetricKeyData_CtrCrypt: Error (fatal)" ", CTR size %u too small for AES key\n", ctr_in_size); rc = TPM_FAIL; /* should never occur */ } } if (rc == 0) { /* make a truncated copy of CTR, since AES_ctr128_encrypt alters the value */ memcpy(ctr, ctr_in, sizeof(ctr)); printf(" TPM_SymmetricKeyData_CtrCrypt: Calling AES in CTR mode\n"); TPM_PrintFour(" TPM_SymmetricKeyData_CtrCrypt: CTR", ctr); rc = TPM_AES_ctr128_encrypt(data_out, data_in, data_size, &(tpm_symmetric_key_data->aes_enc_key), ctr); } TPM_SymmetricKeyData_Free((TPM_SYMMETRIC_KEY_TOKEN *)&tpm_symmetric_key_data); /* @1 */ return rc; } /* TPM_AES_ctr128_encrypt() is a TPM variant of the openSSL AES_ctr128_encrypt() function that increments only the low 4 bytes of the counter. openSSL increments the entire CTR array. The TPM does not follow that convention. */ static TPM_RESULT TPM_AES_ctr128_encrypt(unsigned char *data_out, const unsigned char *data_in, uint32_t data_size, const AES_KEY *aes_enc_key, unsigned char ctr[TPM_AES_BLOCK_SIZE]) { TPM_RESULT rc = 0; uint32_t cint; unsigned char pad_buffer[TPM_AES_BLOCK_SIZE]; /* the XOR pad */ printf(" TPM_AES_Ctr128_encrypt:\n"); while (data_size != 0) { printf(" TPM_AES_Ctr128_encrypt: data_size %lu\n", (unsigned long)data_size); /* get an XOR pad array by encrypting the CTR with the AES key */ AES_encrypt(ctr, pad_buffer, aes_enc_key); /* partial or full last data block */ if (data_size <= TPM_AES_BLOCK_SIZE) { TPM_XOR(data_out, data_in, pad_buffer, data_size); data_size = 0; } /* full block, not the last block */ else { TPM_XOR(data_out, data_in, pad_buffer, TPM_AES_BLOCK_SIZE); data_in += TPM_AES_BLOCK_SIZE; data_out += TPM_AES_BLOCK_SIZE; data_size -= TPM_AES_BLOCK_SIZE; } /* if not the last block, increment CTR, only the low 4 bytes */ if (data_size != 0) { /* CTR is a big endian array, so the low 4 bytes are 12-15 */ cint = LOAD32(ctr, 12); /* byte array to uint32_t */ cint++; /* increment */ STORE32(ctr, 12, cint); /* uint32_t to byte array */ } } return rc; } /* TPM_SymmetricKeyData_OfbCrypt() does an encrypt or decrypt (they are the same XOR operation with a OFB mode pad) of 'data_in' to 'data_out' NOTE: This function looks general, but is currently hard coded to AES128. 'symmetric key' is the raw key, not converted to a non-portable form 'ivec_in' is the initial IV value before possible truncation */ /* openSSL prototype void AES_ofb128_encrypt(const unsigned char *in, unsigned char *out, const unsigned long length, const AES_KEY *key, unsigned char *ivec, int *num); */ TPM_RESULT TPM_SymmetricKeyData_OfbCrypt(unsigned char *data_out, /* output */ const unsigned char *data_in, /* input */ uint32_t data_size, /* input */ const unsigned char *symmetric_key, /* in */ uint32_t symmetric_key_size, /* in */ unsigned char *ivec_in, /* input */ uint32_t ivec_in_size) /* input */ { TPM_RESULT rc = 0; TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = NULL; /* freed @1 */ unsigned char ivec[TPM_AES_BLOCK_SIZE]; int num; printf(" TPM_SymmetricKeyData_OfbCrypt: data_size %u\n", data_size); /* allocate memory for the key token. The token is opaque in the API, but at this low level, the code understands the TPM_SYMMETRIC_KEY_DATA structure */ if (rc == 0) { rc = TPM_SymmetricKeyData_New((TPM_SYMMETRIC_KEY_TOKEN *)&tpm_symmetric_key_data); } /* convert the raw key to the AES key, truncating as required */ if (rc == 0) { rc = TPM_SymmetricKeyData_SetKey(tpm_symmetric_key_data, symmetric_key, symmetric_key_size); } /* check the input OFB size, it can be truncated, but cannot be smaller than the AES key */ if (rc == 0) { if (ivec_in_size < sizeof(ivec)) { printf(" TPM_SymmetricKeyData_OfbCrypt: Error (fatal)," "IV size %u too small for AES key\n", ivec_in_size); rc = TPM_FAIL; /* should never occur */ } } if (rc == 0) { /* make a truncated copy of IV, since AES_ofb128_encrypt alters the value */ memcpy(ivec, ivec_in, sizeof(ivec)); num = 0; printf(" TPM_SymmetricKeyData_OfbCrypt: Calling AES in OFB mode\n"); TPM_PrintFour(" TPM_SymmetricKeyData_OfbCrypt: IV", ivec); AES_ofb128_encrypt(data_in, data_out, data_size, &(tpm_symmetric_key_data->aes_enc_key), ivec, &num); } TPM_SymmetricKeyData_Free((TPM_SYMMETRIC_KEY_TOKEN *)&tpm_symmetric_key_data); return rc; } #endif /* TPM_AES */ libtpms-0.9.3/src/tpm12/tpm_crypto.h000066400000000000000000000243041421143571500173060ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Platform Dependent Crypto */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_crypto.h 4406 2011-02-08 22:11:37Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_CRYPTO_H #define TPM_CRYPTO_H #include "config.h" /* libtpms added */ #include "tpm_secret.h" #include "tpm_types.h" /* self test */ TPM_RESULT TPM_Crypto_Init(void); TPM_RESULT TPM_Crypto_TestSpecific(void); /* random number */ TPM_RESULT TPM_Random(BYTE *buffer, size_t bytes); TPM_RESULT TPM_StirRandomCmd(TPM_SIZED_BUFFER *inData); /* bignum */ TPM_RESULT TPM_BN_num_bytes(unsigned int *numBytes, TPM_BIGNUM bn_in); TPM_RESULT TPM_BN_is_one(TPM_BIGNUM bn_in); TPM_RESULT TPM_BN_mod(TPM_BIGNUM rem_in, const TPM_BIGNUM a_in, const TPM_BIGNUM m_in); TPM_RESULT TPM_BN_mask_bits(TPM_BIGNUM bn_in, unsigned int n); TPM_RESULT TPM_BN_rshift(TPM_BIGNUM *rBignum_in, TPM_BIGNUM aBignum_in, int n); TPM_RESULT TPM_BN_lshift(TPM_BIGNUM *rBignum_in, TPM_BIGNUM aBignum_in, int n); TPM_RESULT TPM_BN_add(TPM_BIGNUM rBignum_in, TPM_BIGNUM aBignum_in, TPM_BIGNUM bBignum_in); TPM_RESULT TPM_BN_mul(TPM_BIGNUM rBignum_in, TPM_BIGNUM aBignum_in, TPM_BIGNUM bBignum_in); TPM_RESULT TPM_BN_mod_exp(TPM_BIGNUM rBignum_in, TPM_BIGNUM aBignum_in, TPM_BIGNUM pBignum_in, TPM_BIGNUM nBignum_in); TPM_RESULT TPM_BN_mod_mul(TPM_BIGNUM rBignum_in, TPM_BIGNUM aBignum_in, TPM_BIGNUM bBignum_in, TPM_BIGNUM mBignum_in); TPM_RESULT TPM_BN_mod_add(TPM_BIGNUM rBignum_in, TPM_BIGNUM aBignum_in, TPM_BIGNUM bBignum_in, TPM_BIGNUM mBignum_in); TPM_RESULT TPM_bin2bn(TPM_BIGNUM *bn_in, const unsigned char *bin, unsigned int bytes); TPM_RESULT TPM_bn2bin(unsigned char *bin, TPM_BIGNUM bn_in); TPM_RESULT TPM_BN_new(TPM_BIGNUM *bn_in); void TPM_BN_free(TPM_BIGNUM bn_in); /* RSA */ TPM_RESULT TPM_RSAGenerateKeyPair(unsigned char **n, unsigned char **p, unsigned char **q, unsigned char **d, int num_bit, const unsigned char *earr, uint32_t e_size); TPM_RESULT TPM_RSAPrivateDecrypt(unsigned char *decrypt_data, uint32_t *decrypt_data_length, size_t decrypt_data_size, TPM_ENC_SCHEME encScheme, unsigned char* encrypt_data, uint32_t encrypt_data_size, unsigned char *n, uint32_t nbytes, unsigned char *e, uint32_t ebytes, unsigned char *d, uint32_t dbytes); TPM_RESULT TPM_RSAPublicEncrypt(unsigned char* encrypt_data, size_t encrypt_data_size, TPM_ENC_SCHEME encScheme, const unsigned char *decrypt_data, size_t decrypt_data_size, unsigned char *narr, uint32_t nbytes, unsigned char *earr, uint32_t ebytes); #if USE_FREEBL_CRYPTO_LIBRARY TPM_RESULT TPM_RSAPublicEncryptRaw(unsigned char *encrypt_data, uint32_t encrypt_data_size, unsigned char *decrypt_data, uint32_t decrypt_data_size, unsigned char *narr, uint32_t nbytes, unsigned char *earr, uint32_t ebytes); #endif TPM_RESULT TPM_RSAGetPrivateKey(uint32_t *qbytes, unsigned char **qarr, uint32_t *dbytes, unsigned char **darr, uint32_t nbytes, unsigned char *narr, uint32_t ebytes, unsigned char *earr, uint32_t pbytes, unsigned char *parr); TPM_RESULT TPM_RSASign(unsigned char *signature, unsigned int *signature_length, unsigned int signature_size, TPM_SIG_SCHEME sigScheme, const unsigned char *message, size_t message_size, unsigned char *narr, uint32_t nbytes, unsigned char *earr, uint32_t ebytes, unsigned char *darr, uint32_t dbytes); TPM_RESULT TPM_RSAVerifySHA1(unsigned char *signature, unsigned int signature_size, const unsigned char *message, uint32_t message_size, unsigned char *narr, uint32_t nbytes, unsigned char *earr, uint32_t ebytes); /* SHA-1 */ TPM_RESULT TPM_SHA1InitCmd(void **context); TPM_RESULT TPM_SHA1UpdateCmd(void *context, const unsigned char *data, uint32_t length); TPM_RESULT TPM_SHA1FinalCmd(unsigned char *md, void *context); void TPM_SHA1Delete(void **context); /* SHA-1 Context */ TPM_RESULT TPM_Sha1Context_Load(void **context, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_Sha1Context_Store(TPM_STORE_BUFFER *sbuffer, void *context); /* TPM_SYMMETRIC_KEY_DATA */ TPM_RESULT TPM_SymmetricKeyData_New(TPM_SYMMETRIC_KEY_TOKEN *tpm_symmetric_key_data); void TPM_SymmetricKeyData_Free(TPM_SYMMETRIC_KEY_TOKEN *tpm_symmetric_key_data); void TPM_SymmetricKeyData_Init(TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token); TPM_RESULT TPM_SymmetricKeyData_Load(TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_SymmetricKeyData_Store(TPM_STORE_BUFFER *sbuffer, const TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token); TPM_RESULT TPM_SymmetricKeyData_GenerateKey(TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token); TPM_RESULT TPM_SymmetricKeyData_Encrypt(unsigned char **encrypt_data, uint32_t *encrypt_length, const unsigned char *decrypt_data, uint32_t decrypt_length, const TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token); TPM_RESULT TPM_SymmetricKeyData_Decrypt(unsigned char **decrypt_data, uint32_t *decrypt_length, const unsigned char *encrypt_data, uint32_t encrypt_length, const TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token); TPM_RESULT TPM_SymmetricKeyData_CtrCrypt(unsigned char *data_out, const unsigned char *data_in, uint32_t data_size, const unsigned char *symmetric_key, uint32_t symmetric_key_size, const unsigned char *ctr_in, uint32_t ctr_in_size); TPM_RESULT TPM_SymmetricKeyData_OfbCrypt(unsigned char *data_out, const unsigned char *data_in, uint32_t data_size, const unsigned char *symmetric_key, uint32_t symmetric_key_size, unsigned char *ivec_in, uint32_t ivec_in_size); #endif libtpms-0.9.3/src/tpm12/tpm_crypto_freebl.c000066400000000000000000002604551421143571500206310ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Platform Dependent Crypto */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_crypto_freebl.c 4655 2011-12-21 21:03:15Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ /* This is the FreeBL implementation setenv CVSROOT :pserver:anonymous@cvsmirror.mozilla.org:/cvsroot cvs co mosilla/nsprpub gmake nss_build_all */ #include #include #include #include #include "blapi.h" #include #include "tpm_cryptoh.h" #include "tpm_debug.h" #include "tpm_error.h" #include "tpm_key.h" #include "tpm_io.h" #include "tpm_load.h" #include "tpm_memory.h" #include "tpm_process.h" #include "tpm_types.h" #include "tpm_crypto.h" /* The TPM OAEP encoding parameter */ static const unsigned char tpm_oaep_pad_str[] = { 'T', 'C', 'P', 'A' }; /* pre-calculate hash of the constant tpm_oaep_pad_str, used often in the OAEP padding calculations */ static const unsigned char pHashConst[TPM_DIGEST_SIZE]; /* ASN.1 industry standard SHA1 with RSA object identifier */ static unsigned char sha1Oid[] = { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14}; /* local prototypes */ static void TPM_RSAPrivateKeyInit(RSAPrivateKey *rsa_pri_key); static TPM_RESULT TPM_RSAGeneratePublicToken(RSAPublicKey *rsa_pub_key, unsigned char *narr, uint32_t nbytes, unsigned char *earr, uint32_t ebytes); static TPM_RESULT TPM_RSAGeneratePrivateToken(RSAPrivateKey *rsa_pri_key, unsigned char *narr, uint32_t nbytes, unsigned char *earr, uint32_t ebytes, unsigned char *darr, uint32_t dbytes); static TPM_RESULT TPM_RSASignSHA1(unsigned char *signature, unsigned int *signature_length, const unsigned char *message, size_t message_size, RSAPrivateKey *rsa_pri_key); static TPM_RESULT TPM_RSASignDER(unsigned char *signature, unsigned int *signature_length, const unsigned char *message, size_t message_size, RSAPrivateKey *rsa_pri_key); static TPM_RESULT TPM_RandomNonZero(BYTE *buffer, size_t bytes); static TPM_RESULT TPM_PKCS1_PaddingType1Add(unsigned char *output, uint32_t outputLength, const unsigned char *input, uint32_t inputLength); static TPM_RESULT TPM_PKCS1_PaddingType1Check(uint32_t *padLength, unsigned char *input, uint32_t inputLength); static TPM_RESULT TPM_PKCS1_PaddingType2Add(unsigned char *encodedMessage, uint32_t encodedMessageLength, const unsigned char *message, uint32_t messageLength); static TPM_RESULT TPM_PKCS1_PaddingType2Check(unsigned char *outputData, uint32_t *outputDataLength, uint32_t outputDataSize, unsigned char *inputData, uint32_t inputDataLength); static TPM_RESULT TPM_memcpyPad(unsigned char **bin_out, unsigned char *bin_in, uint32_t bin_in_length, uint32_t padBytes); /* TPM_SYMMETRIC_KEY_DATA is a crypto library platform dependent symmetric key structure */ #ifdef TPM_AES /* local prototype and structure for AES */ /* AES requires data lengths that are a multiple of the block size */ #define TPM_AES_BITS 128 /* The AES block size is always 16 bytes */ #define TPM_AES_BLOCK_SIZE 16 /* Since the AES key is often derived by truncating the session shared secret, test that it's not too large */ #if (TPM_AES_BLOCK_SIZE > TPM_SECRET_SIZE) #error TPM_AES_BLOCK_SIZE larger than TPM_SECRET_SIZE #endif /* The AES initial CTR value is derived from a nonce. */ #if (TPM_AES_BLOCK_SIZE > TPM_NONCE_SIZE) #error TPM_AES_BLOCK_SIZE larger than TPM_NONCE_SIZE #endif typedef struct tdTPM_SYMMETRIC_KEY_DATA { TPM_TAG tag; TPM_BOOL valid; TPM_BOOL fill; unsigned char userKey[TPM_AES_BLOCK_SIZE]; } TPM_SYMMETRIC_KEY_DATA; #endif /* TPM_AES */ /* Crypto library Initialization function */ TPM_RESULT TPM_Crypto_Init() { TPM_RESULT rc = 0; SECStatus rv = SECSuccess; printf("TPM_Crypto_Init: FreeBL library\n"); /* initialize the random number generator */ if (rc == 0) { printf(" TPM_Crypto_Init: Initializing RNG\n"); rv = RNG_RNGInit(); if (rv != SECSuccess) { printf("TPM_Crypto_Init: Error (fatal), RNG_RNGInit rv %d\n", rv); rc = TPM_FAIL; } } /* add additional seed entropy to the random number generator */ if (rc == 0) { printf(" TPM_Crypto_Init: Seeding RNG\n"); RNG_SystemInfoForRNG(); } if (rc == 0) { rv = BL_Init(); if (rv != SECSuccess) { printf("TPM_Crypto_Init: Error (fatal), BL_Init rv %d\n", rv); rc =TPM_FAIL ; } } /* pre-calculate hash of the constant tpm_oaep_pad_str, used often in the OAEP padding calculations */ if (rc == 0) { rc = TPM_SHA1((unsigned char *)pHashConst, /* cast once to precalculate the constant */ sizeof(tpm_oaep_pad_str), tpm_oaep_pad_str, 0, NULL); TPM_PrintFour("TPM_Crypto_Init: pHashConst", pHashConst); } return rc; } /* TPM_Crypto_TestSpecific() performs any library specific tests For FreeBL */ TPM_RESULT TPM_Crypto_TestSpecific() { TPM_RESULT rc = 0; /* Saving the SHA-1 context is fragile code, so test at startup */ void *context1; void *context2; unsigned char buffer1[] = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; unsigned char expect1[] = {0x84,0x98,0x3E,0x44,0x1C, 0x3B,0xD2,0x6E,0xBA,0xAE, 0x4A,0xA1,0xF9,0x51,0x29, 0xE5,0xE5,0x46,0x70,0xF1}; TPM_DIGEST actual; int not_equal; TPM_STORE_BUFFER sbuffer; const unsigned char *stream; uint32_t stream_size; printf(" TPM_Crypto_TestSpecific: Test 1 - SHA1 two parts\n"); context1 = NULL; /* freed @1 */ context2 = NULL; /* freed @2 */ TPM_Sbuffer_Init(&sbuffer); /* freed @3 */ if (rc== 0) { rc = TPM_SHA1InitCmd(&context1); /* freed @1 */ } /* digest the first part of the array */ if (rc== 0) { rc = TPM_SHA1UpdateCmd(context1, buffer1, 16); } /* store the SHA1 context */ if (rc== 0) { rc = TPM_Sha1Context_Store(&sbuffer, context1); } /* load the SHA1 context */ if (rc== 0) { TPM_Sbuffer_Get(&sbuffer, &stream, &stream_size); rc = TPM_Sha1Context_Load (&context2, (unsigned char **)&stream, &stream_size); /* freed @2 */ } /* digest the rest of the array */ if (rc== 0) { rc = TPM_SHA1UpdateCmd(context2, buffer1 + 16, sizeof(buffer1) - 17); } /* get the digest result */ if (rc== 0) { rc = TPM_SHA1FinalCmd(actual, context2); } /* check the result */ if (rc == 0) { not_equal = memcmp(expect1, actual, TPM_DIGEST_SIZE); if (not_equal) { printf("TPM_Crypto_TestSpecific: Error in test 1\n"); TPM_PrintFour("\texpect", expect1); TPM_PrintFour("\tactual", actual); rc = TPM_FAILEDSELFTEST; } } TPM_SHA1Delete(&context1); /* @1 */ TPM_SHA1Delete(&context2); /* @2 */ TPM_Sbuffer_Delete(&sbuffer); /* @3 */ return rc; } /* Random Number Functions */ /* TPM_Random() fills 'buffer' with 'bytes' bytes. */ TPM_RESULT TPM_Random(BYTE *buffer, size_t bytes) { TPM_RESULT rc = 0; SECStatus rv = SECSuccess; printf(" TPM_Random: Requesting %lu bytes\n", (unsigned long)bytes); /* generate the random bytes */ if (rc == 0) { rv = RNG_GenerateGlobalRandomBytes(buffer, bytes); if (rv != SECSuccess) { printf("TPM_Random: Error (fatal) in RNG_GenerateGlobalRandomBytes rv %d\n", rv); rc = TPM_FAIL; } } return rc; } /* TPM_Random() fills 'buffer' with 'bytes' non-zero bytes This is used for PKCS padding. */ static TPM_RESULT TPM_RandomNonZero(BYTE *buffer, size_t bytes) { TPM_RESULT rc = 0; size_t i; SECStatus rv = SECSuccess; printf(" TPM_RandomNonZero: Requesting %lu bytes\n", (unsigned long)bytes); for (i = 0 ; (rc == 0) && (i < bytes) ; ) { rv = RNG_GenerateGlobalRandomBytes(buffer, 1); if (rv != SECSuccess) { printf("TPM_Random: Error (fatal) in RNG_GenerateGlobalRandomBytes rv %d\n", rv); rc = TPM_FAIL; } else { if (*buffer != 0x00) { buffer++; i++; } } } return rc; } /* TPM_StirRandomCmd() adds the supplied entropy to the random number generator */ TPM_RESULT TPM_StirRandomCmd(TPM_SIZED_BUFFER *inData) { TPM_RESULT rc = 0; SECStatus rv = SECSuccess; printf(" TPM_StirRandomCmd:\n"); if (rc == 0) { /* add the seeding material */ rv = RNG_RandomUpdate(inData->buffer, inData->size); if (rv != SECSuccess) { printf("TPM_StirRandom: Error (fatal) in RNG_RandomUpdate rv %d\n", rv); rc = TPM_FAIL; } } return rc; } /* RSA Functions */ /* TPM_RSAPrivateKeyInit() NULLs all the structure members in preparation for constructing an RSA key token from byte arrays using RSA_PopulatePrivateKey() */ static void TPM_RSAPrivateKeyInit(RSAPrivateKey *rsa_pri_key) { rsa_pri_key->arena = NULL; rsa_pri_key->publicExponent.type = siBuffer; rsa_pri_key->publicExponent.data = NULL; rsa_pri_key->publicExponent.len = 0; rsa_pri_key->modulus.type = siBuffer; rsa_pri_key->modulus.data = NULL; rsa_pri_key->modulus.len = 0; rsa_pri_key->privateExponent.type = siBuffer; rsa_pri_key->privateExponent.data = NULL; rsa_pri_key->privateExponent.len = 0; rsa_pri_key->prime1.type = siBuffer; rsa_pri_key->prime1.data = NULL; rsa_pri_key->prime1.len = 0; rsa_pri_key->prime2.type = siBuffer; rsa_pri_key->prime2.data = NULL; rsa_pri_key->prime2.len = 0; rsa_pri_key->exponent1.type = siBuffer; rsa_pri_key->exponent1.data = NULL; rsa_pri_key->exponent1.len = 0; rsa_pri_key->exponent2.type = siBuffer; rsa_pri_key->exponent2.data = NULL; rsa_pri_key->exponent2.len = 0; rsa_pri_key->coefficient.type = siBuffer; rsa_pri_key->coefficient.data = NULL; rsa_pri_key->coefficient.len = 0; return; } /* Generate an RSA key pair of size 'num_bits' using public exponent 'earr' 'n', 'p', 'q', 'd' must be freed by the caller */ TPM_RESULT TPM_RSAGenerateKeyPair(unsigned char **n, /* public key - modulus */ unsigned char **p, /* private key prime */ unsigned char **q, /* private key prime */ unsigned char **d, /* private key (private exponent) */ int num_bits, /* key size in bits */ const unsigned char *earr, /* public exponent as an array */ uint32_t e_size) { TPM_RESULT rc = 0; SECItem publicExponent = { 0, 0, 0}; RSAPrivateKey *rsaPrivateKey = NULL; /* freed @1 */ unsigned long e; /* public exponent */ printf(" TPM_RSAGenerateKeyPair:\n"); /* initialize in case of error */ *n = NULL; *p = NULL; *q = NULL; *d = NULL; /* check that num_bits is a multiple of 16. If not, the primes p and q will not be a multiple of 8 and will not fit well in a byte */ if (rc == 0) { if ((num_bits % 16) != 0) { printf("TPM_RSAGenerateKeyPair: Error, num_bits %d is not a multiple of 16\n", num_bits); rc = TPM_BAD_KEY_PROPERTY; } } /* convert the e array to an unsigned long */ if (rc == 0) { rc = TPM_LoadLong(&e, earr, e_size); } /* validate the public exponent against a list of legal values. Some values (e.g. even numbers) can hang the key generator. */ if (rc == 0) { rc = TPM_RSA_exponent_verify(e); } /* generate the key pair */ if (rc == 0) { printf(" TPM_RSAGenerateKeyPair: num_bits %d exponent %08lx\n", num_bits, e); publicExponent.type = siBuffer; publicExponent.data = (unsigned char *)earr; publicExponent.len = e_size; /* Generate and return a new RSA public and private key token */ rsaPrivateKey = RSA_NewKey(num_bits, &publicExponent); /* freed @1 */ if (rsaPrivateKey == NULL) { printf("TPM_RSAGenerateKeyPair: Error (fatal) calling RSA_NewKey()\n"); rc = TPM_FAIL; } } /* Key parts can some times have leading zeros, and some crypto libraries truncate. However, the TPM expects fixed lengths. These calls restore any removed padding */ /* load n */ if (rc == 0) { rc = TPM_memcpyPad(n, /* freed by caller */ rsaPrivateKey->modulus.data, rsaPrivateKey->modulus.len, num_bits/8); /* required length */ } /* load p */ if (rc == 0) { rc = TPM_memcpyPad(p, /* freed by caller */ rsaPrivateKey->prime1.data, rsaPrivateKey->prime1.len, num_bits/16); /* required length */ } /* load q */ if (rc == 0) { rc = TPM_memcpyPad(q, /* freed by caller */ rsaPrivateKey->prime2.data, rsaPrivateKey->prime2.len, num_bits/16); /* required length */ } /* load d */ if (rc == 0) { rc = TPM_memcpyPad(d, /* freed by caller */ rsaPrivateKey->privateExponent.data, rsaPrivateKey->privateExponent.len, num_bits/8); /* required length */ } /* on error, free the components and set back to NULL so subsequent free is safe */ if (rc != 0) { free(*n); free(*p); free(*q); free(*d); *n = NULL; *p = NULL; *q = NULL; *d = NULL; } if (rsaPrivateKey != NULL) { PORT_FreeArena(rsaPrivateKey->arena, PR_TRUE); /* @1 */ } return rc; } /* TPM_RSAGeneratePublicToken() generates an RSA key token from n and e */ static TPM_RESULT TPM_RSAGeneratePublicToken(RSAPublicKey *rsaPublicKey, unsigned char *narr, /* public modulus */ uint32_t nbytes, unsigned char *earr, /* public exponent */ uint32_t ebytes) { TPM_RESULT rc = 0; /* simply assign the arrays to the key token */ if (rc == 0) { printf(" TPM_RSAGeneratePublicToken: nbytes %u ebytes %u\n", nbytes, ebytes); rsaPublicKey->arena = NULL; /* public modulus */ rsaPublicKey->modulus.type = siBuffer; rsaPublicKey->modulus.data = narr; rsaPublicKey->modulus.len = nbytes; /* public exponent */ rsaPublicKey->publicExponent.type = siBuffer; rsaPublicKey->publicExponent.data = earr; rsaPublicKey->publicExponent.len = ebytes; } return rc; } /* TPM_RSAGeneratePrivateToken() generates an RSA key token from n, e, d */ static TPM_RESULT TPM_RSAGeneratePrivateToken(RSAPrivateKey *rsa_pri_key, /* freed by caller */ unsigned char *narr, /* public modulus */ uint32_t nbytes, unsigned char *earr, /* public exponent */ uint32_t ebytes, unsigned char *darr, /* private exponent */ uint32_t dbytes) { TPM_RESULT rc = 0; SECStatus rv = SECSuccess; printf(" TPM_RSAGeneratePrivateToken:\n"); if (rc == 0) { rsa_pri_key->arena = NULL; /* public exponent */ rsa_pri_key->publicExponent.type = siBuffer; rsa_pri_key->publicExponent.data = earr; rsa_pri_key->publicExponent.len = ebytes; /* public modulus */ rsa_pri_key->modulus.type = siBuffer; rsa_pri_key->modulus.data = narr; rsa_pri_key->modulus.len = nbytes; /* private exponent */ rsa_pri_key->privateExponent.type = siBuffer; rsa_pri_key->privateExponent.data = darr; rsa_pri_key->privateExponent.len = dbytes; /* given these key parameters (n,e,d), fill in the rest of the parameters */ rv = RSA_PopulatePrivateKey(rsa_pri_key); /* freed by caller */ if (rv != SECSuccess) { printf("TPM_RSAGeneratePrivateToken: Error, RSA_PopulatePrivateKey rv %d\n", rv); rc = TPM_BAD_PARAMETER; } } return rc; } /* TPM_RSAPrivateDecrypt() decrypts 'encrypt_data' using the private key 'n, e, d'. The OAEP padding is removed and 'decrypt_data_length' bytes are moved to 'decrypt_data'. 'decrypt_data_length' is at most 'decrypt_data_size'. */ TPM_RESULT TPM_RSAPrivateDecrypt(unsigned char *decrypt_data, /* decrypted data */ uint32_t *decrypt_data_length, /* length of data put into decrypt_data */ size_t decrypt_data_size, /* size of decrypt_data buffer */ TPM_ENC_SCHEME encScheme, /* encryption scheme */ unsigned char* encrypt_data, /* encrypted data */ uint32_t encrypt_data_size, unsigned char *narr, /* public modulus */ uint32_t nbytes, unsigned char *earr, /* public exponent */ uint32_t ebytes, unsigned char *darr, /* private exponent */ uint32_t dbytes) { TPM_RESULT rc = 0; SECStatus rv = SECSuccess; RSAPrivateKey rsa_pri_key; unsigned char *padded_data = NULL; /* freed @2 */ int padded_data_size = 0; printf(" TPM_RSAPrivateDecrypt: Input data size %u\n", encrypt_data_size); TPM_RSAPrivateKeyInit(&rsa_pri_key); /* freed @1 */ /* the encrypted data size must equal the public key size */ if (rc == 0) { if (encrypt_data_size != nbytes) { printf("TPM_RSAPrivateDecrypt: Error, Encrypted data size is %u not %u\n", encrypt_data_size, nbytes); rc = TPM_DECRYPT_ERROR; } } /* construct the freebl private key object from n,e,d */ if (rc == 0) { rc = TPM_RSAGeneratePrivateToken(&rsa_pri_key, /* freed @1 */ narr, /* public modulus */ nbytes, earr, /* public exponent */ ebytes, darr, /* private exponent */ dbytes); } /* allocate intermediate buffer for the decrypted but still padded data */ if (rc == 0) { /* the size of the decrypted data is guaranteed to be less than this */ padded_data_size = rsa_pri_key.modulus.len; rc = TPM_Malloc(&padded_data, padded_data_size); /* freed @2 */ } if (rc == 0) { /* decrypt with private key. Must decrypt first and then remove padding because the decrypt call cannot specify an encoding parameter */ rv = RSA_PrivateKeyOp(&rsa_pri_key, /* private key token */ padded_data, /* to - the decrypted but padded data */ encrypt_data); /* from - the encrypted data */ if (rv != SECSuccess) { printf("TPM_RSAPrivateDecrypt: Error in RSA_PrivateKeyOp(), rv %d\n", rv); rc = TPM_DECRYPT_ERROR; } } if (rc == 0) { printf(" TPM_RSAPrivateDecrypt: RSA_PrivateKeyOp() success\n"); printf(" TPM_RSAPrivateDecrypt: Padded data size %u\n", padded_data_size); TPM_PrintFour(" TPM_RSAPrivateDecrypt: Decrypt padded data", padded_data); /* check and remove the padding based on the TPM encryption scheme */ if (encScheme == TPM_ES_RSAESOAEP_SHA1_MGF1) { /* recovered seed and pHash are not returned */ unsigned char seed[TPM_DIGEST_SIZE]; unsigned char pHash[TPM_DIGEST_SIZE]; if (rc == 0) { /* the padded data skips the first 0x00 byte, since it expects the padded data to come from a truncated bignum */ rc = TPM_RSA_padding_check_PKCS1_OAEP(decrypt_data, /* to */ decrypt_data_length, /* to length */ decrypt_data_size, /* to buffer size */ padded_data + 1, /* from */ padded_data_size - 1, /* from length */ pHash, /* 20 bytes */ seed); /* 20 bytes */ } } else if (encScheme == TPM_ES_RSAESPKCSv15) { rc = TPM_PKCS1_PaddingType2Check(decrypt_data, /* to */ decrypt_data_length, /* to length */ decrypt_data_size, /* to buffer size*/ padded_data, /* from */ padded_data_size); /* from length */ } else { printf("TPM_RSAPrivateDecrypt: Error, unknown encryption scheme %04x\n", encScheme); rc = TPM_INAPPROPRIATE_ENC; } } if (rc == 0) { printf(" TPM_RSAPrivateDecrypt: RSA_padding_check_PKCS1 recovered %d bytes\n", *decrypt_data_length); TPM_PrintFourLimit(" TPM_RSAPrivateDecrypt: Decrypt data", decrypt_data, decrypt_data_size); } PORT_FreeArena(rsa_pri_key.arena, PR_TRUE); /* @1 */ free(padded_data); /* @2 */ return rc; } /* TPM_RSAPublicEncrypt() PKCS1 pads 'decrypt_data' to 'encrypt_data_size' and encrypts using the public key 'n, e'. */ TPM_RESULT TPM_RSAPublicEncrypt(unsigned char *encrypt_data, /* encrypted data */ size_t encrypt_data_size, /* size of encrypted data buffer */ TPM_ENC_SCHEME encScheme, /* padding type */ const unsigned char *decrypt_data, /* decrypted data */ size_t decrypt_data_size, unsigned char *narr, /* public modulus */ uint32_t nbytes, unsigned char *earr, /* public exponent */ uint32_t ebytes) { TPM_RESULT rc = 0; unsigned char *padded_data = NULL; /* freed @1 */ printf(" TPM_RSAPublicEncrypt: Input data size %lu\n", (unsigned long)decrypt_data_size); /* intermediate buffer for the padded decrypted data */ if (rc == 0) { rc = TPM_Malloc(&padded_data, encrypt_data_size); /* freed @1 */ } /* pad the decrypted data */ if (rc == 0) { /* based on the TPM encryption scheme */ if (encScheme == TPM_ES_RSAESOAEP_SHA1_MGF1) { unsigned char seed[TPM_DIGEST_SIZE]; if (rc == 0) { rc = TPM_Random(seed, TPM_DIGEST_SIZE); } if (rc == 0) { padded_data[0] = 0x00; rc = TPM_RSA_padding_add_PKCS1_OAEP(padded_data +1, /* to */ encrypt_data_size -1, /* to length */ decrypt_data, /* from */ decrypt_data_size, /* from length */ pHashConst, /* 20 bytes */ seed); /* 20 bytes */ } } else if (encScheme == TPM_ES_RSAESPKCSv15) { rc = TPM_PKCS1_PaddingType2Add(padded_data, /* to */ encrypt_data_size, /* to length */ decrypt_data, /* from */ decrypt_data_size); /* from length */ } else { printf("TPM_RSAPublicEncrypt: Error, unknown encryption scheme %04x\n", encScheme); rc = TPM_INAPPROPRIATE_ENC; } } /* raw public key operation on the already padded input data */ if (rc == 0) { rc = TPM_RSAPublicEncryptRaw(encrypt_data, /* output */ encrypt_data_size, /* input, size of enc buffer */ padded_data, /* input */ encrypt_data_size, /* input, size of dec buffer */ narr, /* public modulus */ nbytes, earr, /* public exponent */ ebytes); } free(padded_data); /* @1 */ return rc; } /* TPM_RSAPublicEncryptRaw() does a raw public key operation without any padding. */ TPM_RESULT TPM_RSAPublicEncryptRaw(unsigned char *encrypt_data, /* output */ uint32_t encrypt_data_size, /* input, size of enc buffer */ unsigned char *decrypt_data, /* input */ uint32_t decrypt_data_size, /* input, size of dec buffer */ unsigned char *narr, /* public modulus */ uint32_t nbytes, unsigned char *earr, /* public exponent */ uint32_t ebytes) { TPM_RESULT rc = 0; SECStatus rv = SECSuccess; RSAPublicKey rsa_pub_key; printf(" TPM_RSAPublicEncryptRaw:\n"); /* the input data size must equal the public key size (already padded) */ if (rc == 0) { if (decrypt_data_size != nbytes) { printf("TPM_RSAPublicEncryptRaw: Error, decrypt data size is %u not %u\n", decrypt_data_size, nbytes); rc = TPM_ENCRYPT_ERROR; } } /* the output data size must equal the public key size */ if (rc == 0) { if (encrypt_data_size != nbytes) { printf("TPM_RSAPublicEncryptRaw: Error, Output data size is %u not %u\n", encrypt_data_size, nbytes); rc = TPM_ENCRYPT_ERROR; } } /* construct the freebl public key object */ if (rc == 0) { rc = TPM_RSAGeneratePublicToken(&rsa_pub_key, /* freebl public key token */ narr, /* public modulus */ nbytes, earr, /* public exponent */ ebytes); } if (rc == 0) { TPM_PrintFour(" TPM_RSAPublicEncryptRaw: Public modulus", narr); TPM_PrintAll(" TPM_RSAPublicEncryptRaw: Public exponent", earr, ebytes); TPM_PrintFourLimit(" TPM_RSAPublicEncryptRaw: Decrypt data", decrypt_data, decrypt_data_size); /* raw public key operation, encrypt the decrypt_data */ rv = RSA_PublicKeyOp(&rsa_pub_key, /* freebl public key token */ encrypt_data, /* output - the encrypted data */ decrypt_data); /* input - the clear text data */ if (rv != SECSuccess) { printf("TPM_RSAPublicEncrypt: Error in RSA_PublicKeyOp, rv %d\n", rv); rc = TPM_ENCRYPT_ERROR; } } if (rc == 0) { TPM_PrintFour(" TPM_RSAPublicEncryptRaw: Encrypt data", encrypt_data); #if 0 /* NOTE: Uncomment as a debug aid for signature verification */ TPM_PrintAll(" TPM_RSAPublicEncryptRaw: Encrypt data", encrypt_data, encrypt_data_size); #endif } return rc; } /* TPM_RSASign() signs 'message' of size 'message_size' using the private key n,e,d and the signature scheme 'sigScheme' as specified in PKCS #1 v2.0. 'signature_length' bytes are moved to 'signature'. 'signature_length' is at most 'signature_size'. signature must point to bytes of memory equal to the public modulus size. */ TPM_RESULT TPM_RSASign(unsigned char *signature, /* output */ unsigned int *signature_length, /* output, size of signature */ unsigned int signature_size, /* input, size of signature buffer */ TPM_SIG_SCHEME sigScheme, /* input, type of signature */ const unsigned char *message, /* input */ size_t message_size, /* input */ unsigned char *narr, /* public modulus */ uint32_t nbytes, unsigned char *earr, /* public exponent */ uint32_t ebytes, unsigned char *darr, /* private exponent */ uint32_t dbytes) { TPM_RESULT rc = 0; RSAPrivateKey rsa_pri_key; printf(" TPM_RSASign:\n"); TPM_RSAPrivateKeyInit(&rsa_pri_key); /* freed @1 */ /* construct the free private key object from n,e,d */ if (rc == 0) { rc = TPM_RSAGeneratePrivateToken(&rsa_pri_key, /* freed @1 */ narr, /* public modulus */ nbytes, earr, /* public exponent */ ebytes, darr, /* private exponent */ dbytes); } /* sanity check the size of the output signature buffer */ if (rc == 0) { if (signature_size < nbytes) { printf("TPM_RSASign: Error (fatal), buffer %u too small for signature %u\n", signature_size, nbytes); rc = TPM_FAIL; /* internal error, should never occur */ } } /* determine the signature scheme for the key */ if (rc == 0) { switch(sigScheme) { case TPM_SS_NONE: printf("TPM_RSASign: Error, sigScheme TPM_SS_NONE\n"); rc = TPM_INVALID_KEYUSAGE; break; case TPM_SS_RSASSAPKCS1v15_SHA1: case TPM_SS_RSASSAPKCS1v15_INFO: rc = TPM_RSASignSHA1(signature, signature_length, message, message_size, &rsa_pri_key); break; case TPM_SS_RSASSAPKCS1v15_DER: rc = TPM_RSASignDER(signature, signature_length, message, message_size, &rsa_pri_key); break; default: printf("TPM_RSASign: Error, sigScheme %04hx unknown\n", sigScheme); rc = TPM_INVALID_KEYUSAGE; break; } } PORT_FreeArena(rsa_pri_key.arena, PR_TRUE); /* @1 */ return rc; } /* TPM_RSASignSHA1() performs the following: prepend a DER encoded algorithm ID (SHA1 and RSA) prepend a type 1 pad encrypt with the private key */ static TPM_RESULT TPM_RSASignSHA1(unsigned char *signature, /* output */ unsigned int *signature_length, /* output, size of signature */ const unsigned char *message, /* input */ size_t message_size, /* input */ RSAPrivateKey *rsa_pri_key) /* signing private key */ { TPM_RESULT rc = 0; unsigned char *message_der; /* DER padded message, freed @1 */ printf(" TPM_RSASignSHA1: key size %d\n", rsa_pri_key->modulus.len); message_der = NULL; /* freed @1 */ /* sanity check, SHA1 messages must be 20 bytes */ if (rc == 0) { if (message_size != TPM_DIGEST_SIZE) { printf("TPM_RSASignSHA1: Error, message size %lu not TPM_DIGEST_SIZE\n", (unsigned long)message_size ); rc = TPM_DECRYPT_ERROR; } } /* allocate memory for the DER padded message */ if (rc == 0) { rc = TPM_Malloc(&message_der, sizeof(sha1Oid) + message_size); /* freed @1 */ } if (rc == 0) { /* copy the OID */ memcpy(message_der, sha1Oid, sizeof(sha1Oid)); /* copy the message */ memcpy(message_der + sizeof(sha1Oid), message, message_size); /* sign the DER padded message */ rc = TPM_RSASignDER(signature, /* output */ signature_length, /* output, size of signature */ message_der, /* input */ sizeof(sha1Oid) + message_size, /* input */ rsa_pri_key); /* signing private key */ } free(message_der); /* @1 */ return rc; } /* TPM_RSASignDER() performs the following: prepend a PKCS1 type 1 pad encrypt with the private key The caller must ensure that the signature buffer is >= the key size. */ static TPM_RESULT TPM_RSASignDER(unsigned char *signature, /* output */ unsigned int *signature_length, /* output, size of signature */ const unsigned char *message, /* input */ size_t message_size, /* input */ RSAPrivateKey *rsa_pri_key) /* signing private key */ { TPM_RESULT rc = 0; SECStatus rv = SECSuccess; unsigned char *message_pad; /* PKCS1 type 1 padded message, freed @1 */ printf(" TPM_RSASignDER: key size %d\n", rsa_pri_key->modulus.len); message_pad = NULL; /* freed @1 */ /* the padded message size is the same as the key size */ /* allocate memory for the padded message */ if (rc == 0) { rc = TPM_Malloc(&message_pad, rsa_pri_key->modulus.len); /* freed @1 */ } /* PKCS1 type 1 pad the message */ if (rc == 0) { printf(" TPM_RSASignDER: Applying PKCS1 type 1 padding, size from %lu to %u\n", (unsigned long)message_size, rsa_pri_key->modulus.len); TPM_PrintFourLimit(" TPM_RSASignDER: Input message", message, message_size); /* This call checks that the message will fit with the padding */ rc = TPM_PKCS1_PaddingType1Add(message_pad, /* to */ rsa_pri_key->modulus.len, /* to length */ message, /* from */ message_size); /* from length */ } /* raw sign with private key */ if (rc == 0) { printf(" TPM_RSASignDER: Encrypting with private key, message size %d\n", rsa_pri_key->modulus.len); TPM_PrintFour(" TPM_RSASignDER: Padded message", message_pad); /* sign with private key */ rv = RSA_PrivateKeyOp(rsa_pri_key, /* freebl key token */ signature, /* to - the decrypted but padded data */ message_pad); /* from - the encrypted data */ if (rv != SECSuccess) { printf("TPM_RSASignDER: Error in RSA_PrivateKeyOp(), rv %d\n", rv); rc = TPM_DECRYPT_ERROR; } } if (rc == 0) { TPM_PrintFour(" TPM_RSASignDER: signature", signature); *signature_length = rsa_pri_key->modulus.len; } free(message_pad); /* @1 */ return rc; } /* TPM_RSAVerifySHA1() performs the following: decrypt the signature verify and remove type 1 pad verify and remove DER encoded algorithm ID verify the signature on the message */ TPM_RESULT TPM_RSAVerifySHA1(unsigned char *signature, /* input */ unsigned int signature_size, /* input, size of signature buffer */ const unsigned char *message, /* input */ uint32_t message_size, /* input */ unsigned char *narr, /* public modulus */ uint32_t nbytes, unsigned char *earr, /* public exponent */ uint32_t ebytes) { TPM_RESULT rc = 0; unsigned char *padded_data = NULL; /* decrypted signature, freed @1 */ uint32_t padLength; int irc; printf(" TPM_RSAVerifySHA1:\n"); /* allocate memory for the padded result of the public key operation */ if (rc == 0) { rc = TPM_Malloc(&padded_data, nbytes); /* freed @1 */ } /* do a raw encrypt of the signature */ if (rc == 0) { rc = TPM_RSAPublicEncryptRaw(padded_data, /* output */ nbytes, /* input, size of message buffer */ signature, /* input */ signature_size, /* input, size of signature buffer */ narr, /* public modulus */ nbytes, earr, /* public exponent */ ebytes); } /* check PKCS1 padding and OID */ if (rc == 0) { rc = TPM_PKCS1_PaddingType1Check(&padLength, /* length of the PKCS1 padd and OID */ padded_data, /* input data */ nbytes); /* input data length */ } /* check message length */ if (rc == 0) { if (message_size != (nbytes - padLength)) { printf("TPM_RSAVerifySHA1: Error, " "message size %u not equal to size %u after padding removed\n", message_size, nbytes - padLength); rc = TPM_BAD_SIGNATURE; } } /* check message */ if (rc == 0) { irc = memcmp(message, padded_data + padLength, message_size); if (irc != 0) { printf("TPM_RSAVerifySHA1: Error, message mismatch\n"); TPM_PrintFourLimit(" TPM_RSAVerifySHA1: message", message, message_size); TPM_PrintFourLimit(" TPM_RSAVerifySHA1: message from signature", padded_data + padLength, message_size); rc = TPM_BAD_SIGNATURE; } } /* public encrypt is general, here we're doing a signature check, so adjust the error message */ else { rc = TPM_BAD_SIGNATURE; } free(padded_data); /* @1 */ return rc; } /* TPM_RSAGetPrivateKey calculates q (2nd prime factor) and d (private key) from n (public key), e (public exponent), and p (1st prime factor) 'qarr', darr' must be freed by the caller. */ TPM_RESULT TPM_RSAGetPrivateKey(uint32_t *qbytes, unsigned char **qarr, uint32_t *dbytes, unsigned char **darr, uint32_t nbytes, unsigned char *narr, uint32_t ebytes, unsigned char *earr, uint32_t pbytes, unsigned char *parr) { TPM_RESULT rc = 0; SECStatus rv = SECSuccess; RSAPrivateKey rsa_pri_key; /* set to NULL so caller can free after failure */ printf(" TPM_RSAGetPrivateKey:\n"); TPM_RSAPrivateKeyInit(&rsa_pri_key); /* freed @1 */ *qarr = NULL; *darr = NULL; /* check input parameters */ if (rc == 0) { if ((narr == NULL) || (nbytes == 0)) { printf("TPM_RSAGetPrivateKey: Error, missing n\n"); rc = TPM_BAD_PARAMETER; } } /* check input parameters */ if (rc == 0) { if ((earr == NULL) || (ebytes == 0)) { printf("TPM_RSAGetPrivateKey: Error, missing e\n"); rc = TPM_BAD_PARAMETER; } } /* check input parameters */ if (rc == 0) { if ((parr == NULL) || (pbytes == 0)) { printf("TPM_RSAGetPrivateKey: Error, missing p\n"); rc = TPM_BAD_PARAMETER; } } /* populate the private key token with n, e, p */ if (rc == 0) { rsa_pri_key.publicExponent.type = siBuffer; rsa_pri_key.publicExponent.data = earr; rsa_pri_key.publicExponent.len = ebytes; rsa_pri_key.modulus.type = siBuffer; rsa_pri_key.modulus.data = narr; rsa_pri_key.modulus.len = nbytes; rsa_pri_key.prime1.type = siBuffer; rsa_pri_key.prime1.data = parr; rsa_pri_key.prime1.len = pbytes; /* fill in the rest of the freebl key token parameters. */ rv = RSA_PopulatePrivateKey(&rsa_pri_key); /* freed @1 */ if (rv != SECSuccess) { printf("TPM_RSAGetPrivateKey: Error in RSA_PopulatePrivateKey rv %d\n", rv); rc = TPM_BAD_PARAMETER; } } /* extract and pad q */ if (rc == 0) { rc = TPM_memcpyPad(qarr, /* freed by caller */ rsa_pri_key.prime2.data, rsa_pri_key.prime2.len, pbytes); /* pad to p prime */ *qbytes = pbytes; } /* extract and pad d */ if (rc == 0) { rc = TPM_memcpyPad(darr, /* freed by caller */ rsa_pri_key.privateExponent.data, rsa_pri_key.privateExponent.len, nbytes); /* pad to public modulus */ *dbytes = nbytes; } if (rc == 0) { TPM_PrintFour(" TPM_RSAGetPrivateKey: Calculated q", *qarr); TPM_PrintFour(" TPM_RSAGetPrivateKey: Calculated d", *darr); printf(" TPM_RSAGetPrivateKey: length of n,p,q,d = %u / %u / %u / %u\n", nbytes, pbytes, *qbytes, *dbytes); } PORT_FreeArena(rsa_pri_key.arena, PR_TRUE); /* @1 */ return rc; } /* PKCS1 Padding Functions */ /* TPM_PKCS1_PaddingType1Add() adds PKCS1 type 1 padding. The output buffer is preallocated. */ static TPM_RESULT TPM_PKCS1_PaddingType1Add(unsigned char *output, /* to */ uint32_t outputLength, const unsigned char *input, /* from */ uint32_t inputLength) { TPM_RESULT rc = 0; uint32_t psLength; uint32_t index; /* sanity check the length, this should never fail */ printf(" TPM_PKCS1_PaddingType1Add:\n"); if (rc == 0) { if ((inputLength + 11) > outputLength) { printf("TPM_PKCS1_PaddingType1Add: Error, input %u too big for output %u\n", inputLength, outputLength); rc = TPM_DECRYPT_ERROR; } } if (rc == 0) { index = 0; /* psLength is the number of 0xff bytes, subtract 3 for the leading 00,01 and trailing 00 */ psLength = outputLength - inputLength - 3; /* add the PKCS1 pad 01 || PS || 00 || T where PS is at least 8 0xff bytes */ /* PKCS1 pads to k-1 bytes, implies a leading 0 */ output[index] = 0x00; index++; output[index] = 0x01; index++; memset(output + index, 0xff, psLength); index += psLength; output[index] = 0x00; index++; /* add the input data */ memcpy(output + index, input, inputLength); index += inputLength; } return rc; } /* TPM_PKCS1_PaddingType1Check() checks PKCS1 type 1 padding and the SHA1withRSA OID and returns their length Type 1 is: 00 01 FF's 00 OID message */ static TPM_RESULT TPM_PKCS1_PaddingType1Check(uint32_t *padLength, unsigned char *input, uint32_t inputLength) { TPM_RESULT rc = 0; int irc; printf(" TPM_PKCS1_PaddingType1Check:\n"); /* sanity check the length */ if (rc == 0) { if ((sizeof(sha1Oid) + 11) > inputLength) { printf("TPM_PKCS1_PaddingType1Check: Error, " "sizeof(sha1Oid) %lu + 11 > inputLength %u\n", (unsigned long)sizeof(sha1Oid), inputLength); rc = TPM_ENCRYPT_ERROR; } } /* check byte 0 */ if (rc == 0) { *padLength = 0; if (input[*padLength] != 0x00) { printf("TPM_PKCS1_PaddingType1Check: Error, byte %u %02x not 0x00\n", *padLength, input[*padLength]); rc = TPM_ENCRYPT_ERROR; } (*padLength)++; } /* check byte 1 */ if (rc == 0) { if (input[*padLength] != 0x01) { printf("TPM_PKCS1_PaddingType1Check: Error, byte %u %02x not 0x01\n", *padLength, input[*padLength]); rc = TPM_ENCRYPT_ERROR; } (*padLength)++; } /* check for at least 8 0xff bytes */ for ( ; (rc == 0) && (*padLength < 10) ; (*padLength)++) { if (input[*padLength] != 0xff) { printf("TPM_PKCS1_PaddingType1Check: Error, byte %u %02x not 0xff\n", *padLength, input[*padLength]); rc = TPM_ENCRYPT_ERROR; } } /* check for more 0xff bytes */ for ( ; (rc == 0) && (*padLength < inputLength) ; (*padLength)++) { if (input[*padLength] != 0xff) { break; } } /* check for 0x00 byte */ if (rc == 0) { if (input[*padLength] != 0x00) { printf("TPM_PKCS1_PaddingType1Check: Error, byte %u %02x not 0x00\n", *padLength, input[*padLength]); rc = TPM_ENCRYPT_ERROR; } (*padLength)++; } /* check length for OID */ if (rc == 0) { if (*padLength + sizeof(sha1Oid) > inputLength) { printf("TPM_PKCS1_PaddingType1Check: Error, " "padLength %u + sizeof(sha1Oid) %lu > inputLength %u\n", *padLength, (unsigned long)sizeof(sha1Oid), inputLength); rc = TPM_ENCRYPT_ERROR; } } /* check OID */ if (rc == 0) { irc = memcmp(input + *padLength, sha1Oid, sizeof(sha1Oid)); if (irc != 0) { printf("TPM_PKCS1_PaddingType1Check: Error, OID mismatch\n"); TPM_PrintAll(" TPM_PKCS1_PaddingType1Check: OID", input + *padLength, sizeof(sha1Oid)); rc = TPM_ENCRYPT_ERROR; } *padLength += sizeof(sha1Oid); } return rc; } /* TPM_PKCS1_PaddingType2Add() adds the PKCS1 type 2 padding The output buffer is preallocated. See PKCS1 9.1.2.1 Encoding operation This method cheats a bit by adding a leading 00 as well, which is needed for the RSA operation. M message to be encoded, an octet string of length at most emLen-10 emLen intended length in octets of the encoded message Output: EM encoded message, an octet string of length emLen; or "message too long" */ static TPM_RESULT TPM_PKCS1_PaddingType2Add(unsigned char *encodedMessage, /* to */ uint32_t encodedMessageLength, /* to length */ const unsigned char *message, /* from */ uint32_t messageLength) /* from length */ { TPM_RESULT rc = 0; printf(" TPM_PKCS1_PaddingType2Add: Message length %u padded length %u\n", messageLength, encodedMessageLength); /* 1. If the length of the message M is greater than emLen - 10 octets, output "message too long" and stop. */ if (rc == 0) { if ((messageLength + 11) > encodedMessageLength) { printf("TPM_PKCS1_PaddingType2Add: Error, message length too big for padded length\n"); rc = TPM_ENCRYPT_ERROR; } } /* 2. Generate an octet string PS of length emLen-||M||-2 consisting of pseudorandomly generated nonzero octets. The length of PS will be at least 8 octets. */ if (rc == 0) { rc = TPM_RandomNonZero(encodedMessage + 2, encodedMessageLength - messageLength - 3); } /* 3. Concatenate PS, the message M, and other padding to form the encoded message EM as: */ /* EM = 02 || PS || 00 || M */ if (rc == 0) { encodedMessage[0] = 0x00; encodedMessage[1] = 0x02; encodedMessage[encodedMessageLength - messageLength - 1] = 0x00; memcpy(encodedMessage + encodedMessageLength - messageLength, message, messageLength); } return rc; } /* TPM_PKCS1_Type2PaddingCheck checks the PKCS1 type 2 padding and recovers the message The output buffer is preallocated. */ static TPM_RESULT TPM_PKCS1_PaddingType2Check(unsigned char *outputData, /* to */ uint32_t *outputDataLength, /* to length */ uint32_t outputDataSize, /* pre-allocated to length */ unsigned char *inputData, /* from - padded data */ uint32_t inputDataLength) /* from length */ { TPM_RESULT rc = 0; size_t i; printf(" TPM_PKCS1_PaddingType2Check:\n"); /* check the leading bytes for 0x00, 0x02 */ if (rc == 0) { if ((inputData[0] != 0x00) || (inputData[1] != 0x02)) { printf("TPM_PKCS1_PaddingType2Check: Error, bad leading bytes %02x %02x\n", inputData[0], inputData[1]); rc = TPM_DECRYPT_ERROR; } } /* skip the non-zero random PS */ for (i = 2 ; (rc == 0) && (i < inputDataLength) ; i++) { if (inputData[i] == 0x00) { break; } } /* check for the trailing 0x00 */ if (rc == 0) { if (i == inputDataLength) { printf("TPM_PKCS1_PaddingType2Check: Error, missing trailing 0x00\n"); rc = TPM_DECRYPT_ERROR; } } /* check that PS was at least 8 bytes */ if (rc == 0) { if (i < 10) { printf("TPM_PKCS1_PaddingType2Check: Error, bad PS length %lu\n", (unsigned long)i-2); rc = TPM_DECRYPT_ERROR; } } /* check that the output can accommodate the message */ if (rc == 0) { i++; /* index past the trailing 0x00 */ *outputDataLength = inputDataLength - i; if (*outputDataLength > outputDataSize) { printf("TPM_PKCS1_PaddingType2Check: Error, " "message %u greater than output data size %u\n", *outputDataLength, outputDataSize); rc = TPM_DECRYPT_ERROR; } } /* copy the message */ if (rc == 0) { memcpy(outputData, inputData + inputDataLength - *outputDataLength, *outputDataLength); } return rc; } /* GNU MP wrappers do error logging and transformation of errors to TPM type errors */ /* TPM_BN_num_bytes() wraps the gnump function in a TPM error handler Returns number of bytes in the input */ TPM_RESULT TPM_BN_num_bytes(unsigned int *numBytes, TPM_BIGNUM bn_in) { TPM_RESULT rc = 0; mpz_t *bn = (mpz_t *)bn_in; /* is the bignum zero */ int result = mpz_cmp_ui(*bn, 0); /* mpz_sizeinbase() always returns at least one. If the value is zero, there should really be 0 bytes */ if (result == 0) { *numBytes = 0; } /* take the base 2 number and round up to the next byte */ else { *numBytes = (mpz_sizeinbase (*bn, 2) +7) / 8; } return rc; } /* TPM_BN_is_one() wraps the gnump function in a TPM error handler Returns success if input is 1 */ TPM_RESULT TPM_BN_is_one(TPM_BIGNUM bn_in) { TPM_RESULT rc = 0; mpz_t *bn = (mpz_t *)bn_in; int irc; irc = mpz_cmp_ui(*bn, 1); if (irc != 0) { printf("TPM_BN_is_one: Error, result is not 1\n"); rc = TPM_DAA_WRONG_W; } return rc; } /* TPM_BN_mod() wraps the gnump function in a TPM error handler r = a mod m */ TPM_RESULT TPM_BN_mod(TPM_BIGNUM rem_in, const TPM_BIGNUM a_in, const TPM_BIGNUM m_in) { TPM_RESULT rc = 0; mpz_t *rBignum = (mpz_t *)rem_in; mpz_t *aBignum = (mpz_t *)a_in; mpz_t *mBignum = (mpz_t *)m_in; /* set r to a mod m */ mpz_mod(*rBignum, *aBignum, *mBignum); return rc; } /* TPM_BN_mask_bits() wraps the gnump function in a TPM error handler erase all but the lowest n bits of bn bn = bn mod 2^^n */ TPM_RESULT TPM_BN_mask_bits(TPM_BIGNUM bn_in, unsigned int n) { TPM_RESULT rc = 0; unsigned int numBytes; mpz_t *bn = (mpz_t *)bn_in; if (rc == 0) { rc = TPM_BN_num_bytes(&numBytes, bn_in); } if (rc == 0) { /* if the BIGNUM is already fewer bits, no need to mask */ if (numBytes > (n / 8)) { /* divide and return remainder, divisor is 2^^n */ mpz_fdiv_r_2exp(*bn, *bn, n); } } return rc; } /* TPM_BN_rshift() wraps the gnump function in a TPM error handler Shift a right by n bits (discard the lowest n bits) and label the result r */ TPM_RESULT TPM_BN_rshift(TPM_BIGNUM *rBignum_in, /* freed by caller */ TPM_BIGNUM aBignum_in, int n) { TPM_RESULT rc = 0; mpz_t **rBignum = (mpz_t **)rBignum_in; mpz_t *aBignum = (mpz_t *)aBignum_in; printf(" TPM_BN_rshift: n %d\n", n); if (rc == 0) { rc = TPM_BN_new(rBignum_in); } if (rc == 0) { /* divide and return quotient, rounded down (floor) */ mpz_fdiv_q_2exp(**rBignum, *aBignum, n); } return rc; } /* TPM_BN_lshift() wraps the gnump function in a TPM error handler Shift a left by n bits and label the result r */ TPM_RESULT TPM_BN_lshift(TPM_BIGNUM *rBignum_in, /* freed by caller */ TPM_BIGNUM aBignum_in, int n) { TPM_RESULT rc = 0; mpz_t **rBignum = (mpz_t **)rBignum_in; mpz_t *aBignum = (mpz_t *)aBignum_in; printf(" TPM_BN_lshift: n %d\n", n); if (rc == 0) { rc = TPM_BN_new(rBignum_in); } if (rc == 0) { /* multiply by 2^^n is is a left shift by n */ mpz_mul_2exp(**rBignum, *aBignum, n); } return rc; } /* TPM_BN_add() wraps the gnump function in a TPM error handler r = a + b */ TPM_RESULT TPM_BN_add(TPM_BIGNUM rBignum_in, TPM_BIGNUM aBignum_in, TPM_BIGNUM bBignum_in) { TPM_RESULT rc = 0; mpz_t *rBignum = (mpz_t *)rBignum_in; mpz_t *aBignum = (mpz_t *)aBignum_in; mpz_t *bBignum = (mpz_t *)bBignum_in; printf(" TPM_BN_add:\n"); /* result = a + b */ mpz_add(*rBignum, *aBignum, *bBignum); return rc; } /* TPM_BN_mul() wraps the gnump function in a TPM error handler r = a * b */ TPM_RESULT TPM_BN_mul(TPM_BIGNUM rBignum_in, TPM_BIGNUM aBignum_in, TPM_BIGNUM bBignum_in) { TPM_RESULT rc = 0; mpz_t *rBignum = (mpz_t *)rBignum_in; mpz_t *aBignum = (mpz_t *)aBignum_in; mpz_t *bBignum = (mpz_t *)bBignum_in; printf(" TPM_BN_mul:\n"); /* r = a * b */ mpz_mul(*rBignum, *aBignum, *bBignum); return rc; } /* TPM_BN_mod_exp() wraps the gnump function in a TPM error handler computes a to the p-th power modulo m (r=a^p % n) */ TPM_RESULT TPM_BN_mod_exp(TPM_BIGNUM rBignum_in, TPM_BIGNUM aBignum_in, TPM_BIGNUM pBignum_in, TPM_BIGNUM nBignum_in) { TPM_RESULT rc = 0; mpz_t *rBignum = (mpz_t *)rBignum_in; mpz_t *aBignum = (mpz_t *)aBignum_in; mpz_t *pBignum = (mpz_t *)pBignum_in; mpz_t *nBignum = (mpz_t *)nBignum_in; printf(" TPM_BN_mod_exp:\n"); mpz_powm(*rBignum, *aBignum, *pBignum, *nBignum); return rc; } /* TPM_BN_Mod_add() wraps the gnump function in a TPM error handler adds a to b modulo m */ TPM_RESULT TPM_BN_mod_add(TPM_BIGNUM rBignum_in, TPM_BIGNUM aBignum_in, TPM_BIGNUM bBignum_in, TPM_BIGNUM mBignum_in) { TPM_RESULT rc = 0; mpz_t *rBignum = (mpz_t *)rBignum_in; mpz_t *aBignum = (mpz_t *)aBignum_in; mpz_t *bBignum = (mpz_t *)bBignum_in; mpz_t *mBignum = (mpz_t *)mBignum_in; printf(" TPM_BN_mod_add:\n"); /* r = a + b */ mpz_add(*rBignum, *aBignum, *bBignum); /* set r to r mod m */ mpz_mod(*rBignum, *rBignum, *mBignum); return rc; } /* TPM_BN_mod_mul() wraps the gnump function in a TPM error handler r = (a * b) mod m */ TPM_RESULT TPM_BN_mod_mul(TPM_BIGNUM rBignum_in, TPM_BIGNUM aBignum_in, TPM_BIGNUM bBignum_in, TPM_BIGNUM mBignum_in) { TPM_RESULT rc = 0; mpz_t *rBignum = (mpz_t *)rBignum_in; mpz_t *aBignum = (mpz_t *)aBignum_in; mpz_t *bBignum = (mpz_t *)bBignum_in; mpz_t *mBignum = (mpz_t *)mBignum_in; printf(" TPM_BN_mod_mul:\n"); /* r = a * b */ mpz_mul(*rBignum, *aBignum, *bBignum); /* set r to r mod m */ mpz_mod(*rBignum, *rBignum, *mBignum); return rc; } /* TPM_BN_new() wraps the gnump function in a TPM error handler Allocates a new bignum */ TPM_RESULT TPM_BN_new(TPM_BIGNUM *bn_in) /* freed by caller */ { TPM_RESULT rc = 0; mpz_t *bn; if (rc== 0) { rc = TPM_Malloc(bn_in, sizeof(mpz_t)); /* freed by caller */ } if (rc== 0) { bn = (mpz_t *)*bn_in; mpz_init(*bn); } return rc; } /* TPM_BN_free() wraps the gnump function Frees the bignum */ void TPM_BN_free(TPM_BIGNUM bn_in) { mpz_t *bn = (mpz_t *)bn_in; if (bn != NULL) { mpz_clear(*bn); free(bn_in); } return; } /* TPM_bn2bin wraps the function in gnump a TPM error handler. Converts a bignum to char array 'bin' must already be checked for sufficient size. */ TPM_RESULT TPM_bn2bin(unsigned char *bin, TPM_BIGNUM bn_in) { TPM_RESULT rc = 0; mpz_t *bn = (mpz_t *)bn_in; mpz_export(bin, /* output */ NULL, /* countp */ 1, /* order, MSB first */ 1, /* size, char */ 0, /* endian, native (unused) */ 0, /* nails, don't discard */ *bn); /* input */ return rc; } /* TPM_memcpyPad allocates a buffer 'bin_out' and loads it from 'bin_in'. If padBytes is non-zero, 'bin_out' is padded with leading zeros if necessary, so that 'bytes' will equal 'padBytes'. This is used when TPM data structures expect a fixed length while the crypto library truncates leading zeros. '*bin_out' must be freed by the caller */ static TPM_RESULT TPM_memcpyPad(unsigned char **bin_out, unsigned char *bin_in, uint32_t bin_in_length, uint32_t padBytes) { TPM_RESULT rc = 0; printf(" TPM_memcpyPad: padBytes %u\n", padBytes); if (rc == 0) { /* padBytes 0 says that no padding is required */ if (padBytes == 0) { padBytes = bin_in_length; /* setting equal yields no padding */ } /* The required output should never be less than the supplied input. Sanity check and return a fatal error. */ if (padBytes < bin_in_length) { printf("TPM_memcpyPad: Error (fatal), " "padBytes %u less than %u\n", padBytes, bin_in_length); rc = TPM_FAIL; } if (padBytes != bin_in_length) { printf(" TPM_memcpyPad: padBytes %u bytes %u\n", padBytes, bin_in_length); } } /* allocate memory for the padded output */ if (rc == 0) { rc = TPM_Malloc(bin_out, padBytes); } if (rc == 0) { memset(*bin_out, 0, padBytes - bin_in_length); /* leading 0 padding */ memcpy((*bin_out) + padBytes - bin_in_length, /* start copy after padding */ bin_in, bin_in_length); } return rc; } /* TPM_bin2bn() wraps the gnump function in a TPM error handler Converts a char array to bignum bn must be freed by the caller. */ TPM_RESULT TPM_bin2bn(TPM_BIGNUM *bn_in, const unsigned char *bin, unsigned int bytes) { TPM_RESULT rc = 0; if (rc == 0) { rc = TPM_BN_new(bn_in); } if (rc == 0) { mpz_t *bn = (mpz_t *)*bn_in; mpz_import(*bn, /* output */ bytes, /* count */ 1, /* order, MSB first */ 1, /* size, char */ 0, /* endian, native (unused) */ 0, /* nail, don't discard */ bin); /* input */ } return rc; } /* Hash Functions */ /* TPM_SHA1InitCmd() initializes a platform dependent TPM_SHA1Context structure. The structure must be freed using TPM_SHA1FinalCmd() */ TPM_RESULT TPM_SHA1InitCmd(void **context) { TPM_RESULT rc = 0; printf(" TPM_SHA1InitCmd:\n"); if (rc == 0) { /* create a new freebl SHA1 context */ *context = SHA1_NewContext(); if (*context == NULL) { printf("TPM_SHA1InitCmd: Error allocating a new context\n"); rc = TPM_SIZE; } } /* reset the SHA-1 context, preparing it for a fresh round of hashing */ if (rc== 0) { SHA1_Begin(*context); } return rc; } /* TPM_SHA1UpdateCmd() adds 'data' of 'length' to the SHA-1 context */ TPM_RESULT TPM_SHA1UpdateCmd(void *context, const unsigned char *data, uint32_t length) { TPM_RESULT rc = 0; printf(" TPM_SHA1Update: length %u\n", length); if (context != NULL) { SHA1_Update(context, data, length); } else { printf("TPM_SHA1Update: Error, no existing SHA1 thread\n"); rc = TPM_SHA_THREAD; } return rc; } /* TPM_SHA1FinalCmd() extracts the SHA-1 digest 'md' from the context */ TPM_RESULT TPM_SHA1FinalCmd(unsigned char *md, void *context) { TPM_RESULT rc = 0; unsigned int digestLen; printf(" TPM_SHA1FinalCmd:\n"); if (rc== 0) { if (context == NULL) { printf("TPM_SHA1FinalCmd: Error, no existing SHA1 thread\n"); rc = TPM_SHA_THREAD; } } if (rc== 0) { SHA1_End(context, md, &digestLen, TPM_DIGEST_SIZE); /* Sanity check. For SHA1 it should always be 20 bytes. */ if (digestLen != TPM_DIGEST_SIZE) { printf("TPM_SHA1Final: Error (fatal), SHA1_End returned %u bytes\n", digestLen); rc = TPM_FAIL; } } return rc; } /* TPM_SHA1Delete() zeros and frees the SHA1 context */ void TPM_SHA1Delete(void **context) { if (*context != NULL) { printf(" TPM_SHA1Delete:\n"); /* zero because the SHA1 context might have data left from an HMAC */ SHA1_DestroyContext(*context, PR_TRUE); *context = NULL; } return; } #if defined (__x86_64__) || \ defined(__amd64__) || \ defined(__ia64__) || \ defined(__powerpc64__) || \ defined(__s390x__) || \ (defined(__sparc__) && defined(__arch64__)) || \ defined(__aarch64__) #define IS_64 typedef PRUint64 SHA_HW_t; #elif defined (__i386__) || \ defined (__powerpc__) || \ defined (__s390__) || \ defined(__sparc__) || \ defined(__arm__) typedef PRUint32 SHA_HW_t; #undef IS_64 #else #error "Cannot determine 32 or 64 bit platform" #endif /* The structure returned by the SHA1_Flatten() command and passed to SHA1_Resurrect() */ typedef struct SHA1SaveContextStrtd { union { PRUint32 w[16]; /* input buffer */ PRUint8 b[64]; } u; PRUint64 size; /* count of hashed bytes. */ SHA_HW_t H[22]; /* 5 state variables, 16 tmp values, 1 extra */ } SHA1SaveContextStr; /* TPM_Sha1Context_Load() is non-portable code to deserialize the FreeBL SHA1 context. If the contextPresent prepended by TPM_Sha1Context_Store() is FALSE, context remains NULL. If TRUE, context is allocated and loaded. */ TPM_RESULT TPM_Sha1Context_Load(void **context, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; TPM_BOOL contextPresent; /* is there a context to be loaded */ uint32_t flattenSize; /* from the freebl library */ SHA1Context *tmpContext = NULL; /* temp to get flatten size, freed @1 */ uint32_t tmp32; /* temp to recreate 64-bit size */ SHA1SaveContextStr restoreContext; size_t i; printf(" TPM_Sha1Context_Load: FreeBL\n"); /* TPM_Sha1Context_Store() stored a flag to indicate whether a context was stored */ if (rc== 0) { rc = TPM_LoadBool(&contextPresent, stream, stream_size); printf(" TPM_Sha1Context_Load: contextPresent %u\n", contextPresent); } /* check format tag */ /* In the future, if multiple formats are supported, this check will be replaced by a 'switch' on the tag */ if ((rc== 0) && contextPresent) { rc = TPM_CheckTag(TPM_TAG_SHA1CONTEXT_FREEBL_V1, stream, stream_size); } /* check that context is NULL to detect memory leak */ if ((rc== 0) && contextPresent) { if (*context != NULL) { printf("TPM_Sha1Context_Load: Error (fatal), *context %p should be NULL\n", *context ); rc = TPM_FAIL; } } /* create a temporary context just to get the freebl library size */ if ((rc== 0) && contextPresent) { rc = TPM_SHA1InitCmd((void **)&tmpContext); /* freed @1 */ } /* get the size of the FreeBL library SHA1 context */ if ((rc== 0) && contextPresent) { flattenSize = SHA1_FlattenSize(tmpContext); /* sanity check that the freebl library and TPM structure here are in sync */ if (flattenSize != sizeof(SHA1SaveContextStr)) { printf("TPM_Sha1Context_Load: Error, " "SHA1 context size %u from SHA1_FlattenSize not equal %lu from structure\n", flattenSize, (unsigned long)sizeof(SHA1SaveContextStr)); rc = TPM_BAD_PARAM_SIZE; } } /* deserialization code to fill in restoreContext */ /* b[0..63] <- u.b[0..63] (bytes only, no bytswapping) */ if ((rc== 0) && contextPresent) { rc = TPM_Loadn(restoreContext.u.b, 64, stream, stream_size); } /* count <- size (this is 64 bits on all platforms) */ if ((rc== 0) && contextPresent) { rc = TPM_Load32(&tmp32, stream, stream_size); restoreContext.size = (uint64_t)tmp32 << 32; /* big endian */ } if ((rc== 0) && contextPresent) { rc = TPM_Load32(&tmp32, stream, stream_size); restoreContext.size += (uint64_t)tmp32 & 0xffffffff; /* big endian */ } for (i = 0 ; (rc == 0) && contextPresent && (i < 5) ; i++) { rc = TPM_Load32(&tmp32, stream, stream_size); restoreContext.H[i] = tmp32; /* H can be 32 or 64 bits */ } /* load the context */ if ((rc== 0) && contextPresent) { /* the size test above ensures that the cast here is safe */ *context = SHA1_Resurrect((unsigned char *)&restoreContext, NULL); if (*context == NULL) { printf("TPM_Sha1Context_Load: Error, could not SHA1_Resurrect\n"); rc = TPM_SIZE; } } TPM_SHA1Delete((void *)&tmpContext); /* @1 */ return rc; } /* TPM_Sha1Context_Store() is non-portable code to serialize the FreeBL SHA1 context. context is not altered. It prepends a contextPresent flag to the stream, FALSE if context is NULL, TRUE if not. */ TPM_RESULT TPM_Sha1Context_Store(TPM_STORE_BUFFER *sbuffer, void *context) { TPM_RESULT rc = 0; SECStatus rv = SECSuccess; size_t i; unsigned int flattenSize; SHA1SaveContextStr saveContext; TPM_BOOL contextPresent; /* is there a context to be stored */ printf(" TPM_Sha1Context_Store: FreeBL\n"); /* store contextPresent */ if (rc == 0) { if (context != NULL) { printf(" TPM_Sha1Context_Store: Storing context\n"); contextPresent = TRUE; } else { printf(" TPM_Sha1Context_Store: No context to store\n"); contextPresent = FALSE; } printf(" TPM_Sha1Context_Store: contextPresent %u \n", contextPresent); rc = TPM_Sbuffer_Append(sbuffer, &contextPresent, sizeof(TPM_BOOL)); } /* overall format tag */ if ((rc== 0) && contextPresent) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_SHA1CONTEXT_FREEBL_V1); } if ((rc== 0) && contextPresent) { /* get the size of the FreeBL SHA1 context */ flattenSize = SHA1_FlattenSize(context); /* it will not be NULL here */ /* sanity check that the freebl library and TPM structure here are in sync */ if (flattenSize != sizeof(SHA1SaveContextStr)) { printf("TPM_Sha1Context_Store: Error (fatal), " "SHA1 context size %u from SHA1_FlattenSize not equal %lu from structure\n", flattenSize, (unsigned long)sizeof(SHA1SaveContextStr)); rc = TPM_FAIL; } } /* store into the structure from the library */ if ((rc== 0) && contextPresent) { /* the size test above ensures that the cast here is safe */ rv = SHA1_Flatten(context, (unsigned char *)&saveContext); if (rv != SECSuccess) { printf("TPM_Sha1Context_Store: Error (fatal), SHA1_Flatten rv %d\n", rv); rc = TPM_FAIL; } } /* append the FreeBL SHA1 context to the stream */ /* b[0..63] <- u.b[0..63] (bytes only, no byte swapping) */ if ((rc== 0) && contextPresent) { rc = TPM_Sbuffer_Append(sbuffer, saveContext.u.b, 64); } /* count <- size (this is 64 bits on all platforms) */ if ((rc== 0) && contextPresent) { rc = TPM_Sbuffer_Append32(sbuffer, saveContext.size >> 32); /* big endian */ } if ((rc== 0) && contextPresent) { rc = TPM_Sbuffer_Append32(sbuffer, saveContext.size & 0xffffffff); } /* SHA_HW_t - NSS uses 64 bits on 64 bit platforms for performance reasons only. The lower 32 bits are critical, so you can always serialize/deserialize just the lower 32 bits. */ /* The remainder of the H array is scratch memory and does not need to be preserved or transmitted. */ for (i = 0 ; (rc == 0) && contextPresent && (i < 5) ; i++) { rc = TPM_Sbuffer_Append32(sbuffer, saveContext.H[i] & 0xffffffff); } return rc; } /* TPM_SYMMETRIC_KEY_DATA */ #ifdef TPM_AES /* TPM_SymmetricKeyData_New() allocates memory for and initializes a TPM_SYMMETRIC_KEY_DATA token. */ TPM_RESULT TPM_SymmetricKeyData_New(TPM_SYMMETRIC_KEY_TOKEN *tpm_symmetric_key_data) { TPM_RESULT rc = 0; printf(" TPM_SymmetricKeyData_New:\n"); if (rc == 0) { rc = TPM_Malloc(tpm_symmetric_key_data, sizeof(TPM_SYMMETRIC_KEY_DATA)); } if (rc == 0) { TPM_SymmetricKeyData_Init(*tpm_symmetric_key_data); } return rc; } /* TPM_SymmetricKeyData_Free() initializes the key token to wipe secrets. It then frees the TPM_SYMMETRIC_KEY_DATA token and sets it to NULL. */ void TPM_SymmetricKeyData_Free(TPM_SYMMETRIC_KEY_TOKEN *tpm_symmetric_key_data) { printf(" TPM_SymmetricKeyData_Free:\n"); if (*tpm_symmetric_key_data != NULL) { TPM_SymmetricKeyData_Init(*tpm_symmetric_key_data); free(*tpm_symmetric_key_data); *tpm_symmetric_key_data = NULL; } return; } /* TPM_SymmetricKeyData_Init() is AES non-portable code to initialize the TPM_SYMMETRIC_KEY_DATA It depends on the TPM_SYMMETRIC_KEY_DATA declaration. */ void TPM_SymmetricKeyData_Init(TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token) { TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; printf(" TPM_SymmetricKeyData_Init:\n"); tpm_symmetric_key_data->tag = TPM_TAG_KEY; tpm_symmetric_key_data->valid = FALSE; tpm_symmetric_key_data->fill = 0; /* zero to wipe secrets */ memset(tpm_symmetric_key_data->userKey, 0, sizeof(tpm_symmetric_key_data->userKey)); return; } /* TPM_SymmetricKeyData_Load() is AES non-portable code to deserialize the TPM_SYMMETRIC_KEY_DATA It depends on the above TPM_SYMMETRIC_KEY_DATA declaration. */ TPM_RESULT TPM_SymmetricKeyData_Load(TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; printf(" TPM_SymmetricKeyData_Load:\n"); /* check tag */ if (rc == 0) { rc = TPM_CheckTag(TPM_TAG_KEY, stream, stream_size); } /* load valid */ if (rc == 0) { rc = TPM_LoadBool(&(tpm_symmetric_key_data->valid), stream, stream_size); } /* load fill */ if (rc == 0) { rc = TPM_Load8(&(tpm_symmetric_key_data->fill), stream, stream_size); } /* The AES key is a simple array. */ if (rc == 0) { rc = TPM_Loadn(tpm_symmetric_key_data->userKey, sizeof(tpm_symmetric_key_data->userKey), stream, stream_size); } return rc; } /* TPM_SymmetricKeyData_Store() is AES non-portable code to serialize the TPM_SYMMETRIC_KEY_DATA It depends on the above TPM_SYMMETRIC_KEY_DATA declaration. */ TPM_RESULT TPM_SymmetricKeyData_Store(TPM_STORE_BUFFER *sbuffer, const TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token) { TPM_RESULT rc = 0; TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; printf(" TPM_SymmetricKeyData_Store:\n"); /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, tpm_symmetric_key_data->tag); } /* store valid */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_symmetric_key_data->valid), sizeof(TPM_BOOL)); } /* store fill */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_symmetric_key_data->fill), sizeof(TPM_BOOL)); } /* store AES key */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, tpm_symmetric_key_data->userKey, sizeof(tpm_symmetric_key_data->userKey)); } return rc; } /* TPM_SymmetricKeyData_GenerateKey() is AES non-portable code to generate a random symmetric key tpm_symmetric_key_data should be initialized before and after use */ TPM_RESULT TPM_SymmetricKeyData_GenerateKey(TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token) { TPM_RESULT rc = 0; TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; printf(" TPM_SymmetricKeyData_GenerateKey:\n"); /* generate a random key */ if (rc == 0) { rc = TPM_Random(tpm_symmetric_key_data->userKey, sizeof(tpm_symmetric_key_data->userKey)); } if (rc == 0) { tpm_symmetric_key_data->valid = TRUE; } return rc; } /* TPM_SymmetricKeyData_Encrypt() is AES non-portable code to CBC encrypt 'decrypt_data' to 'encrypt_data' The stream is padded as per PKCS#7 / RFC2630 'encrypt_data' must be free by the caller */ TPM_RESULT TPM_SymmetricKeyData_Encrypt(unsigned char **encrypt_data, /* output, caller frees */ uint32_t *encrypt_length, /* output */ const unsigned char *decrypt_data, /* input */ uint32_t decrypt_length, /* input */ const TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token) /* input */ { TPM_RESULT rc = 0; SECStatus rv; AESContext *cx; uint32_t pad_length; uint32_t output_length; /* dummy */ unsigned char *decrypt_data_pad; unsigned char ivec[TPM_AES_BLOCK_SIZE]; /* initial chaining vector */ TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; printf(" TPM_SymmetricKeyData_Encrypt: Length %u\n", decrypt_length); decrypt_data_pad = NULL; /* freed @1 */ cx = NULL; /* freed @2 */ /* sanity check that the AES key has previously been generated */ if (rc == 0) { if (!tpm_symmetric_key_data->valid) { printf("TPM_SymmetricKeyData_Encrypt: Error (fatal), AES key not valid\n"); rc = TPM_FAIL; } } if (rc == 0) { /* calculate the PKCS#7 / RFC2630 pad length and padded data length */ pad_length = TPM_AES_BLOCK_SIZE - (decrypt_length % TPM_AES_BLOCK_SIZE); *encrypt_length = decrypt_length + pad_length; printf(" TPM_SymmetricKeyData_Encrypt: Padded length %u pad length %u\n", *encrypt_length, pad_length); /* allocate memory for the encrypted response */ rc = TPM_Malloc(encrypt_data, *encrypt_length); } /* allocate memory for the padded decrypted data */ if (rc == 0) { rc = TPM_Malloc(&decrypt_data_pad, *encrypt_length); } if (rc == 0) { /* set the IV */ memset(ivec, 0, sizeof(ivec)); /* create a new AES context */ cx = AES_CreateContext(tpm_symmetric_key_data->userKey, ivec, /* CBC initialization vector */ NSS_AES_CBC, /* CBC mode */ TRUE, /* encrypt */ TPM_AES_BLOCK_SIZE, /* key length */ TPM_AES_BLOCK_SIZE); /* AES block length */ if (cx == NULL) { printf("TPM_SymmetricKeyData_Encrypt: Error creating AES context\n"); rc = TPM_SIZE; } } /* pad the decrypted clear text data */ if (rc == 0) { /* unpadded original data */ memcpy(decrypt_data_pad, decrypt_data, decrypt_length); /* last gets pad = pad length */ memset(decrypt_data_pad + decrypt_length, pad_length, pad_length); /* encrypt the padded input to the output */ TPM_PrintFour(" TPM_SymmetricKeyData_Encrypt: Input", decrypt_data_pad); /* perform the AES encryption */ rv = AES_Encrypt(cx, *encrypt_data, &output_length, *encrypt_length, /* output */ decrypt_data_pad, *encrypt_length); /* input */ if (rv != SECSuccess) { printf("TPM_SymmetricKeyData_Encrypt: Error, rv %d\n", rv); rc = TPM_ENCRYPT_ERROR; } } if (rc == 0) { TPM_PrintFour(" TPM_SymmetricKeyData_Encrypt: Output", *encrypt_data); } free(decrypt_data_pad); /* @1 */ if (cx != NULL) { /* due to a FreeBL bug, must zero the context before destroying it */ unsigned char dummy_key[TPM_AES_BLOCK_SIZE]; unsigned char dummy_ivec[TPM_AES_BLOCK_SIZE]; memset(dummy_key, 0x00, TPM_AES_BLOCK_SIZE); memset(dummy_ivec, 0x00, TPM_AES_BLOCK_SIZE); rv = AES_InitContext(cx, /* AES context */ dummy_key, /* AES key */ TPM_AES_BLOCK_SIZE, /* key length */ dummy_ivec, /* ivec */ NSS_AES_CBC, /* CBC mode */ TRUE, /* encrypt */ TPM_AES_BLOCK_SIZE); /* AES block length */ AES_DestroyContext(cx, PR_TRUE); /* @2 */ } return rc; } /* TPM_SymmetricKeyData_Decrypt() is AES non-portable code to CBC decrypt 'encrypt_data' to 'decrypt_data' The stream must be padded as per PKCS#7 / RFC2630 decrypt_data must be free by the caller */ TPM_RESULT TPM_SymmetricKeyData_Decrypt(unsigned char **decrypt_data, /* output, caller frees */ uint32_t *decrypt_length, /* output */ const unsigned char *encrypt_data, /* input */ uint32_t encrypt_length, /* input */ const TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_token) /* input */ { TPM_RESULT rc = 0; SECStatus rv; AESContext *cx; uint32_t pad_length; uint32_t output_length; /* dummy */ uint32_t i; unsigned char *pad_data; unsigned char ivec[TPM_AES_BLOCK_SIZE]; /* initial chaining vector */ TPM_SYMMETRIC_KEY_DATA *tpm_symmetric_key_data = (TPM_SYMMETRIC_KEY_DATA *)tpm_symmetric_key_token; printf(" TPM_SymmetricKeyData_Decrypt: Length %u\n", encrypt_length); cx = NULL; /* freed @1 */ /* sanity check encrypted length */ if (rc == 0) { if (encrypt_length < TPM_AES_BLOCK_SIZE) { printf("TPM_SymmetricKeyData_Decrypt: Error, bad length\n"); rc = TPM_DECRYPT_ERROR; } } /* sanity check that the AES key has previously been generated */ if (rc == 0) { if (!tpm_symmetric_key_data->valid) { printf("TPM_SymmetricKeyData_Decrypt: Error (fatal), AES key not valid\n"); rc = TPM_FAIL; } } /* allocate memory for the PKCS#7 / RFC2630 padded decrypted data */ if (rc == 0) { rc = TPM_Malloc(decrypt_data, encrypt_length); } if (rc == 0) { /* set the IV */ memset(ivec, 0, sizeof(ivec)); /* create a new AES context */ cx = AES_CreateContext(tpm_symmetric_key_data->userKey, ivec, /* CBC initialization vector */ NSS_AES_CBC, /* CBC mode */ FALSE, /* decrypt */ TPM_AES_BLOCK_SIZE, /* key length */ TPM_AES_BLOCK_SIZE); /* AES block length */ if (cx == NULL) { printf("TPM_SymmetricKeyData_Decrypt: Error creating AES context\n"); rc = TPM_SIZE; } } /* decrypt the input to the PKCS#7 / RFC2630 padded output */ if (rc == 0) { TPM_PrintFour(" TPM_SymmetricKeyData_Decrypt: Input", encrypt_data); /* perform the AES decryption */ rv = AES_Decrypt(cx, *decrypt_data, &output_length, encrypt_length, /* output */ encrypt_data, encrypt_length); /* input */ if (rv != SECSuccess) { printf("TPM_SymmetricKeyData_Decrypt: Error, rv %d\n", rv); rc = TPM_DECRYPT_ERROR; } } if (rc == 0) { TPM_PrintFour(" TPM_SymmetricKeyData_Decrypt: Output", *decrypt_data); } /* get the pad length */ if (rc == 0) { /* get the pad length from the last byte */ pad_length = (uint32_t)*(*decrypt_data + encrypt_length - 1); /* sanity check the pad length */ printf(" TPM_SymmetricKeyData_Decrypt: Pad length %u\n", pad_length); if ((pad_length == 0) || (pad_length > TPM_AES_BLOCK_SIZE)) { printf("TPM_SymmetricKeyData_Decrypt: Error, illegal pad length\n"); rc = TPM_DECRYPT_ERROR; } } if (rc == 0) { /* get the unpadded length */ *decrypt_length = encrypt_length - pad_length; /* pad starting point */ pad_data = *decrypt_data + *decrypt_length; /* sanity check the pad */ for (i = 0 ; i < pad_length ; i++, pad_data++) { if (*pad_data != pad_length) { printf("TPM_SymmetricKeyData_Decrypt: Error, bad pad %02x at index %u\n", *pad_data, i); rc = TPM_DECRYPT_ERROR; } } } if (cx != NULL) { /* due to a FreeBL bug, must zero the context before destroying it */ unsigned char dummy_key[TPM_AES_BLOCK_SIZE]; unsigned char dummy_ivec[TPM_AES_BLOCK_SIZE]; memset(dummy_key, 0x00, TPM_AES_BLOCK_SIZE); memset(dummy_ivec, 0x00, TPM_AES_BLOCK_SIZE); rv = AES_InitContext(cx, /* AES context */ dummy_key, /* AES key */ TPM_AES_BLOCK_SIZE, /* key length */ dummy_ivec, /* ivec */ NSS_AES_CBC, /* CBC mode */ TRUE, /* encrypt */ TPM_AES_BLOCK_SIZE); /* AES block length */ AES_DestroyContext(cx, PR_TRUE); /* @1 */ } return rc; } /* TPM_SymmetricKeyData_CtrCrypt() does an encrypt or decrypt (they are the same XOR operation with a CTR mode pad) of 'data_in' to 'data_out'. TPM_SymmetricKeyData_CtrCrypt() is a TPM variant of the standard CTR encrypt function that increments only the low 4 bytes of the counter. NOTE: This function looks general, but is currently hard coded to AES128. 'symmetric key' is the raw key, not converted to a non-portable form 'ctr_in' is the initial CTR value before possible truncation */ TPM_RESULT TPM_SymmetricKeyData_CtrCrypt(unsigned char *data_out, /* output */ const unsigned char *data_in, /* input */ uint32_t data_size, /* input */ const unsigned char *symmetric_key, /* input */ uint32_t symmetric_key_size, /* input */ const unsigned char *ctr_in, /* input */ uint32_t ctr_in_size) /* input */ { TPM_RESULT rc = 0; SECStatus rv; AESContext *cx = NULL; unsigned char ctr[TPM_AES_BLOCK_SIZE]; unsigned char pad_buffer[TPM_AES_BLOCK_SIZE]; /* the XOR pad */ uint32_t output_length; /* dummy */ uint32_t cint; /* counter as a 32-bit integer */ printf(" TPM_SymmetricKeyData_CtrCrypt: data_size %u\n", data_size); symmetric_key_size = symmetric_key_size; /* check the input CTR size, it can be truncated, but cannot be smaller than the AES key */ if (rc == 0) { if (ctr_in_size < sizeof(ctr)) { printf(" TPM_SymmetricKeyData_CtrCrypt: Error (fatal)" ", CTR size %u too small for AES key\n", ctr_in_size); rc = TPM_FAIL; /* should never occur */ } } if (rc == 0) { /* make a truncated copy of CTR, since this function alters the value */ memcpy(ctr, ctr_in, sizeof(ctr)); TPM_PrintFour(" TPM_SymmetricKeyData_CtrCrypt: CTR", ctr); } /* create a new AES context */ if (rc == 0) { cx = AES_CreateContext(symmetric_key, /* AES key */ NULL, /* ivec not used in NSS_AES */ NSS_AES, /* mode */ TRUE, /* encrypt */ TPM_AES_BLOCK_SIZE, /* key length */ TPM_AES_BLOCK_SIZE); /* AES block length */ if (cx == NULL) { printf("TPM_SymmetricKeyData_CtrCrypt: Error creating AES context\n"); rc = TPM_SIZE; } } while (data_size != 0) { printf(" TPM_SymmetricKeyData_CtrCrypt : data_size remaining %u\n", data_size); /* initialize the context each time through the loop */ if (rc == 0) { rv = AES_InitContext(cx, /* AES context */ symmetric_key, /* AES key */ TPM_AES_BLOCK_SIZE, /* key length */ NULL, /* ivec not used in NSS_AES */ NSS_AES, /* mode */ TRUE, /* encrypt */ TPM_AES_BLOCK_SIZE); /* AES block length */ if (rv != SECSuccess) { printf("TPM_SymmetricKeyData_CtrCrypt: Error, rv %d\n", rv); rc = TPM_ENCRYPT_ERROR; } } /* get an XOR pad array by encrypting the CTR with the AES key */ if (rc == 0) { rv = AES_Encrypt(cx, pad_buffer, &output_length, TPM_AES_BLOCK_SIZE, /* output */ ctr, TPM_AES_BLOCK_SIZE); /* input */ if (rv != SECSuccess) { printf("TPM_SymmetricKeyData_CtrCrypt: Error, rv %d\n", rv); rc = TPM_ENCRYPT_ERROR; } } if (rc == 0) { /* partial or full last data block */ if (data_size <= TPM_AES_BLOCK_SIZE) { TPM_XOR(data_out, data_in, pad_buffer, data_size); data_size = 0; } /* full block, not the last block */ else { TPM_XOR(data_out, data_in, pad_buffer, TPM_AES_BLOCK_SIZE); data_in += TPM_AES_BLOCK_SIZE; data_out += TPM_AES_BLOCK_SIZE; data_size -= TPM_AES_BLOCK_SIZE; } /* if not the last block, increment CTR, only the low 4 bytes */ if (data_size != 0) { /* CTR is a big endian array, so the low 4 bytes are used */ cint = LOAD32(ctr, TPM_AES_BLOCK_SIZE-4); /* byte array to uint32_t */ cint++; /* increment */ STORE32(ctr, TPM_AES_BLOCK_SIZE-4, cint); /* uint32_t to byte array */ } } } if (cx != NULL) { /* due to a FreeBL bug, must zero the context before destroying it */ unsigned char dummy_key[TPM_AES_BLOCK_SIZE]; memset(dummy_key, 0x00, TPM_AES_BLOCK_SIZE); rv = AES_InitContext(cx, /* AES context */ dummy_key, /* AES key */ TPM_AES_BLOCK_SIZE, /* key length */ NULL, /* ivec not used in NSS_AES */ NSS_AES, /* mode */ TRUE, /* encrypt */ TPM_AES_BLOCK_SIZE); /* AES block length */ AES_DestroyContext(cx, PR_TRUE); /* @2 */ } return rc; } /* TPM_SymmetricKeyData_OfbCrypt() does an encrypt or decrypt (they are the same XOR operation with a OFB mode pad) of 'data_in' to 'data_out' NOTE: This function looks general, but is currently hard coded to AES128. 'symmetric key' is the raw key, not converted to a non-portable form 'ivec_in' is the initial IV value before possible truncation */ TPM_RESULT TPM_SymmetricKeyData_OfbCrypt(unsigned char *data_out, /* output */ const unsigned char *data_in, /* input */ uint32_t data_size, /* input */ const unsigned char *symmetric_key, /* in */ uint32_t symmetric_key_size, /* in */ unsigned char *ivec_in, /* input */ uint32_t ivec_in_size) /* input */ { TPM_RESULT rc = 0; SECStatus rv; AESContext *cx = NULL; unsigned char ivec_loop[TPM_AES_BLOCK_SIZE]; /* ivec input to loop */ unsigned char pad_buffer[TPM_AES_BLOCK_SIZE]; /* the XOR pad */ uint32_t output_length; /* dummy */ printf(" TPM_SymmetricKeyData_OfbCrypt: data_size %u\n", data_size); symmetric_key_size = symmetric_key_size; /* check the input OFB size, it can be truncated, but cannot be smaller than the AES key */ if (rc == 0) { if (ivec_in_size < TPM_AES_BLOCK_SIZE) { printf(" TPM_SymmetricKeyData_OfbCrypt: Error (fatal)," "IV size %u too small for AES key\n", ivec_in_size); rc = TPM_FAIL; /* should never occur */ } } /* first time through, the ivec_loop will be the input ivec */ if (rc == 0) { memcpy(ivec_loop, ivec_in, sizeof(ivec_loop)); TPM_PrintFour(" TPM_SymmetricKeyData_OfbCrypt: IV", ivec_loop); } /* create a new AES context */ if (rc == 0) { cx = AES_CreateContext(symmetric_key, NULL, /* ivec not used in NSS_AES */ NSS_AES, /* mode */ TRUE, /* encrypt */ TPM_AES_BLOCK_SIZE, /* key length */ TPM_AES_BLOCK_SIZE); /* AES block length */ if (cx == NULL) { printf("TPM_SymmetricKeyData_OfbCrypt: Error creating AES context\n"); rc = TPM_SIZE; } } while (data_size != 0) { printf(" TPM_SymmetricKeyData_OfbCrypt: data_size remaining %u\n", data_size); /* initialize the context each time through the loop */ if (rc == 0) { rv = AES_InitContext(cx, /* AES context */ symmetric_key, /* AES key */ TPM_AES_BLOCK_SIZE, /* key length */ NULL, /* ivec not used in NSS_AES */ NSS_AES, /* mode */ TRUE, /* encrypt */ TPM_AES_BLOCK_SIZE); /* AES block length */ if (rv != SECSuccess) { printf("TPM_SymmetricKeyData_OfbCrypt: Error, rv %d\n", rv); rc = TPM_ENCRYPT_ERROR; } } /* get an XOR pad array by encrypting the IV with the AES key */ if (rc == 0) { TPM_PrintFour(" TPM_SymmetricKeyData_OfbCrypt: IV", ivec_loop); rv = AES_Encrypt(cx, pad_buffer, &output_length, TPM_AES_BLOCK_SIZE, /* output */ ivec_loop, TPM_AES_BLOCK_SIZE); /* input */ if (rv != SECSuccess) { printf("TPM_SymmetricKeyData_OfbCrypt: Error, rv %d\n", rv); rc = TPM_ENCRYPT_ERROR; } } if (rc == 0) { /* partial or full last data block */ if (data_size <= TPM_AES_BLOCK_SIZE) { TPM_XOR(data_out, data_in, pad_buffer, data_size); data_size = 0; } /* full block, not the last block */ else { TPM_XOR(data_out, data_in, pad_buffer, TPM_AES_BLOCK_SIZE); data_in += TPM_AES_BLOCK_SIZE; data_out += TPM_AES_BLOCK_SIZE; data_size -= TPM_AES_BLOCK_SIZE; } /* if not the last block, wrap the pad_buffer back to ivec_loop (output feed back) */ memcpy(ivec_loop, pad_buffer, TPM_AES_BLOCK_SIZE); } } if (cx != NULL) { /* due to a FreeBL bug, must zero the context before destroying it */ unsigned char dummy_key[TPM_AES_BLOCK_SIZE]; memset(dummy_key, 0x00, TPM_AES_BLOCK_SIZE); rv = AES_InitContext(cx, /* AES context */ dummy_key, /* AES key */ TPM_AES_BLOCK_SIZE, /* key length */ NULL, /* ivec not used in NSS_AES */ NSS_AES, /* mode */ TRUE, /* encrypt */ TPM_AES_BLOCK_SIZE); /* AES block length */ AES_DestroyContext(cx, PR_TRUE); /* @2 */ } return rc; } #endif /* TPM_AES */ libtpms-0.9.3/src/tpm12/tpm_cryptoh.c000066400000000000000000005704301421143571500174570ustar00rootroot00000000000000/********************************************************************************/ /* */ /* High Level Platform Independent Cryptography */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_cryptoh.c 4540 2011-04-07 18:51:34Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include #include #include #include #include "tpm_admin.h" #include "tpm_auth.h" #include "tpm_crypto.h" #include "tpm_debug.h" #include "tpm_digest.h" #include "tpm_error.h" #include "tpm_io.h" #include "tpm_memory.h" #include "tpm_migration.h" #include "tpm_nonce.h" #include "tpm_key.h" #include "tpm_pcr.h" #include "tpm_process.h" #include "tpm_store.h" #include "tpm_ver.h" #include "tpm_cryptoh.h" /* local prototypes */ static TPM_RESULT TPM_SHA1_valist(TPM_DIGEST md, uint32_t length0, unsigned char *buffer0, va_list ap); static TPM_RESULT TPM_HMAC_Generatevalist(TPM_HMAC hmac, const TPM_SECRET key, va_list ap); static TPM_RESULT TPM_SHA1CompleteCommon(TPM_DIGEST hashValue, void **sha1_context, TPM_SIZED_BUFFER *hashData); /* TPM_SIGN_INFO */ /* TPM_SignInfo_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_SignInfo_Init(TPM_SIGN_INFO *tpm_sign_info) { printf(" TPM_SignInfo_Init:\n"); memset(tpm_sign_info->fixed, 0, TPM_SIGN_INFO_FIXED_SIZE); TPM_Nonce_Init(tpm_sign_info->replay); TPM_SizedBuffer_Init(&(tpm_sign_info->data)); return; } /* TPM_SignInfo_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_SignInfo_Store(TPM_STORE_BUFFER *sbuffer, const TPM_SIGN_INFO *tpm_sign_info) { TPM_RESULT rc = 0; printf(" TPM_SignInfo_Store:\n"); /* store the tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_SIGNINFO); } /* store the fixed */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, tpm_sign_info->fixed, TPM_SIGN_INFO_FIXED_SIZE); } /* store the replay */ if (rc == 0) { rc = TPM_Nonce_Store(sbuffer, tpm_sign_info->replay); } /* store the dataLen and data */ if (rc == 0) { rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_sign_info->data)); } if (rc == 0) { const unsigned char *buffer; uint32_t length; TPM_Sbuffer_Get(sbuffer, &buffer, &length); TPM_PrintAll(" TPM_SignInfo_Store: Buffer", buffer, length); } return rc; } /* TPM_SignInfo_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the sign_info sets pointers to NULL calls TPM_SignInfo_Init to set members back to default values The sign_info itself is not freed */ void TPM_SignInfo_Delete(TPM_SIGN_INFO *tpm_sign_info) { printf(" TPM_SignInfo_Delete:\n"); if (tpm_sign_info != NULL) { TPM_SizedBuffer_Delete(&(tpm_sign_info->data)); TPM_SignInfo_Init(tpm_sign_info); } return; } /* TPM_CERTIFY_INFO */ /* TPM_CertifyInfo_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_CertifyInfo_Init(TPM_CERTIFY_INFO *tpm_certify_info) { printf(" TPM_CertifyInfo_Init:\n"); TPM_StructVer_Init(&(tpm_certify_info->version)); tpm_certify_info->keyUsage = TPM_KEY_UNINITIALIZED; tpm_certify_info->keyFlags = 0; tpm_certify_info->authDataUsage = TPM_AUTH_ALWAYS; TPM_KeyParms_Init(&(tpm_certify_info->algorithmParms)); TPM_Digest_Init(tpm_certify_info->pubkeyDigest); TPM_Nonce_Init(tpm_certify_info->data); tpm_certify_info->parentPCRStatus = TRUE; TPM_SizedBuffer_Init(&(tpm_certify_info->pcrInfo)); tpm_certify_info->tpm_pcr_info = NULL; return; } #if 0 /* TPM_CertifyInfo_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_CertifyInfo_Init() After use, call TPM_CertifyInfo_Delete() to free memory NOTE: Never called. */ TPM_RESULT TPM_CertifyInfo_Load(TPM_CERTIFY_INFO *tpm_certify_info, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_CertifyInfo_Load:\n"); /* load version */ if (rc == 0) { rc = TPM_StructVer_Load(&(tpm_certify_info->version), stream, stream_size); } /* check ver immediately to ease debugging */ if (rc == 0) { rc = TPM_StructVer_CheckVer(&(tpm_certify_info->version)); } /* load keyUsage */ if (rc == 0) { rc = TPM_Load16(&(tpm_certify_info->keyUsage), stream, stream_size); } /* load keyFlags */ if (rc == 0) { rc = TPM_KeyFlags_Load(&(tpm_certify_info->keyFlags), stream, stream_size); } /* load authDataUsage */ if (rc == 0) { rc = TPM_Load8(&(tpm_certify_info->authDataUsage), stream, stream_size); } /* load algorithmParms */ if (rc == 0) { rc = TPM_KeyParms_Load(&(tpm_certify_info->algorithmParms), stream, stream_size); } /* load pubkeyDigest */ if (rc == 0) { rc = TPM_Digest_Load(tpm_certify_info->pubkeyDigest, stream, stream_size); } /* load data */ if (rc == 0) { rc = TPM_Nonce_Load(tpm_certify_info->data, stream, stream_size); } /* load parentPCRStatus */ if (rc == 0) { rc = TPM_LoadBool(&(tpm_certify_info->parentPCRStatus), stream, stream_size); } /* load pcrInfo */ if (rc == 0) { rc = TPM_SizedBuffer_Load(&(tpm_certify_info->pcrInfo), stream, stream_size); } /* set TPM_PCR_INFO tpm_pcr_info cache from pcrInfo */ if (rc == 0) { rc = TPM_PCRInfo_CreateFromBuffer(&(tpm_certify_info->tpm_pcr_info), &(tpm_certify_info->pcrInfo)); } return rc; } #endif /* TPM_CertifyInfo_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_CertifyInfo_Store(TPM_STORE_BUFFER *sbuffer, TPM_CERTIFY_INFO *tpm_certify_info) { TPM_RESULT rc = 0; printf(" TPM_CertifyInfo_Store:\n"); /* store version */ if (rc == 0) { rc = TPM_StructVer_Store(sbuffer, &(tpm_certify_info->version)); } /* store keyUsage */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, tpm_certify_info->keyUsage); } /* store keyFlags */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_certify_info->keyFlags); } /* store authDataUsage */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_certify_info->authDataUsage), sizeof(TPM_AUTH_DATA_USAGE)); } /* store algorithmParms */ if (rc == 0) { rc = TPM_KeyParms_Store(sbuffer, &(tpm_certify_info->algorithmParms)); } /* store pubkeyDigest */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_certify_info->pubkeyDigest); } /* store data */ if (rc == 0) { rc = TPM_Nonce_Store(sbuffer, tpm_certify_info->data); } /* store parentPCRStatus */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_certify_info->parentPCRStatus), sizeof(TPM_BOOL)); } /* copy cache to pcrInfo */ if (rc == 0) { rc = TPM_SizedBuffer_SetStructure(&(tpm_certify_info->pcrInfo), tpm_certify_info->tpm_pcr_info, (TPM_STORE_FUNCTION_T)TPM_PCRInfo_Store); } /* copy pcrInfo to sbuffer */ if (rc == 0) { rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_certify_info->pcrInfo)); } return rc; } /* TPM_CertifyInfo_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_CertifyInfo_Init to set members back to default values The object itself is not freed */ void TPM_CertifyInfo_Delete(TPM_CERTIFY_INFO *tpm_certify_info) { printf(" TPM_CertifyInfo_Delete:\n"); if (tpm_certify_info != NULL) { TPM_KeyParms_Delete(&(tpm_certify_info->algorithmParms)); /* pcrInfo */ TPM_SizedBuffer_Delete(&(tpm_certify_info->pcrInfo)); /* pcr cache */ TPM_PCRInfo_Delete(tpm_certify_info->tpm_pcr_info); free(tpm_certify_info->tpm_pcr_info); TPM_CertifyInfo_Init(tpm_certify_info); } return; } /* TPM_CertifyInfo_Set() fills in tpm_certify_info with the information from the key pointed to be tpm_key */ TPM_RESULT TPM_CertifyInfo_Set(TPM_CERTIFY_INFO *tpm_certify_info, TPM_KEY *tpm_key) { TPM_RESULT rc = 0; printf(" TPM_CertifyInfo_Set:\n"); if (rc == 0) { tpm_certify_info->keyUsage = tpm_key->keyUsage; tpm_certify_info->keyFlags = tpm_key->keyFlags; tpm_certify_info->authDataUsage = tpm_key->authDataUsage; rc = TPM_KeyParms_Copy(&(tpm_certify_info->algorithmParms), &(tpm_key->algorithmParms)); } /* pubkeyDigest SHALL be a digest of the value TPM_KEY -> pubKey -> key in a TPM_KEY representation of the key to be certified */ if (rc == 0) { rc = TPM_SHA1(tpm_certify_info->pubkeyDigest, tpm_key->pubKey.size, tpm_key->pubKey.buffer, 0, NULL); } return rc; } /* TPM_CERTIFY_INFO2 */ /* TPM_CertifyInfo2_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_CertifyInfo2_Init(TPM_CERTIFY_INFO2 *tpm_certify_info2) { printf(" TPM_CertifyInfo2_Init:\n"); tpm_certify_info2->fill = 0x00; tpm_certify_info2->payloadType = TPM_PT_ASYM; tpm_certify_info2->keyUsage = TPM_KEY_UNINITIALIZED; tpm_certify_info2->keyFlags = 0; tpm_certify_info2->authDataUsage = TPM_AUTH_ALWAYS; TPM_KeyParms_Init(&(tpm_certify_info2->algorithmParms)); TPM_Digest_Init(tpm_certify_info2->pubkeyDigest); TPM_Nonce_Init(tpm_certify_info2->data); tpm_certify_info2->parentPCRStatus = TRUE; TPM_SizedBuffer_Init(&(tpm_certify_info2->pcrInfo)); TPM_SizedBuffer_Init(&(tpm_certify_info2->migrationAuthority)); tpm_certify_info2->tpm_pcr_info_short = NULL; return; } #if 0 /* TPM_CertifyInfo2_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_CertifyInfo2_Init() After use, call TPM_CertifyInfo2_Delete() to free memory */ TPM_RESULT TPM_CertifyInfo2_Load(TPM_CERTIFY_INFO2 *tpm_certify_info2, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_CertifyInfo2_Load:\n"); /* check tag */ if (rc == 0) { rc = TPM_CheckTag(TPM_TAG_CERTIFY_INFO2, stream, stream_size); } /* load fill */ if (rc == 0) { rc = TPM_Load8(&(tpm_certify_info2->fill), stream, stream_size); } /* check fill immediately to ease debugging */ if (rc == 0) { if (tpm_certify_info2->fill != 0x00) { printf("TPM_CertifyInfo2_Load: Error checking fill %02x\n", tpm_certify_info2->fill); rc = TPM_INVALID_STRUCTURE; } } /* load payloadType */ if (rc == 0) { rc = TPM_Load8(&(tpm_certify_info2->payloadType), stream, stream_size); } /* load keyUsage */ if (rc == 0) { rc = TPM_Load16(&(tpm_certify_info2->keyUsage), stream, stream_size); } /* load keyFlags */ if (rc == 0) { rc = TPM_KeyFlags_Load(&(tpm_certify_info2->keyFlags), stream, stream_size); } /* load authDataUsage */ if (rc == 0) { rc = TPM_Load8(&(tpm_certify_info2->authDataUsage), stream, stream_size); } /* load algorithmParms */ if (rc == 0) { rc = TPM_KeyParms_Load(&(tpm_certify_info2->algorithmParms), stream, stream_size); } /* load pubkeyDigest */ if (rc == 0) { rc = TPM_Digest_Load(tpm_certify_info2->pubkeyDigest, stream, stream_size); } /* load data */ if (rc == 0) { rc = TPM_Nonce_Load(tpm_certify_info2->data, stream, stream_size); } /* load parentPCRStatus */ if (rc == 0) { rc = TPM_LoadBool(&(tpm_certify_info2->parentPCRStatus), stream, stream_size); } /* load pcrInfo */ if (rc == 0) { rc = TPM_SizedBuffer_Load(&(tpm_certify_info2->pcrInfo), stream, stream_size); } /* set TPM_PCR_INFO2 tpm_pcr_info cache from pcrInfo */ if (rc == 0) { rc = TPM_PCRInfoShort_CreateFromBuffer(&(tpm_certify_info2->tpm_pcr_info_short), &(tpm_certify_info2->pcrInfo)); } /* load migrationAuthority */ if (rc == 0) { rc = TPM_SizedBuffer_Load(&(tpm_certify_info2->migrationAuthority), stream, stream_size); } /* check migrationAuthority immediately to ease debugging */ if (rc == 0) { if ((tpm_certify_info2->migrationAuthority.buffer != NULL) && (tpm_certify_info2->migrationAuthority.size != TPM_DIGEST_SIZE)) { printf("TPM_CertifyInfo2_Load: Error checking migrationAuthority %p, %u\n", tpm_certify_info2->migrationAuthority.buffer, tpm_certify_info2->migrationAuthority.size); rc = TPM_INVALID_STRUCTURE; } } return rc; } #endif /* TPM_CertifyInfo2_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_CertifyInfo2_Store(TPM_STORE_BUFFER *sbuffer, TPM_CERTIFY_INFO2 *tpm_certify_info2) { TPM_RESULT rc = 0; printf(" TPM_CertifyInfo2_Store:\n"); /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_CERTIFY_INFO2); } /* store fill */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_certify_info2->fill), sizeof(BYTE)); } /* store payloadType */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_certify_info2->payloadType), sizeof(TPM_PAYLOAD_TYPE)); } /* store keyUsage */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, tpm_certify_info2->keyUsage); } /* store keyFlags */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_certify_info2->keyFlags); } /* store authDataUsage */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_certify_info2->authDataUsage), sizeof(TPM_AUTH_DATA_USAGE)); } /* store algorithmParms */ if (rc == 0) { rc = TPM_KeyParms_Store(sbuffer, &(tpm_certify_info2->algorithmParms)); } /* store pubkeyDigest */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_certify_info2->pubkeyDigest); } /* store data */ if (rc == 0) { rc = TPM_Nonce_Store(sbuffer, tpm_certify_info2->data); } /* store parentPCRStatus */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_certify_info2->parentPCRStatus), sizeof(TPM_BOOL)); } /* copy cache to pcrInfo */ if (rc == 0) { rc = TPM_SizedBuffer_SetStructure(&(tpm_certify_info2->pcrInfo), tpm_certify_info2->tpm_pcr_info_short, (TPM_STORE_FUNCTION_T)TPM_PCRInfoShort_Store); } /* copy pcrInfo to sbuffer */ if (rc == 0) { rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_certify_info2->pcrInfo)); } /* store migrationAuthority */ if (rc == 0) { rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_certify_info2->migrationAuthority)); } return rc; } /* TPM_CertifyInfo2_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_CertifyInfo2_Init to set members back to default values The object itself is not freed */ void TPM_CertifyInfo2_Delete(TPM_CERTIFY_INFO2 *tpm_certify_info2) { printf(" TPM_CertifyInfo2_Delete:\n"); if (tpm_certify_info2 != NULL) { TPM_KeyParms_Delete(&(tpm_certify_info2->algorithmParms)); /* pcrInfo */ TPM_SizedBuffer_Delete(&(tpm_certify_info2->pcrInfo)); /* pcr cache */ TPM_PCRInfoShort_Delete(tpm_certify_info2->tpm_pcr_info_short); free(tpm_certify_info2->tpm_pcr_info_short); TPM_SizedBuffer_Delete(&(tpm_certify_info2->migrationAuthority)); TPM_CertifyInfo2_Init(tpm_certify_info2); } return; } /* TPM_CertifyInfo2_Set() fills in tpm_certify_info2 with the information from the key pointed to by tpm_key. */ TPM_RESULT TPM_CertifyInfo2_Set(TPM_CERTIFY_INFO2 *tpm_certify_info2, TPM_KEY *tpm_key) { TPM_RESULT rc = 0; TPM_STORE_ASYMKEY *tpm_store_asymkey; printf(" TPM_CertifyInfo_Set:\n"); /* get the TPM_STORE_ASYMKEY object */ if (rc == 0) { rc = TPM_Key_GetStoreAsymkey(&tpm_store_asymkey, tpm_key); } if (rc == 0) { tpm_certify_info2->payloadType = tpm_store_asymkey->payload; tpm_certify_info2->keyUsage = tpm_key->keyUsage; tpm_certify_info2->keyFlags = tpm_key->keyFlags; tpm_certify_info2->authDataUsage = tpm_key->authDataUsage; rc = TPM_Key_GetStoreAsymkey(&tpm_store_asymkey, tpm_key); } if (rc == 0) { rc = TPM_KeyParms_Copy(&(tpm_certify_info2->algorithmParms), &(tpm_key->algorithmParms)); } /* pubkeyDigest SHALL be a digest of the value TPM_KEY -> pubKey -> key in a TPM_KEY representation of the key to be certified */ if (rc == 0) { rc = TPM_SHA1(tpm_certify_info2->pubkeyDigest, tpm_key->pubKey.size, tpm_key->pubKey.buffer, 0, NULL); } return rc; } /* TPM_SYMMETRIC_KEY */ /* TPM_SymmetricKey_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_SymmetricKey_Init(TPM_SYMMETRIC_KEY *tpm_symmetric_key) { printf(" TPM_SymmetricKey_Init:\n"); tpm_symmetric_key->algId = 0; tpm_symmetric_key->encScheme = TPM_ES_NONE; tpm_symmetric_key->size = 0; tpm_symmetric_key->data = NULL; return; } /* TPM_SymmetricKey_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_SymmetricKey_Init() After use, call TPM_SymmetricKey_Delete() to free memory */ TPM_RESULT TPM_SymmetricKey_Load(TPM_SYMMETRIC_KEY *tpm_symmetric_key, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_SymmetricKey_Load:\n"); /* load algId */ if (rc == 0) { rc = TPM_Load32(&(tpm_symmetric_key->algId), stream, stream_size); } /* load encScheme */ if (rc == 0) { rc = TPM_Load16(&(tpm_symmetric_key->encScheme), stream, stream_size); } /* load size */ if (rc == 0) { rc = TPM_Load16(&(tpm_symmetric_key->size), stream, stream_size); } /* allocate memory for the data */ if ((rc == 0) && (tpm_symmetric_key->size > 0)) { rc = TPM_Malloc(&(tpm_symmetric_key->data), tpm_symmetric_key->size); } /* load data */ if ((rc == 0) && (tpm_symmetric_key->size > 0)) { rc = TPM_Loadn(tpm_symmetric_key->data, tpm_symmetric_key->size, stream, stream_size); } return rc; } /* TPM_SymmetricKey_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_SymmetricKey_Store(TPM_STORE_BUFFER *sbuffer, const TPM_SYMMETRIC_KEY *tpm_symmetric_key) { TPM_RESULT rc = 0; printf(" TPM_SymmetricKey_Store:\n"); /* store algId */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_symmetric_key->algId); } /* store encScheme */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, tpm_symmetric_key->encScheme); } /* NOTE: Cannot use TPM_SizedBuffer_Store since the first parameter is a uint16_t */ /* store size */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, tpm_symmetric_key->size); } /* store data */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, tpm_symmetric_key->data, tpm_symmetric_key->size); } return rc; } /* TPM_SymmetricKey_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_SymmetricKey_Init to set members back to default values The object itself is not freed */ void TPM_SymmetricKey_Delete(TPM_SYMMETRIC_KEY *tpm_symmetric_key) { printf(" TPM_SymmetricKey_Delete:\n"); if (tpm_symmetric_key != NULL) { free(tpm_symmetric_key->data); TPM_SymmetricKey_Init(tpm_symmetric_key); } return; } /* TPM_SymmetricKeyData_EncryptSbuffer() encrypts 'sbuffer' to 'encrypt_data' Padding is included, so the output may be larger than the input. 'encrypt_data' must be free by the caller */ TPM_RESULT TPM_SymmetricKeyData_EncryptSbuffer(TPM_SIZED_BUFFER *encrypt_data, TPM_STORE_BUFFER *sbuffer, const TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_data) { TPM_RESULT rc = 0; const unsigned char *decrypt_data; /* serialization buffer */ uint32_t decrypt_data_size; /* serialization size */ printf(" TPM_SymmetricKeyData_EncryptSbuffer:\n"); if (rc == 0) { /* get the serialization results */ TPM_Sbuffer_Get(sbuffer, &decrypt_data, &decrypt_data_size); /* platform dependent symmetric key encrypt */ rc = TPM_SymmetricKeyData_Encrypt(&(encrypt_data->buffer), /* output, caller frees */ &(encrypt_data->size), /* output */ decrypt_data, /* input */ decrypt_data_size, /* input */ tpm_symmetric_key_data); } return rc; } /* TPM_SymmetricKeyData_StreamCrypt() encrypts or decrypts 'data_in' to 'data_out ' It assumes that the size of data_out and data_in are equal, and that a stream cipher mode is used. For the supported stream ciphers, encrypt and decrypt are equivalent, so no direction flag is required. AES 128 with CTR or OFB modes are supported. For CTR mode, pad is the initial count. For OFB mode, pad is the IV. */ TPM_RESULT TPM_SymmetricKeyData_StreamCrypt(unsigned char *data_out, /* output */ const unsigned char *data_in, /* input */ uint32_t data_size, /* input */ TPM_ALGORITHM_ID algId, /* algorithm */ TPM_ENC_SCHEME encScheme, /* mode */ const unsigned char *symmetric_key, /* input */ uint32_t symmetric_key_size, /* input */ unsigned char *pad_in, /* input */ uint32_t pad_in_size) /* input */ { TPM_RESULT rc = 0; printf(" TPM_SymmetricKeyData_StreamCrypt:\n"); switch (algId) { case TPM_ALG_AES128: switch (encScheme) { case TPM_ES_SYM_CTR: rc = TPM_SymmetricKeyData_CtrCrypt(data_out, data_in, data_size, symmetric_key, symmetric_key_size, pad_in, pad_in_size); break; case TPM_ES_SYM_OFB: rc = TPM_SymmetricKeyData_OfbCrypt(data_out, data_in, data_size, symmetric_key, symmetric_key_size, pad_in, pad_in_size); break; default: printf("TPM_SymmetricKeyData_StreamCrypt: Error, bad AES128 encScheme %04x\n", encScheme); rc = TPM_INAPPROPRIATE_ENC; break; } break; default: printf("TPM_SymmetricKeyData_StreamCrypt: Error, bad algID %08x\n", algId); rc = TPM_INAPPROPRIATE_ENC; break; } return rc; } /* These functions perform high-level, platform independent functions. They call the lower level, platform dependent crypto functions in tpm_crypto.c */ /* TPM_SHA1Sbuffer() calculates the SHA-1 digest of a TPM_STORE_BUFFER. This is commonly used when calculating a digest on a serialized structure. Structures are serialized to a TPM_STORE_BUFFER. The TPM_STORE_BUFFER is not deleted. */ TPM_RESULT TPM_SHA1Sbuffer(TPM_DIGEST tpm_digest, TPM_STORE_BUFFER *sbuffer) { TPM_RESULT rc = 0; const unsigned char *buffer; /* serialized buffer */ uint32_t length; /* serialization length */ printf(" TPM_SHA1Sbuffer:\n"); if (rc == 0) { /* get the components of the TPM_STORE_BUFFER */ TPM_Sbuffer_Get(sbuffer, &buffer, &length); TPM_PrintFour(" TPM_SHA1Sbuffer: input", buffer); /* hash the serialized buffer to tpm_digest */ rc = TPM_SHA1(tpm_digest, length, buffer, 0, NULL); } return rc; } /* TPM_SHA1_GenerateStructure() generates a SHA-1 digest of a structure. It serializes the structure and hashes the result. tpmStructure is the structure to be serialized storeFunction is the serialization function for the structure */ TPM_RESULT TPM_SHA1_GenerateStructure(TPM_DIGEST tpm_digest, void *tpmStructure, TPM_STORE_FUNCTION_T storeFunction) { TPM_RESULT rc = 0; TPM_STORE_BUFFER sbuffer; /* serialized tpmStructure */ printf(" TPM_SHA1_GenerateStructure:\n"); TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ /* Serialize the structure */ if (rc == 0) { rc = storeFunction(&sbuffer, tpmStructure); } /* hash the serialized buffer to tpm_hmac */ if (rc == 0) { rc = TPM_SHA1Sbuffer(tpm_digest, &sbuffer); } TPM_Sbuffer_Delete(&sbuffer); /* @1 */ return rc; } /* TPM_SHA1_CheckStructure() generates a SHA-1 digest of a structure. It serializes the structure and hashes the result. It compares the result to 'expected_digest' and returns 'error' on mismatch. tpmStructure is the structure to be serialized storeFunction is the serialization function for the structure */ TPM_RESULT TPM_SHA1_CheckStructure(TPM_DIGEST expected_digest, void *tpmStructure, TPM_STORE_FUNCTION_T storeFunction, TPM_RESULT error) { TPM_RESULT rc = 0; TPM_DIGEST actual_digest; printf(" TPM_SHA1_CheckStructure:\n"); /* hash the serialized buffer to tpm_digest */ if (rc == 0) { rc = TPM_SHA1_GenerateStructure(actual_digest, tpmStructure, storeFunction); } /* check the digests */ if (rc == 0) { rc = TPM_Digest_Compare(actual_digest, expected_digest); if (rc != 0) { rc = error; } } return rc; } /* TPM_SHA1() can be called directly to hash a list of streams. The ... arguments to be hashed are a list of the form size_t length, unsigned char *buffer terminated by a 0 length */ TPM_RESULT TPM_SHA1(TPM_DIGEST md, ...) { TPM_RESULT rc = 0; va_list ap; printf(" TPM_SHA1:\n"); va_start(ap, md); rc = TPM_SHA1_valist(md, 0, NULL, ap); va_end(ap); return rc; } /* TPM_SHA1_Check() digests the list of streams and compares the result to 'digest_expect' */ TPM_RESULT TPM_SHA1_Check(TPM_DIGEST digest_expect, ...) { TPM_RESULT rc = 0; TPM_DIGEST digest_actual; va_list ap; printf(" TPM_SHA1_Check:\n"); if (rc == 0) { va_start(ap, digest_expect); rc = TPM_SHA1_valist(digest_actual, 0, NULL, ap); va_end(ap); } if (rc == 0) { rc = TPM_Digest_Compare(digest_expect, digest_actual); } return rc; } /* TPM_SHA1_valist() is the internal function, called with the va_list already created. It is called from TPM_SHA1() to do a simple hash. Typically length0==0 and buffer0==NULL. It can also be called from the HMAC function to hash the variable number of input parameters. In that case, the va_list for the text is already formed. length0 and buffer0 are used to input the padded key. */ static TPM_RESULT TPM_SHA1_valist(TPM_DIGEST md, uint32_t length0, unsigned char *buffer0, va_list ap) { TPM_RESULT rc = 0; uint32_t length; unsigned char *buffer; void *context = NULL; /* platform dependent context */ TPM_BOOL done = FALSE; printf(" TPM_SHA1_valist:\n"); if (rc == 0) { rc = TPM_SHA1InitCmd(&context); } if (rc == 0) { if (length0 !=0) { /* optional first text block */ printf(" TPM_SHA1_valist: Digesting %u bytes\n", length0); rc = TPM_SHA1UpdateCmd(context, buffer0, length0); /* hash the buffer */ } } while ((rc == 0) && !done) { length = va_arg(ap, uint32_t); /* first vararg is the length */ if (length != 0) { /* loop until a zero length argument terminates */ buffer = va_arg(ap, unsigned char *); /* second vararg is the array */ printf(" TPM_SHA1_valist: Digesting %u bytes\n", length); rc = TPM_SHA1UpdateCmd(context, buffer, length); /* hash the buffer */ } else { done = TRUE; } } if (rc == 0) { rc = TPM_SHA1FinalCmd(md, context); } if (rc == 0) { TPM_PrintFour(" TPM_SHA1_valist: Digest", md); } /* call TPM_SHA1Delete even if there was an error */ TPM_SHA1Delete(&context); return rc; } /* TPM_HMAC_GenerateSbuffer() calculates the HMAC digest of a TPM_STORE_BUFFER. This is commonly used when calculating an HMAC on a serialized structure. Structures are serialized to a TPM_STORE_BUFFER. The TPM_STORE_BUFFER is not deleted. */ TPM_RESULT TPM_HMAC_GenerateSbuffer(TPM_HMAC tpm_hmac, const TPM_SECRET hmac_key, TPM_STORE_BUFFER *sbuffer) { TPM_RESULT rc = 0; const unsigned char *buffer; /* serialized buffer */ uint32_t length; /* serialization length */ printf(" TPM_HMAC_GenerateSbuffer:\n"); if (rc == 0) { /* get the components of the TPM_STORE_BUFFER */ TPM_Sbuffer_Get(sbuffer, &buffer, &length); /* HMAC the serialized buffer to tpm_hmac */ rc = TPM_HMAC_Generate(tpm_hmac, hmac_key, length, buffer, 0, NULL); } return rc; } /* TPM_HMAC_GenerateStructure() generates an HMAC of a structure. It serializes the structure and HMAC's the result. hmacKey is the HMAC key tpmStructure is the structure to be serialized storeFunction is the serialization function for the structure */ TPM_RESULT TPM_HMAC_GenerateStructure(TPM_HMAC tpm_hmac, const TPM_SECRET hmac_key, void *tpmStructure, TPM_STORE_FUNCTION_T storeFunction) { TPM_RESULT rc = 0; TPM_STORE_BUFFER sbuffer; /* serialized tpmStructure */ printf(" TPM_HMAC_GenerateStructure:\n"); TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ /* Serialize the structure */ if (rc == 0) { rc = storeFunction(&sbuffer, tpmStructure); } /* hash the serialized buffer to tpm_hmac */ if (rc == 0) { rc = TPM_HMAC_GenerateSbuffer(tpm_hmac, hmac_key, &sbuffer); } TPM_Sbuffer_Delete(&sbuffer); /* @1 */ return rc; } /* TPM_HMAC_Generate() can be called directly to HMAC a list of streams. The ... arguments are a message list of the form size_t length, unsigned char *buffer terminated by a 0 length */ TPM_RESULT TPM_HMAC_Generate(TPM_HMAC tpm_hmac, const TPM_SECRET hmac_key, ...) { TPM_RESULT rc = 0; va_list ap; printf(" TPM_HMAC_Generate:\n"); va_start(ap, hmac_key); rc = TPM_HMAC_Generatevalist(tpm_hmac, hmac_key, ap); va_end(ap); return rc; } /* TPM_HMAC_Generatevalist() is the internal function, called with the va_list already created. It is called from TPM_HMAC_Generate() and TPM_HMAC_Check() with the va_list for the text already formed. */ #define TPM_HMAC_BLOCK_SIZE 64 static TPM_RESULT TPM_HMAC_Generatevalist(TPM_HMAC tpm_hmac, const TPM_SECRET key, va_list ap) { TPM_RESULT rc = 0; unsigned char ipad[TPM_HMAC_BLOCK_SIZE]; unsigned char opad[TPM_HMAC_BLOCK_SIZE]; size_t i; TPM_DIGEST inner_hash; printf(" TPM_HMAC_Generatevalist:\n"); /* calculate key XOR ipad and key XOR opad */ if (rc == 0) { /* first part, key XOR pad */ for (i = 0 ; i < TPM_AUTHDATA_SIZE ; i++) { ipad[i] = key[i] ^ 0x36; /* magic numbers from RFC 2104 */ opad[i] = key[i] ^ 0x5c; } /* second part, 0x00 XOR pad */ memset(ipad + TPM_AUTHDATA_SIZE, 0x36, TPM_HMAC_BLOCK_SIZE - TPM_AUTHDATA_SIZE); memset(opad + TPM_AUTHDATA_SIZE, 0x5c, TPM_HMAC_BLOCK_SIZE - TPM_AUTHDATA_SIZE); /* calculate the inner hash, hash the key XOR ipad and the text */ rc = TPM_SHA1_valist(inner_hash, TPM_HMAC_BLOCK_SIZE, ipad, ap); } /* hash the key XOR opad and the previous hash */ if (rc == 0) { rc = TPM_SHA1(tpm_hmac, TPM_HMAC_BLOCK_SIZE, opad, TPM_DIGEST_SIZE, inner_hash, 0, NULL); } if (rc == 0) { TPM_PrintFour(" TPM_HMAC_Generatevalist: HMAC", tpm_hmac); } return rc; } /* TPM_HMAC_CheckSbuffer() checks the HMAC of a TPM_STORE_BUFFER. This is commonly used when checking an HMAC on a serialized structure. Structures are serialized to a TPM_STORE_BUFFER. The TPM_STORE_BUFFER is not deleted. */ TPM_RESULT TPM_HMAC_CheckSbuffer(TPM_BOOL *valid, /* result */ TPM_HMAC expect, /* expected */ const TPM_SECRET hmac_key, /* key */ TPM_STORE_BUFFER *sbuffer) /* data stream */ { TPM_RESULT rc = 0; const unsigned char *buffer; /* serialized buffer */ uint32_t length; /* serialization length */ printf(" TPM_HMAC_CheckSbuffer:\n"); if (rc == 0) { /* get the components of the TPM_STORE_BUFFER */ TPM_Sbuffer_Get(sbuffer, &buffer, &length); /* HMAC the serialized buffer to tpm_hmac */ rc = TPM_HMAC_Check(valid, expect, hmac_key, length, buffer, 0, NULL); } return rc; } /* TPM_HMAC_Check() can be called directly to check the HMAC of a list of streams. The ... arguments are a list of the form size_t length, unsigned char *buffer terminated by a 0 length */ TPM_RESULT TPM_HMAC_Check(TPM_BOOL *valid, TPM_HMAC expect, const TPM_SECRET key, ...) { TPM_RESULT rc = 0; va_list ap; TPM_HMAC actual; int result; printf(" TPM_HMAC_Check:\n"); va_start(ap, key); if (rc == 0) { rc = TPM_HMAC_Generatevalist(actual, key, ap); } if (rc == 0) { TPM_PrintFour(" TPM_HMAC_Check: Calculated", actual); TPM_PrintFour(" TPM_HMAC_Check: Received ", expect); result = memcmp(expect, actual, TPM_DIGEST_SIZE); if (result == 0) { *valid = TRUE; } else { *valid = FALSE; } } va_end(ap); return rc; } /* TPM_HMAC_CheckStructure() is a generic function that checks the integrity HMAC of a structure. hmacKey is the HMAC key tpmStructure is the structure to be serialized expect is the expected HMAC, a member of the structure storeFunction is the serialization function for the structure error is the failure return code The function saves a copy of the expected HMAC, and then NULL's the structure member. It serializes the structure, generates an HMAC, and compares it to the expected value. As a side effect, the structure member is zeroed. */ TPM_RESULT TPM_HMAC_CheckStructure(const TPM_SECRET hmac_key, void *tpmStructure, TPM_HMAC expect, TPM_STORE_FUNCTION_T storeFunction, TPM_RESULT error) { TPM_RESULT rc = 0; TPM_STORE_BUFFER sbuffer; /* serialized tpmStructure */ TPM_HMAC saveExpect; TPM_BOOL valid; printf(" TPM_HMAC_CheckStructure:\n"); TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ if (rc == 0) { TPM_Digest_Copy(saveExpect, expect); /* save the expected value */ TPM_Digest_Init(expect); /* set value in structure to NULL */ rc = storeFunction(&sbuffer, tpmStructure); } /* verify the HMAC of the serialized structure */ if (rc == 0) { rc = TPM_HMAC_CheckSbuffer(&valid, /* result */ saveExpect, /* expected */ hmac_key, /* key */ &sbuffer); /* data stream */ } if (rc == 0) { if (!valid) { printf("TPM_HMAC_CheckStructure: Error checking HMAC\n"); rc = error; } } TPM_Sbuffer_Delete(&sbuffer); /* @1 */ return rc; } /* TPM_XOR XOR's 'in1' and 'in2' of 'length', putting the result in 'out' */ void TPM_XOR(unsigned char *out, const unsigned char *in1, const unsigned char *in2, size_t length) { size_t i; for (i = 0 ; i < length ; i++) { out[i] = in1[i] ^ in2[i]; } return; } /* TPM_MGF1() generates an MGF1 'array' of length 'arrayLen' from 'seed' of length 'seedlen' The openSSL DLL doesn't export MGF1 in Windows or Linux 1.0.0, so this version is created from scratch. Algorithm and comments (not the code) from: PKCS #1: RSA Cryptography Specifications Version 2.1 B.2.1 MGF1 Prototype designed to be compatible with openSSL MGF1 is a Mask Generation Function based on a hash function. MGF1 (mgfSeed, maskLen) Options: Hash hash function (hLen denotes the length in octets of the hash function output) Input: mgfSeed seed from which mask is generated, an octet string maskLen intended length in octets of the mask, at most 2^32(hLen) Output: mask mask, an octet string of length l; or "mask too long" Error: "mask too long' */ TPM_RESULT TPM_MGF1(unsigned char *mask, uint32_t maskLen, const unsigned char *mgfSeed, uint32_t mgfSeedlen) { TPM_RESULT rc = 0; unsigned char counter[4]; /* 4 octets */ uint32_t count; /* counter as an integral type */ uint32_t outLen; TPM_DIGEST lastDigest; printf(" TPM_MGF1: Output length %u\n", maskLen); if (rc == 0) { /* this is possible with arrayLen on a 64 bit architecture, comment to quiet beam */ if ((maskLen / TPM_DIGEST_SIZE) > 0xffffffff) { /*constant condition*/ printf(" TPM_MGF1: Error (fatal), Output length too large for 32 bit counter\n"); rc = TPM_FAIL; /* should never occur */ } } /* 1.If l > 2^32(hLen), output "mask too long" and stop. */ /* NOTE Checked by caller */ /* 2. Let T be the empty octet string. */ /* 3. For counter from 0 to [masklen/hLen] - 1, do the following: */ for (count = 0, outLen = 0 ; (rc == 0) && (outLen < maskLen) ; count++) { /* a. Convert counter to an octet string C of length 4 octets - see Section 4.1 */ /* C = I2OSP(counter, 4) NOTE Basically big endian */ uint32_t count_n = htonl(count); memcpy(counter, &count_n, 4); /* b.Concatenate the hash of the seed mgfSeed and C to the octet string T: */ /* T = T || Hash (mgfSeed || C) */ /* If the entire digest is needed for the mask */ if ((outLen + TPM_DIGEST_SIZE) < maskLen) { rc = TPM_SHA1(mask + outLen, mgfSeedlen, mgfSeed, 4, counter, 0, NULL); outLen += TPM_DIGEST_SIZE; } /* if the mask is not modulo TPM_DIGEST_SIZE, only part of the final digest is needed */ else { /* hash to a temporary digest variable */ rc = TPM_SHA1(lastDigest, mgfSeedlen, mgfSeed, 4, counter, 0, NULL); /* copy what's needed */ memcpy(mask + outLen, lastDigest, maskLen - outLen); outLen = maskLen; /* outLen = outLen + maskLen - outLen */ } } /* 4.Output the leading l octets of T as the octet string mask. */ return rc; } /* TPM_MGF1_GenerateArray() generates an array of length arrayLen using the varargs as the seed. Since the seed is a known length, it is passed in rather that extracted from the varargs. If the seed length turns out to be wrong once the varargs are parsed, TPM_FAIL is returned. 'array' must be freed by the caller. */ TPM_RESULT TPM_MGF1_GenerateArray(unsigned char **array, uint32_t arrayLen, uint32_t seedLen, ...) { TPM_RESULT rc = 0; va_list ap; unsigned char *seed; /* constructed MGF1 seed */ size_t vaLength; /* next seed segment length */ unsigned char *vaBuffer; /* next seed segment buffer */ uint32_t seedLeft; /* remaining seed bytes required */ unsigned char *seedBuffer; /* running pointer to the seed array */ TPM_BOOL done = FALSE; /* done when a vaLength == 0 is reached */ printf(" TPM_MGF1_GenerateArray: arrayLen %u seedLen %u\n", arrayLen, seedLen); seed = NULL; /* freed @1 */ *array = NULL; /* freed by caller */ va_start(ap, seedLen); /* allocate temporary memory for the seed */ if (rc == 0) { rc = TPM_Malloc(&seed, seedLen); seedBuffer = seed; seedLeft = seedLen; } /* construct the seed */ while ((rc == 0) && !done) { vaLength = (size_t)va_arg(ap, uint32_t); /* first vararg is the length */ if (vaLength != 0) { /* loop until a zero length argument terminates */ if (rc == 0) { printf(" TPM_MGF1_GenerateArray: Appending %lu bytes\n", (unsigned long)vaLength); if (vaLength > seedLeft) { printf("TPM_MGF1_GenerateArray: Error (fatal), seedLen too small\n"); rc = TPM_FAIL; /* internal error, should never occur */ } } if (rc == 0) { vaBuffer = va_arg(ap, unsigned char *); /* second vararg is the array */ memcpy(seedBuffer, vaBuffer, vaLength); seedBuffer += vaLength; seedLeft-= vaLength; } } else { done = TRUE; if (seedLeft != 0) { printf("TPM_MGF1_GenerateArray: Error (fatal), seedLen too large by %u\n", seedLeft); rc = TPM_FAIL; /* internal error, should never occur */ } } } /* allocate memory for the array */ if (rc == 0) { rc = TPM_Malloc(array, arrayLen); } /* generate the MGF1 array */ if (rc == 0) { TPM_MGF1(*array, arrayLen, seed, seedLen); TPM_PrintFour(" TPM_MGF1_GenerateArray: MGF1", *array); } va_end(ap); free(seed); /* @1 */ return rc; } /* TPM_bn2binMalloc() allocates a buffer 'bin' and loads it from 'bn'. 'bytes' is set to the allocated size of 'bin'. If padBytes is non-zero, 'bin' is padded with leading zeros if necessary, so that 'bytes' will equal 'padBytes'. This is used when TPM data structures expect a fixed length while the crypto library 'bn to bin' function might truncates leading zeros. '*bin' must be freed by the caller */ TPM_RESULT TPM_bn2binMalloc(unsigned char **bin, /* freed by caller */ unsigned int *bytes, TPM_BIGNUM bn, uint32_t padBytes) { TPM_RESULT rc = 0; printf(" TPM_bn2binMalloc: padBytes %u\n", padBytes); /* number of bytes required in the bin array */ if (rc == 0) { rc = TPM_BN_num_bytes(bytes, bn); } /* calculate the array size to malloc */ if (rc == 0) { /* padBytes 0 says that no padding is required */ if (padBytes == 0) { padBytes = *bytes; /* setting equal yields no padding */ } /* if the array with padding is still less than the number of bytes required by the bignum, this function fails */ if (padBytes < *bytes) { printf("TPM_bn2binMalloc: Error, " "padBytes %u less than BN bytes %u\n", padBytes, *bytes); rc = TPM_SIZE; } /* log if padding is occurring */ if (padBytes != *bytes) { printf(" TPM_bn2binMalloc: padBytes %u bytes %u\n", padBytes, *bytes); } } /* allocate for the padded array */ if (rc == 0) { rc = TPM_Malloc(bin, padBytes); *bytes = padBytes; } /* call the bignum to bin conversion */ if (rc == 0) { rc = TPM_bn2binArray(*bin, padBytes, bn); } return rc; } /* TPM_bn2binArray() loads the array 'bin' of size 'bytes' from 'bn' The data from 'bn' is right justified and zero padded. */ TPM_RESULT TPM_bn2binArray(unsigned char *bin, unsigned int bytes, TPM_BIGNUM bn) { TPM_RESULT rc = 0; unsigned int numBytes; printf(" TPM_bn2binArray: size %u\n", bytes); if (rc == 0) { /* zero pad */ memset(bin, 0, bytes); /* bytes required for the bignum */ rc = TPM_BN_num_bytes(&numBytes, bn); } /* if the array is less than the number of bytes required by the bignum, this function fails */ if (rc == 0) { printf(" TPM_bn2binArray: numBytes in bignum %u\n", numBytes); if (numBytes > bytes) { printf("TPM_bn2binArray: Error, " "BN bytes %u greater than array bytes %u\n", numBytes, bytes); rc = TPM_SIZE; } } if (rc == 0) { /* if there are bytes in the bignum (it is not zero) */ if (numBytes > 0) { rc = TPM_bn2bin(bin + bytes - numBytes, /* store right justified */ bn); } } return rc; } /* TPM_2bin2bn() converts two byte arrays to a positive BIGNUM. The two byte arrays are concatenated. The concatenation is used to create the BIGNUM. bignum must be freed by the caller. */ TPM_RESULT TPM_2bin2bn(TPM_BIGNUM *bignum_in, /* freed by caller */ const unsigned char *bin0, uint32_t size0, const unsigned char *bin1, uint32_t size1) { TPM_RESULT rc = 0; /* TPM return code */ TPM_STORE_BUFFER sBuffer; /* used of >1 element or first element is negative */ const unsigned char *buffer; uint32_t size; printf(" TPM_bin2bn:\n"); TPM_Sbuffer_Init(&sBuffer); /* freed @1 */ /* append the first element */ if (rc == 0) { rc = TPM_Sbuffer_Append(&sBuffer, bin0, size0); } /* append the next element */ if (rc == 0) { rc = TPM_Sbuffer_Append(&sBuffer, bin1, size1); } /* create the BIGNUM from the array */ if (rc == 0) { TPM_Sbuffer_Get(&sBuffer, &buffer, &size); /* create the BIGNUM */ rc = TPM_bin2bn(bignum_in, buffer, size); /* freed by caller */ } TPM_Sbuffer_Delete(&sBuffer); /* @1 */ return rc; } /* TPM_RSAPrivateDecryptMalloc() allocates a buffer 'decrypt_data' of size 'decrypt_data_size' and then calls TPM_RSAPrivateDecryptH(). */ TPM_RESULT TPM_RSAPrivateDecryptMalloc(unsigned char **decrypt_data, /* decrypted data */ uint32_t *decrypt_data_length, /* length of data put into decrypt_data */ unsigned char *encrypt_data, uint32_t encrypt_data_size, TPM_KEY *tpm_key) { TPM_RESULT rc = 0; /* allocate space for the decrypted blob */ printf(" TPM_RSAPrivateDecryptMalloc: Return max data size %u bytes\n", tpm_key->pubKey.size); if (rc == 0) { rc = TPM_Malloc(decrypt_data, tpm_key->pubKey.size); } if (rc == 0) { rc = TPM_RSAPrivateDecryptH(*decrypt_data, decrypt_data_length, tpm_key->pubKey.size, encrypt_data, encrypt_data_size, tpm_key); } return rc; } /* TPM_RSAPrivateDecryptH() decrypts 'encrypt_data' using the private key in 'tpm_key' and 'decrypt_data_length' bytes are moved to 'decrypt_data'. 'decrypt_data_length' is at most 'decrypt_data_size'. */ TPM_RESULT TPM_RSAPrivateDecryptH(unsigned char *decrypt_data, /* decrypted data */ uint32_t *decrypt_data_length, /* length of data put into decrypt_data */ uint32_t decrypt_data_size, /* size of decrypt_data buffer */ unsigned char *encrypt_data, uint32_t encrypt_data_size, TPM_KEY *tpm_key) { TPM_RESULT rc = 0; unsigned char *narr; /* public modulus */ uint32_t nbytes; unsigned char *earr; /* public exponent */ uint32_t ebytes; unsigned char *darr; /* private exponent */ uint32_t dbytes; printf(" TPM_RSAPrivateDecryptH: Data size %u bytes\n", encrypt_data_size); TPM_PrintFourLimit(" TPM_RSAPrivateDecryptH: Encrypt data", encrypt_data, encrypt_data_size); if (rc == 0) { if (tpm_key == NULL) { printf("TPM_RSAPrivateDecryptH: Error, NULL key\n"); rc = TPM_DECRYPT_ERROR; } } /* extract the public key from TPM_KEY */ if (rc == 0) { rc = TPM_Key_GetPublicKey(&nbytes, &narr, tpm_key); } /* extract the private key from TPM_KEY */ if (rc == 0) { rc = TPM_Key_GetPrivateKey(&dbytes, &darr, tpm_key); } /* extract the exponent from TPM_KEY */ if (rc == 0) { rc = TPM_Key_GetExponent(&ebytes, &earr, tpm_key); } /* check the key size vs the data size */ if (rc == 0) { if (encrypt_data_size > nbytes) { printf("TPM_RSAPrivateDecryptH: Error, data size too long for key size %u bytes\n", nbytes); rc = TPM_BAD_DATASIZE; } } if (rc == 0) { /* debug printing */ printf(" TPM_RSAPrivateDecryptH: Public key length %u\n", nbytes); printf(" TPM_RSAPrivateDecryptH: Private key length %u\n", dbytes); TPM_PrintFour(" TPM_RSAPrivateDecryptH: Public key", narr); printf(" TPM_RSAPrivateDecryptH: Exponent %02x %02x %02x\n", earr[0], earr[1], earr[2]); TPM_PrintFour(" TPM_RSAPrivateDecryptH: Private key", darr); /* decrypt with private key */ rc = TPM_RSAPrivateDecrypt(decrypt_data, /* decrypted data */ decrypt_data_length, /* length of data put into decrypt_data */ decrypt_data_size, /* size of decrypt_data buffer */ tpm_key->algorithmParms.encScheme, /* encryption scheme */ encrypt_data, /* encrypted data */ encrypt_data_size, narr, /* public modulus */ nbytes, earr, /* public exponent */ ebytes, darr, /* private exponent */ dbytes); } if (rc == 0) { TPM_PrintFourLimit(" TPM_RSAPrivateDecryptH: Decrypt data", decrypt_data, *decrypt_data_length); } return rc; } /* TPM_RSAPublicEncryptSbuffer_Key() encrypts 'sbuffer' using the public key in 'tpm_key' and puts the results in 'encData' */ TPM_RESULT TPM_RSAPublicEncryptSbuffer_Key(TPM_SIZED_BUFFER *enc_data, TPM_STORE_BUFFER *sbuffer, TPM_KEY *tpm_key) { TPM_RESULT rc = 0; const unsigned char *decrypt_data; /* serialization buffer */ uint32_t decrypt_data_size; /* serialization size */ printf(" TPM_RSAPublicEncryptSbuffer_Key:\n"); /* get the serialization results */ TPM_Sbuffer_Get(sbuffer, &decrypt_data, &decrypt_data_size); /* encrypt the serialization buffer with the public key, and place the result in the enc_data buffer */ rc = TPM_RSAPublicEncrypt_Key(enc_data, decrypt_data, decrypt_data_size, tpm_key); return rc; } /* TPM_RSAPublicEncrypt_Key() encrypts 'buffer' of 'length' using the public key in 'tpm_key' and puts the results in 'encData' */ TPM_RESULT TPM_RSAPublicEncrypt_Key(TPM_SIZED_BUFFER *enc_data, const unsigned char *decrypt_data, size_t decrypt_data_size, TPM_KEY *tpm_key) { TPM_RESULT rc = 0; unsigned char *narr; /* public modulus */ uint32_t nbytes; unsigned char *earr; /* public exponent */ uint32_t ebytes; printf(" TPM_RSAPublicEncrypt_Key: Data size %lu bytes\n", (unsigned long)decrypt_data_size); if (rc == 0) { if (tpm_key == NULL) { printf("TPM_RSAPublicEncrypt_Key: Error, NULL key\n"); rc = TPM_ENCRYPT_ERROR; } } /* extract the public key from TPM_KEY */ if (rc == 0) { rc = TPM_Key_GetPublicKey(&nbytes, &narr, tpm_key); } /* extract the exponent from TPM_KEY */ if (rc == 0) { rc = TPM_Key_GetExponent(&ebytes, &earr, tpm_key); } if (rc == 0) { rc = TPM_RSAPublicEncrypt_Common(enc_data, decrypt_data, decrypt_data_size, tpm_key->algorithmParms.encScheme, /* encryption scheme */ narr, nbytes, earr, ebytes); } return rc; } /* TPM_RSAPublicEncrypt_Key() encrypts 'buffer' of 'length' using the public key in 'tpm_pubkey' and puts the results in 'encData' */ TPM_RESULT TPM_RSAPublicEncrypt_Pubkey(TPM_SIZED_BUFFER *enc_data, const unsigned char *decrypt_data, size_t decrypt_data_size, TPM_PUBKEY *tpm_pubkey) { TPM_RESULT rc = 0; unsigned char *narr; /* public modulus */ uint32_t nbytes; unsigned char *earr; /* public exponent */ uint32_t ebytes; printf(" TPM_RSAPublicEncrypt_Pubkey: Data size %lu bytes\n", (unsigned long)decrypt_data_size); if (rc == 0) { if (tpm_pubkey == NULL) { printf("TPM_RSAPublicEncrypt_Pubkey: Error, NULL key\n"); rc = TPM_ENCRYPT_ERROR; } } /* extract the public key from TPM_PUBKEY */ if (rc == 0) { rc = TPM_Pubkey_GetPublicKey(&nbytes, &narr, tpm_pubkey); } /* extract the exponent from TPM_KEY */ if (rc == 0) { rc = TPM_Pubkey_GetExponent(&ebytes, &earr, tpm_pubkey); } if (rc == 0) { rc = TPM_RSAPublicEncrypt_Common(enc_data, decrypt_data, decrypt_data_size, tpm_pubkey->algorithmParms.encScheme, narr, nbytes, earr, ebytes); } return rc; } /* TPM_RSAPublicEncrypt_Key() encrypts 'buffer' of 'length' using the public key modulus and exponent, and puts the results in 'encData' */ TPM_RESULT TPM_RSAPublicEncrypt_Common(TPM_SIZED_BUFFER *enc_data, const unsigned char *decrypt_data, size_t decrypt_data_size, TPM_ENC_SCHEME encScheme, unsigned char *narr, /* public modulus */ uint32_t nbytes, unsigned char *earr, /* public exponent */ uint32_t ebytes) { TPM_RESULT rc = 0; unsigned char *encrypt_data = NULL; printf(" TPM_RSAPublicEncrypt_Common: Data size %lu bytes\n", (unsigned long)decrypt_data_size); TPM_PrintFourLimit(" TPM_RSAPublicEncrypt_Common: Decrypt data", decrypt_data, decrypt_data_size); /* check the key size vs the data size */ if (rc == 0) { if (decrypt_data_size > nbytes) { printf("TPM_RSAPublicEncrypt_Common: Error, data size too long for key size %u bytes\n", nbytes); rc = TPM_BAD_DATASIZE; } } /* allocate an array for the encrypted data */ if (rc == 0) { rc = TPM_Malloc(&encrypt_data, nbytes); } /* pad and encrypt the data */ if (rc == 0) { TPM_PrintFour(" TPM_RSAPublicEncrypt_Common: Public key", narr); printf(" TPM_RSAPublicEncrypt_Common: Exponent %02x %02x %02x\n", earr[0], earr[1], earr[2]); rc = TPM_RSAPublicEncrypt(encrypt_data, /* encrypted data */ nbytes, /* encrypted data size */ encScheme, /* encryption scheme */ decrypt_data, /* decrypted data */ decrypt_data_size, narr, /* public modulus */ nbytes, earr, /* public exponent */ ebytes); } /* copy the result to the sized buffer */ if (rc == 0) { printf(" TPM_RSAPublicEncrypt_Common: Encrypt data size %u\n", nbytes); TPM_PrintFour(" TPM_RSAPublicEncrypt_Common: Encrypt data", encrypt_data); rc = TPM_SizedBuffer_Set(enc_data, nbytes, encrypt_data); } free(encrypt_data); /* @1 */ return rc; } /* Signing Functions These commands show the TPM command and the allowed signature schemes: SHA DER INFO TPM_GetAuditDigestSigned y n y TPM_CertifyKey y n y TPM_CertifyKey2 y n y TPM_CertifySelfTest y n y TPM_Quote y n y TPM_Quote2 y n y TPM_Sign y y y TPM_MakeIdentity y n y TPM_GetCapabilitySigned y n y */ /* TPM_RSASignToSizedBuffer() signs 'message' using the private key in 'tpm_key' and places the result in 'signature' 'signature' should be initialized and deleted by the caller */ TPM_RESULT TPM_RSASignToSizedBuffer(TPM_SIZED_BUFFER *signature, const unsigned char *message, /* input */ size_t message_size, /* input */ TPM_KEY *tpm_key) /* input, signing key */ { TPM_RESULT rc = 0; TPM_RSA_KEY_PARMS *rsa_key_parms; unsigned int signature_length; printf(" TPM_RSASignToSizedBuffer: Message size %lu bytes\n", (unsigned long)message_size); if (rc == 0) { rc = TPM_KeyParms_GetRSAKeyParms(&rsa_key_parms, &(tpm_key->algorithmParms)); } /* allocating space for the signature */ if (rc == 0) { rc = TPM_SizedBuffer_Allocate(signature, (rsa_key_parms->keyLength)/CHAR_BIT); } /* sign */ if (rc == 0) { rc = TPM_RSASignH(signature->buffer, /* output signature */ &signature_length, /* output, size of signature */ signature->size, /* input, size of signature buffer */ message, /* message */ message_size, /* message size */ tpm_key); /* input, signing key */ } /* sanity check on signature */ if (rc == 0) { if (signature_length != signature->size) { printf("TPM_RSASignToSizedBuffer: Error (fatal) signature_length %u sigSize %u\n", signature_length, signature->size); rc = TPM_FAIL; /* internal error, should never occur */ } } return rc; } /* TPM_RSASignH() signs 'message' using the private key in 'tpm_key'. 'signature_length' bytes are moved to 'signature'. 'signature_length' is at most 'signature_size'. */ TPM_RESULT TPM_RSASignH(unsigned char *signature, /* output */ unsigned int *signature_length, /* output, size of signature */ unsigned int signature_size, /* input, size of signature buffer */ const unsigned char *message, /* input */ size_t message_size, /* input */ TPM_KEY *tpm_key) /* input, signing key */ { TPM_RESULT rc = 0; unsigned char *narr; /* public modulus */ uint32_t nbytes; unsigned char *earr; /* public exponent */ uint32_t ebytes; unsigned char *darr; /* private exponent */ uint32_t dbytes; printf(" TPM_RSASignH: Message size %lu bytes\n", (unsigned long)message_size); TPM_PrintFourLimit(" TPM_RSASignH: Message", message, message_size); /* extract the public key from TPM_KEY */ if (rc == 0) { rc = TPM_Key_GetPublicKey(&nbytes, &narr, tpm_key); } /* extract the private key from TPM_KEY */ if (rc == 0) { rc = TPM_Key_GetPrivateKey(&dbytes, &darr, tpm_key); } /* extract the exponent from TPM_KEY */ if (rc == 0) { rc = TPM_Key_GetExponent(&ebytes, &earr, tpm_key); } if (rc == 0) { /* debug printing */ TPM_PrintFour(" TPM_RSASignH: Public key", narr); printf(" TPM_RSASignH: Exponent %02x %02x %02x\n", earr[0], earr[1], earr[2]); TPM_PrintFour(" TPM_RSASignH: Private key", darr); /* sign with private key */ rc = TPM_RSASign(signature, /* output */ signature_length, /* output, size of signature */ signature_size, /* input, size of signature buffer */ tpm_key->algorithmParms.sigScheme, /* input, type of signature */ message, /* input */ message_size, /* input */ narr, /* public modulus */ nbytes, earr, /* public exponent */ ebytes, darr, /* private exponent */ dbytes); } if (rc == 0) { TPM_PrintFour(" TPM_RSASignH: Signature", signature); } return rc; } /* TPM_RSAVerifyH() verifies 'message' using the TPM format public key in 'tpm_pubkey' */ TPM_RESULT TPM_RSAVerifyH(TPM_SIZED_BUFFER *signature, /* input */ const unsigned char *message, /* input */ uint32_t message_size, /* input */ TPM_PUBKEY *tpm_pubkey) /* input, verify key */ { TPM_RESULT rc = 0; unsigned char *narr; /* public modulus */ uint32_t nbytes; unsigned char *earr; /* public exponent */ uint32_t ebytes; printf(" TPM_RSAVerifyH: Message size %u bytes\n", message_size); /* extract the public key from TPM_PUBKEY */ if (rc == 0) { rc = TPM_Pubkey_GetPublicKey(&nbytes, &narr, tpm_pubkey); } /* extract the exponent from TPM_PUBKEY */ if (rc == 0) { rc = TPM_Pubkey_GetExponent(&ebytes, &earr, tpm_pubkey); } if (rc == 0) { /* debug printing */ TPM_PrintFour(" TPM_RSAVerifyH: Public key", narr); TPM_PrintAll(" TPM_RSAVerifyH: Public exponent", earr, ebytes); /* verify with public key */ rc = TPM_RSAVerify(signature->buffer, /* input signature buffer */ signature->size, /* input, size of signature buffer */ tpm_pubkey->algorithmParms.sigScheme, /* input, type of signature */ message, /* message */ message_size, /* message size */ narr, /* public modulus */ nbytes, earr, /* public exponent */ ebytes); } return rc; } /* TPM_RSAVerify() verifies the 'signature' of size 'signature_size' on the 'message' of size 'message_size' using the public key n,e and the signature scheme 'sigScheme' as specified in PKCS #1 v2.0. */ TPM_RESULT TPM_RSAVerify(unsigned char *signature, /* input */ unsigned int signature_size, /* input, size of signature buffer */ TPM_SIG_SCHEME sigScheme, /* input, type of signature */ const unsigned char *message, /* input */ uint32_t message_size, /* input */ unsigned char *narr, /* public modulus */ uint32_t nbytes, unsigned char *earr, /* public exponent */ uint32_t ebytes) { TPM_RESULT rc = 0; printf(" TPM_RSAVerify:\n"); /* determine the signature scheme for the key */ if (rc == 0) { switch(sigScheme) { case TPM_SS_NONE: printf("TPM_RSAVerify: Error, sigScheme TPM_SS_NONE\n"); rc = TPM_INVALID_KEYUSAGE; break; case TPM_SS_RSASSAPKCS1v15_SHA1: case TPM_SS_RSASSAPKCS1v15_INFO: rc = TPM_RSAVerifySHA1(signature, signature_size, message, message_size, narr, /* public modulus */ nbytes, earr, /* public exponent */ ebytes); break; case TPM_SS_RSASSAPKCS1v15_DER: printf("TPM_RSAVerify: Error, sigScheme %04hx unsupported\n", sigScheme); rc = TPM_INVALID_KEYUSAGE; break; default: printf("TPM_RSAVerify: Error, sigScheme %04hx unknown\n", sigScheme); rc = TPM_INVALID_KEYUSAGE; break; } } return rc; } /* OAEP Padding */ /* TPM_RSA_padding_add_PKCS1_OAEP() is a variation of the the openSSL function int RSA_padding_add_PKCS1_OAEP(unsigned char *to, int tlen, unsigned char *f, int fl, unsigned char *p, int pl); It is used for TPM migration. The "encoding parameter" pl is replaced by pHash and the generated random seed is replaced by a seed parameter. This function was independently written from the PKCS1 specification "9.1.1.1 Encoding Operation", intended to be unencumbered by any license. | seed | pHash | PS | 01 | Message | SHA1 SHA1 flen | <- emLen -> | | db | maskDb | dbMask | | seedMask | maskSeed */ TPM_RESULT TPM_RSA_padding_add_PKCS1_OAEP(unsigned char *em, uint32_t emLen, const unsigned char *from, uint32_t fLen, const unsigned char *pHash, /* input 20 bytes */ const unsigned char *seed) /* input 20 bytes */ { TPM_RESULT rc = 0; unsigned char *dbMask; unsigned char *db; unsigned char *maskedDb; unsigned char *seedMask; unsigned char *maskedSeed; printf(" TPM_RSA_padding_add_PKCS1_OAEP: fLen %d emLen %d\n", fLen, emLen); TPM_PrintFourLimit(" TPM_RSA_padding_add_PKCS1_OAEP: from", from, fLen); TPM_PrintFour(" TPM_RSA_padding_add_PKCS1_OAEP: pHash", pHash); TPM_PrintFour(" TPM_RSA_padding_add_PKCS1_OAEP: seed", seed); dbMask = NULL; /* freed @1 */ /* 1. If the length of P is greater than the input limitation for */ /* the hash function (2^61-1 octets for SHA-1) then output "parameter */ /* string too long" and stop. */ /* NOTE Not done, pHash is input directly */ /* 2. If ||M|| > emLen-2hLen-1 then output "message too long" and stop. */ if (rc == 0) { if (emLen < ((2 * TPM_DIGEST_SIZE) + 1 + fLen)) { printf("TPM_RSA_padding_add_PKCS1_OAEP: Error, " "message length %u too large for encoded length %u\n", fLen, emLen); rc = TPM_ENCRYPT_ERROR; } } /* 3. Generate an octet string PS consisting of emLen-||M||-2hLen-1 zero octets. The length of PS may be 0. */ /* NOTE Created directly in DB (step 5) */ /* 4. Let pHash = Hash(P), an octet string of length hLen. */ /* NOTE pHash is input directly */ /* 5. Concatenate pHash, PS, the message M, and other padding to form a data block DB as: DB = pHash || PS || 01 || M */ if (rc == 0) { /* NOTE Since db is eventually maskedDb, part of em, create directly in em */ db = em + TPM_DIGEST_SIZE; memcpy(db, pHash, TPM_DIGEST_SIZE); /* pHash */ memset(db + TPM_DIGEST_SIZE, 0, /* PS */ emLen - fLen - (2 * TPM_DIGEST_SIZE) - 1); /* PSlen = emlen - flen - (2 * TPM_DIGEST_SIZE) - 1 0x01 index = TPM_DIGEST_SIZE + PSlen = TPM_DIGEST_SIZE + emlen - flen - (2 * TPM_DIGEST_SIZE) - 1 = emlen - fLen - TPM_DIGEST_SIZE - 1 */ db[emLen - fLen - TPM_DIGEST_SIZE - 1] = 0x01; memcpy(db + emLen - fLen - TPM_DIGEST_SIZE, from, fLen); /* M */ /* 6. Generate a random octet string seed of length hLen. */ /* NOTE seed is input directly */ /* 7. Let dbMask = MGF(seed, emLen-hLen). */ rc = TPM_Malloc(&dbMask, emLen - TPM_DIGEST_SIZE); } if (rc == 0) { rc = TPM_MGF1(dbMask, emLen - TPM_DIGEST_SIZE, seed, TPM_DIGEST_SIZE); } if (rc == 0) { /* 8. Let maskedDB = DB \xor dbMask. */ /* NOTE Since maskedDB is eventually em, XOR directly to em */ maskedDb = em + TPM_DIGEST_SIZE; TPM_XOR(maskedDb, db, dbMask, emLen - TPM_DIGEST_SIZE); /* 9. Let seedMask = MGF(maskedDB, hLen). */ /* NOTE Since seedMask is eventually em, create directly to em */ seedMask = em; rc = TPM_MGF1(seedMask, TPM_DIGEST_SIZE, maskedDb, emLen - TPM_DIGEST_SIZE); } if (rc == 0) { /* 10. Let maskedSeed = seed \xor seedMask. */ /* NOTE Since maskedSeed is eventually em, create directly to em */ maskedSeed = em; TPM_XOR(maskedSeed, seed, seedMask, TPM_DIGEST_SIZE); /* 11. Let EM = maskedSeed || maskedDB. */ /* NOTE Created directly in em */ /* 12. Output EM. */ TPM_PrintFourLimit(" TPM_RSA_padding_add_PKCS1_OAEP: em", em, emLen); } free(dbMask); /* @1 */ return rc; } /* TPM_RSA_padding_check_PKCS1_OAEP() is a variation of the openSSL function int RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen, unsigned char *f, int fl, int rsa_len, unsigned char *p, int pl); It is used for TPM key migration. In addition to the message 'to' and message length 'tlen', the seed and 'pHash are returned. This function was independently written from the PKCS1 specification "9.1.1.2 Decoding Operation", intended to be unencumbered by the any license. | seed | pHash | PS | 01 | Message | SHA1 SHA1 | <- emLen -> | | maskedSeed | seedMask | maskedDB | db | <- dbMask -> | */ TPM_RESULT TPM_RSA_padding_check_PKCS1_OAEP(unsigned char *to, uint32_t *tLen, uint32_t tSize, const unsigned char *em, uint32_t emLen, unsigned char *pHash, /* output 20 bytes */ unsigned char *seed) /* output 20 bytes */ { TPM_RESULT rc = 0; const unsigned char *maskedSeed; const unsigned char *maskedDB; uint32_t dbLen; unsigned char *dbMask; unsigned char *seedMask; unsigned char *db; size_t i; printf(" TPM_RSA_padding_check_PKCS1_OAEP: emLen %d tSize %d\n", emLen, tSize); TPM_PrintFourLimit(" TPM_RSA_padding_check_PKCS1_OAEP: em", em, emLen); dbMask = NULL; /* freed @1 */ /* 1. If the length of P is greater than the input limitation for the hash function (2^61-1 octets for SHA-1) then output "parameter string too long" and stop. */ /* NOTE There is no P input. pHash is calculated for the output, but no comparison is performed. */ /* 2. If ||EM|| < 2hLen+1, then output "decoding error" and stop. */ if (rc == 0) { if (emLen < (2 * TPM_DIGEST_SIZE) + 1) { printf("TPM_RSA_padding_check_PKCS1_OAEP: Error, encoded length %u too small\n", emLen); rc = TPM_DECRYPT_ERROR; } } if (rc == 0) { /* 3. Let maskedSeed be the first hLen octets of EM and let maskedDB be the remaining ||EM|| - hLen octets. */ maskedSeed = em; maskedDB = em + TPM_DIGEST_SIZE; dbLen = emLen - TPM_DIGEST_SIZE; /* 4. Let seedMask = MGF(maskedDB, hLen). */ /* NOTE Created directly in seed */ seedMask = seed; rc = TPM_MGF1(seedMask, TPM_DIGEST_SIZE, maskedDB, dbLen); } if (rc == 0) { /* 5. Let seed = maskedSeed \xor seedMask. */ TPM_XOR(seed, maskedSeed, seedMask, TPM_DIGEST_SIZE); /* 6. Let dbMask = MGF(seed, ||EM|| - hLen). */ rc = TPM_Malloc(&dbMask, dbLen); } if (rc == 0) { rc = TPM_MGF1(dbMask, dbLen, seed, TPM_DIGEST_SIZE); } if (rc == 0) { /* 7. Let DB = maskedDB \xor dbMask. */ /* NOTE XOR back to dbMask, since dbMask no longer needed */ db = dbMask; TPM_XOR(db, maskedDB, dbMask, dbLen); /* 8. Let pHash = Hash(P), an octet string of length hLen. */ /* NOTE pHash is input directly */ /* 9. Separate DB into an octet string pHash' consisting of the first hLen octets of DB, ... */ memcpy(pHash, db, TPM_DIGEST_SIZE); /* ... a (possibly empty) octet string PS consisting of consecutive zero octets following pHash', and a message M as: DB = pHash' || PS || 01 || M */ for (i = TPM_DIGEST_SIZE; i < dbLen; i++) { if (db[i] != 0x00) { break; /* skip the PS segment */ } } /* If there is no 01 octet to separate PS from M, output "decoding error" and stop. */ if (i == dbLen) { printf("TPM_RSA_padding_check_PKCS1_OAEP: Error, missing 0x01\n"); rc = TPM_DECRYPT_ERROR; } } if (rc == 0) { if (db[i] != 0x01) { printf("TPM_RSA_padding_check_PKCS1_OAEP: Error, missing 0x01\n"); rc = TPM_DECRYPT_ERROR; } } /* 10. If pHash' does not equal pHash, output "decoding error" and stop. */ /* NOTE No pHash input to compare */ /* 11. Output M. */ if (rc == 0) { i++; /* skip the 0x01 to the beginning of the message M */ *tLen = dbLen - i; if (*tLen > tSize) { printf("TPM_RSA_padding_check_PKCS1_OAEP: Error, tSize %u too small for message %u\n", tSize, *tLen); rc = TPM_DECRYPT_ERROR; } } if (rc == 0) { memcpy(to, db + i, *tLen); printf(" TPM_RSA_padding_check_PKCS1_OAEP: tLen %d \n", *tLen); TPM_PrintFourLimit(" TPM_RSA_padding_check_PKCS1_OAEP: to", to, *tLen); TPM_PrintFour(" TPM_RSA_padding_check_PKCS1_OAEP: pHash", pHash); TPM_PrintFour(" TPM_RSA_padding_check_PKCS1_OAEP: seed", seed); } free(dbMask); /* @1 */ return rc; } /* TPM_RSA_exponent_verify() validates the public exponent against a list of legal values. Some values (e.g. even numbers) will have the key generator. */ TPM_RESULT TPM_RSA_exponent_verify(unsigned long exponent) { TPM_RESULT rc = 0; size_t i; int found; static const unsigned long legalExponent[] = { 3,5,7,17,257,65537 }; for (i = 0, found = FALSE ; !found && (i < (sizeof(legalExponent) / sizeof (unsigned long))) ; i++) { if (exponent == legalExponent[i]) { found = TRUE; } } if (!found) { printf("TPM_RSA_exponent_verify: Error, public exponent %lu is illegal\n", exponent ); rc = TPM_BAD_KEY_PROPERTY; } return rc; } /* SHA1 and HMAC test driver Returns TPM_FAILEDSELFTEST on error */ TPM_RESULT TPM_CryptoTest(void) { TPM_RESULT rc = 0; int not_equal; TPM_BOOL valid; /* SHA1 */ unsigned char buffer1[] = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; unsigned char expect1[] = {0x84,0x98,0x3E,0x44,0x1C, 0x3B,0xD2,0x6E,0xBA,0xAE, 0x4A,0xA1,0xF9,0x51,0x29, 0xE5,0xE5,0x46,0x70,0xF1}; TPM_DIGEST actual; uint32_t actual_size; /* HMAC */ unsigned char key2[] = {0xaa,0xaa,0xaa,0xaa,0xaa, 0xaa,0xaa,0xaa,0xaa,0xaa, 0xaa,0xaa,0xaa,0xaa,0xaa, 0xaa,0xaa,0xaa,0xaa,0xaa}; unsigned char expect2[] = {0x12,0x5d,0x73,0x42,0xb9,0xac,0x11,0xcd,0x91,0xa3, 0x9a,0xf4,0x8a,0xa1,0x7b,0x4f,0x63,0xf1,0x75,0xd3}; /* data 0xdd repeated 50 times */ unsigned char data2[50]; /* oaep tests */ const unsigned char oaep_pad_str[] = { 'T', 'C', 'P', 'A' }; unsigned char pHash_in[TPM_DIGEST_SIZE]; unsigned char pHash_out[TPM_DIGEST_SIZE]; unsigned char seed_in[TPM_DIGEST_SIZE] = {0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, 0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff, 0xf0,0xf1,0xf2,0xf3}; unsigned char seed_out[TPM_DIGEST_SIZE]; unsigned char oaep_in[8] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07}; unsigned char oaep_pad[256]; unsigned char oaep_out[8]; uint32_t oeap_length; /* symmetric key with pad */ TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_data = NULL; /* opaque structure, freed @7 */ unsigned char clrStream[64]; /* expected */ unsigned char *encStream; /* encrypted */ uint32_t encSize; unsigned char *decStream; /* actual */ uint32_t decSize; /* symmetric key ctr and ofb mode */ TPM_SECRET symKey; TPM_NONCE pad; /* CTR or IV */ TPM_ENCAUTH symClear; TPM_ENCAUTH symEnc; TPM_ENCAUTH symDec; /* RSA encrypt and decrypt, sign and verify */ unsigned char *n; /* public key - modulus */ unsigned char *p; /* private key prime */ unsigned char *q; /* private key prime */ unsigned char *d; /* private key (private exponent) */ unsigned char encrypt_data[2048/8]; /* encrypted data */ unsigned char signature[2048/8]; /* signature; libtpms added */ printf(" TPM_CryptoTest:\n"); encStream = NULL; /* freed @1 */ decStream = NULL; /* freed @2 */ n = NULL; /* freed @3 */ p = NULL; /* freed @4 */ q = NULL; /* freed @5 */ d = NULL; /* freed @6 */ if (rc == 0) { printf(" TPM_CryptoTest: Test 1 - SHA1 one part\n"); rc = TPM_SHA1(actual, sizeof(buffer1) - 1, buffer1, 0, NULL); } if (rc == 0) { not_equal = memcmp(expect1, actual, TPM_DIGEST_SIZE); if (not_equal) { printf("TPM_CryptoTest: Error in test 1\n"); TPM_PrintFour("\texpect", expect1); TPM_PrintFour("\tactual", actual); rc = TPM_FAILEDSELFTEST; } } if (rc == 0) { printf(" TPM_CryptoTest: Test 2 - SHA1 two parts\n"); rc = TPM_SHA1(actual, 16, buffer1, /* first 16 */ sizeof(buffer1) - 17, buffer1 + 16, /* rest */ 0, NULL); } if (rc == 0) { not_equal = memcmp(expect1, actual, TPM_DIGEST_SIZE); if (not_equal) { printf("TPM_CryptoTest: Error in test 2\n"); TPM_PrintFour("\texpect", expect1); TPM_PrintFour("\tactual", actual); rc = TPM_FAILEDSELFTEST; } } if (rc == 0) { printf(" TPM_CryptoTest: Test 3 - HMAC generate - one part\n"); memset(data2, 0xdd, 50); rc = TPM_HMAC_Generate(actual, key2, 50, data2, 0, NULL); } if (rc == 0) { not_equal = memcmp(expect2, actual, TPM_DIGEST_SIZE); if (not_equal) { printf("TPM_CryptoTest: Error in test 3\n"); TPM_PrintFour("\texpect", expect1); TPM_PrintFour("\tactual", actual); rc = TPM_FAILEDSELFTEST; } } if (rc == 0) { printf(" TPM_CryptoTest: Test 4 - HMAC generate - two parts\n"); memset(data2, 0xdd, 50); rc = TPM_HMAC_Generate(actual, key2, 20, data2, 30, data2 + 20, 0, NULL); } if (rc == 0) { not_equal = memcmp(expect2, actual, TPM_DIGEST_SIZE); if (not_equal) { printf("TPM_CryptoTest: Error in test 3\n"); TPM_PrintFour("\texpect", expect2); TPM_PrintFour("\tactual", actual); rc = TPM_FAILEDSELFTEST; } } if (rc == 0) { printf(" TPM_CryptoTest: Test 4 - HMAC check - two parts\n"); memset(data2, 0xdd, 50); rc = TPM_HMAC_Check(&valid, expect2, key2, 20, data2, 30, data2 + 20, 0, NULL); } if (rc == 0) { if (!valid) { printf("TPM_CryptoTest: Error in test 4\n"); TPM_PrintFour("\texpect", expect1); TPM_PrintFour("\tactual", actual); rc = TPM_FAILEDSELFTEST; } } if (rc == 0) { printf(" TPM_CryptoTest: Test 5 - OAEP add and check\n"); rc = TPM_SHA1(pHash_in, sizeof(oaep_pad_str), oaep_pad_str, 0, NULL); } if (rc == 0) { rc = TPM_RSA_padding_add_PKCS1_OAEP(oaep_pad, sizeof(oaep_pad), oaep_in, sizeof(oaep_in), pHash_in, seed_in); } if (rc == 0) { rc = TPM_RSA_padding_check_PKCS1_OAEP(oaep_out, &oeap_length, sizeof(oaep_out), oaep_pad, sizeof(oaep_pad), pHash_out, seed_out); } if (rc == 0) { if (oeap_length != sizeof(oaep_out)) { printf("TPM_CryptoTest: Error in test 5, expect length %lu, actual length %u\n", (unsigned long)sizeof(oaep_out), oeap_length); rc = TPM_FAILEDSELFTEST; } } if (rc == 0) { not_equal = memcmp(oaep_in, oaep_out, sizeof(oaep_out)); if (not_equal) { printf("TPM_CryptoTest: Error in test 5 oaep\n"); TPM_PrintFour("\tin ", oaep_in); TPM_PrintFour("\tout", oaep_out); rc = TPM_FAILEDSELFTEST; } } if (rc == 0) { not_equal = memcmp(pHash_in, pHash_out, sizeof(pHash_in)); if (not_equal) { printf("TPM_CryptoTest: Error in test 5 pHash\n"); TPM_PrintFour("\tpHash_in ", pHash_in); TPM_PrintFour("\tpHash_out", pHash_out); rc = TPM_FAILEDSELFTEST; } } if (rc == 0) { not_equal = memcmp(seed_in, seed_out, sizeof(seed_in)); if (not_equal) { printf("TPM_CryptoTest: Error in test 5 seed\n"); TPM_PrintFour("\tseed_in ", seed_in); TPM_PrintFour("\tseed_out", seed_out); rc = TPM_FAILEDSELFTEST; } } if (rc == 0) { printf(" TPM_CryptoTest: Test 6 - Symmetric key with PKCS pad test\n"); /* allocate memory for the key token */ rc = TPM_SymmetricKeyData_New(&tpm_symmetric_key_data); /* freed @7 */ } /* generate a key */ if (rc == 0) { rc = TPM_SymmetricKeyData_GenerateKey(tpm_symmetric_key_data); } /* generate clear text */ if (rc == 0) { rc = TPM_Random(clrStream, sizeof(clrStream)); } /* symmetric encrypt */ if (rc == 0) { rc = TPM_SymmetricKeyData_Encrypt(&encStream, /* output, freed @1 */ &encSize, /* output */ clrStream, /* input */ sizeof(clrStream), /* input */ tpm_symmetric_key_data); /* key */ } /* symmetric decrypt */ if (rc == 0) { rc = TPM_SymmetricKeyData_Decrypt(&decStream, /* output, freed by caller */ &decSize, /* output */ encStream, /* input */ encSize, /* input */ tpm_symmetric_key_data); /* key */ } /* symmetric compare */ if (rc == 0) { if (sizeof(clrStream) != decSize) { printf("TPM_CryptoTest: Error in test 6, in %lu, out %u\n", (unsigned long)sizeof(clrStream), decSize); rc = TPM_FAILEDSELFTEST; } } if (rc == 0) { not_equal = memcmp(clrStream, decStream, sizeof(clrStream)); if (not_equal) { printf("TPM_CryptoTest: Error in test 6\n"); TPM_PrintFour("\tclear stream in", clrStream); TPM_PrintFour("\tdecrypted stream", decStream); rc = TPM_FAILEDSELFTEST; } } if (rc == 0) { printf(" TPM_CryptoTest: Test 7 - Symmetric key with CTR mode\n"); /* generate a key */ rc = TPM_Random(symKey, TPM_SECRET_SIZE); } /* generate CTR */ if (rc == 0) { rc = TPM_Random(pad, TPM_NONCE_SIZE); } /* generate clear text */ if (rc == 0) { rc = TPM_Random(symClear, TPM_AUTHDATA_SIZE); } if (rc == 0) { rc = TPM_SymmetricKeyData_CtrCrypt(symEnc, /* output */ symClear, /* input */ TPM_AUTHDATA_SIZE, /* input */ symKey, /* in */ TPM_SECRET_SIZE, /* in */ pad, /* input */ TPM_NONCE_SIZE); /* input */ } if (rc == 0) { rc = TPM_SymmetricKeyData_CtrCrypt(symDec, /* output */ symEnc, /* input */ TPM_AUTHDATA_SIZE, /* input */ symKey, /* in */ TPM_SECRET_SIZE, /* in */ pad, /* input */ TPM_NONCE_SIZE); /* input */ } /* symmetric compare */ if (rc == 0) { rc = TPM_Secret_Compare(symDec, symClear); if (rc != 0) { printf("TPM_CryptoTest: Error in test 8\n"); TPM_PrintFour("\tclear stream in", symClear); TPM_PrintFour("\tdecrypted stream", symDec); } } if (rc == 0) { printf(" TPM_CryptoTest: Test 8 - Symmetric key with OFB mode\n"); /* generate a key */ rc = TPM_Random(symKey, TPM_SECRET_SIZE); } /* generate IV */ if (rc == 0) { rc = TPM_Random(pad, TPM_NONCE_SIZE); } /* generate clear text */ if (rc == 0) { rc = TPM_Random(symClear, TPM_AUTHDATA_SIZE); } if (rc == 0) { rc = TPM_SymmetricKeyData_OfbCrypt(symEnc, /* output */ symClear, /* input */ TPM_AUTHDATA_SIZE, /* input */ symKey, /* in */ TPM_SECRET_SIZE, /* in */ pad, /* input */ TPM_NONCE_SIZE); /* input */ } if (rc == 0) { rc = TPM_SymmetricKeyData_OfbCrypt(symDec, /* output */ symEnc, /* input */ TPM_AUTHDATA_SIZE, /* input */ symKey, /* in */ TPM_SECRET_SIZE, /* in */ pad, /* input */ TPM_NONCE_SIZE); /* input */ } /* symmetric compare */ if (rc == 0) { rc = TPM_Secret_Compare(symDec, symClear); if (rc != 0) { printf("TPM_CryptoTest: Error in test 8\n"); TPM_PrintFour("\tclear stream in", symClear); TPM_PrintFour("\tdecrypted stream", symDec); } } /* RSA OAEP encrypt and decrypt */ if (rc == 0) { printf(" TPM_CryptoTest: Test 9 - RSA encrypt with OAEP padding\n"); /* generate a key */ rc = TPM_RSAGenerateKeyPair(&n, /* public key - modulus */ &p, /* private key prime */ &q, /* private key prime */ &d, /* private key (private exponent) */ 2048, /* key size in bits */ tpm_default_rsa_exponent, /* public exponent as an array */ 3); } /* encrypt */ if (rc == 0) { rc = TPM_RSAPublicEncrypt(encrypt_data, /* encrypted data */ sizeof(encrypt_data), /* size of encrypted data buffer */ TPM_ES_RSAESOAEP_SHA1_MGF1, /* TPM_ENC_SCHEME */ expect1, /* decrypted data */ sizeof(expect1), n, /* public modulus */ 2048/8, tpm_default_rsa_exponent, /* public exponent */ 3); } if (rc == 0) { rc = TPM_RSAPrivateDecrypt(actual, /* decrypted data */ &actual_size, /* length of data put into decrypt_data */ TPM_DIGEST_SIZE, /* size of decrypt_data buffer */ TPM_ES_RSAESOAEP_SHA1_MGF1, /* TPM_ENC_SCHEME */ encrypt_data, /* encrypted data */ sizeof(encrypt_data), n, /* public modulus */ 2048/8, tpm_default_rsa_exponent, /* public exponent */ 3, d, /* private exponent */ 2048/8); } if (rc == 0) { if (actual_size != TPM_DIGEST_SIZE) { printf("TPM_CryptoTest: Error in test 9, expect length %u, actual length %u\n", TPM_DIGEST_SIZE, actual_size); rc = TPM_FAILEDSELFTEST; } } if (rc == 0) { not_equal = memcmp(expect1, actual, TPM_DIGEST_SIZE); if (not_equal) { printf("TPM_CryptoTest: Error in test 9\n"); TPM_PrintFour("\tin ", expect1); TPM_PrintFour("\tout", actual); rc = TPM_FAILEDSELFTEST; } } /* RSA PKCS1 pad, encrypt and decrypt */ if (rc == 0) { printf(" TPM_CryptoTest: Test 10 - RSA encrypt with PKCS padding\n"); /* encrypt */ rc = TPM_RSAPublicEncrypt(encrypt_data, /* encrypted data */ sizeof(encrypt_data), /* size of encrypted data buffer */ TPM_ES_RSAESPKCSv15, /* TPM_ENC_SCHEME */ expect1, /* decrypted data */ sizeof(expect1), n, /* public modulus */ 2048/8, tpm_default_rsa_exponent, /* public exponent */ 3); } /* decrypt */ if (rc == 0) { rc = TPM_RSAPrivateDecrypt(actual, /* decrypted data */ &actual_size, /* length of data put into decrypt_data */ TPM_DIGEST_SIZE, /* size of decrypt_data buffer */ TPM_ES_RSAESPKCSv15, /* TPM_ENC_SCHEME */ encrypt_data, /* encrypted data */ sizeof(encrypt_data), n, /* public modulus */ 2048/8, tpm_default_rsa_exponent, /* public exponent */ 3, d, /* private exponent */ 2048/8); } /* check length after padding removed */ if (rc == 0) { if (actual_size != TPM_DIGEST_SIZE) { printf("TPM_CryptoTest: Error in test 10, expect length %u, actual length %u\n", TPM_DIGEST_SIZE, actual_size); rc = TPM_FAILEDSELFTEST; } } /* check data */ if (rc == 0) { not_equal = memcmp(expect1, actual, TPM_DIGEST_SIZE); if (not_equal) { printf("TPM_CryptoTest: Error in test 10\n"); TPM_PrintFour("\tin ", expect1); TPM_PrintFour("\tout", actual); rc = TPM_FAILEDSELFTEST; } } // libtpms added begin if (rc == 0) { printf(" TPM_CryptoTest: Test 11a - RSA sign with PKCS1v15 padding\n"); rc = TPM_RSASign(signature, &actual_size, sizeof(signature), TPM_SS_RSASSAPKCS1v15_SHA1, expect1, sizeof(expect1), n, /* public modulus */ 2048/8, tpm_default_rsa_exponent, /* public exponent */ 3, d, /* private exponent */ 2048/8); } if (rc == 0) { rc = TPM_RSAVerify(signature, /* input signature buffer */ sizeof(signature), /* input, size of signature buffer */ TPM_SS_RSASSAPKCS1v15_SHA1, /* input, type of signature */ expect1, /* message */ sizeof(expect1), /* message size */ n, /* public modulus */ 2048/8, tpm_default_rsa_exponent,/* public exponent */ 3); } #if 0 /* Verification with TPM_SS_RSASSAPKCS1v15_DER is not supported */ if (rc == 0) { printf(" TPM_CryptoTest: Test 11b - RSA sign with PKCS1v15_DER padding\n"); rc = TPM_RSASign(signature, &actual_size, sizeof(signature), TPM_SS_RSASSAPKCS1v15_DER, expect1, sizeof(expect1), n, /* public modulus */ 2048/8, tpm_default_rsa_exponent, /* public exponent */ 3, d, /* private exponent */ 2048/8); } if (rc == 0) { rc = TPM_RSAVerify(signature, /* input signature buffer */ sizeof(signature), /* input, size of signature buffer */ TPM_SS_RSASSAPKCS1v15_DER, /* input, type of signature */ expect1, /* message */ sizeof(expect1), /* message size */ n, /* public modulus */ 2048/8, tpm_default_rsa_exponent,/* public exponent */ 3); } #endif // libtpms added end /* run library specific self tests as required */ if (rc == 0) { rc = TPM_Crypto_TestSpecific(); } if (rc != 0) { rc = TPM_FAILEDSELFTEST; } free(encStream); /* @1 */ free(decStream); /* @2 */ free(n); /* @3 */ free(p); /* @4 */ free(q); /* @5 */ free(d); /* @6 */ TPM_SymmetricKeyData_Free(&tpm_symmetric_key_data); /* @7 */ return rc; } /* 13.5 TPM_Sign rev 111 The Sign command signs data and returns the resulting digital signature. The TPM does not allow TPM_Sign with a TPM_KEY_IDENTITY (AIK) because TPM_Sign can sign arbitrary data and could be used to fake a quote. (This could have been relaxed to allow TPM_Sign with an AIK if the signature scheme is _INFO For an _INFO key, the metadata prevents TPM_Sign from faking a quote.) The TPM MUST support all values of areaToSignSize that are legal for the defined signature scheme and key size. The maximum value of areaToSignSize is determined by the defined signature scheme and key size. In the case of PKCS1v15_SHA1 the areaToSignSize MUST be TPM_DIGEST (the hash size of a sha1 operation - see 8.5.1 TPM_SS_RSASSAPKCS1v15_SHA1). In the case of PKCS1v15_DER the maximum size of areaToSign is k - 11 octets, where k is limited by the key size (see 8.5.2 TPM_SS_RSASSAPKCS1v15_DER). */ TPM_RESULT TPM_Process_Sign(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_KEY_HANDLE keyHandle; /* The keyHandle identifier of a loaded key that can perform digital signatures. */ TPM_SIZED_BUFFER areaToSign; /* The value to sign */ TPM_AUTHHANDLE authHandle; /* The authorization handle used for keyHandle authorization */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization handle */ TPM_AUTHDATA privAuth; /* The authorization digest that authorizes the use of keyHandle. HMAC key: key.usageAuth */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus ; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_SECRET *hmacKey; TPM_KEY *key = NULL; /* the key specified by keyHandle */ TPM_RSA_KEY_PARMS *rsa_key_parms; /* for key */ TPM_BOOL parentPCRStatus; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ TPM_SECRET *keyUsageAuth; TPM_SIGN_INFO tpm_sign_info; const unsigned char *S1_data; /* data to be signed */ uint32_t S1_size; TPM_DIGEST infoDigest; /* TPM_SIGN_INFO structure digest */ TPM_STORE_BUFFER sbuffer; /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_SIZED_BUFFER sig; /* The resulting digital signature. */ printf("TPM_Process_Sign: Ordinal Entry\n"); TPM_SizedBuffer_Init(&areaToSign); /* freed @1 */ TPM_SignInfo_Init(&tpm_sign_info); /* freed @2 */ TPM_Sbuffer_Init(&sbuffer); /* freed @3 */ TPM_SizedBuffer_Init(&sig); /* freed @4 */ /* get inputs */ /* get keyHandle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&keyHandle, &command, ¶mSize); } /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; if (returnCode == TPM_SUCCESS) { printf("TPM_Process_Sign: keyHandle %08x\n", keyHandle); /* get areaToSignSize and areaToSign parameters */ returnCode = TPM_SizedBuffer_Load(&areaToSign, &command, ¶mSize); /* freed @1 */ } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_Sign: Signing %u bytes\n", areaToSign.size); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag10(tag); } /* get the optional 'below the line' authorization parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, privAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_Sign: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* get the key corresponding to the keyHandle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyHandleEntries_GetKey(&key, &parentPCRStatus, tpm_state, keyHandle, FALSE, /* not r/o, used to sign */ FALSE, /* do not ignore PCRs */ FALSE); /* cannot use EK */ } /* check TPM_AUTH_DATA_USAGE authDataUsage */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)) { if (key->authDataUsage != TPM_AUTH_NEVER) { printf("TPM_Process_Sign: Error, authorization required\n"); returnCode = TPM_AUTHFAIL; } } /* get keyHandle -> usageAuth */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_Key_GetUsageAuth(&keyUsageAuth, key); } /* get the session data */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_KEYHANDLE, ordinal, key, keyUsageAuth, /* OIAP */ key->tpm_store_asymkey->pubDataDigest); /* OSAP */ } /* 1. The TPM validates the AuthData to use the key pointed to by keyHandle. */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, privAuth); /* Authorization digest for input */ } /* 2. If the areaToSignSize is 0 the TPM returns TPM_BAD_PARAMETER. */ if (returnCode == TPM_SUCCESS) { if (areaToSign.size == 0) { printf("TPM_Process_Sign: Error, areaToSignSize is 0\n"); returnCode = TPM_BAD_PARAMETER; } } /* 3. Validate that keyHandle -> keyUsage is TPM_KEY_SIGNING or TPM_KEY_LEGACY, if not return the error code TPM_INVALID_KEYUSAGE */ if (returnCode == TPM_SUCCESS) { if ((key->keyUsage != TPM_KEY_SIGNING) && ((key->keyUsage) != TPM_KEY_LEGACY)) { printf("TPM_Process_Sign: Error, keyUsage %04hx is invalid\n", key->keyUsage); returnCode = TPM_INVALID_KEYUSAGE; } } /* 4. The TPM verifies that the signature scheme and key size can properly sign the areaToSign parameter. NOTE Done in 5. - 7.*/ /* get key -> TPM_RSA_KEY_PARMS */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyParms_GetRSAKeyParms(&rsa_key_parms, &(key->algorithmParms)); } if (returnCode == TPM_SUCCESS) { /* 5. If signature scheme is TPM_SS_RSASSAPKCS1v15_SHA1 then */ if (key->algorithmParms.sigScheme == TPM_SS_RSASSAPKCS1v15_SHA1) { printf("TPM_Process_Sign: sigScheme is TPM_SS_RSASSAPKCS1v15_SHA1\n"); /* a. Validate that areaToSignSize is 20 return TPM_BAD_PARAMETER on error */ if (returnCode == TPM_SUCCESS) { if (areaToSign.size != TPM_DIGEST_SIZE) { printf("TPM_Process_Sign: Error, areaToSignSize %d should be %u\n", areaToSign.size, TPM_DIGEST_SIZE); returnCode = TPM_BAD_PARAMETER; } } /* b. Set S1 to areaToSign */ if (returnCode == TPM_SUCCESS) { S1_size = areaToSign.size; S1_data = areaToSign.buffer; } } /* 6. Else if signature scheme is TPM_SS_RSASSAPKCS1v15_DER then */ else if (key->algorithmParms.sigScheme == TPM_SS_RSASSAPKCS1v15_DER) { printf("TPM_Process_Sign: sigScheme is TPM_SS_RSASSAPKCS1v15_DER\n"); /* a. Validate that areaToSignSize is at least 11 bytes less than the key size, return TPM_BAD_PARAMETER on error */ if (returnCode == TPM_SUCCESS) { if (areaToSign.size > (((rsa_key_parms->keyLength)/CHAR_BIT) - 11)) { printf("TPM_Process_Sign: Error, areaToSignSize %d should be 11-%u\n", areaToSign.size, ((rsa_key_parms->keyLength)/CHAR_BIT)); returnCode = TPM_BAD_PARAMETER; } } /* b. Set S1 to areaToSign */ if (returnCode == TPM_SUCCESS) { S1_size = areaToSign.size; S1_data = areaToSign.buffer; } } /* 7. else if signature scheme is TPM_SS_RSASSAPKCS1v15_INFO then */ else if (key->algorithmParms.sigScheme == TPM_SS_RSASSAPKCS1v15_INFO) { printf("TPM_Process_Sign: sigScheme is TPM_SS_RSASSAPKCS1v15_INFO\n"); if (returnCode == TPM_SUCCESS) { /* a. Create S2 a TPM_SIGN_INFO structure */ /* NOTE: Done by TPM_SignInfo_Init() */ /* b. Set S2 -> fixed to "SIGN" */ memcpy(tpm_sign_info.fixed, "SIGN", TPM_SIGN_INFO_FIXED_SIZE); /* c.i. If nonceOdd is not present due to an unauthorized command return TPM_BAD_PARAMETER */ if (tag == TPM_TAG_RQU_COMMAND) { printf("TPM_Process_Sign: Error, TPM_SS_RSASSAPKCS1v15_INFO and no auth\n"); returnCode = TPM_BAD_PARAMETER; } } if (returnCode == TPM_SUCCESS) { /* c. Set S2 -> replay to nonceOdd */ TPM_Nonce_Copy(tpm_sign_info.replay, nonceOdd); /* d. Set S2 -> dataLen to areaToSignSize */ /* e. Set S2 -> data to areaToSign */ returnCode = TPM_SizedBuffer_Copy(&(tpm_sign_info.data), &areaToSign); } /* f. Set S1 to the SHA-1(S2) */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SHA1_GenerateStructure(infoDigest, &tpm_sign_info, (TPM_STORE_FUNCTION_T)TPM_SignInfo_Store); S1_size = TPM_DIGEST_SIZE; S1_data = infoDigest; } } /* 8. Else return TPM_INVALID_KEYUSAGE */ else { printf("TPM_Process_Sign: Error, sigScheme %04hx\n", key->algorithmParms.sigScheme); returnCode = TPM_INVALID_KEYUSAGE; } } /* 9. The TPM computes the signature, sig, using the key referenced by keyHandle using S1 as the value to sign */ if (returnCode == TPM_SUCCESS) { TPM_PrintAll("TPM_Process_Sign: Digest to sign", S1_data, S1_size); returnCode = TPM_RSASignToSizedBuffer(&sig, /* signature */ S1_data, /* message */ S1_size, /* message size */ key); /* input, signing key */ } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_Sign: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* 10. Return the computed signature in Sig */ returnCode = TPM_SizedBuffer_Store(response, &sig); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* owner HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ TPM_SizedBuffer_Delete(&areaToSign); /* @1 */ TPM_SignInfo_Delete(&tpm_sign_info); /* @2 */ TPM_Sbuffer_Delete(&sbuffer); /* @3 */ TPM_SizedBuffer_Delete(&sig); /* @4 */ return rcf; } /* 13.1 TPM_SHA1Start rev 96 This capability starts the process of calculating a SHA-1 digest. The exposure of the SHA-1 processing is a convenience to platforms in a mode that do not have sufficient memory to perform SHA-1 themselves. As such the use of SHA-1 is restrictive on the TPM. The TPM may not allow any other types of processing during the execution of a SHA-1 session. There is only one SHA-1 session active on a TPM. The exclusivity of a SHA-1 context is due to the relatively large volatile buffer it requires in order to hold the intermediate results between the SHA-1 context commands. This buffer can be in contradiction to other command needs. After the execution of SHA1Start, and prior to SHA1End, the receipt of any command other than SHA1Update will cause the invalidation of the SHA-1 session. */ TPM_RESULT TPM_Process_SHA1Start(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters - none */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; uint32_t maxNumBytes = TPM_SHA1_MAXNUMBYTES; /* Maximum number of bytes that can be sent to TPM_SHA1Update. Must be a multiple of 64 bytes. */ printf("TPM_Process_SHA1Start: Ordinal Entry\n"); /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | TPM_CHECK_NO_LOCKOUT)); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_SHA1Start: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ /* This capability prepares the TPM for a subsequent TPM_SHA1Update, TPM_SHA1Complete or TPM_SHA1CompleteExtend command. The capability SHALL open a thread that calculates a SHA-1 digest. */ if (returnCode == TPM_SUCCESS) { if (transportInternal == NULL) { tpm_state->transportHandle = 0; /* SHA-1 thread not within transport */ } else { tpm_state->transportHandle = transportInternal->transHandle; /* SHA-1 thread within transport */ } returnCode = TPM_SHA1InitCmd(&(tpm_state->sha1_context)); } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_SHA1Start: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* append maxNumBytes */ returnCode = TPM_Sbuffer_Append32(response, maxNumBytes); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } return rcf; } /* 13.2 TPM_SHA1Update rev 114 This capability inputs complete blocks of data into a pending SHA-1 digest. At the end of the process, the digest remains pending. */ TPM_RESULT TPM_Process_SHA1Update(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_SIZED_BUFFER hashData; /* Bytes to be hashed */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_SHA1Update: Ordinal Entry\n"); TPM_SizedBuffer_Init(&hashData); /* freed @1 */ /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* load hashData */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_Load(&hashData, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | TPM_CHECK_NO_LOCKOUT)); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_SHA1Update: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ /* This command SHALL incorporate complete blocks of data into the digest of an existing SHA-1 thread. Only integral numbers of complete blocks (64 bytes each) can be processed. */ /* 1. If there is no existing SHA-1 thread, return TPM_SHA_THREAD */ if (returnCode == TPM_SUCCESS) { if (tpm_state->sha1_context == NULL) { printf("TPM_Process_SHA1Update: Error, no existing SHA1 thread\n"); returnCode = TPM_SHA_THREAD; } } /* 2. If numBytes is not a multiple of 64 */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_SHA1Update: numBytes %u bytes\n", hashData.size); if ((hashData.size % 64) != 0) { printf("TPM_Process_SHA1Update: Error, numBytes not integral number of blocks\n"); /* a. Return TPM_SHA_ERROR */ returnCode = TPM_SHA_ERROR; /* b. The TPM MAY terminate the SHA-1 thread */ TPM_SHA1Delete(&(tpm_state->sha1_context)); } } /* 3. If numBytes is greater than maxNumBytes returned by TPM_SHA1Start */ if (returnCode == TPM_SUCCESS) { if (hashData.size > TPM_SHA1_MAXNUMBYTES) { /* a. Return TPM_SHA_ERROR */ returnCode = TPM_SHA_ERROR; /* b. The TPM MAY terminate the SHA-1 thread */ TPM_SHA1Delete(&(tpm_state->sha1_context)); } } /* 4. Incorporate hashData into the digest of the existing SHA-1 thread. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SHA1UpdateCmd(tpm_state->sha1_context, hashData.buffer, hashData.size); } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_SHA1Update: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* cleanup */ TPM_SizedBuffer_Delete(&hashData); /* @1 */ return rcf; } /* 13.3 TPM_SHA1Complete rev 87 This capability terminates a pending SHA-1 calculation. */ TPM_RESULT TPM_Process_SHA1Complete(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_SIZED_BUFFER hashData; /* Final bytes to be hashed */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_DIGEST hashValue; /* The output of the SHA-1 hash. */ TPM_SizedBuffer_Init(&hashData); /* freed @1 */ printf("TPM_Process_SHA1Complete: Ordinal Entry\n"); /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* load hashData */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_Load(&hashData, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | TPM_CHECK_NO_LOCKOUT)); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_SHA1Complete: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ /* This command SHALL incorporate a partial or complete block of data into the digest of an existing SHA-1 thread, and terminate that thread. hashDataSize MAY have values in the range of 0 through 64, inclusive. If the SHA-1 thread has received no bytes the TPM SHALL calculate the SHA-1 of the empty buffer. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SHA1CompleteCommon(hashValue, &(tpm_state->sha1_context), &hashData); } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_SHA1Complete: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* append hashValue */ returnCode = TPM_Digest_Store(response, hashValue); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* cleanup */ TPM_SizedBuffer_Delete(&hashData); /* @1 */ return rcf; } /* 13.4 TPM_SHA1CompleteExtend rev 109 This capability terminates a pending SHA-1 calculation and EXTENDS the result into a Platform Configuration Register using a SHA-1 hash process. This command is designed to complete a hash sequence and extend a PCR in memory-less environments. This command SHALL incorporate a partial or complete block of data into the digest of an existing SHA-1 thread, EXTEND the resultant digest into a PCR, and terminate the thread. hashDataSize MAY have values in the range of 0 through 64, inclusive. */ TPM_RESULT TPM_Process_SHA1CompleteExtend(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_PCRINDEX pcrNum; /* Index of the PCR to be modified */ TPM_SIZED_BUFFER hashData; /* Final bytes to be hashed */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_DIGEST h1HashValue; /* The output of the SHA-1 hash. */ TPM_PCRVALUE outDigest; /* The PCR value after execution of the command. */ printf("TPM_Process_SHA1CompleteExtend: Ordinal Entry\n"); TPM_SizedBuffer_Init(&hashData); /* freed @1 */ /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get pcrNum */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&pcrNum, &command, ¶mSize); } /* get hashData */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_SHA1CompleteExtend: pcrNum %u\n", pcrNum); returnCode = TPM_SizedBuffer_Load(&hashData, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | TPM_CHECK_NO_LOCKOUT)); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_SHA1CompleteExtend: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ /* 1. 1.Validate that pcrNum represents a legal PCR number. On error, return TPM_BADINDEX. */ /* 2. Map V1 to TPM_STANY_DATA */ /* 3. Map L1 to V1 -> localityModifier */ /* 4. If the current locality, held in L1, is not selected in TPM_PERMANENT_DATA -> pcrAttrib [PCRIndex]. pcrExtendLocal, return TPM_BAD_LOCALITY */ /* NOTE Done in TPM_ExtendCommon() */ /* 5. Create H1 the TPM_DIGEST of the SHA-1 session ensuring that hashData, if any, is */ /* added to the SHA-1 session */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SHA1CompleteCommon(h1HashValue, &(tpm_state->sha1_context), &hashData); } /* 6. Perform the actions of TPM_Extend using H1 as the data and pcrNum as the PCR to extend */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_ExtendCommon(outDigest, tpm_state, ordinal, pcrNum, h1HashValue); } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_SHA1CompleteExtend: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* append hashValue */ returnCode = TPM_Digest_Store(response, h1HashValue); } /* append outDigest */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Digest_Store(response, outDigest); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* cleanup */ TPM_SizedBuffer_Delete(&hashData); /* @1 */ return rcf; } /* TPM_SHA1CompleteCommon() is common code for TPM_Process_SHA1Complete() and TPM_Process_SHA1CompleteExtend() */ TPM_RESULT TPM_SHA1CompleteCommon(TPM_DIGEST hashValue, /* output: digest */ void **sha1_context, /* IO: SHA1 context */ TPM_SIZED_BUFFER *hashData) /* final data to be hashed */ { TPM_RESULT rc = 0; /* The TPM specification says that the last data chunk must be 0-64 bytes */ printf("TPM_SHA1CompleteCommon: %u bytes\n", hashData->size); if (rc == 0) { if (hashData->size > 64) { printf("TPM_SHA1CompleteCommon: Error, hashDataSize %u not 0-64\n", hashData->size); rc = TPM_SHA_ERROR; } } /* cannot call SHA1Complete() before SHA1Start() */ if (rc == 0) { if (*sha1_context == NULL) { printf("TPM_SHA1CompleteCommon: Error, no existing SHA1 thread\n"); rc = TPM_SHA_THREAD; } } if ((rc == 0) && (hashData->size != 0)) { rc = TPM_SHA1UpdateCmd(*sha1_context, hashData->buffer, hashData->size); } if (rc == 0) { rc = TPM_SHA1FinalCmd(hashValue, *sha1_context); } /* the SHA1 thread should be terminated even if there is an error */ TPM_SHA1Delete(sha1_context); return rc; } /* 13.6 TPM_GetRandom rev 87 GetRandom returns the next bytesRequested bytes from the random number generator to the caller. It is recommended that a TPM implement the RNG in a manner that would allow it to return RNG bytes such that the frequency of bytesRequested being more than the number of bytes available is an infrequent occurrence. */ TPM_RESULT TPM_Process_GetRandom(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ uint32_t bytesRequested; /* Number of bytes to return */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_SIZED_BUFFER randomBytes; /* The returned bytes */ printf("TPM_Process_GetRandom: Ordinal Entry\n"); TPM_SizedBuffer_Init(&randomBytes); /* freed @1 */ /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get bytesRequested parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&bytesRequested, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_GetRandom: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ /* 1. The TPM determines if amount bytesRequested is available from the TPM. */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_GetRandom: bytesRequested %u\n", bytesRequested); if (bytesRequested > TPM_RANDOM_MAX) { bytesRequested = TPM_RANDOM_MAX; printf("TPM_Process_GetRandom: bytes available %u\n", bytesRequested); } } /* 2. Set randomBytesSize to the number of bytes available from the RNG. This number MAY be less than bytesRequested. */ if ((returnCode == TPM_SUCCESS) && (bytesRequested > 0)) { returnCode = TPM_SizedBuffer_Allocate(&randomBytes, bytesRequested); } /* 3. Set randomBytes to the next randomBytesSize bytes from the RNG */ if ((returnCode == TPM_SUCCESS) && (bytesRequested > 0)) { returnCode = TPM_Random(randomBytes.buffer, bytesRequested); } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_GetRandom: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* append randomBytes */ returnCode = TPM_SizedBuffer_Store(response, &randomBytes); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* cleanup */ TPM_SizedBuffer_Delete(&randomBytes); /* freed @1 */ return rcf; } /* 13.7 TPM_StirRandom rev 109 StirRandom adds entropy to the RNG state. */ TPM_RESULT TPM_Process_StirRandom(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_SIZED_BUFFER inData; /* Data to add entropy to RNG state, Number of bytes of input */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_StirRandom: Ordinal Entry\n"); TPM_SizedBuffer_Init(&inData); /* freed @1 */ /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get inData parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_Load(&inData, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_StirRandom: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ /* 1. If dataSize is not less than 256 bytes, the TPM MAY return TPM_BAD_PARAMETER. */ /* The TPM updates the state of the current RNG using the appropriate mixing function. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_StirRandomCmd(&inData); } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_StirRandom: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* cleanup */ TPM_SizedBuffer_Delete(&inData); /* @1 */ return rcf; } /* 13.8 TPM_CertifyKey rev 107 The TPM_CertifyKey operation allows one key to certify the public portion of another key. A TPM identity key may be used to certify non-migratable keys but is not permitted to certify migratory keys or certified migration keys. As such, it allows the TPM to make the statement "this key is held in a TPM-shielded location, and it will never be revealed." For this statement to have veracity, the Challenger must trust the policies used by the entity that issued the identity and the maintenance policy of the TPM manufacturer. Signing and legacy keys may be used to certify both migratable and non-migratable keys. Then the usefulness of a certificate depends on the trust in the certifying key by the recipient of the certificate. The key to be certified must be loaded before TPM_CertifyKey is called. The determination to use the TPM_CERTIFY_INFO or TPM_CERTIFY_INFO2 on the output is based on which PCRs and what localities the certified key is restricted to. A key to be certified that does not have locality restrictions and which uses no PCRs greater than PCR #15 will cause this command to return and sign a TPM_CERTIFY_INFO structure, which provides compatibility with V1.1 TPMs. When this command is run to certify all other keys (those that use PCR #16 or higher, as well as those limited by locality in any way), it will return and sign a TPM_CERTIFY_INFO2 structure. TPM_CertifyKey does not support the case where (a) the certifying key requires a usage authorization to be provided but (b) the key-to-be-certified does not. In such cases, TPM_CertifyKey2 must be used. If a command tag (in the parameter array) specifies only one authorisation session, then the TPM convention is that the first session listed is ignored (authDataUsage must be TPM_AUTH_NEVER for this key) and the incoming session data is used for the second auth session in the list. In TPM_CertifyKey, the first session is the certifying key and the second session is the key-to-be-certified. In TPM_CertifyKey2, the first session is the key-to-be-certified and the second session is the certifying key. */ TPM_RESULT TPM_Process_CertifyKey(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_KEY_HANDLE certHandle; /* Handle of the key to be used to certify the key. */ TPM_KEY_HANDLE keyHandle; /* Handle of the key to be certified. */ TPM_NONCE antiReplay; /* 160 bits of externally supplied data (typically a nonce provided to prevent replay-attacks) */ TPM_AUTHHANDLE certAuthHandle; /* The authorization session handle used for certHandle. */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with certAuthHandle */ TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization session handle */ TPM_AUTHDATA certAuth; /* The authorization session digest for inputs and certHandle. HMAC key: certKey.auth. */ TPM_AUTHHANDLE keyAuthHandle; /* The authorization session handle used for the key to be signed. */ TPM_NONCE keynonceOdd; /* Nonce generated by system associated with keyAuthHandle */ TPM_BOOL continueKeySession = TRUE; /* The continue use flag for the authorization session handle */ TPM_AUTHDATA keyAuth; /* The authorization session digest for the inputs and key to be signed. HMAC key: key.usageAuth. */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_AUTH_SESSION_DATA *cert_auth_session_data = NULL; /* session data for authHandle */ TPM_AUTH_SESSION_DATA *target_auth_session_data = NULL; /* session data for authHandle */ TPM_BOOL certAuthHandleValid = FALSE; TPM_BOOL keyAuthHandleValid = FALSE; TPM_SECRET *certHmacKey; TPM_SECRET *targetHmacKey; TPM_BOOL certPCRStatus; TPM_BOOL targetPCRStatus; TPM_KEY *certKey = NULL; /* the key specified by certHandle */ TPM_KEY *targetKey = NULL; /* the key specified by keyHandle */ TPM_SECRET *certKeyUsageAuth; TPM_SECRET *targetKeyUsageAuth; TPM_BOOL pcrUsage; TPM_LOCALITY_SELECTION localityAtRelease; int v1Version; /* TPM 1.1 or TPM 1.2 */ int certifyType = 0; /* TPM_CERTIFY_INFO or TPM_CERTIFY_INFO2 */ TPM_DIGEST m1Digest; /* digest of certifyInfo */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_CERTIFY_INFO certifyInfo; /* TPM_CERTIFY_INFO or TPM_CERTIFY_INFO2 structure that provides information relative to keyhandle NOTE This is c1 in the Actions. */ TPM_CERTIFY_INFO2 certifyInfo2; TPM_SIZED_BUFFER outData; /* The signature of certifyInfo */ printf("TPM_Process_CertifyKey: Ordinal Entry\n"); TPM_CertifyInfo_Init(&certifyInfo); /* freed @1 */ TPM_CertifyInfo2_Init(&certifyInfo2); /* freed @2 */ TPM_SizedBuffer_Init(&outData); /* freed @3 */ /* get inputs */ /* get certHandle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&certHandle, &command, ¶mSize); } /* get keyHandle parameter */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CertifyKey: certHandle %08x\n", certHandle); returnCode = TPM_Load32(&keyHandle, &command, ¶mSize); } /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get antiReplay parameter */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CertifyKey: keyHandle %08x\n", keyHandle); returnCode = TPM_Nonce_Load(antiReplay, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag210(tag); } /* get the optional 'below the line' authorization parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { returnCode = TPM_AuthParams_Get(&certAuthHandle, &certAuthHandleValid, nonceOdd, &continueAuthSession, certAuth, &command, ¶mSize); } if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { printf("TPM_Process_CertifyKey: certAuthHandle %08x\n", certAuthHandle); } /* get the optional 'below the line' authorization parameters */ if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) { returnCode = TPM_AuthParams_Get(&keyAuthHandle, &keyAuthHandleValid, keynonceOdd, &continueKeySession, keyAuth, &command, ¶mSize); } if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) { printf("TPM_Process_CertifyKey: keyAuthHandle %08x\n", keyAuthHandle); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_CertifyKey: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { certAuthHandleValid = FALSE; keyAuthHandleValid = FALSE; } /* Processing */ /* get the key corresponding to the certHandle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyHandleEntries_GetKey(&certKey, &certPCRStatus, tpm_state, certHandle, FALSE, /* not read-only */ FALSE, /* do not ignore PCRs */ FALSE); /* cannot use EK */ } /* get the key corresponding to the keyHandle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyHandleEntries_GetKey(&targetKey, &targetPCRStatus, tpm_state, keyHandle, FALSE, /* not read-only */ FALSE, /* do not ignore PCRs */ FALSE); /* cannot use EK */ } /* 1. The TPM validates that the key pointed to by certHandle has a signature scheme of TPM_SS_RSASSAPKCS1v15_SHA1 or TPM_SS_RSASSAPKCS1v15_INFO */ if (returnCode == TPM_SUCCESS) { if ((certKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1) && (certKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_INFO)) { printf("TPM_Process_CertifyKey: Error, invalid certKey sigScheme %04hx\n", certKey->algorithmParms.sigScheme); returnCode = TPM_BAD_KEY_PROPERTY; } } /* 2. Verify command and key AuthData values */ /* a. If tag is TPM_TAG_RQU_AUTH2_COMMAND */ /* i. The TPM verifies the AuthData in certAuthHandle provides authorization to use the key pointed to by certHandle, return TPM_AUTHFAIL on error */ /* ii. The TPM verifies the AuthData in keyAuthHandle provides authorization to use the key pointed to by keyHandle, return TPM_AUTH2FAIL on error */ /* b. else if tag is TPM_TAG_RQU_AUTH1_COMMAND */ /* i. Verify that authDataUsage is TPM_AUTH_NEVER for the key referenced by certHandle, return TPM_AUTHFAIL on error. */ /* ii. The TPM verifies the AuthData in keyAuthHandle provides authorization to use the key pointed to by keyHandle, return TPM_AUTHFAIL on error */ /* c. else if tag is TPM_TAG_RQU_COMMAND */ /* i. Verify that authDataUsage is TPM_AUTH_NEVER for the key referenced by certHandle, return TPM_AUTHFAIL on error. */ /* ii. Verify that authDataUsage is TPM_AUTH_NEVER or TPM_NO_READ_PUBKEY_AUTH for the key referenced by keyHandle, return TPM_AUTHFAIL on error. */ /* NOTE: Simplified the above logic as follows */ /* If tag is TPM_TAG_RQU_AUTH2_COMMAND, process the first set of authorization data */ /* get certHandle -> usageAuth */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { returnCode = TPM_Key_GetUsageAuth(&certKeyUsageAuth, certKey); } /* get the first session data */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { returnCode = TPM_AuthSessions_GetData(&cert_auth_session_data, &certHmacKey, tpm_state, certAuthHandle, TPM_PID_NONE, TPM_ET_KEYHANDLE, ordinal, certKey, certKeyUsageAuth, /* OIAP */ certKey->tpm_store_asymkey->pubDataDigest); /* OSAP */ } /* The TPM verifies the AuthData in certAuthHandle provides authorization to use the key pointed to by certHandle, return TPM_AUTHFAIL on error */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { returnCode = TPM_Authdata_Check(tpm_state, *certHmacKey, /* HMAC key */ inParamDigest, cert_auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, certAuth); /* Authorization digest for input */ } /* If tag is not TPM_TAG_RQU_AUTH2_COMMAND */ /* Verify that authDataUsage is TPM_AUTH_NEVER for the key referenced by certHandle, return TPM_AUTHFAIL on error. */ if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_AUTH2_COMMAND)) { if (certKey->authDataUsage != TPM_AUTH_NEVER) { printf("TPM_Process_CertifyKey: Error, cert key authorization required\n"); returnCode = TPM_AUTHFAIL; } } /* If tag is TPM_TAG_RQU_AUTH2_COMMAND or TPM_TAG_RQU_AUTH1_COMMAND process the second set of authorization data */ /* get keyHandle -> usageAuth */ if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) { returnCode = TPM_Key_GetUsageAuth(&targetKeyUsageAuth, targetKey); } /* get the second session data */ if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) { returnCode = TPM_AuthSessions_GetData(&target_auth_session_data, &targetHmacKey, tpm_state, keyAuthHandle, TPM_PID_NONE, TPM_ET_KEYHANDLE, ordinal, targetKey, targetKeyUsageAuth, /* OIAP */ targetKey->tpm_store_asymkey->pubDataDigest); /*OSAP*/ } /* The TPM verifies the AuthData in keyAuthHandle provides authorization to use the key pointed to by keyHandle, return TPM_AUTH2FAIL on error */ if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) { returnCode = TPM_Auth2data_Check(tpm_state, *targetHmacKey, /* HMAC key */ inParamDigest, target_auth_session_data, /* authorization session */ keynonceOdd, /* Nonce generated by system associated with authHandle */ continueKeySession, keyAuth); /* Authorization digest for input */ } /* Verify that authDataUsage is TPM_AUTH_NEVER or TPM_NO_READ_PUBKEY_AUTH for the key referenced by keyHandle, return TPM_AUTHFAIL on error. */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)) { if (targetKey->authDataUsage == TPM_AUTH_ALWAYS) { printf("TPM_Process_CertifyKey: Error, target key authorization required\n"); returnCode = TPM_AUTHFAIL; } } /* 3. If keyHandle -> payload is not TPM_PT_ASYM, return TPM_INVALID_KEYUSAGE. */ if (returnCode == TPM_SUCCESS) { if (targetKey->tpm_store_asymkey->payload != TPM_PT_ASYM) { printf("TPM_Process_CertifyKey: Error, target key invalid payload %02x\n", targetKey->tpm_store_asymkey->payload); returnCode = TPM_INVALID_KEYUSAGE; } } /* 4. If the key pointed to by certHandle is an identity key (certHandle -> keyUsage is TPM_KEY_IDENTITY) */ if ((returnCode == TPM_SUCCESS) && (certKey->keyUsage == TPM_KEY_IDENTITY)) { /* a. If keyHandle -> keyflags -> keyInfo -> migratable is TRUE return TPM_MIGRATEFAIL */ if (targetKey->keyFlags & TPM_MIGRATABLE) { printf("TPM_Process_CertifyKey: Error, target key is migratable\n"); returnCode = TPM_MIGRATEFAIL; } } /* 5. Validate that certHandle -> keyUsage is TPM_KEY_SIGN, TPM_KEY_IDENTITY or TPM_KEY_LEGACY, if not return TPM_INVALID_KEYUSAGE */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CertifyKey: certHandle -> keyUsage %04hx\n", certKey->keyUsage); if ((certKey->keyUsage != TPM_KEY_SIGNING) && ((certKey->keyUsage) != TPM_KEY_IDENTITY) && ((certKey->keyUsage) != TPM_KEY_LEGACY)) { printf("TPM_Process_CertifyKey: Error, certHandle -> keyUsage %04hx is invalid\n", certKey->keyUsage); returnCode = TPM_INVALID_KEYUSAGE; } } /* 6. Validate that keyHandle -> keyUsage is TPM_KEY_SIGN, TPM_KEY_STORAGE, TPM_KEY_IDENTITY, TPM_KEY_BIND or TPM_KEY_LEGACY, if not return the error code TPM_INVALID_KEYUSAGE */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CertifyKey: keyHandle -> keyUsage %04hx\n", targetKey->keyUsage); if ((targetKey->keyUsage != TPM_KEY_SIGNING) && ((targetKey->keyUsage) != TPM_KEY_STORAGE) && ((targetKey->keyUsage) != TPM_KEY_IDENTITY) && ((targetKey->keyUsage) != TPM_KEY_BIND) && ((targetKey->keyUsage) != TPM_KEY_LEGACY)) { printf("TPM_Process_CertifyKey: Error, keyHandle -> keyUsage %04hx is invalid\n", targetKey->keyUsage); returnCode = TPM_INVALID_KEYUSAGE; } } /* 7. If keyHandle -> digestAtRelease requires the use of PCRs 16 or higher to calculate or if keyHandle -> localityAtRelease is not 0x1F */ /* get PCR usage 16 and higher */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Key_GetPCRUsage(&pcrUsage, targetKey, 2); } /* get localityAtRelease */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Key_GetLocalityAtRelease(&localityAtRelease, targetKey); } if (returnCode == TPM_SUCCESS) { if (pcrUsage || (localityAtRelease != TPM_LOC_ALL)) { /* a. Set V1 to 1.2 */ v1Version = 2; /* locality or >2 PCR's */ } /* 8. Else */ else { /* a. Set V1 to 1.1 */ v1Version = 1; /* no locality and <= 2 PCR's */ } } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CertifyKey: V1 %d\n", v1Version); /* 9. If keyHandle -> pcrInfoSize is not 0 */ if (targetKey->pcrInfo.size != 0) { printf("TPM_Process_CertifyKey: Setting PCR info from key\n"); /* a. If keyHandle -> keyFlags has pcrIgnoredOnRead set to FALSE */ /* i. Create a digestAtRelease according to the specified PCR registers and compare to keyHandle -> digestAtRelease and if a mismatch return TPM_WRONGPCRVAL */ /* ii. If specified validate any locality requests on error TPM_BAD_LOCALITY */ /* NOTE: Done by TPM_KeyHandleEntries_GetKey() */ /* b. If V1 is 1.1 */ if (v1Version == 1) { certifyType = 1; /* i. Create C1 a TPM_CERTIFY_INFO structure */ /* NOTE: Done by TPM_CertifyInfo_Init() */ /* ii. Fill in C1 with the information from the key pointed to by keyHandle */ /* NOTE: Done in common _Set() code below */ /* iii. The TPM MUST set c1 -> pcrInfoSize to 44. */ /* iv. The TPM MUST set c1 -> pcrInfo to a TPM_PCR_INFO structure properly filled out using the information from keyHandle. */ /* This function actually creates the cache, which is serialized later */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_PCRInfo_CreateFromKey(&(certifyInfo.tpm_pcr_info), targetKey); } /* v. The TPM MUST set c1 -> digestAtCreation to 20 bytes of 0x00. */ if (returnCode == TPM_SUCCESS) { TPM_Digest_Init(certifyInfo.tpm_pcr_info->digestAtCreation); } } /* c. Else */ else { certifyType = 2; /* i. Create C1 a TPM_CERTIFY_INFO2 structure */ /* NOTE: Done by TPM_CertifyInfo2_Init() */ /* ii. Fill in C1 with the information from the key pointed to by keyHandle */ /* NOTE: Done in common _Set() code below */ /* iii. Set C1 -> pcrInfoSize to the size of an appropriate TPM_PCR_INFO_SHORT structure. */ /* iv. Set C1 -> pcrInfo to a properly filled out TPM_PCR_INFO_SHORT structure, using the information from keyHandle. */ /* This function actually creates the cache, which is serialized later */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_PCRInfoShort_CreateFromKey(&(certifyInfo2.tpm_pcr_info_short), targetKey); } /* v. Set C1 -> migrationAuthoritySize to 0 */ /* NOTE: Done by TPM_CertifyInfo2_Init() */ } } /* 10. Else */ else { certifyType = 1; /* a. Create C1 a TPM_CERTIFY_INFO structure */ /* NOTE: Done by TPM_CertifyInfo_Init() */ /* b. Fill in C1 with the information from the key pointed to be keyHandle */ /* NOTE: Done in common _Set() code below */ /* c. The TPM MUST set c1 -> pcrInfoSize to 0 */ /* NOTE: Done by TPM_CertifyInfo_Init() */ } } /* 11. Create TPM_DIGEST H1 which is the SHA-1 hash of keyHandle -> pubKey -> key. Note that is the actual public modulus, and does not include any structure formatting. */ /* 12. Set C1 -> pubKeyDigest to H1 */ /* NOTE: Done by TPM_CertifyInfo_Set() or TPM_CertifyInfo2_Set() */ /* 13. The TPM copies the antiReplay parameter to c1 -> data. */ /* Set C1 -> parentPCRStatus to the value from keyHandle NOTE: Implied in specification */ /* Fill in C1 with the information from the key pointed to by keyHandle */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CertifyKey: Setting certifyInfo from target key\n"); if (certifyType == 1) { TPM_Digest_Copy(certifyInfo.data, antiReplay); certifyInfo.parentPCRStatus = targetPCRStatus; returnCode = TPM_CertifyInfo_Set(&certifyInfo, targetKey); } else { TPM_Digest_Copy(certifyInfo2.data, antiReplay); certifyInfo2.parentPCRStatus = targetPCRStatus; returnCode = TPM_CertifyInfo2_Set(&certifyInfo2, targetKey); } } /* 14. The TPM sets certifyInfo to C1. */ /* NOTE Created as certifyInfo or certifyInfo2 */ /* 15. The TPM creates m1, a message digest formed by taking the SHA-1 of c1. */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CertifyKey: Digesting certifyInfo\n"); if (certifyType == 1) { returnCode = TPM_SHA1_GenerateStructure(m1Digest, &certifyInfo, (TPM_STORE_FUNCTION_T)TPM_CertifyInfo_Store); } else { returnCode = TPM_SHA1_GenerateStructure(m1Digest, &certifyInfo2, (TPM_STORE_FUNCTION_T)TPM_CertifyInfo2_Store); } } /* a. The TPM then computes a signature using certHandle -> sigScheme. The resulting signed blob is returned in outData. */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CertifyKey: Signing certifyInfo digest with certifying key\n"); returnCode = TPM_RSASignToSizedBuffer(&outData, /* signature */ m1Digest, /* message */ TPM_DIGEST_SIZE, /* message size */ certKey); /* input, signing key */ } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_CertifyKey: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* Return certifyInfo */ if (certifyType == 1) { returnCode = TPM_CertifyInfo_Store(response, &certifyInfo); } else { returnCode = TPM_CertifyInfo2_Store(response, &certifyInfo2); } } if (returnCode == TPM_SUCCESS) { /* Return outData */ returnCode = TPM_SizedBuffer_Store(response, &outData); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { returnCode = TPM_AuthParams_Set(response, *certHmacKey, /* HMAC key */ cert_auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* calculate and set the below the line parameters */ if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) { returnCode = TPM_AuthParams_Set(response, *targetHmacKey, /* HMAC key */ target_auth_session_data, outParamDigest, keynonceOdd, continueKeySession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueKeySession) && keyAuthHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, keyAuthHandle); } if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && certAuthHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, certAuthHandle); } /* cleanup */ TPM_CertifyInfo_Delete(&certifyInfo); /* @1 */ TPM_CertifyInfo2_Delete(&certifyInfo2); /* @2 */ TPM_SizedBuffer_Delete(&outData); /* @3 */ return rcf; } /* 13.9 TPM_CertifyKey2 rev 107 This command is based on TPM_CertifyKey, but includes the ability to certify a Certifiable Migration Key (CMK), which requires extra input parameters. TPM_CertifyKey2 always produces a TPM_CERTIFY_INFO2 structure. TPM_CertifyKey2 does not support the case where (a) the key-to-be-certified requires a usage authorization to be provided but (b) the certifying key does not. If a command tag (in the parameter array) specifies only one authorisation session, then the TPM convention is that the first session listed is ignored (authDataUsage must be TPM_NO_READ_PUBKEY_AUTH or TPM_AUTH_NEVER for this key) and the incoming session data is used for the second auth session in the list. In TPM_CertifyKey2, the first session is the key to be certified and the second session is the certifying key. */ TPM_RESULT TPM_Process_CertifyKey2(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_KEY_HANDLE keyHandle; /* Handle of the key to be certified. */ TPM_KEY_HANDLE certHandle; /* Handle of the key to be used to certify the key. */ TPM_DIGEST migrationPubDigest; /* The digest of a TPM_MSA_COMPOSITE structure, containing at least one public key of a Migration Authority */ TPM_NONCE antiReplay; /* 160 bits of externally supplied data (typically a nonce provided to prevent replay-attacks) */ TPM_AUTHHANDLE keyAuthHandle; /* The authorization session handle used for the key to be signed. */ TPM_NONCE keynonceOdd; /* Nonce generated by system associated with keyAuthHandle */ TPM_BOOL continueKeySession; /* The continue use flag for the authorization session handle */ TPM_AUTHDATA keyAuth; /* The authorization session digest for the inputs and key to be signed. HMAC key: key.usageAuth. */ TPM_AUTHHANDLE certAuthHandle; /* The authorization session handle used for certHandle. */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with certAuthHandle */ TPM_BOOL continueAuthSession; /* The continue use flag for the authorization session handle */ TPM_AUTHDATA certAuth; /* Authorization HMAC key: certKey.auth. */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_AUTH_SESSION_DATA *cert_auth_session_data = NULL; /* session data for authHandle */ TPM_AUTH_SESSION_DATA *target_auth_session_data = NULL; /* session data for authHandle */ TPM_BOOL certAuthHandleValid = FALSE; TPM_BOOL keyAuthHandleValid = FALSE; TPM_SECRET *certHmacKey; TPM_SECRET *targetHmacKey; TPM_BOOL certPCRStatus; TPM_BOOL targetPCRStatus; TPM_KEY *certKey = NULL; /* the key specified by certHandle */ TPM_KEY *targetKey = NULL; /* the key specified by keyHandle */ TPM_SECRET *certKeyUsageAuth; TPM_SECRET *targetKeyUsageAuth; TPM_STORE_ASYMKEY *targetStoreAsymkey; TPM_CMK_MIGAUTH m2CmkMigauth; TPM_BOOL hmacValid; TPM_DIGEST migrationAuthority; TPM_DIGEST m1Digest; /* digest of certifyInfo */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_CERTIFY_INFO2 certifyInfo2; /* TPM_CERTIFY_INFO2 relative to keyHandle */ TPM_SIZED_BUFFER outData; /* The signed public key. */ printf("TPM_Process_CertifyKey2: Ordinal Entry\n"); TPM_CertifyInfo2_Init(&certifyInfo2); /* freed @1 */ TPM_SizedBuffer_Init(&outData); /* freed @2 */ TPM_CmkMigauth_Init(&m2CmkMigauth); /* freed @3 */ /* get inputs */ /* get keyHandle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&keyHandle, &command, ¶mSize); } /* get certHandle parameter */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CertifyKey2: keyHandle %08x\n", keyHandle); returnCode = TPM_Load32(&certHandle, &command, ¶mSize); } /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get antiReplay parameter */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CertifyKey2: certHandle %08x\n", certHandle); /* get the migrationPubDigest parameter */ returnCode = TPM_Digest_Load(migrationPubDigest, &command, ¶mSize); } /* get the antiReplay parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Nonce_Load(antiReplay, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag210(tag); } /* get the optional 'below the line' authorization parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { returnCode = TPM_AuthParams_Get(&keyAuthHandle, &keyAuthHandleValid, keynonceOdd, &continueKeySession, keyAuth, &command, ¶mSize); } if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { printf("TPM_Process_CertifyKey2: keyAuthHandle %08x\n", keyAuthHandle); } /* get the optional 'below the line' authorization parameters */ if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) { returnCode = TPM_AuthParams_Get(&certAuthHandle, &certAuthHandleValid, nonceOdd, &continueAuthSession, certAuth, &command, ¶mSize); } if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) { printf("TPM_Process_CertifyKey2: certAuthHandle %08x\n", certAuthHandle); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_CertifyKey2: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { certAuthHandleValid = FALSE; keyAuthHandleValid = FALSE; } /* Processing */ /* get the keys corresponding to the certHandle and keyHandle parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyHandleEntries_GetKey(&targetKey, &targetPCRStatus, tpm_state, keyHandle, FALSE, /* not read-only */ FALSE, /* do not ignore PCRs */ FALSE); /* cannot use EK */ } if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyHandleEntries_GetKey(&certKey, &certPCRStatus, tpm_state, certHandle, FALSE, /* not read-only */ FALSE, /* do not ignore PCRs */ FALSE); /* cannot use EK */ } /* get the TPM_STORE_ASYMKEY cache for the target TPM_KEY */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Key_GetStoreAsymkey(&targetStoreAsymkey, targetKey); } /* 1. The TPM validates that the key pointed to by certHandle has a signature scheme of TPM_SS_RSASSAPKCS1v15_SHA1 or TPM_SS_RSASSAPKCS1v15_INFO */ if (returnCode == TPM_SUCCESS) { if ((certKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1) && (certKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_INFO)) { printf("TPM_Process_CertifyKey2: Error, invalid certKey sigScheme %04hx\n", certKey->algorithmParms.sigScheme); returnCode = TPM_BAD_KEY_PROPERTY; } } /* 2. Verify command and key AuthData values: */ /* a. If tag is TPM_TAG_RQU_AUTH2_COMMAND */ /* i. The TPM verifies the AuthData in keyAuthHandle provides authorization to use the key pointed to by keyHandle, return TPM_AUTHFAIL on error */ /* ii. The TPM verifies the AuthData in certAuthHandle provides authorization to use the key pointed to by certHandle, return TPM_AUTH2FAIL on error */ /* b. else if tag is TPM_TAG_RQU_AUTH1_COMMAND */ /* i. Verify that authDataUsage is TPM_AUTH_NEVER or TPM_NO_READ_PUBKEY_AUTH for the key referenced by keyHandle, return TPM_AUTHFAIL on error */ /* ii. The TPM verifies the AuthData in certAuthHandle provides authorization to use the key pointed to by certHandle, return TPM_AUTHFAIL on error */ /* c. else if tag is TPM_TAG_RQU_COMMAND */ /* i. Verify that authDataUsage is TPM_AUTH_NEVER or TPM_NO_READ_PUBKEY_AUTH for the key referenced by keyHandle, return TPM_AUTHFAIL on error */ /* ii. Verify that authDataUsage is TPM_AUTH_NEVER for the key referenced by certHandle, return TPM_AUTHFAIL on error. */ /* NOTE: Simplified the above logic as follows */ /* If tag is TPM_TAG_RQU_AUTH2_COMMAND, process the first set of authorization data */ /* get keyHandle -> usageAuth */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { returnCode = TPM_Key_GetUsageAuth(&targetKeyUsageAuth, targetKey); } /* get the first session data */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { returnCode = TPM_AuthSessions_GetData(&target_auth_session_data, &targetHmacKey, tpm_state, keyAuthHandle, TPM_PID_NONE, TPM_ET_KEYHANDLE, ordinal, targetKey, targetKeyUsageAuth, /* OIAP */ targetKey->tpm_store_asymkey->pubDataDigest); /*OSAP*/ } /* The TPM verifies the AuthData in keyAuthHandle provides authorization to use the key pointed to by keyHandle, return TPM_AUTHFAIL on error */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { returnCode = TPM_Authdata_Check(tpm_state, *targetHmacKey, /* HMAC key */ inParamDigest, target_auth_session_data, /* authorization session */ keynonceOdd, /* Nonce generated by system associated with authHandle */ continueKeySession, keyAuth); /* Authorization digest for input */ } /* If tag is not TPM_TAG_RQU_AUTH2_COMMAND */ /* Verify that authDataUsage is TPM_AUTH_NEVER or TPM_NO_READ_PUBKEY_AUTH for the key referenced by keyHandle, return TPM_AUTHFAIL on error. */ if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_AUTH2_COMMAND)) { if (targetKey->authDataUsage == TPM_AUTH_ALWAYS) { printf("TPM_Process_CertifyKey2: Error, target key authorization required\n"); returnCode = TPM_AUTHFAIL; } } /* If tag is TPM_TAG_RQU_AUTH2_COMMAND or TPM_TAG_RQU_AUTH1_COMMAND process the second set of authorization data */ /* get certHandle -> usageAuth */ if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) { returnCode = TPM_Key_GetUsageAuth(&certKeyUsageAuth, certKey); } /* get the second session data */ if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) { returnCode = TPM_AuthSessions_GetData(&cert_auth_session_data, &certHmacKey, tpm_state, certAuthHandle, TPM_PID_NONE, TPM_ET_KEYHANDLE, ordinal, certKey, certKeyUsageAuth, /* OIAP */ certKey->tpm_store_asymkey->pubDataDigest); /* OSAP */ } /* The TPM verifies the AuthData in certAuthHandle provides authorization to use the key pointed to by certHandle, return TPM_AUTH2FAIL on error */ if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) { returnCode = TPM_Auth2data_Check(tpm_state, *certHmacKey, /* HMAC key */ inParamDigest, cert_auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, certAuth); /* Authorization digest for input */ } /* If the command is TPM_TAG_RQU_COMMAND */ /* Verify that authDataUsage is TPM_AUTH_NEVER for the key referenced by certHandle, return TPM_AUTHFAIL on error. */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)) { if (certKey->authDataUsage != TPM_AUTH_NEVER) { printf("TPM_Process_CertifyKey2: Error, cert key authorization required\n"); returnCode = TPM_AUTHFAIL; } } /* 3. If the key pointed to by certHandle is an identity key (certHandle -> keyUsage is TPM_KEY_IDENTITY) */ if ((returnCode == TPM_SUCCESS) && (certKey->keyUsage == TPM_KEY_IDENTITY)) { /* a. If keyHandle -> keyFlags -> migratable is TRUE and [keyHandle -> keyFlags-> migrateAuthority is FALSE or (keyHandle -> payload != TPM_PT_MIGRATE_RESTRICTED and keyHandle -> payload != TPM_PT_MIGRATE_EXTERNAL)] return TPM_MIGRATEFAIL */ if ((targetKey->keyFlags & TPM_MIGRATABLE) && (!(targetKey->keyFlags & TPM_MIGRATEAUTHORITY) || ((targetStoreAsymkey->payload != TPM_PT_MIGRATE_RESTRICTED) && (targetStoreAsymkey->payload != TPM_PT_MIGRATE_EXTERNAL)))) { printf("TPM_Process_CertifyKey2: Error, target key migrate fail\n"); returnCode = TPM_MIGRATEFAIL; } } /* 4. Validate that certHandle -> keyUsage is TPM_KEY_SIGNING, TPM_KEY_IDENTITY or TPM_KEY_LEGACY, if not return the error code TPM_INVALID_KEYUSAGE */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CertifyKey2: certHandle ->keyUsage %04hx\n", certKey->keyUsage); if ((certKey->keyUsage != TPM_KEY_SIGNING) && ((certKey->keyUsage) != TPM_KEY_IDENTITY) && ((certKey->keyUsage) != TPM_KEY_LEGACY)) { printf("TPM_Process_CertifyKey2: Error, keyUsage %04hx is invalid\n", certKey->keyUsage); returnCode = TPM_INVALID_KEYUSAGE; } } /* 5. Validate that keyHandle -> keyUsage is TPM_KEY_SIGNING, TPM_KEY_STORAGE, TPM_KEY_IDENTITY, TPM_KEY_BIND or TPM_KEY_LEGACY, if not return the error code TPM_INVALID_KEYUSAGE */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CertifyKey2: keyHandle -> keyUsage %04hx\n", targetKey->keyUsage); if ((targetKey->keyUsage != TPM_KEY_SIGNING) && ((targetKey->keyUsage) != TPM_KEY_STORAGE) && ((targetKey->keyUsage) != TPM_KEY_IDENTITY) && ((targetKey->keyUsage) != TPM_KEY_BIND) && ((targetKey->keyUsage) != TPM_KEY_LEGACY)) { printf("TPM_Process_CertifyKey2: Error, keyHandle -> keyUsage %04hx is invalid\n", targetKey->keyUsage); returnCode = TPM_INVALID_KEYUSAGE; } } /* 6. The TPM SHALL create a c1 a TPM_CERTIFY_INFO2 structure from the key pointed to by keyHandle */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CertifyInfo2_Set(&certifyInfo2, targetKey); } /* 7. Create TPM_DIGEST H1 which is the SHA-1 hash of keyHandle -> pubKey -> key. Note that is the actual public modulus, and does not include any structure formatting. */ /* 8. Set C1 -> pubKeyDigest to H1 */ /* NOTE: Done by TPM_CertifyInfo2_Set() */ if (returnCode == TPM_SUCCESS) { /* 9. Copy the antiReplay parameter to c1 -> data */ TPM_Digest_Copy(certifyInfo2.data, antiReplay); /* 10. Copy other keyHandle parameters into C1 */ certifyInfo2.parentPCRStatus = targetPCRStatus; /* 11. If keyHandle -> payload == TPM_PT_MIGRATE_RESTRICTED or TPM_PT_MIGRATE_EXTERNAL */ if ((targetStoreAsymkey->payload == TPM_PT_MIGRATE_RESTRICTED) || (targetStoreAsymkey->payload == TPM_PT_MIGRATE_EXTERNAL)) { printf("TPM_Process_CertifyKey2: " "TPM_PT_MIGRATE_RESTRICTED or TPM_PT_MIGRATE_RESTRICTED\n"); /* a. create thisPubKey, a TPM_PUBKEY structure containing the public key, algorithm and parameters corresponding to keyHandle */ /* NOTE Not required. Digest is created directly below */ /* b. Verify that the migration authorization is valid for this key */ /* i. Create M2 a TPM_CMK_MIGAUTH structure */ /* NOTE Done by TPM_CmkMigauth_Init() */ if (returnCode == TPM_SUCCESS) { /* ii. Set M2 -> msaDigest to migrationPubDigest */ TPM_Digest_Copy(m2CmkMigauth.msaDigest, migrationPubDigest ); /* iii. Set M2 -> pubKeyDigest to SHA-1[thisPubKey] */ returnCode = TPM_Key_GeneratePubkeyDigest(m2CmkMigauth.pubKeyDigest, targetKey); } /* iv. Verify that [keyHandle -> migrationAuth] == HMAC(M2) signed by using tpmProof as the secret and return error TPM_MA_SOURCE on mismatch */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CertifyKey2: Check migrationAuth\n"); returnCode = TPM_CmkMigauth_CheckHMAC(&hmacValid, /* result */ targetStoreAsymkey->migrationAuth, /* expect */ tpm_state->tpm_permanent_data.tpmProof, /* HMAC key */ &m2CmkMigauth); } if (returnCode == TPM_SUCCESS) { if (!hmacValid) { printf("TPM_Process_CertifyKey2: Error, Invalid migrationAuth\n"); returnCode = TPM_MA_SOURCE; } } /* c. Set C1 -> migrationAuthority = SHA-1(migrationPubDigest || keyHandle -> payload) */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CertifyKey2: Set migrationAuthority\n"); returnCode = TPM_SHA1(migrationAuthority, TPM_DIGEST_SIZE, migrationPubDigest, sizeof(TPM_PAYLOAD_TYPE), &(targetStoreAsymkey->payload), 0, NULL); } if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_Set(&(certifyInfo2.migrationAuthority), TPM_DIGEST_SIZE, migrationAuthority); } /* d. if keyHandle -> payload == TPM_PT_MIGRATE_RESTRICTED */ /* i. Set C1 -> payloadType = TPM_PT_MIGRATE_RESTRICTED */ /* e. if keyHandle -> payload == TPM_PT_MIGRATE_EXTERNAL */ /* i. Set C1 -> payloadType = TPM_PT_MIGRATE_EXTERNAL */ /* NOTE: Done by TPM_CertifyInfo2_Set() */ } /* 12. Else */ else { printf("TPM_Process_CertifyKey2: " " Not TPM_PT_MIGRATE_RESTRICTED or TPM_PT_MIGRATE_RESTRICTED\n"); /* a. set C1 -> migrationAuthority = NULL */ /* b. set C1 -> migrationAuthoritySize = 0 */ /* NOTE: Done by TPM_CertifyInfo2_Init() */ /* c. Set C1 -> payloadType = TPM_PT_ASYM */ certifyInfo2.payloadType = TPM_PT_ASYM; } } if (returnCode == TPM_SUCCESS) { /* 13. If keyHandle -> pcrInfoSize is not 0 */ if (targetKey->pcrInfo.size != 0) { printf("TPM_Process_CertifyKey2: Setting PCR info from key\n"); /* a. The TPM MUST set c1 -> pcrInfoSize to match the pcrInfoSize from the keyHandle key. */ /* b. The TPM MUST set c1 -> pcrInfo to match the pcrInfo from the keyHandle key */ /* This function actually creates the cache, which is serialized later */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_PCRInfoShort_CreateFromKey(&(certifyInfo2.tpm_pcr_info_short), targetKey); } /* c. If keyHandle -> keyFlags has pcrIgnoredOnRead set to FALSE */ /* i. Create a digestAtRelease according to the specified PCR registers and compare to keyHandle -> digestAtRelease and if a mismatch return TPM_WRONGPCRVAL */ /* ii. If specified validate any locality requests on error TPM_BAD_LOCALITY */ /* NOTE: Done by TPM_KeyHandleEntries_GetKey() */ } /* 14. Else */ /* a. The TPM MUST set c1 -> pcrInfoSize to 0 */ /* NOTE: Done by TPM_CertifyInfo2_Init() */ } /* 15. The TPM creates m1, a message digest formed by taking the SHA-1 of c1 */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CertifyKey2: Digesting certifyInfo\n"); returnCode = TPM_SHA1_GenerateStructure(m1Digest, &certifyInfo2, (TPM_STORE_FUNCTION_T)TPM_CertifyInfo2_Store); } /* a. The TPM then computes a signature using certHandle -> sigScheme. The resulting signed blob is returned in outData */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CertifyKey2: Signing certifyInfo digest\n"); returnCode = TPM_RSASignToSizedBuffer(&outData, /* signature */ m1Digest, /* message */ TPM_DIGEST_SIZE, /* message size */ certKey); /* input, signing key */ } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_CertifyKey2: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* Return certifyInfo */ returnCode = TPM_CertifyInfo2_Store(response, &certifyInfo2); } if (returnCode == TPM_SUCCESS) { /* Return outData */ returnCode = TPM_SizedBuffer_Store(response, &outData); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { returnCode = TPM_AuthParams_Set(response, *targetHmacKey, /* HMAC key */ target_auth_session_data, outParamDigest, keynonceOdd, continueKeySession); } /* calculate and set the below the line parameters */ if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_COMMAND)) { returnCode = TPM_AuthParams_Set(response, *certHmacKey, /* HMAC key */ cert_auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueKeySession) && keyAuthHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, keyAuthHandle); } if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && certAuthHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, certAuthHandle); } /* cleanup */ TPM_CertifyInfo2_Delete(&certifyInfo2); /* @1 */ TPM_SizedBuffer_Delete(&outData); /* @2 */ TPM_CmkMigauth_Delete(&m2CmkMigauth); /* @3 */ return rcf; } /* 28.3 TPM_CertifySelfTest rev 94 CertifySelfTest causes the TPM to perform a full self-test and return an authenticated value if the test passes. If a caller itself requires proof, it is sufficient to use any signing key for which only the TPM and the caller have AuthData. If a caller requires proof for a third party, the signing key must be one whose signature is trusted by the third party. A TPM-identity key may be suitable. Information returned by TPM_CertifySelfTest MUST NOT aid identification of an individual TPM. */ TPM_RESULT TPM_Process_CertifySelfTest(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_KEY_HANDLE keyHandle; /* The keyHandle identifier of a loaded key that can perform digital signatures. */ TPM_NONCE antiReplay; /* AntiReplay nonce to prevent replay of messages */ TPM_AUTHHANDLE authHandle; /* The authorization session handle used for keyHandle authorization */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization session handle */ TPM_AUTHDATA privAuth; /* The authorization session digest that authorizes the inputs and use of keyHandle. HMAC key: key.usageAuth */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ TPM_BOOL authHandleValid = FALSE; TPM_SECRET *hmacKey; TPM_KEY *sigKey; /* from keyHandle */ TPM_BOOL sigKeyPCRStatus; TPM_SECRET *sigKeyUsageAuth; TPM_COMMAND_CODE nOrdinal; /* ordinal in nbo */ TPM_DIGEST m2Digest; /* message to sign */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_SIZED_BUFFER sig; /* The resulting digital signature. */ printf("TPM_Process_CertifySelfTest: Ordinal Entry\n"); TPM_SizedBuffer_Init(&sig); /* freed @1 */ /* get inputs */ /* get keyHandle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&keyHandle, &command, ¶mSize); } /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get the antiReplay parameter */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CertifySelfTest: keyHandle %08x\n", keyHandle); returnCode = TPM_Nonce_Load(antiReplay, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag10(tag); } /* get the optional 'below the line' authorization parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, privAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_CertifySelfTest: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* 1. The TPM SHALL perform TPM_SelfTestFull. If the test fails the TPM returns the appropriate error code. */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CertifySelfTest: Running self test\n"); returnCode = TPM_SelfTestFullCmd(tpm_state); } /* 2. After successful completion of the self-test the TPM then validates the authorization to use the key pointed to by keyHandle */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyHandleEntries_GetKey(&sigKey, &sigKeyPCRStatus, tpm_state, keyHandle, FALSE, /* not read-only */ FALSE, /* do not ignore PCRs */ FALSE); /* cannot use EK */ } if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)){ if (sigKey->authDataUsage != TPM_AUTH_NEVER) { printf("TPM_Process_CertifySelfTest: Error, authorization required\n"); returnCode = TPM_AUTHFAIL; } } /* get keyHandle -> usageAuth */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_Key_GetUsageAuth(&sigKeyUsageAuth, sigKey); } /* get the session data */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_KEYHANDLE, ordinal, sigKey, sigKeyUsageAuth, /* OIAP */ sigKey->tpm_store_asymkey->pubDataDigest); /* OSAP */ } /* Validate the command parameters using privAuth */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, privAuth); /* Authorization digest for input */ } /* a. If the key pointed to by keyHandle has a signature scheme that is not TPM_SS_RSASSAPKCS1v15_SHA1, the TPM may either return TPM_BAD_SCHEME or may return TPM_SUCCESS and a vendor specific signature. */ if (returnCode == TPM_SUCCESS) { if (sigKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1) { printf("TPM_Process_CertifySelfTest: Error, invalid sigKey sigScheme %04hx\n", sigKey->algorithmParms.sigScheme); returnCode = TPM_BAD_SCHEME; } } /* The key in keyHandle MUST have a KEYUSAGE value of type TPM_KEY_SIGNING or TPM_KEY_LEGACY or TPM_KEY_IDENTITY. */ if (returnCode == TPM_SUCCESS) { if ((sigKey->keyUsage != TPM_KEY_SIGNING) && (sigKey->keyUsage != TPM_KEY_LEGACY) && (sigKey->keyUsage != TPM_KEY_IDENTITY)) { printf("TPM_Process_CertifySelfTest: Error, Illegal keyUsage %04hx\n", sigKey->keyUsage); returnCode = TPM_INVALID_KEYUSAGE; } } /* 3. Create t1 the NOT null terminated string of "Test Passed" */ /* 4. The TPM creates m2 the message to sign by concatenating t1 || AntiReplay || ordinal. */ if (returnCode == TPM_SUCCESS) { nOrdinal = htonl(ordinal); returnCode = TPM_SHA1(m2Digest, sizeof("Test Passed") - 1, "Test Passed", TPM_NONCE_SIZE, antiReplay, sizeof(TPM_COMMAND_CODE), &nOrdinal, 0, NULL); } /* 5. The TPM signs the SHA-1 of m2 using the key identified by keyHandle, and returns the signature as sig. */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CertifySelfTest: Signing certifyInfo digest\n"); returnCode = TPM_RSASignToSizedBuffer(&sig, /* signature */ m2Digest, /* message */ TPM_DIGEST_SIZE, /* message size */ sigKey); /* input, signing key */ } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_CertifySelfTest: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* return sig */ returnCode = TPM_SizedBuffer_Store(response, &sig); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* owner HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ TPM_SizedBuffer_Delete(&sig); /* @1 */ return rcf; } libtpms-0.9.3/src/tpm12/tpm_cryptoh.h000066400000000000000000000402321421143571500174540ustar00rootroot00000000000000/********************************************************************************/ /* */ /* High Level Platform Independent Crypto */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_cryptoh.h 4300 2011-01-18 18:00:27Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_CRYPTOH_H #define TPM_CRYPTOH_H #include "tpm_global.h" #include "tpm_types.h" #include "tpm_sizedbuffer.h" #include "tpm_structures.h" /* TPM_SIGN_INFO */ void TPM_SignInfo_Init(TPM_SIGN_INFO *tpm_sign_info); TPM_RESULT TPM_SignInfo_Store(TPM_STORE_BUFFER *sbuffer, const TPM_SIGN_INFO *tpm_sign_info); void TPM_SignInfo_Delete(TPM_SIGN_INFO *tpm_sign_info); /* TPM_CERTIFY_INFO */ void TPM_CertifyInfo_Init(TPM_CERTIFY_INFO *tpm_certify_info); #if 0 TPM_RESULT TPM_CertifyInfo_Load(TPM_CERTIFY_INFO *tpm_certify_info, unsigned char **stream, uint32_t *stream_size); #endif TPM_RESULT TPM_CertifyInfo_Store(TPM_STORE_BUFFER *sbuffer, TPM_CERTIFY_INFO *tpm_certify_info); void TPM_CertifyInfo_Delete(TPM_CERTIFY_INFO *tpm_certify_info); TPM_RESULT TPM_CertifyInfo_Set(TPM_CERTIFY_INFO *tpm_certify_info, TPM_KEY *tpm_key); /* TPM_CERTIFY_INFO2 */ void TPM_CertifyInfo2_Init(TPM_CERTIFY_INFO2 *tpm_certify_info2); #if 0 TPM_RESULT TPM_CertifyInfo2_Load(TPM_CERTIFY_INFO2 *tpm_certify_info2, unsigned char **stream, uint32_t *stream_size); #endif TPM_RESULT TPM_CertifyInfo2_Store(TPM_STORE_BUFFER *sbuffer, TPM_CERTIFY_INFO2 *tpm_certify_info2); void TPM_CertifyInfo2_Delete(TPM_CERTIFY_INFO2 *tpm_certify_info2); TPM_RESULT TPM_CertifyInfo2_Set(TPM_CERTIFY_INFO2 *tpm_certify_info2, TPM_KEY *tpm_key); /* TPM_SYMMETRIC_KEY */ void TPM_SymmetricKey_Init(TPM_SYMMETRIC_KEY *tpm_symmetric_key); TPM_RESULT TPM_SymmetricKey_Load(TPM_SYMMETRIC_KEY *tpm_symmetric_key, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_SymmetricKey_Store(TPM_STORE_BUFFER *sbuffer, const TPM_SYMMETRIC_KEY *tpm_symmetric_key); void TPM_SymmetricKey_Delete(TPM_SYMMETRIC_KEY *tpm_symmetric_key); TPM_RESULT TPM_SymmetricKeyData_EncryptSbuffer(TPM_SIZED_BUFFER *encrypt_data, TPM_STORE_BUFFER *sbuffer, const TPM_SYMMETRIC_KEY_TOKEN tpm_symmetric_key_data); TPM_RESULT TPM_SymmetricKeyData_StreamCrypt(unsigned char *data_out, const unsigned char *data_in, uint32_t data_size, TPM_ALGORITHM_ID algId, TPM_ENC_SCHEME encScheme, const unsigned char *symmetric_key, uint32_t symmetric_key_size, unsigned char *pad_in, uint32_t pad_in_size); /* RSA functions */ TPM_RESULT TPM_RSAPrivateDecryptMalloc(unsigned char **decrypt_data, uint32_t *decrypt_data_length, unsigned char *encrypt_data, uint32_t encrypt_data_size, TPM_KEY *tpm_key); TPM_RESULT TPM_RSAPrivateDecryptH(unsigned char *decrypt_data, uint32_t *decrypt_data_length, uint32_t decrypt_data_size, unsigned char *encrypt_data, uint32_t encrypt_data_size, TPM_KEY *tpm_key); TPM_RESULT TPM_RSAPublicEncryptSbuffer_Key(TPM_SIZED_BUFFER *enc_data, TPM_STORE_BUFFER *sbuffer, TPM_KEY *tpm_key); TPM_RESULT TPM_RSAPublicEncrypt_Key(TPM_SIZED_BUFFER *enc_data, const unsigned char *decrypt_data, size_t decrypt_data_size, TPM_KEY *tpm_key); TPM_RESULT TPM_RSAPublicEncrypt_Pubkey(TPM_SIZED_BUFFER *enc_data, const unsigned char *decrypt_data, size_t decrypt_data_size, TPM_PUBKEY *tpm_pubkey); TPM_RESULT TPM_RSAPublicEncrypt_Common(TPM_SIZED_BUFFER *enc_data, const unsigned char *decrypt_data, size_t decrypt_data_size, TPM_ENC_SCHEME encScheme, unsigned char *narr, uint32_t nbytes, unsigned char *earr, uint32_t ebytes); TPM_RESULT TPM_RSASignH(unsigned char *signature, unsigned int *signature_length, unsigned int signature_size, const unsigned char *message, size_t message_size, TPM_KEY *tpm_key); TPM_RESULT TPM_RSASignToSizedBuffer(TPM_SIZED_BUFFER *signature, const unsigned char *message, size_t message_size, TPM_KEY *tpm_key); TPM_RESULT TPM_RSAVerifyH(TPM_SIZED_BUFFER *signature, const unsigned char *message, uint32_t message_size, TPM_PUBKEY *tpm_pubkey); TPM_RESULT TPM_RSAVerify(unsigned char *signature, unsigned int signature_size, TPM_SIG_SCHEME sigScheme, const unsigned char *message, uint32_t message_size, unsigned char *narr, uint32_t nbytes, unsigned char *earr, uint32_t ebytes); TPM_RESULT TPM_RSA_exponent_verify(unsigned long exponent); /* OAEP Padding */ TPM_RESULT TPM_RSA_padding_add_PKCS1_OAEP(unsigned char *em, uint32_t emLen, const unsigned char *from, uint32_t fLen, const unsigned char *pHash, const unsigned char *seed); TPM_RESULT TPM_RSA_padding_check_PKCS1_OAEP(unsigned char *to, uint32_t *tLen, uint32_t tSize, const unsigned char *em, uint32_t emLen, unsigned char *pHash, unsigned char *seed); /* Digest functions - SHA-1 and HMAC */ TPM_RESULT TPM_SHA1(TPM_DIGEST md, ...); TPM_RESULT TPM_SHA1_Check(TPM_DIGEST digest_expect, ...); TPM_RESULT TPM_SHA1Sbuffer(TPM_DIGEST tpm_digest, TPM_STORE_BUFFER *sbuffer); TPM_RESULT TPM_SHA1_GenerateStructure(TPM_DIGEST tpm_digest, void *tpmStructure, TPM_STORE_FUNCTION_T storeFunction); TPM_RESULT TPM_SHA1_CheckStructure(TPM_DIGEST expected_digest, void *tpmStructure, TPM_STORE_FUNCTION_T storeFunction, TPM_RESULT error); TPM_RESULT TPM_HMAC_GenerateSbuffer(TPM_HMAC tpm_hmac, const TPM_SECRET hmac_key, TPM_STORE_BUFFER *sbuffer); TPM_RESULT TPM_HMAC_GenerateStructure(TPM_HMAC tpm_hmac, const TPM_SECRET hmac_key, void *tpmStructure, TPM_STORE_FUNCTION_T storeFunction); TPM_RESULT TPM_HMAC_Generate(TPM_HMAC tpm_hmac, const TPM_SECRET hmac_key, ...); TPM_RESULT TPM_HMAC_CheckSbuffer(TPM_BOOL *valid, TPM_HMAC expect, const TPM_SECRET hmac_key, TPM_STORE_BUFFER *sbuffer); TPM_RESULT TPM_HMAC_Check(TPM_BOOL *valid, TPM_HMAC expect, const TPM_SECRET key, ...); TPM_RESULT TPM_HMAC_CheckStructure(const TPM_SECRET hmac_key, void *structure, TPM_HMAC expect, TPM_STORE_FUNCTION_T storeFunction, TPM_RESULT error); /* XOR */ void TPM_XOR(unsigned char *out, const unsigned char *in1, const unsigned char *in2, size_t length); /* MGF1 */ TPM_RESULT TPM_MGF1(unsigned char *array, uint32_t arrayLen, const unsigned char *seed, uint32_t seedLen); TPM_RESULT TPM_MGF1_GenerateArray(unsigned char **array, uint32_t arrayLen, uint32_t seedLen, ...); /* bignum */ TPM_RESULT TPM_bn2binMalloc(unsigned char **bin, unsigned int *bytes, TPM_BIGNUM bn_in, uint32_t padBytes); TPM_RESULT TPM_bn2binArray(unsigned char *bin, unsigned int bytes, TPM_BIGNUM bn); TPM_RESULT TPM_2bin2bn(TPM_BIGNUM *bignum_in, const unsigned char *bin0, uint32_t size0, const unsigned char *bin1, uint32_t size1); /* Self Test */ TPM_RESULT TPM_CryptoTest(void); /* Processing functions */ TPM_RESULT TPM_Process_Sign(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_SHA1Start(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_SHA1Update(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_SHA1Complete(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_SHA1CompleteExtend(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_GetRandom(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_StirRandom(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_CertifyKey(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_CertifyKey2(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_CertifySelfTest(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); #endif libtpms-0.9.3/src/tpm12/tpm_daa.c000066400000000000000000006123251421143571500165140ustar00rootroot00000000000000/********************************************************************************/ /* */ /* DAA Handler */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_daa.c 4768 2017-07-28 13:19:28Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include #include #include #include "tpm_auth.h" #include "tpm_crypto.h" #include "tpm_cryptoh.h" #include "tpm_debug.h" #include "tpm_error.h" #include "tpm_init.h" #include "tpm_key.h" #include "tpm_memory.h" #include "tpm_nonce.h" #include "tpm_process.h" #include "tpm_sizedbuffer.h" #include "tpm_daa.h" /* TPM_DAA_SESSION_DATA (the entire array) */ void TPM_DaaSessions_Init(TPM_DAA_SESSION_DATA *daaSessions) { size_t i; printf(" TPM_DaaSessions_Init:\n"); for (i = 0 ; i < TPM_MIN_DAA_SESSIONS ; i++) { TPM_DaaSessionData_Init(&(daaSessions[i])); } return; } /* TPM_DaaSessions_Load() reads a count of the number of stored sessions and then loads those sessions. deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_DaaSessions_Init() */ TPM_RESULT TPM_DaaSessions_Load(TPM_DAA_SESSION_DATA *daaSessions, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; size_t i; uint32_t activeCount; printf(" TPM_DaaSessions_Load:\n"); /* load active count */ if (rc == 0) { rc = TPM_Load32(&activeCount, stream, stream_size); } if (rc == 0) { if (activeCount > TPM_MIN_DAA_SESSIONS) { printf("TPM_DaaSessions_Load: Error (fatal) %u sessions, %u slots\n", activeCount, TPM_MIN_DAA_SESSIONS); rc = TPM_FAIL; } } if (rc == 0) { printf(" TPM_DaaSessions_Load: Loading %u sessions\n", activeCount); } /* load DAA sessions */ for (i = 0 ; (rc == 0) && (i < activeCount) ; i++) { rc = TPM_DaaSessionData_Load(&(daaSessions[i]), stream, stream_size); } return rc; } /* TPM_DaaSessions_Store() stores a count of the active sessions, followed by the sessions. serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_DaaSessions_Store(TPM_STORE_BUFFER *sbuffer, TPM_DAA_SESSION_DATA *daaSessions) { TPM_RESULT rc = 0; size_t i; uint32_t space; uint32_t activeCount; /* store active count */ if (rc == 0) { TPM_DaaSessions_GetSpace(&space, daaSessions); activeCount = TPM_MIN_DAA_SESSIONS - space; printf(" TPM_DaaSessions_Store: Storing %u sessions\n", activeCount); rc = TPM_Sbuffer_Append32(sbuffer, activeCount); } /* store DAA sessions */ for (i = 0 ; (rc == 0) && (i < TPM_MIN_DAA_SESSIONS) ; i++) { if ((daaSessions[i]).valid) { /* if the session is active */ rc = TPM_DaaSessionData_Store(sbuffer, &(daaSessions[i])); } } return rc; } /* TPM_DaaSessions_Delete() terminates all loaded DAA sessions */ void TPM_DaaSessions_Delete(TPM_DAA_SESSION_DATA *daaSessions) { size_t i; printf(" TPM_DaaSessions_Delete:\n"); for (i = 0 ; i < TPM_MIN_DAA_SESSIONS ; i++) { TPM_DaaSessionData_Delete(&(daaSessions[i])); } return; } /* TPM_DaaSessions_IsSpace() returns 'isSpace' TRUE if an entry is available, FALSE if not. If TRUE, 'index' holds the first free position. */ void TPM_DaaSessions_IsSpace(TPM_BOOL *isSpace, uint32_t *index, TPM_DAA_SESSION_DATA *daaSessions) { printf(" TPM_DaaSessions_IsSpace:\n"); for (*index = 0, *isSpace = FALSE ; *index < TPM_MIN_DAA_SESSIONS ; (*index)++) { if (!((daaSessions[*index]).valid)) { printf(" TPM_DaaSessions_IsSpace: Found space at %u\n", *index); *isSpace = TRUE; break; } } return; } /* TPM_DaaSessions_GetSpace() returns the number of unused daaHandle's. */ void TPM_DaaSessions_GetSpace(uint32_t *space, TPM_DAA_SESSION_DATA *daaSessions) { uint32_t i; printf(" TPM_DaaSessions_GetSpace:\n"); for (*space = 0 , i = 0 ; i < TPM_MIN_DAA_SESSIONS ; i++) { if (!((daaSessions[i]).valid)) { (*space)++; } } return; } /* TPM_DaaSessions_StoreHandles() stores - the number of loaded sessions - a list of session handles */ TPM_RESULT TPM_DaaSessions_StoreHandles(TPM_STORE_BUFFER *sbuffer, TPM_DAA_SESSION_DATA *daaSessions) { TPM_RESULT rc = 0; uint16_t i; uint32_t space; printf(" TPM_DaaSessions_StoreHandles:\n"); /* get the number of loaded handles */ if (rc == 0) { TPM_DaaSessions_GetSpace(&space, daaSessions); /* store loaded handle count. Safe case because of TPM_MIN_DAA_SESSIONS value */ rc = TPM_Sbuffer_Append16(sbuffer, (uint16_t)(TPM_MIN_DAA_SESSIONS - space)); } for (i = 0 ; (rc == 0) && (i < TPM_MIN_DAA_SESSIONS) ; i++) { if ((daaSessions[i]).valid) { /* if the index is loaded */ rc = TPM_Sbuffer_Append32(sbuffer, (daaSessions[i]).daaHandle); /* store it */ } } return rc; } /* TPM_DaaSessions_GetNewHandle() checks for space in the DAA sessions table. If there is space, it returns a TPM_DAA_SESSION_DATA entry in 'tpm_daa_session_data' and its handle in 'daaHandle'. The entry is marked 'valid'. If *daaHandle non-zero, the suggested value is tried first. Returns TPM_RESOURCES if there is no space in the sessions table. */ TPM_RESULT TPM_DaaSessions_GetNewHandle(TPM_DAA_SESSION_DATA **tpm_daa_session_data, /* entry */ TPM_HANDLE *daaHandle, TPM_BOOL *daaHandleValid, TPM_DAA_SESSION_DATA *daaSessions) /* array */ { TPM_RESULT rc = 0; uint32_t index; TPM_BOOL isSpace; printf(" TPM_DaaSessions_GetNewHandle:\n"); *daaHandle = FALSE; /* is there an empty entry, get the location index */ if (rc == 0) { TPM_DaaSessions_IsSpace(&isSpace, /* TRUE if space available */ &index, /* if space available, index into array */ daaSessions); /* array */ if (!isSpace) { printf("TPM_DaaSessions_GetNewHandle: Error, no space in daaSessions table\n"); rc = TPM_RESOURCES; } } if (rc == 0) { rc = TPM_Handle_GenerateHandle(daaHandle, /* I/O, pointer to handle */ daaSessions, /* handle array */ FALSE, /* keepHandle */ FALSE, /* isKeyHandle */ (TPM_GETENTRY_FUNCTION_T)TPM_DaaSessions_GetEntry); } if (rc == 0) { printf(" TPM_DaaSessions_GetNewHandle: Assigned handle %08x\n", *daaHandle); *tpm_daa_session_data = &(daaSessions[index]); TPM_DaaSessionData_Init(*tpm_daa_session_data); /* should be redundant since terminate should have done this */ (*tpm_daa_session_data)->daaHandle = *daaHandle; (*tpm_daa_session_data)->valid = TRUE; *daaHandleValid = TRUE; } return rc; } /* TPM_DaaSessions_GetEntry() searches all entries for the entry matching the handle, and returns the TPM_DAA_SESSION_DATA entry associated with the handle. Returns 0 for success TPM_BAD_HANDLE if the handle is not found */ TPM_RESULT TPM_DaaSessions_GetEntry(TPM_DAA_SESSION_DATA **tpm_daa_session_data, /* session for daaHandle */ TPM_DAA_SESSION_DATA *daaSessions, /* points to first session in array */ TPM_HANDLE daaHandle) /* input */ { TPM_RESULT rc = 0; size_t i; TPM_BOOL found; printf(" TPM_DaaSessions_GetEntry: daaHandle %08x\n", daaHandle); for (i = 0, found = FALSE ; (i < TPM_MIN_DAA_SESSIONS) && !found ; i++) { if ((daaSessions[i].valid) && (daaSessions[i].daaHandle == daaHandle)) { /* found */ found = TRUE; *tpm_daa_session_data = &(daaSessions[i]); } } if (!found) { printf(" TPM_DaaSessions_GetEntry: session handle %08x not found\n", daaHandle); rc = TPM_BAD_HANDLE; } return rc; } /* TPM_DaaSessions_AddEntry() adds an TPM_DAA_SESSION_DATA object to the list. If *tpm_handle == 0, a value is assigned. If *tpm_handle != 0, that value is used if it it not currently in use. The handle is returned in tpm_handle. */ TPM_RESULT TPM_DaaSessions_AddEntry(TPM_HANDLE *tpm_handle, /* i/o */ TPM_BOOL keepHandle, /* input */ TPM_DAA_SESSION_DATA *daaSessions, /* input */ TPM_DAA_SESSION_DATA *tpm_daa_session_data) /* input */ { TPM_RESULT rc = 0; uint32_t index; TPM_BOOL isSpace; printf(" TPM_DaaSessions_AddEntry:\n"); /* check for valid TPM_DAA_SESSION_DATA */ if (rc == 0) { if (tpm_daa_session_data == NULL) { /* NOTE: should never occur */ printf("TPM_DaaSessions_AddEntry: Error (fatal), NULL TPM_DAA_SESSION_DATA\n"); rc = TPM_FAIL; } } /* is there an empty entry, get the location index */ if (rc == 0) { TPM_DaaSessions_IsSpace(&isSpace, &index, daaSessions); if (!isSpace) { printf("TPM_DaaSessions_AddEntry: Error, session entries full\n"); rc = TPM_RESOURCES; } } if (rc == 0) { rc = TPM_Handle_GenerateHandle(tpm_handle, /* I/O */ daaSessions, /* handle array */ keepHandle, /* keepHandle */ FALSE, /* isKeyHandle */ (TPM_GETENTRY_FUNCTION_T)TPM_DaaSessions_GetEntry); } if (rc == 0) { TPM_DaaSessionData_Copy(&(daaSessions[index]), *tpm_handle, tpm_daa_session_data); daaSessions[index].valid = TRUE; printf(" TPM_DaaSessions_AddEntry: Index %u handle %08x\n", index, daaSessions[index].daaHandle); } return rc; } /* TPM_DaaSessions_TerminateHandle() terminates the session associated with 'daaHandle'. */ TPM_RESULT TPM_DaaSessions_TerminateHandle(TPM_DAA_SESSION_DATA *daaSessions, TPM_HANDLE daaHandle) { TPM_RESULT rc = 0; TPM_DAA_SESSION_DATA *tpm_daa_session_data; printf(" TPM_DaaSessions_TerminateHandle: daaHandle %08x\n", daaHandle); /* get the TPM_DAA_SESSION_DATA associated with the TPM_HANDLE */ if (rc == 0) { rc = TPM_DaaSessions_GetEntry(&tpm_daa_session_data, /* returns entry in array */ daaSessions, /* array */ daaHandle); } /* invalidate the valid handle */ if (rc == 0) { TPM_DaaSessionData_Delete(tpm_daa_session_data); } return rc; } /* TPM_DAA_SESSION_DATA (one element of the array) */ /* TPM_DaaSessionData_Init() initializes the DAA session. sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_DaaSessionData_Init(TPM_DAA_SESSION_DATA *tpm_daa_session_data) { printf(" TPM_DaaSessionData_Init:\n"); TPM_DAAIssuer_Init(&(tpm_daa_session_data->DAA_issuerSettings)); TPM_DAATpm_Init(&(tpm_daa_session_data->DAA_tpmSpecific)); TPM_DAAContext_Init(&(tpm_daa_session_data->DAA_session)); TPM_DAAJoindata_Init(&(tpm_daa_session_data->DAA_joinSession)); tpm_daa_session_data->daaHandle = 0; tpm_daa_session_data->valid = FALSE; return; } /* TPM_DaaSessionData_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_DaaSessionData_Init() After use, call TPM_DaaSessionData_Delete() to free memory */ TPM_RESULT TPM_DaaSessionData_Load(TPM_DAA_SESSION_DATA *tpm_daa_session_data, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_DaaSessionData_Load:\n"); /* load DAA_issuerSettings */ if (rc == 0) { rc = TPM_DAAIssuer_Load(&(tpm_daa_session_data->DAA_issuerSettings), stream, stream_size); } /* load DAA_tpmSpecific */ if (rc == 0) { rc = TPM_DAATpm_Load(&(tpm_daa_session_data->DAA_tpmSpecific), stream, stream_size); } /* load DAA_session */ if (rc == 0) { rc = TPM_DAAContext_Load(&(tpm_daa_session_data->DAA_session),stream, stream_size); } /* load DAA_joinSession */ if (rc == 0) { rc = TPM_DAAJoindata_Load(&(tpm_daa_session_data->DAA_joinSession), stream, stream_size); } /* load daaHandle */ if (rc == 0) { rc = TPM_Load32(&(tpm_daa_session_data->daaHandle), stream, stream_size); } /* set valid */ if (rc == 0) { tpm_daa_session_data->valid = TRUE; } return rc; } /* TPM_DaaSessionData_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_DaaSessionData_Store(TPM_STORE_BUFFER *sbuffer, const TPM_DAA_SESSION_DATA *tpm_daa_session_data) { TPM_RESULT rc = 0; printf(" TPM_DaaSessionData_Store:\n"); /* store DAA_issuerSettings */ if (rc == 0) { rc = TPM_DAAIssuer_Store(sbuffer, &(tpm_daa_session_data->DAA_issuerSettings)); } /* store DAA_tpmSpecific */ if (rc == 0) { rc = TPM_DAATpm_Store(sbuffer, &(tpm_daa_session_data->DAA_tpmSpecific)); } /* store DAA_session */ if (rc == 0) { rc = TPM_DAAContext_Store(sbuffer, &(tpm_daa_session_data->DAA_session)); } /* store DAA_joinSession */ if (rc == 0) { rc = TPM_DAAJoindata_Store(sbuffer, &(tpm_daa_session_data->DAA_joinSession)); } /* store daaHandle */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_daa_session_data->daaHandle); } return rc; } /* TPM_DaaSessionData_Delete() terminates the DAA session. No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_DaaSessionData_Init to set members back to default values The object itself is not freed */ void TPM_DaaSessionData_Delete(TPM_DAA_SESSION_DATA *tpm_daa_session_data) { printf(" TPM_DaaSessionData_Delete:\n"); if (tpm_daa_session_data != NULL) { TPM_DAAIssuer_Delete(&(tpm_daa_session_data->DAA_issuerSettings)); TPM_DAATpm_Delete(&(tpm_daa_session_data->DAA_tpmSpecific)); TPM_DAAContext_Delete(&(tpm_daa_session_data->DAA_session)); TPM_DAAJoindata_Delete(&(tpm_daa_session_data->DAA_joinSession)); TPM_DaaSessionData_Init(tpm_daa_session_data); } return; } /* TPM_DaaSessionData_Copy() copies the source to the destination. The source handle is ignored, since it might already be used. */ void TPM_DaaSessionData_Copy(TPM_DAA_SESSION_DATA *dest_daa_session_data, TPM_HANDLE tpm_handle, TPM_DAA_SESSION_DATA *src_daa_session_data) { dest_daa_session_data->daaHandle = tpm_handle; TPM_DAAIssuer_Copy(&(dest_daa_session_data->DAA_issuerSettings), &(src_daa_session_data->DAA_issuerSettings)); TPM_DAATpm_Copy(&(dest_daa_session_data->DAA_tpmSpecific), &(src_daa_session_data->DAA_tpmSpecific)); TPM_DAAContext_Copy(&(dest_daa_session_data->DAA_session), &(src_daa_session_data->DAA_session)); TPM_DAAJoindata_Copy(&(dest_daa_session_data->DAA_joinSession), &(src_daa_session_data->DAA_joinSession)); dest_daa_session_data->valid= src_daa_session_data->valid; return; } /* TPM_DaaSessionData_CheckStage() verifies that the actual command processing stage is consistent with the stage expected by the TPM state. */ TPM_RESULT TPM_DaaSessionData_CheckStage(TPM_DAA_SESSION_DATA *tpm_daa_session_data, BYTE stage) { TPM_RESULT rc = 0; printf(" TPM_DaaSessionData_CheckStage:\n"); if (tpm_daa_session_data->DAA_session.DAA_stage != stage) { printf("TPM_DaaSessionData_CheckStage: Error, stage expected %u actual %u\n", tpm_daa_session_data->DAA_session.DAA_stage, stage); rc = TPM_DAA_STAGE; } return rc; } /* TPM_DAA_ISSUER */ /* TPM_DAAIssuer_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_DAAIssuer_Init(TPM_DAA_ISSUER *tpm_daa_issuer) { printf(" TPM_DAAIssuer_Init:\n"); TPM_Digest_Init(tpm_daa_issuer->DAA_digest_R0); TPM_Digest_Init(tpm_daa_issuer->DAA_digest_R1); TPM_Digest_Init(tpm_daa_issuer->DAA_digest_S0); TPM_Digest_Init(tpm_daa_issuer->DAA_digest_S1); TPM_Digest_Init(tpm_daa_issuer->DAA_digest_n); TPM_Digest_Init(tpm_daa_issuer->DAA_digest_gamma); memset(tpm_daa_issuer->DAA_generic_q, 0, sizeof(tpm_daa_issuer->DAA_generic_q)); return; } /* TPM_DAAIssuer_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_DAAIssuer_Init() After use, call TPM_DAAIssuer_Delete() to free memory */ TPM_RESULT TPM_DAAIssuer_Load(TPM_DAA_ISSUER *tpm_daa_issuer, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_DAAIssuer_Load:\n"); /* check tag */ if (rc == 0) { rc = TPM_CheckTag(TPM_TAG_DAA_ISSUER, stream, stream_size); } /* load DAA_digest_R0 */ if (rc == 0) { rc = TPM_Digest_Load(tpm_daa_issuer->DAA_digest_R0, stream, stream_size); } /* load DAA_digest_R1 */ if (rc == 0) { rc = TPM_Digest_Load(tpm_daa_issuer->DAA_digest_R1, stream, stream_size); } /* load DAA_digest_S0 */ if (rc == 0) { rc = TPM_Digest_Load(tpm_daa_issuer->DAA_digest_S0, stream, stream_size); } /* load DAA_digest_S1 */ if (rc == 0) { rc = TPM_Digest_Load(tpm_daa_issuer->DAA_digest_S1, stream, stream_size); } /* load DAA_digest_n */ if (rc == 0) { rc = TPM_Digest_Load(tpm_daa_issuer->DAA_digest_n, stream, stream_size); } /* load DAA_digest_gamma */ if (rc == 0) { rc = TPM_Digest_Load (tpm_daa_issuer->DAA_digest_gamma, stream, stream_size); } /* load DAA_generic_q */ if (rc == 0) { rc = TPM_Loadn(tpm_daa_issuer->DAA_generic_q, sizeof(tpm_daa_issuer->DAA_generic_q), stream, stream_size); } return rc; } /* TPM_DAAIssuer_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_DAAIssuer_Store(TPM_STORE_BUFFER *sbuffer, const TPM_DAA_ISSUER *tpm_daa_issuer) { TPM_RESULT rc = 0; printf(" TPM_DAAIssuer_Store:\n"); /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_DAA_ISSUER); } /* store DAA_digest_R0 */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_daa_issuer->DAA_digest_R0); } /* store DAA_digest_R1 */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_daa_issuer->DAA_digest_R1); } /* store DAA_digest_S0 */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_daa_issuer->DAA_digest_S0); } /* store DAA_digest_S1 */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_daa_issuer->DAA_digest_S1); } /* store DAA_digest_n */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_daa_issuer->DAA_digest_n); } /* store DAA_digest_gamma */ if (rc == 0) { rc = TPM_Digest_Store (sbuffer, tpm_daa_issuer->DAA_digest_gamma); } /* store DAA_generic_q */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, tpm_daa_issuer->DAA_generic_q, sizeof(tpm_daa_issuer->DAA_generic_q)); } return rc; } /* TPM_DAAIssuer_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_DAAIssuer_Init to set members back to default values The object itself is not freed */ void TPM_DAAIssuer_Delete(TPM_DAA_ISSUER *tpm_daa_issuer) { printf(" TPM_DAAIssuer_Delete:\n"); if (tpm_daa_issuer != NULL) { TPM_DAAIssuer_Init(tpm_daa_issuer); } return; } /* TPM_DAAIssuer_Copy() copies the source to the destination */ void TPM_DAAIssuer_Copy(TPM_DAA_ISSUER *dest_daa_issuer, TPM_DAA_ISSUER *src_daa_issuer) { printf(" TPM_DAAIssuer_Copy:\n"); TPM_Digest_Copy(dest_daa_issuer->DAA_digest_R0, src_daa_issuer->DAA_digest_R0); TPM_Digest_Copy(dest_daa_issuer->DAA_digest_R1, src_daa_issuer->DAA_digest_R1); TPM_Digest_Copy(dest_daa_issuer->DAA_digest_S0, src_daa_issuer->DAA_digest_S0); TPM_Digest_Copy(dest_daa_issuer->DAA_digest_S1, src_daa_issuer->DAA_digest_S1); TPM_Digest_Copy(dest_daa_issuer->DAA_digest_n, src_daa_issuer->DAA_digest_n); TPM_Digest_Copy(dest_daa_issuer->DAA_digest_gamma, src_daa_issuer->DAA_digest_gamma); memcpy(dest_daa_issuer->DAA_generic_q, src_daa_issuer->DAA_generic_q, sizeof(src_daa_issuer->DAA_generic_q)); return; } /* TPM_DAA_TPM */ /* TPM_DAATpm_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_DAATpm_Init(TPM_DAA_TPM *tpm_daa_tpm) { printf(" TPM_DAATpm_Init:\n"); TPM_Digest_Init(tpm_daa_tpm->DAA_digestIssuer); TPM_Digest_Init(tpm_daa_tpm->DAA_digest_v0); TPM_Digest_Init(tpm_daa_tpm->DAA_digest_v1); TPM_Digest_Init(tpm_daa_tpm->DAA_rekey); tpm_daa_tpm->DAA_count = 0; return; } /* TPM_DAATpm_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_DAATpm_Init() After use, call TPM_DAATpm_Delete() to free memory */ TPM_RESULT TPM_DAATpm_Load(TPM_DAA_TPM *tpm_daa_tpm, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_DAATpm_Load:\n"); /* check tag */ if (rc == 0) { rc = TPM_CheckTag(TPM_TAG_DAA_TPM, stream, stream_size); } /* load DAA_digestIssuer */ if (rc == 0) { rc = TPM_Digest_Load(tpm_daa_tpm->DAA_digestIssuer, stream, stream_size); } /* load DAA_digest_v0 */ if (rc == 0) { rc = TPM_Digest_Load(tpm_daa_tpm->DAA_digest_v0, stream, stream_size); } /* load DAA_digest_v1 */ if (rc == 0) { rc = TPM_Digest_Load(tpm_daa_tpm->DAA_digest_v1, stream, stream_size); } /* load DAA_rekey */ if (rc == 0) { rc = TPM_Digest_Load(tpm_daa_tpm->DAA_rekey, stream, stream_size); } /* load DAA_count */ if (rc == 0) { rc = TPM_Load32(&(tpm_daa_tpm->DAA_count), stream, stream_size); } return rc; } /* TPM_DAATpm_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_DAATpm_Store(TPM_STORE_BUFFER *sbuffer, const TPM_DAA_TPM *tpm_daa_tpm) { TPM_RESULT rc = 0; printf(" TPM_DAATpm_Store:\n"); /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_DAA_TPM); } /* store DAA_digestIssuer */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_daa_tpm->DAA_digestIssuer); } /* store DAA_digest_v0 */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_daa_tpm->DAA_digest_v0); } /* store DAA_digest_v1 */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_daa_tpm->DAA_digest_v1); } /* store DAA_rekey */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_daa_tpm->DAA_rekey); } /* store DAA_count */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_daa_tpm->DAA_count); } return rc; } /* TPM_DAATpm_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_DAATpm_Init to set members back to default values The object itself is not freed */ void TPM_DAATpm_Delete(TPM_DAA_TPM *tpm_daa_tpm) { printf(" TPM_DAATpm_Delete:\n"); if (tpm_daa_tpm != NULL) { TPM_DAATpm_Init(tpm_daa_tpm); } return; } /* TPM_DAATpm_Copy() copies the source to the destination */ void TPM_DAATpm_Copy(TPM_DAA_TPM *dest_daa_tpm, TPM_DAA_TPM *src_daa_tpm) { printf(" TPM_DAATpm_Copy:\n"); TPM_Digest_Copy(dest_daa_tpm->DAA_digestIssuer, src_daa_tpm->DAA_digestIssuer); TPM_Digest_Copy(dest_daa_tpm->DAA_digest_v0, src_daa_tpm->DAA_digest_v0); TPM_Digest_Copy(dest_daa_tpm->DAA_digest_v1, src_daa_tpm->DAA_digest_v1); TPM_Digest_Copy(dest_daa_tpm->DAA_rekey, src_daa_tpm->DAA_rekey); dest_daa_tpm->DAA_count = src_daa_tpm->DAA_count; return; } /* TPM_DAA_CONTEXT */ /* TPM_DAAContext_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_DAAContext_Init(TPM_DAA_CONTEXT *tpm_daa_context) { printf(" TPM_DAAContext_Init:\n"); TPM_Digest_Init(tpm_daa_context->DAA_digestContext); TPM_Digest_Init(tpm_daa_context->DAA_digest); TPM_Nonce_Init(tpm_daa_context->DAA_contextSeed); memset(tpm_daa_context->DAA_scratch, 0, sizeof(tpm_daa_context->DAA_scratch)); tpm_daa_context->DAA_stage = 0; tpm_daa_context->DAA_scratch_null = TRUE; return; } /* TPM_DAAContext_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_DAAContext_Init() After use, call TPM_DAAContext_Delete() to free memory */ TPM_RESULT TPM_DAAContext_Load(TPM_DAA_CONTEXT *tpm_daa_context, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_DAAContext_Load:\n"); /* check tag */ if (rc == 0) { rc = TPM_CheckTag(TPM_TAG_DAA_CONTEXT, stream, stream_size); } /* load DAA_digestContext */ if (rc == 0) { rc = TPM_Digest_Load(tpm_daa_context->DAA_digestContext, stream, stream_size); } /* load DAA_digest */ if (rc == 0) { rc = TPM_Digest_Load(tpm_daa_context->DAA_digest, stream, stream_size); } /* load DAA_contextSeed */ if (rc == 0) { rc = TPM_Nonce_Load(tpm_daa_context->DAA_contextSeed, stream, stream_size); } /* load DAA_scratch */ if (rc == 0) { rc = TPM_Loadn(tpm_daa_context->DAA_scratch, sizeof(tpm_daa_context->DAA_scratch), stream, stream_size); } /* load DAA_stage */ if (rc == 0) { rc = TPM_Load8(&(tpm_daa_context->DAA_stage), stream, stream_size); } /* load DAA_scratch_null */ if (rc == 0) { rc = TPM_LoadBool(&(tpm_daa_context->DAA_scratch_null), stream, stream_size); } return rc; } /* TPM_DAAContext_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_DAAContext_Store(TPM_STORE_BUFFER *sbuffer, const TPM_DAA_CONTEXT *tpm_daa_context) { TPM_RESULT rc = 0; printf(" TPM_DAAContext_Store:\n"); /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_DAA_CONTEXT); } /* store DAA_digestContext */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_daa_context->DAA_digestContext); } /* store DAA_digest */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_daa_context->DAA_digest); } /* store DAA_contextSeed */ if (rc == 0) { rc = TPM_Nonce_Store(sbuffer, tpm_daa_context->DAA_contextSeed); } /* store DAA_scratch */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, tpm_daa_context->DAA_scratch, sizeof(tpm_daa_context->DAA_scratch)); } /* store DAA_stage */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_daa_context->DAA_stage), sizeof(BYTE)); } /* store DAA_scratch_null */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_daa_context->DAA_scratch_null), sizeof(TPM_BOOL)); } return rc; } /* TPM_DAAContext_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_DAAContext_Init to set members back to default values The object itself is not freed */ void TPM_DAAContext_Delete(TPM_DAA_CONTEXT *tpm_daa_context) { printf(" TPM_DAAContext_Delete:\n"); if (tpm_daa_context != NULL) { TPM_DAAContext_Init(tpm_daa_context); } return; } /* TPM_DAAContext_Copy() copies the source to the destination */ void TPM_DAAContext_Copy(TPM_DAA_CONTEXT *dest_daa_context, TPM_DAA_CONTEXT *src_daa_context) { printf(" TPM_DAAContext_Copy:\n"); TPM_Digest_Copy(dest_daa_context->DAA_digestContext, src_daa_context->DAA_digestContext); TPM_Digest_Copy(dest_daa_context->DAA_digest, src_daa_context->DAA_digest); TPM_Nonce_Copy(dest_daa_context->DAA_contextSeed, src_daa_context->DAA_contextSeed); memcpy(dest_daa_context->DAA_scratch, src_daa_context->DAA_scratch, sizeof(src_daa_context->DAA_scratch)); dest_daa_context->DAA_stage = src_daa_context->DAA_stage; dest_daa_context->DAA_scratch_null = src_daa_context->DAA_scratch_null; return; } /* TPM_DAA_JOINDATA */ /* TPM_DAAJoindata_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_DAAJoindata_Init(TPM_DAA_JOINDATA *tpm_daa_joindata) { printf(" TPM_DAAJoindata_Init:\n"); memset(tpm_daa_joindata->DAA_join_u0, 0, sizeof(tpm_daa_joindata->DAA_join_u0)); memset(tpm_daa_joindata->DAA_join_u1, 0, sizeof(tpm_daa_joindata->DAA_join_u1)); TPM_Digest_Init(tpm_daa_joindata->DAA_digest_n0); return; } /* TPM_DAAJoindata_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_DAAJoindata_Init() After use, call TPM_DAAJoindata_Delete() to free memory */ TPM_RESULT TPM_DAAJoindata_Load(TPM_DAA_JOINDATA *tpm_daa_joindata, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_DAAJoindata_Load:\n"); /* load DAA_join_u0 */ if (rc == 0) { rc = TPM_Loadn(tpm_daa_joindata->DAA_join_u0, sizeof(tpm_daa_joindata->DAA_join_u0), stream, stream_size); } /* load DAA_join_u1 */ if (rc == 0) { rc = TPM_Loadn(tpm_daa_joindata->DAA_join_u1, sizeof(tpm_daa_joindata->DAA_join_u1), stream, stream_size); } /* load DAA_digest_n0 */ if (rc == 0) { rc = TPM_Digest_Load(tpm_daa_joindata->DAA_digest_n0, stream, stream_size); } return rc; } /* TPM_DAAJoindata_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_DAAJoindata_Store(TPM_STORE_BUFFER *sbuffer, const TPM_DAA_JOINDATA *tpm_daa_joindata) { TPM_RESULT rc = 0; printf(" TPM_DAAJoindata_Store:\n"); /* store DAA_join_u0 */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, tpm_daa_joindata->DAA_join_u0, sizeof(tpm_daa_joindata->DAA_join_u0)); } /* store DAA_join_u1 */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, tpm_daa_joindata->DAA_join_u1, sizeof(tpm_daa_joindata->DAA_join_u1)); } /* store DAA_digest_n0 */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_daa_joindata->DAA_digest_n0); } return rc; } /* TPM_DAAJoindata_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_DAAJoindata_Init to set members back to default values The object itself is not freed */ void TPM_DAAJoindata_Delete(TPM_DAA_JOINDATA *tpm_daa_joindata) { printf(" TPM_DAAJoindata_Delete:\n"); if (tpm_daa_joindata != NULL) { TPM_DAAJoindata_Init(tpm_daa_joindata); } return; } /* TPM_DAAJoindata_Copy() copies the source to the destination */ void TPM_DAAJoindata_Copy(TPM_DAA_JOINDATA *dest_daa_joindata, TPM_DAA_JOINDATA *src_daa_joindata) { printf(" TPM_DAAJoindata_Copy:\n"); memcpy(dest_daa_joindata->DAA_join_u0, src_daa_joindata->DAA_join_u0, sizeof(src_daa_joindata->DAA_join_u0)); memcpy(dest_daa_joindata->DAA_join_u1, src_daa_joindata->DAA_join_u1, sizeof(src_daa_joindata->DAA_join_u1)); TPM_Digest_Copy(dest_daa_joindata->DAA_digest_n0, src_daa_joindata->DAA_digest_n0); return; } /* TPM_DAA_BLOB */ /* TPM_DAABlob_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_DAABlob_Init(TPM_DAA_BLOB *tpm_daa_blob) { printf(" TPM_DAABlob_Init:\n"); tpm_daa_blob->resourceType = 0; memset(tpm_daa_blob->label, 0, sizeof(tpm_daa_blob->label)); TPM_Digest_Init(tpm_daa_blob->blobIntegrity); TPM_SizedBuffer_Init(&(tpm_daa_blob->additionalData)); TPM_SizedBuffer_Init(&(tpm_daa_blob->sensitiveData)); return; } /* TPM_DAABlob_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_DAABlob_Init() After use, call TPM_DAABlob_Delete() to free memory */ TPM_RESULT TPM_DAABlob_Load(TPM_DAA_BLOB *tpm_daa_blob, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_DAABlob_Load:\n"); /* check tag */ if (rc == 0) { rc = TPM_CheckTag(TPM_TAG_DAA_BLOB, stream, stream_size); } /* load resourceType */ if (rc == 0) { rc = TPM_Load32(&(tpm_daa_blob->resourceType), stream, stream_size); } /* load label */ if (rc == 0) { rc = TPM_Loadn(tpm_daa_blob->label, sizeof(tpm_daa_blob->label), stream, stream_size); } /* load blobIntegrity */ if (rc == 0) { rc = TPM_Digest_Load(tpm_daa_blob->blobIntegrity, stream, stream_size); } /* load additionalData */ if (rc == 0) { rc = TPM_SizedBuffer_Load(&(tpm_daa_blob->additionalData), stream, stream_size); } /* load sensitiveData */ if (rc == 0) { rc = TPM_SizedBuffer_Load(&(tpm_daa_blob->sensitiveData), stream, stream_size); } return rc; } /* TPM_DAABlob_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_DAABlob_Store(TPM_STORE_BUFFER *sbuffer, const TPM_DAA_BLOB *tpm_daa_blob) { TPM_RESULT rc = 0; printf(" TPM_DAABlob_Store:\n"); /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_DAA_BLOB); } /* store resourceType */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_daa_blob->resourceType); } /* store label */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, tpm_daa_blob->label, sizeof(tpm_daa_blob->label)); } /* store blobIntegrity */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_daa_blob->blobIntegrity); } /* store additionalData */ if (rc == 0) { rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_daa_blob->additionalData)); } /* store sensitiveData */ if (rc == 0) { rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_daa_blob->sensitiveData)); } return rc; } /* TPM_DAABlob_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_DAABlob_Init to set members back to default values The object itself is not freed */ void TPM_DAABlob_Delete(TPM_DAA_BLOB *tpm_daa_blob) { printf(" TPM_DAABlob_Delete:\n"); if (tpm_daa_blob != NULL) { TPM_SizedBuffer_Delete(&(tpm_daa_blob->additionalData)); TPM_SizedBuffer_Delete(&(tpm_daa_blob->sensitiveData)); TPM_DAABlob_Init(tpm_daa_blob); } return; } /* TPM_DAA_SENSITIVE */ /* TPM_DAASensitive_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_DAASensitive_Init(TPM_DAA_SENSITIVE *tpm_daa_sensitive) { printf(" TPM_DAASensitive_Init:\n"); TPM_SizedBuffer_Init(&(tpm_daa_sensitive->internalData)); return; } /* TPM_DAASensitive_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_DAASensitive_Init() After use, call TPM_DAASensitive_Delete() to free memory */ TPM_RESULT TPM_DAASensitive_Load(TPM_DAA_SENSITIVE *tpm_daa_sensitive, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_DAASensitive_Load:\n"); /* check tag */ if (rc == 0) { rc = TPM_CheckTag(TPM_TAG_DAA_SENSITIVE, stream, stream_size); } /* load internalData */ if (rc == 0) { rc = TPM_SizedBuffer_Load(&(tpm_daa_sensitive->internalData), stream, stream_size); } return rc; } /* TPM_DAASensitive_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_DAASensitive_Store(TPM_STORE_BUFFER *sbuffer, const TPM_DAA_SENSITIVE *tpm_daa_sensitive) { TPM_RESULT rc = 0; printf(" TPM_DAASensitive_Store:\n"); /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_DAA_SENSITIVE); } /* store internalData */ if (rc == 0) { rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_daa_sensitive->internalData)); } return rc; } /* TPM_DAASensitive_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_DAASensitive_Init to set members back to default values The object itself is not freed */ void TPM_DAASensitive_Delete(TPM_DAA_SENSITIVE *tpm_daa_sensitive) { printf(" TPM_DAASensitive_Delete:\n"); if (tpm_daa_sensitive != NULL) { TPM_SizedBuffer_Delete(&(tpm_daa_sensitive->internalData)); TPM_DAASensitive_Init(tpm_daa_sensitive); } return; } /* Processing Common Stage Functions */ TPM_RESULT TPM_DAAJoin_Stage00(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA **tpm_daa_session_data, TPM_BOOL *daaHandleValid, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0) { TPM_RESULT rc = 0; unsigned char *stream; uint32_t stream_size; uint32_t count; TPM_HANDLE daaHandle = 0; /* no preassigned handle */ printf("TPM_DAAJoin_Stage00:\n"); if (rc == 0) { /* a. Determine that sufficient resources are available to perform a TPM_DAA_Join. */ /* i. The TPM MUST support sufficient resources to perform one (1) TPM_DAA_Join/TPM_DAA_Sign. The TPM MAY support additional TPM_DAA_Join/TPM_DAA_Sign sessions. */ /* ii. The TPM may share internal resources between the DAA operations and other variable resource requirements: */ /* iii. If there are insufficient resources within the stored key pool (and one or more keys need to be removed to permit the DAA operation to execute) return TPM_NOSPACE */ /* iv. If there are insufficient resources within the stored session pool (and one or more authorization or transport sessions need to be removed to permit the DAA operation to execute), return TPM_RESOURCES. */ rc = TPM_DaaSessions_GetNewHandle(tpm_daa_session_data, &daaHandle, /* output */ daaHandleValid, /* output */ tpm_state->tpm_stclear_data.daaSessions); /* array */ } if (rc == 0) { /* b. Set all fields in DAA_issuerSettings = NULL */ /* c. set all fields in DAA_tpmSpecific = NULL */ /* d. set all fields in DAA_session = NULL */ /* e. Set all fields in DAA_joinSession = NULL */ /* NOTE Done by TPM_DaaSessions_GetNewHandle() */ /* f. Verify that sizeOf(inputData0) == sizeof(DAA_tpmSpecific -> DAA_count) and return error TPM_DAA_INPUT_DATA0 on mismatch */ if (inputData0->size != sizeof((*tpm_daa_session_data)->DAA_tpmSpecific.DAA_count)) { printf("TPM_DAAJoin_Stage00: Error, inputData0 size %u should be %lu\n", inputData0->size, (unsigned long)sizeof((*tpm_daa_session_data)->DAA_tpmSpecific.DAA_count)); rc = TPM_DAA_INPUT_DATA0; } } if (rc == 0) { /* g. Verify that inputData0 > 0, and return error TPM_DAA_INPUT_DATA0 on mismatch */ stream = inputData0->buffer; stream_size = inputData0->size; rc = TPM_Load32(&count, &stream, &stream_size); if (rc != 0) { rc = TPM_DAA_INPUT_DATA0; } } if (rc == 0) { printf("TPM_DAAJoin_Stage00: count %u\n", count); if (count == 0) { printf("TPM_DAAJoin_Stage00: Error, count is zero\n"); rc = TPM_DAA_INPUT_DATA0; } } if (rc == 0) { /* h. Set DAA_tpmSpecific -> DAA_count = inputData0 */ (*tpm_daa_session_data)->DAA_tpmSpecific.DAA_count = count; /* i. set DAA_session -> DAA_digestContext = SHA-1(DAA_tpmSpecific || DAA_joinSession) */ rc = TPM_DAADigestContext_GenerateDigestJoin ((*tpm_daa_session_data)->DAA_session.DAA_digestContext, (*tpm_daa_session_data)); } if (rc == 0) { /* j. set DAA_session -> DAA_stage = 1 */ (*tpm_daa_session_data)->DAA_session.DAA_stage = 1; /* k. Assign session handle for TPM_DAA_Join */ /* NOTE Done by TPM_DaaSessions_GetNewHandle() */ printf("TPM_DAAJoin_Stage00: handle %08x\n", (*tpm_daa_session_data)->daaHandle); /* l. set outputData = new session handle */ /* i. The handle in outputData is included the output HMAC. */ rc = TPM_SizedBuffer_Append32(outputData, (*tpm_daa_session_data)->daaHandle); } /* m. return TPM_SUCCESS */ return rc; } TPM_RESULT TPM_DAAJoin_Stage01(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0, TPM_SIZED_BUFFER *inputData1) { TPM_RESULT rc = 0; TPM_DIGEST signedDataDigest; printf("TPM_DAAJoin_Stage01:\n"); outputData = outputData; /* not used */ /* a. Verify that DAA_session ->DAA_stage==1. Return TPM_DAA_STAGE and flush handle on mismatch */ /* NOTE Done by common code */ /* b. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) and return TPM_DAA_TPM_SETTINGS on mismatch */ /* NOTE Done by common code */ /* c. Verify that sizeOf(inputData0) == DAA_SIZE_issuerModulus and return error TPM_DAA_INPUT_DATA0 on mismatch */ if (rc == 0) { if (inputData0->size != DAA_SIZE_issuerModulus) { printf("TPM_DAAJoin_Stage01: Error, bad input0 size %u\n", inputData0->size); rc = TPM_DAA_INPUT_DATA0; } } if (rc == 0) { /* d. If DAA_session -> DAA_scratch == NULL: */ if (tpm_daa_session_data->DAA_session.DAA_scratch_null) { printf("TPM_DAAJoin_Stage01: DAA_scratch null\n"); if (rc == 0) { /* i. Set DAA_session -> DAA_scratch = inputData0 */ tpm_daa_session_data->DAA_session.DAA_scratch_null = FALSE; memcpy(tpm_daa_session_data->DAA_session.DAA_scratch, inputData0->buffer, DAA_SIZE_issuerModulus); /* ii. set DAA_joinSession -> DAA_digest_n0 = SHA-1(DAA_session -> DAA_scratch) */ rc = TPM_SHA1(tpm_daa_session_data->DAA_joinSession.DAA_digest_n0, sizeof(tpm_daa_session_data->DAA_session.DAA_scratch), tpm_daa_session_data->DAA_session.DAA_scratch, 0, NULL); } /* iii. set DAA_tpmSpecific -> DAA_rekey = SHA-1(tpmDAASeed || DAA_joinSession -> DAA_digest_n0) */ if (rc == 0) { rc = TPM_SHA1(tpm_daa_session_data->DAA_tpmSpecific.DAA_rekey, TPM_NONCE_SIZE, tpm_state->tpm_permanent_data.tpmDAASeed, TPM_DIGEST_SIZE, tpm_daa_session_data->DAA_joinSession.DAA_digest_n0, 0, NULL); } } /* e. Else (If DAA_session -> DAA_scratch != NULL): */ else { printf("TPM_DAAJoin_Stage01: DAA_scratch not null\n"); /* i. Set signedData = inputData0 */ /* ii. Verify that sizeOf(inputData1) == DAA_SIZE_issuerModulus and return error TPM_DAA_INPUT_DATA1 on mismatch */ if (rc == 0) { if (inputData1->size != DAA_SIZE_issuerModulus) { printf("TPM_DAAJoin_Stage01: Error, bad input1 size %u\n", inputData1->size); rc = TPM_DAA_INPUT_DATA1; } } /* iii. Set signatureValue = inputData1 */ /* iv. Use the RSA key == [DAA_session -> DAA_scratch] to verify that signatureValue is a signature on signedData using TPM_SS_RSASSAPKCS1v15_SHA1 (RSA PKCS1.5 with SHA-1), and return error TPM_DAA_ISSUER_VALIDITY on mismatch */ if (rc == 0) { printf("TPM_DAAJoin_Stage01: Digesting signedData\n"); rc = TPM_SHA1(signedDataDigest, inputData0->size, inputData0->buffer, 0, NULL); } if (rc == 0) { printf("TPM_DAAJoin_Stage01: Verifying signature\n"); rc = TPM_RSAVerify(inputData1->buffer, /* signature */ inputData1->size, TPM_SS_RSASSAPKCS1v15_INFO, /* signature scheme */ signedDataDigest, /* signed data */ TPM_DIGEST_SIZE, tpm_daa_session_data->DAA_session.DAA_scratch, /* pub modulus */ sizeof(tpm_daa_session_data->DAA_session.DAA_scratch), tpm_default_rsa_exponent, /* public exponent */ 3); if (rc != 0) { printf("TPM_DAAJoin_Stage01: Error, bad signature\n"); rc = TPM_DAA_ISSUER_VALIDITY; } } /* v. Set DAA_session -> DAA_scratch = signedData */ if (rc == 0) { memcpy(tpm_daa_session_data->DAA_session.DAA_scratch, inputData0->buffer, inputData1->size); } } } if (rc == 0) { /* f. Decrement DAA_tpmSpecific -> DAA_count by 1 (unity) */ tpm_daa_session_data->DAA_tpmSpecific.DAA_count--; /* g. If DAA_tpmSpecific -> DAA_count ==0: */ if (tpm_daa_session_data->DAA_tpmSpecific.DAA_count == 0) { /* h. increment DAA_session -> DAA_Stage by 1 */ tpm_daa_session_data->DAA_session.DAA_stage++; } /* i. set DAA_session -> DAA_digestContext = SHA-1(DAA_tpmSpecific || DAA_joinSession) */ rc = TPM_DAADigestContext_GenerateDigestJoin (tpm_daa_session_data->DAA_session.DAA_digestContext, tpm_daa_session_data); } /* j. set outputData = NULL */ /* NOTE Done by caller */ /* k. return TPM_SUCCESS */ return rc; } TPM_RESULT TPM_DAAJoin_Stage02(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0, TPM_SIZED_BUFFER *inputData1) { TPM_RESULT rc = 0; unsigned char *stream; uint32_t stream_size; TPM_STORE_BUFFER signedDataSbuffer; TPM_DIGEST signedDataDigest; printf("TPM_DAAJoin_Stage02:\n"); outputData = outputData; /* not used */ tpm_state = tpm_state; /* not used */ TPM_Sbuffer_Init(&signedDataSbuffer); /* freed @1*/ /* a. Verify that DAA_session ->DAA_stage==2. Return TPM_DAA_STAGE and flush handle on mismatch */ /* NOTE Done by common code */ /* b. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error TPM_DAA_TPM_SETTINGS on mismatch */ /* NOTE Done by common code */ /* c. Verify that sizeOf(inputData0) == sizeOf(TPM_DAA_ISSUER) and return error TPM_DAA_INPUT_DATA0 on mismatch */ /* NOTE cannot use sizeof because packing may not be exact */ /* d. Set DAA_issuerSettings = inputData0. Verify that all fields in DAA_issuerSettings are present and return error TPM_DAA_INPUT_DATA0 if not. */ if (rc == 0) { stream = inputData0->buffer; stream_size = inputData0->size; rc = TPM_DAAIssuer_Load(&(tpm_daa_session_data->DAA_issuerSettings), &stream, &stream_size); if (rc != 0) { rc = TPM_DAA_INPUT_DATA0; } } if (rc == 0) { if (stream_size != 0) { printf("TPM_DAAJoin_Stage02: Error, bad input0 size %u\n", inputData0->size); rc = TPM_DAA_INPUT_DATA0; } } /* e. Verify that sizeOf(inputData1) == DAA_SIZE_issuerModulus and return error TPM_DAA_INPUT_DATA1 on mismatch */ if (rc == 0) { if (inputData1->size != DAA_SIZE_issuerModulus) { printf("TPM_DAAJoin_Stage02: Error, bad input1 size %u\n", inputData1->size); rc = TPM_DAA_INPUT_DATA1; } } /* f. Set signatureValue = inputData1 */ /* g. Set signedData = (DAA_joinSession -> DAA_digest_n0 || DAA_issuerSettings) */ if (rc == 0) { rc = TPM_Digest_Store(&signedDataSbuffer, tpm_daa_session_data->DAA_joinSession.DAA_digest_n0); } if (rc == 0) { rc = TPM_DAAIssuer_Store(&signedDataSbuffer, &(tpm_daa_session_data->DAA_issuerSettings)); } /* h. Use the RSA key [DAA_session -> DAA_scratch] to verify that signatureValue is a */ /* signature on signedData using TPM_SS_RSASSAPKCS1v15_SHA1 (RSA PKCS1.5 with SHA-1), and return error TPM_DAA_ISSUER_VALIDITY on mismatch */ if (rc == 0) { printf("TPM_DAAJoin_Stage02: Digesting signedData\n"); rc = TPM_SHA1Sbuffer(signedDataDigest, &signedDataSbuffer); } if (rc == 0) { printf("TPM_DAAJoin_Stage02: Verifying signature\n"); rc = TPM_RSAVerify(inputData1->buffer, /* signature */ inputData1->size, TPM_SS_RSASSAPKCS1v15_INFO, /* signature scheme */ signedDataDigest, /* signed data */ TPM_DIGEST_SIZE, tpm_daa_session_data->DAA_session.DAA_scratch, /* public modulus */ sizeof(tpm_daa_session_data->DAA_session.DAA_scratch), tpm_default_rsa_exponent, /* public exponent */ 3); if (rc != 0) { printf("TPM_DAAJoin_Stage02: Error, bad signature\n"); rc = TPM_DAA_ISSUER_VALIDITY; } } /* i. Set DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) */ if (rc == 0) { rc = TPM_SHA1_GenerateStructure(tpm_daa_session_data->DAA_tpmSpecific.DAA_digestIssuer, &(tpm_daa_session_data->DAA_issuerSettings), (TPM_STORE_FUNCTION_T)TPM_DAAIssuer_Store); } /* j. set DAA_session -> DAA_digestContext = SHA-1(DAA_tpmSpecific || DAA_joinSession) */ if (rc == 0) { rc = TPM_DAADigestContext_GenerateDigestJoin (tpm_daa_session_data->DAA_session.DAA_digestContext, tpm_daa_session_data); } if (rc == 0) { /* k. Set DAA_session -> DAA_scratch = NULL */ tpm_daa_session_data->DAA_session.DAA_scratch_null = TRUE; /* l. increment DAA_session -> DAA_stage by 1 */ /* NOTE Done by common code */ } /* m. return TPM_SUCCESS */ TPM_Sbuffer_Delete(&signedDataSbuffer); /* @1*/ return rc; } TPM_RESULT TPM_DAAJoin_Stage03(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0) { TPM_RESULT rc = 0; unsigned char *stream; uint32_t stream_size; printf("TPM_DAAJoin_Stage03:\n"); tpm_state = tpm_state; /* not used */ outputData = outputData; /* not used */ /* a. Verify that DAA_session ->DAA_stage==3. Return TPM_DAA_STAGE and flush handle on mismatch */ /* NOTE Done by common code */ /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS on mismatch */ /* NOTE Done by common code */ /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error TPM_DAA_TPM_SETTINGS on mismatch */ /* NOTE Done by common code */ /* d. Verify that sizeOf(inputData0) == sizeOf(DAA_tpmSpecific -> DAA_count) and return error TPM_DAA_INPUT_DATA0 on mismatch */ if (rc == 0) { if (inputData0->size != sizeof(tpm_daa_session_data->DAA_tpmSpecific.DAA_count)) { printf("TPM_DAAJoin_Stage03: Error, inputData0 size %u should be %lu\n", inputData0->size, (unsigned long)sizeof(tpm_daa_session_data->DAA_tpmSpecific.DAA_count)); rc = TPM_DAA_INPUT_DATA0; } } /* e. Set DAA_tpmSpecific -> DAA_count = inputData0 */ if (rc == 0) { stream = inputData0->buffer; stream_size = inputData0->size; rc = TPM_Load32(&(tpm_daa_session_data->DAA_tpmSpecific.DAA_count), &stream, &stream_size); } /* f. Obtain random data from the RNG and store it as DAA_joinSession -> DAA_join_u0 */ if (rc == 0) { rc = TPM_Random(tpm_daa_session_data->DAA_joinSession.DAA_join_u0, sizeof(tpm_daa_session_data->DAA_joinSession.DAA_join_u0)); } /* g. Obtain random data from the RNG and store it as DAA_joinSession -> DAA_join_u1 */ if (rc == 0) { rc = TPM_Random(tpm_daa_session_data->DAA_joinSession.DAA_join_u1, sizeof(tpm_daa_session_data->DAA_joinSession.DAA_join_u1)); } /* h. set outputData = NULL */ /* NOTE Done by caller */ /* i. increment DAA_session -> DAA_stage by 1 */ /* NOTE Done by common code */ /* j. set DAA_session -> DAA_digestContext = SHA-1(DAA_tpmSpecific || DAA_joinSession) */ if (rc == 0) { rc = TPM_DAADigestContext_GenerateDigestJoin (tpm_daa_session_data->DAA_session.DAA_digestContext, tpm_daa_session_data); } /* k. return TPM_SUCCESS */ return rc; } TPM_RESULT TPM_DAAJoin_Stage04(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0, TPM_SIZED_BUFFER *inputData1) { TPM_RESULT rc = 0; TPM_BIGNUM xBignum = NULL; /* freed @1 */ TPM_BIGNUM nBignum = NULL; /* freed @2 */ TPM_BIGNUM fBignum = NULL; /* freed @3 */ TPM_BIGNUM rBignum = NULL; /* freed @4 */ printf("TPM_DAAJoin_Stage04:\n"); tpm_state = tpm_state; /* not used */ outputData = outputData; /* not used */ /* a. Verify that DAA_session ->DAA_stage==4. Return TPM_DAA_STAGE and flush handle on mismatch */ /* NOTE Done by common code */ /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS on mismatch */ /* NOTE Done by common code */ /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error TPM_DAA_TPM_SETTINGS on mismatch */ /* NOTE Done by common code */ /* d. Set DAA_generic_R0 = inputData0 */ /* e. Verify that SHA-1(DAA_generic_R0) == DAA_issuerSettings -> DAA_digest_R0 and return error TPM_DAA_INPUT_DATA0 on mismatch */ if (rc == 0) { printf("TPM_DAAJoin_Stage04: Checking DAA_generic_R0\n"); rc = TPM_SHA1_Check(tpm_daa_session_data->DAA_issuerSettings.DAA_digest_R0, /* expect */ inputData0->size, inputData0->buffer, /* DAA_generic_R0 */ 0, NULL); if (rc != 0) { rc = TPM_DAA_INPUT_DATA0; } } /* f. Set DAA_generic_n = inputData1 */ /* g. Verify that SHA-1(DAA_generic_n) == DAA_issuerSettings -> DAA_digest_n and return error TPM_DAA_INPUT_DATA1 on mismatch */ if (rc == 0) { printf("TPM_DAAJoin_Stage04: Checking DAA_digest_n\n"); rc = TPM_SHA1_Check(tpm_daa_session_data->DAA_issuerSettings.DAA_digest_n, /* expect */ inputData1->size, inputData1->buffer, /* DAA_generic_n */ 0, NULL); if (rc != 0) { rc = TPM_DAA_INPUT_DATA1; } } /* h. Set X = DAA_generic_R0 */ if (rc == 0) { printf("TPM_DAAJoin_Stage04: Creating X\n"); rc = TPM_bin2bn(&xBignum, inputData0->buffer, inputData0->size); } /* i. Set n = DAA_generic_n */ if (rc == 0) { printf("TPM_DAAJoin_Stage04: Creating n\n"); rc = TPM_bin2bn(&nBignum, inputData1->buffer, inputData1->size); } /* j. Set f = SHA-1(DAA_tpmSpecific -> DAA_rekey || DAA_tpmSpecific -> DAA_count || 0) || SHA-1(DAA_tpmSpecific -> DAA_rekey || DAA_tpmSpecific -> DAA_count || 1 ) mod DAA_issuerSettings -> DAA_generic_q */ if (rc == 0) { rc = TPM_ComputeF(&fBignum, tpm_daa_session_data); /* freed @3 */ } /* k. Set f0 = f mod 2^DAA_power0 (erase all but the lowest DAA_power0 bits of f) */ if (rc == 0) { rc = TPM_BN_mask_bits(fBignum, DAA_power0); /* f becomes f0 */ } /* l. Set DAA_session -> DAA_scratch = (X^f0) mod n */ if (rc == 0) { rc = TPM_ComputeAexpPmodn(tpm_daa_session_data->DAA_session.DAA_scratch, sizeof(tpm_daa_session_data->DAA_session.DAA_scratch), &rBignum, /* R */ xBignum, /* A */ fBignum, /* P */ nBignum); /* n */ } /* m. set outputData = NULL */ /* NOTE Done by caller */ /* n. increment DAA_session -> DAA_stage by 1 */ /* NOTE Done by common code */ /* o. return TPM_SUCCESS */ TPM_BN_free(xBignum); /* @1 */ TPM_BN_free(nBignum); /* @2 */ TPM_BN_free(fBignum); /* @3 */ TPM_BN_free(rBignum); /* @4 */ return rc; } TPM_RESULT TPM_DAAJoin_Stage05(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0, TPM_SIZED_BUFFER *inputData1) { TPM_RESULT rc = 0; TPM_BIGNUM xBignum = NULL; /* freed @1 */ TPM_BIGNUM nBignum = NULL; /* freed @2 */ TPM_BIGNUM fBignum = NULL; /* freed @3 */ TPM_BIGNUM f1Bignum = NULL; /* freed @4 */ TPM_BIGNUM zBignum = NULL; /* freed @5 */ printf("TPM_DAAJoin_Stage05:\n"); tpm_state = tpm_state; /* not used */ outputData = outputData; /* not used */ /* a. Verify that DAA_session ->DAA_stage==5. Return TPM_DAA_STAGE and flush handle on mismatch */ /* NOTE Done by common code */ /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS on mismatch */ /* NOTE Done by common code */ /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error TPM_DAA_TPM_SETTINGS on mismatch */ /* NOTE Done by common code */ /* d. Set DAA_generic_R1 = inputData0 */ /* e. Verify that SHA-1(DAA_generic_R1) == DAA_issuerSettings -> DAA_digest_R1 and return error TPM_DAA_INPUT_DATA0 on mismatch */ if (rc == 0) { printf("TPM_DAAJoin_Stage05: Checking DAA_generic_R1\n"); rc = TPM_SHA1_Check(tpm_daa_session_data->DAA_issuerSettings.DAA_digest_R1, /* expect */ inputData0->size, inputData0->buffer, /* DAA_generic_R1 */ 0, NULL); if (rc != 0) { rc = TPM_DAA_INPUT_DATA0; } } /* f. Set DAA_generic_n = inputData1 */ /* g. Verify that SHA-1(DAA_generic_n) == DAA_issuerSettings -> DAA_digest_n and return error TPM_DAA_INPUT_DATA1 on mismatch */ if (rc == 0) { printf("TPM_DAAJoin_Stage05: Checking DAA_digest_n\n"); rc = TPM_SHA1_Check(tpm_daa_session_data->DAA_issuerSettings.DAA_digest_n, /* expect */ inputData1->size, inputData1->buffer, /* DAA_generic_n */ 0, NULL); if (rc != 0) { rc = TPM_DAA_INPUT_DATA1; } } /* h. Set X = DAA_generic_R1 */ if (rc == 0) { printf("TPM_DAAJoin_Stage05: Creating X\n"); rc = TPM_bin2bn(&xBignum, inputData0->buffer, inputData0->size); } /* i. Set n = DAA_generic_n */ if (rc == 0) { printf("TPM_DAAJoin_Stage05: Creating n\n"); rc = TPM_bin2bn(&nBignum, inputData1->buffer, inputData1->size); } /* j. Set f = SHA-1(DAA_tpmSpecific -> DAA_rekey || DAA_tpmSpecific -> DAA_count || 0) || SHA-1(DAA_tpmSpecific -> DAA_rekey || DAA_tpmSpecific -> DAA_count || 1 ) mod DAA_issuerSettings -> DAA_generic_q. */ if (rc == 0) { rc = TPM_ComputeF(&fBignum, tpm_daa_session_data); /* freed @3 */ } /* k. Shift f right by DAA_power0 bits (discard the lowest DAA_power0 bits) and label the result f1 */ if (rc == 0) { rc = TPM_BN_rshift(&f1Bignum, fBignum, DAA_power0); /* f becomes f1 */ } /* l. Set Z = DAA_session -> DAA_scratch */ if (rc == 0) { printf("TPM_DAAJoin_Stage05: Creating Z\n"); rc = TPM_bin2bn(&zBignum, tpm_daa_session_data->DAA_session.DAA_scratch, sizeof(tpm_daa_session_data->DAA_session.DAA_scratch)); } /* m. Set DAA_session -> DAA_scratch = Z*(X^f1) mod n */ if (rc == 0) { rc = TPM_ComputeZxAexpPmodn(tpm_daa_session_data->DAA_session.DAA_scratch, sizeof(tpm_daa_session_data->DAA_session.DAA_scratch), zBignum, /* Z */ xBignum, /* A */ f1Bignum, /* P */ nBignum); /* N */ } /* n. set outputData = NULL */ /* NOTE Done by caller */ /* o. increment DAA_session -> DAA_stage by 1 */ /* NOTE Done by common code */ /* p. return TPM_SUCCESS */ TPM_BN_free(xBignum); /* @1 */ TPM_BN_free(nBignum); /* @2 */ TPM_BN_free(fBignum); /* @3 */ TPM_BN_free(f1Bignum); /* @4 */ TPM_BN_free(zBignum); /* @5 */ return rc; } TPM_RESULT TPM_DAAJoin_Stage06(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0, TPM_SIZED_BUFFER *inputData1) { TPM_RESULT rc = 0; TPM_BIGNUM xBignum = NULL; /* freed @1 */ TPM_BIGNUM nBignum = NULL; /* freed @2 */ TPM_BIGNUM zBignum = NULL; /* freed @3 */ TPM_BIGNUM yBignum = NULL; /* freed @4 */ printf("TPM_DAAJoin_Stage06:\n"); tpm_state = tpm_state; /* not used */ outputData = outputData; /* not used */ /* a. Verify that DAA_session ->DAA_stage==6. Return TPM_DAA_STAGE and flush handle on mismatch */ /* NOTE Done by common code */ /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS on mismatch */ /* NOTE Done by common code */ /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error TPM_DAA_TPM_SETTINGS on mismatch */ /* NOTE Done by common code */ /* d. Set DAA_generic_S0 = inputData0 */ /* e. Verify that SHA-1(DAA_generic_S0) == DAA_issuerSettings -> DAA_digest_S0 and return error TPM_DAA_INPUT_DATA0 on mismatch */ if (rc == 0) { printf("TPM_DAAJoin_Stage06: Checking DAA_generic_S0\n"); rc = TPM_SHA1_Check(tpm_daa_session_data->DAA_issuerSettings.DAA_digest_S0, /* expect */ inputData0->size, inputData0->buffer, /* DAA_generic_S0 */ 0, NULL); if (rc != 0) { rc = TPM_DAA_INPUT_DATA0; } } /* f. Set DAA_generic_n = inputData1 */ /* g. Verify that SHA-1(DAA_generic_n) == DAA_issuerSettings -> DAA_digest_n and return error TPM_DAA_INPUT_DATA1 on mismatch */ if (rc == 0) { printf("TPM_DAAJoin_Stage06: Checking DAA_digest_n\n"); rc = TPM_SHA1_Check(tpm_daa_session_data->DAA_issuerSettings.DAA_digest_n, /* expect */ inputData1->size, inputData1->buffer, /* DAA_generic_n */ 0, NULL); if (rc != 0) { rc = TPM_DAA_INPUT_DATA1; } } /* h. Set X = DAA_generic_S0 */ if (rc == 0) { printf("TPM_DAAJoin_Stage06: Creating X\n"); rc = TPM_bin2bn(&xBignum, inputData0->buffer, inputData0->size); } /* i. Set n = DAA_generic_n */ if (rc == 0) { printf("TPM_DAAJoin_Stage06: Creating n\n"); rc = TPM_bin2bn(&nBignum, inputData1->buffer, inputData1->size); } /* j. Set Z = DAA_session -> DAA_scratch */ if (rc == 0) { printf("TPM_DAAJoin_Stage06: Creating Z\n"); rc = TPM_bin2bn(&zBignum, tpm_daa_session_data->DAA_session.DAA_scratch, sizeof(tpm_daa_session_data->DAA_session.DAA_scratch)); } /* k. Set Y = DAA_joinSession -> DAA_join_u0 */ if (rc == 0) { printf("TPM_DAAJoin_Stage06: Creating Y\n"); rc = TPM_bin2bn(&yBignum, tpm_daa_session_data->DAA_joinSession.DAA_join_u0, sizeof(tpm_daa_session_data->DAA_joinSession.DAA_join_u0)); } /* l. Set DAA_session -> DAA_scratch = Z*(X^Y) mod n */ if (rc == 0) { rc = TPM_ComputeZxAexpPmodn(tpm_daa_session_data->DAA_session.DAA_scratch, sizeof(tpm_daa_session_data->DAA_session.DAA_scratch), zBignum, /* Z */ xBignum, /* A */ yBignum, /* P */ nBignum); /* N */ } /* m. set outputData = NULL */ /* NOTE Done by caller */ /* n. increment DAA_session -> DAA_stage by 1 */ /* NOTE Done by common code */ /* o. return TPM_SUCCESS */ TPM_BN_free(xBignum); /* @1 */ TPM_BN_free(nBignum); /* @2 */ TPM_BN_free(zBignum); /* @3 */ TPM_BN_free(yBignum); /* @4 */ return rc; } TPM_RESULT TPM_DAAJoin_Stage07(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0, TPM_SIZED_BUFFER *inputData1) { TPM_RESULT rc = 0; uint32_t nCount; /* DAA_count in nbo */ TPM_BIGNUM xBignum = NULL; /* freed @1 */ TPM_BIGNUM nBignum = NULL; /* freed @2 */ TPM_BIGNUM yBignum = NULL; /* freed @3 */ TPM_BIGNUM zBignum = NULL; /* freed @4 */ printf("TPM_DAAJoin_Stage07:\n"); tpm_state = tpm_state; /* not used */ /* a. Verify that DAA_session ->DAA_stage==7. Return TPM_DAA_STAGE and flush handle on mismatch */ /* NOTE Done by common code */ /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS on mismatch */ /* NOTE Done by common code */ /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error TPM_DAA_TPM_SETTINGS on mismatch */ /* NOTE Done by common code */ /* d. Set DAA_generic_S1 = inputData0 */ /* e. Verify that SHA-1(DAA_generic_S1) == DAA_issuerSettings -> DAA_digest_S1 and return error TPM_DAA_INPUT_DATA0 on mismatch */ if (rc == 0) { printf("TPM_DAAJoin_Stage07: Checking DAA_generic_S1\n"); rc = TPM_SHA1_Check(tpm_daa_session_data->DAA_issuerSettings.DAA_digest_S1, /* expect */ inputData0->size, inputData0->buffer, /* DAA_generic_S1 */ 0, NULL); if (rc != 0) { rc = TPM_DAA_INPUT_DATA0; } } /* f. Set DAA_generic_n = inputData1 */ /* g. Verify that SHA-1(DAA_generic_n) == DAA_issuerSettings -> DAA_digest_n and return error TPM_DAA_INPUT_DATA1 on mismatch */ if (rc == 0) { printf("TPM_DAAJoin_Stage07: Checking DAA_digest_n\n"); rc = TPM_SHA1_Check(tpm_daa_session_data->DAA_issuerSettings.DAA_digest_n, /* expect */ inputData1->size, inputData1->buffer, /* DAA_generic_n */ 0, NULL); if (rc != 0) { rc = TPM_DAA_INPUT_DATA1; } } /* h. Set X = DAA_generic_S1 */ if (rc == 0) { printf("TPM_DAAJoin_Stage07: Creating X\n"); rc = TPM_bin2bn(&xBignum, inputData0->buffer, inputData0->size); } /* i. Set n = DAA_generic_n */ if (rc == 0) { printf("TPM_DAAJoin_Stage07: Creating n\n"); rc = TPM_bin2bn(&nBignum, inputData1->buffer, inputData1->size); } /* j. Set Y = DAA_joinSession -> DAA_join_u1 */ if (rc == 0) { printf("TPM_DAAJoin_Stage07: Creating Y\n"); rc = TPM_bin2bn(&yBignum, tpm_daa_session_data->DAA_joinSession.DAA_join_u1, sizeof(tpm_daa_session_data->DAA_joinSession.DAA_join_u1)); } /* k. Set Z = DAA_session -> DAA_scratch */ if (rc == 0) { printf("TPM_DAAJoin_Stage07: Creating Z\n"); rc = TPM_bin2bn(&zBignum, tpm_daa_session_data->DAA_session.DAA_scratch, sizeof(tpm_daa_session_data->DAA_session.DAA_scratch)); } /* l. Set DAA_session -> DAA_scratch = Z*(X^Y) mod n */ if (rc == 0) { rc = TPM_ComputeZxAexpPmodn(tpm_daa_session_data->DAA_session.DAA_scratch, sizeof(tpm_daa_session_data->DAA_session.DAA_scratch), zBignum, /* Z */ xBignum, /* A */ yBignum, /* P */ nBignum); /* N */ } /* m. Set DAA_session -> DAA_digest to the SHA-1 (DAA_session -> DAA_scratch || DAA_tpmSpecific -> DAA_count || DAA_joinSession -> DAA_digest_n0) */ if (rc == 0) { printf("TPM_DAAJoin_Stage07: Computing DAA_digest\n"); nCount = htonl(tpm_daa_session_data->DAA_tpmSpecific.DAA_count); rc = TPM_SHA1(tpm_daa_session_data->DAA_session.DAA_digest, sizeof(tpm_daa_session_data->DAA_session.DAA_scratch), tpm_daa_session_data->DAA_session.DAA_scratch, sizeof(uint32_t), &nCount, TPM_DIGEST_SIZE, tpm_daa_session_data->DAA_joinSession.DAA_digest_n0, 0, NULL); } /* n. set outputData = DAA_session -> DAA_scratch */ if (rc == 0) { rc = TPM_SizedBuffer_Set(outputData, sizeof(tpm_daa_session_data->DAA_session.DAA_scratch), tpm_daa_session_data->DAA_session.DAA_scratch); } /* o. set DAA_session -> DAA_scratch = NULL */ if (rc == 0) { tpm_daa_session_data->DAA_session.DAA_scratch_null = TRUE; } /* p. increment DAA_session -> DAA_stage by 1 */ /* NOTE Done by common code */ /* q. return TPM_SUCCESS */ TPM_BN_free(xBignum); /* @1 */ TPM_BN_free(nBignum); /* @2 */ TPM_BN_free(yBignum); /* @3 */ TPM_BN_free(zBignum); /* @4 */ return rc; } TPM_RESULT TPM_DAAJoin_Stage08(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0) { TPM_RESULT rc = 0; unsigned char *NE = NULL; /* freed @1 */ uint32_t NELength; TPM_DIGEST outDigest; printf("TPM_DAAJoin_Stage08:\n"); /* a. Verify that DAA_session ->DAA_stage==8. Return TPM_DAA_STAGE and flush handle on mismatch */ /* NOTE Done by common code */ /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS on mismatch */ /* NOTE Done by common code */ /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error TPM_DAA_TPM_SETTINGS on mismatch */ /* NOTE Done by common code */ /* d. Verify inputSize0 == DAA_SIZE_NE and return error TPM_DAA_INPUT_DATA0 on mismatch */ if (rc == 0) { if (inputData0->size != DAA_SIZE_NE) { printf("TPM_DAAJoin_Stage08: Error, inputData0 size %u should be %u\n", inputData0->size, DAA_SIZE_NE); rc = TPM_DAA_INPUT_DATA0; } } /* e. Set NE = decrypt(inputData0, privEK) */ if (rc == 0) { rc = TPM_RSAPrivateDecryptMalloc(&NE, /* decrypted data */ &NELength, /* length of data put into decrypt_data */ inputData0->buffer, /* encrypted data */ inputData0->size, /* encrypted data size */ &(tpm_state->tpm_permanent_data.endorsementKey)); } /* f. set outputData = SHA-1(DAA_session -> DAA_digest || NE) */ if (rc == 0) { rc = TPM_SHA1(outDigest, TPM_DIGEST_SIZE, tpm_daa_session_data->DAA_session.DAA_digest, NELength, NE, 0, NULL); } if (rc == 0) { rc = TPM_SizedBuffer_Set(outputData, TPM_DIGEST_SIZE, outDigest); } /* g. set DAA_session -> DAA_digest = NULL */ if (rc == 0) { TPM_Digest_Init(tpm_daa_session_data->DAA_session.DAA_digest); } /* h. increment DAA_session -> DAA_stage by 1 */ /* NOTE Done by common code */ /* i. return TPM_SUCCESS */ free(NE); /* @1 */ return rc; } TPM_RESULT TPM_DAAJoin_Stage09_Sign_Stage2(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0, TPM_SIZED_BUFFER *inputData1) { TPM_RESULT rc = 0; unsigned char *Y = NULL; /* freed @1 */ TPM_BIGNUM yBignum = NULL; /* freed @2 */ TPM_BIGNUM xBignum = NULL; /* freed @3 */ TPM_BIGNUM nBignum = NULL; /* freed @4 */ TPM_BIGNUM rBignum = NULL; /* freed @5 */ printf("TPM_DAAJoin_Stage09_Sign_Stage2:\n"); tpm_state = tpm_state; /* not used */ outputData = outputData; /* not used */ /* a. Verify that DAA_session ->DAA_stage==9. Return TPM_DAA_STAGE and flush handle on mismatch */ /* NOTE Done by common code */ /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS on mismatch */ /* NOTE Done by common code */ /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific ||DAA_joinSession) and return error TPM_DAA_TPM_SETTINGS on mismatch */ /* NOTE Done by common code */ /* d. Set DAA_generic_R0 = inputData0 */ /* e. Verify that SHA-1(DAA_generic_R0) == DAA_issuerSettings -> DAA_digest_R0 and return error TPM_DAA_INPUT_DATA0 on mismatch */ if (rc == 0) { printf("TPM_DAAJoin_Stage09_Sign_Stage2: Checking DAA_generic_R0\n"); rc = TPM_SHA1_Check(tpm_daa_session_data->DAA_issuerSettings.DAA_digest_R0, /* expect */ inputData0->size, inputData0->buffer, /* DAA_generic_R0 */ 0, NULL); if (rc != 0) { rc = TPM_DAA_INPUT_DATA0; } } /* f. Set DAA_generic_n = inputData1 */ /* g. Verify that SHA-1(DAA_generic_n) == DAA_issuerSettings -> DAA_digest_n and return error TPM_DAA_INPUT_DATA1 on mismatch */ if (rc == 0) { printf("TPM_DAAJoin_Stage09_Sign_Stage2: Checking DAA_digest_n\n"); rc = TPM_SHA1_Check(tpm_daa_session_data->DAA_issuerSettings.DAA_digest_n, /* expect */ inputData1->size, inputData1->buffer, /* DAA_generic_n */ 0, NULL); if (rc != 0) { rc = TPM_DAA_INPUT_DATA1; } } /* h. Obtain random data from the RNG and store it as DAA_session -> DAA_contextSeed */ if (rc == 0) { rc = TPM_Nonce_Generate(tpm_daa_session_data->DAA_session.DAA_contextSeed); } /* i. Obtain DAA_SIZE_r0 bytes using the MGF1 function and label them Y. "r0" || DAA_session -> DAA_contextSeed is the Z seed. */ if (rc == 0) { printf("TPM_DAAJoin_Stage09_Sign_Stage2: Creating Y\n"); rc = TPM_MGF1_GenerateArray(&Y, /* returned MGF1 array */ DAA_SIZE_r0, /* size of Y */ /* length of the entire seed */ sizeof("r0") -1 + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), sizeof("r0") -1, "r0", sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), tpm_daa_session_data->DAA_session.DAA_contextSeed, 0, NULL); } if (rc == 0) { rc = TPM_bin2bn(&yBignum, Y, DAA_SIZE_r0); } /* j. Set X = DAA_generic_R0 */ if (rc == 0) { printf("TPM_DAAJoin_Stage09_Sign_Stage2: Creating X\n"); rc = TPM_bin2bn(&xBignum, inputData0->buffer, inputData0->size); } /* k. Set n = DAA_generic_n */ if (rc == 0) { printf("TPM_DAAJoin_Stage09_Sign_Stage2: Creating n\n"); rc = TPM_bin2bn(&nBignum, inputData1->buffer, inputData1->size); } /* l. Set DAA_session -> DAA_scratch = (X^Y) mod n */ if (rc == 0) { rc = TPM_ComputeAexpPmodn(tpm_daa_session_data->DAA_session.DAA_scratch, sizeof(tpm_daa_session_data->DAA_session.DAA_scratch), &rBignum, /* R */ xBignum, /* A */ yBignum, /* P */ nBignum); /* n */ } /* m. set outputData = NULL */ /* NOTE Done by caller */ /* n. increment DAA_session -> DAA_stage by 1 */ /* NOTE Done by common code */ /* o. return TPM_SUCCESS */ free(Y); /* @1 */ TPM_BN_free(yBignum); /* @2 */ TPM_BN_free(xBignum); /* @3 */ TPM_BN_free(nBignum); /* @4 */ TPM_BN_free(rBignum); /* @5 */ return rc; } TPM_RESULT TPM_DAAJoin_Stage10_Sign_Stage3(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0, TPM_SIZED_BUFFER *inputData1) { TPM_RESULT rc = 0; unsigned char *Y= NULL; /* freed @1 */ TPM_BIGNUM xBignum = NULL; /* freed @2 */ TPM_BIGNUM nBignum = NULL; /* freed @3 */ TPM_BIGNUM zBignum = NULL; /* freed @4 */ TPM_BIGNUM yBignum = NULL; /* freed @5*/ printf("TPM_DAAJoin_Stage10_Sign_Stage3:\n"); tpm_state = tpm_state; /* not used */ outputData = outputData; /* not used */ /* a. Verify that DAA_session ->DAA_stage==10. Return TPM_DAA_STAGE and flush handle on mismatch h */ /* NOTE Done by common code */ /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS on mismatch */ /* NOTE Done by common code */ /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error TPM_DAA_TPM_SETTINGS on mismatch */ /* NOTE Done by common code */ /* d. Set DAA_generic_R1 = inputData0 */ /* e. Verify that SHA-1(DAA_generic_R1) == DAA_issuerSettings -> DAA_digest_R1 and return error TPM_DAA_INPUT_DATA0 on mismatch */ if (rc == 0) { printf("TPM_DAAJoin_Stage10_Sign_Stage3: Checking DAA_generic_R1\n"); rc = TPM_SHA1_Check(tpm_daa_session_data->DAA_issuerSettings.DAA_digest_R1, /* expect */ inputData0->size, inputData0->buffer, /* DAA_generic_R1 */ 0, NULL); if (rc != 0) { rc = TPM_DAA_INPUT_DATA0; } } /* f. Set DAA_generic_n = inputData1 */ /* g. Verify that SHA-1(DAA_generic_n) == DAA_issuerSettings -> DAA_digest_n and return error TPM_DAA_INPUT_DATA1 on mismatch */ if (rc == 0) { printf("TPM_DAAJoin_Stage10_Sign_Stage3: Checking DAA_digest_n\n"); rc = TPM_SHA1_Check(tpm_daa_session_data->DAA_issuerSettings.DAA_digest_n, /* expect */ inputData1->size, inputData1->buffer, /* DAA_generic_n */ 0, NULL); if (rc != 0) { rc = TPM_DAA_INPUT_DATA1; } } /* h. Obtain DAA_SIZE_r1 bytes using the MGF1 function and label them Y. "r1" || DAA_session -> DAA_contextSeed is the Z seed. */ if (rc == 0) { printf("TPM_DAAJoin_Stage10_Sign_Stage3: Creating Y\n"); rc = TPM_MGF1_GenerateArray(&Y, /* returned MGF1 array */ DAA_SIZE_r1, /* size of Y */ /* length of the entire seed */ sizeof("r1") -1 + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), sizeof("r1") -1, "r1", sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), tpm_daa_session_data->DAA_session.DAA_contextSeed, 0, NULL); } if (rc == 0) { rc = TPM_bin2bn(&yBignum, Y, DAA_SIZE_r1); } /* i. Set X = DAA_generic_R1 */ if (rc == 0) { printf("TPM_DAAJoin_Stage10_Sign_Stage3: Creating X\n"); rc = TPM_bin2bn(&xBignum, inputData0->buffer, inputData0->size); } /* j. Set n = DAA_generic_n */ if (rc == 0) { printf("TPM_DAAJoin_Stage10_Sign_Stage3: Creating n\n"); rc = TPM_bin2bn(&nBignum, inputData1->buffer, inputData1->size); } /* k. Set Z = DAA_session -> DAA_scratch */ if (rc == 0) { printf("TPM_DAAJoin_Stage10_Sign_Stage3: Creating Z\n"); rc = TPM_bin2bn(&zBignum, tpm_daa_session_data->DAA_session.DAA_scratch, sizeof(tpm_daa_session_data->DAA_session.DAA_scratch)); } /* l. Set DAA_session -> DAA_scratch = Z*(X^Y) mod n */ if (rc == 0) { rc = TPM_ComputeZxAexpPmodn(tpm_daa_session_data->DAA_session.DAA_scratch, sizeof(tpm_daa_session_data->DAA_session.DAA_scratch), zBignum, /* Z */ xBignum, /* A */ yBignum, /* P */ nBignum); /* N */ } /* m. set outputData = NULL */ /* NOTE Done by caller */ /* n. increment DAA_session -> DAA_stage by 1 */ /* NOTE Done by common code */ /* o. return TPM_SUCCESS */ free(Y); /* @1 */ TPM_BN_free(xBignum); /* @2 */ TPM_BN_free(nBignum); /* @3 */ TPM_BN_free(zBignum); /* @4 */ TPM_BN_free(yBignum); /* @5 */ return rc; } TPM_RESULT TPM_DAAJoin_Stage11_Sign_Stage4(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0, TPM_SIZED_BUFFER *inputData1) { TPM_RESULT rc = 0; unsigned char *Y= NULL; /* freed @1 */ TPM_BIGNUM yBignum = NULL; /* freed @2 */ TPM_BIGNUM xBignum = NULL; /* freed @3 */ TPM_BIGNUM nBignum = NULL; /* freed @4 */ TPM_BIGNUM zBignum = NULL; /* freed @5 */ printf("TPM_DAAJoin_Stage11_Sign_Stage4:\n"); tpm_state = tpm_state; /* not used */ outputData = outputData; /* not used */ /* a. Verify that DAA_session ->DAA_stage==11. Return TPM_DAA_STAGE and flush handle on mismatch */ /* NOTE Done by common code */ /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS on mismatch */ /* NOTE Done by common code */ /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error TPM_DAA_TPM_SETTINGS on mismatch */ /* NOTE Done by common code */ /* d. Set DAA_generic_S0 = inputData0 */ /* e. Verify that SHA-1(DAA_generic_S0) == DAA_issuerSettings -> DAA_digest_S0 and return error TPM_DAA_INPUT_DATA0 on mismatch */ if (rc == 0) { printf("TPM_DAAJoin_Stage11_Sign_Stage4: Checking DAA_generic_S0\n"); rc = TPM_SHA1_Check(tpm_daa_session_data->DAA_issuerSettings.DAA_digest_S0, /* expect */ inputData0->size, inputData0->buffer, /* DAA_generic_S0 */ 0, NULL); if (rc != 0) { rc = TPM_DAA_INPUT_DATA0; } } /* f. Set DAA_generic_n = inputData1 */ /* g. Verify that SHA-1(DAA_generic_n) == DAA_issuerSettings -> DAA_digest_n and return error TPM_DAA_INPUT_DATA1 on mismatch */ if (rc == 0) { printf("TPM_DAAJoin_Stage11_Sign_Stage4: Checking DAA_digest_n\n"); rc = TPM_SHA1_Check(tpm_daa_session_data->DAA_issuerSettings.DAA_digest_n, /* expect */ inputData1->size, inputData1->buffer, /* DAA_generic_n */ 0, NULL); if (rc != 0) { rc = TPM_DAA_INPUT_DATA1; } } /* h. Obtain DAA_SIZE_r2 bytes using the MGF1 function and label them Y. "r2" || DAA_session -> DAA_contextSeed is the Z seed. */ if (rc == 0) { printf("TPM_DAAJoin_Stage11_Sign_Stage4: Creating Y\n"); rc = TPM_MGF1_GenerateArray(&Y, /* returned MGF1 array */ DAA_SIZE_r2, /* size of Y */ /* length of the entire seed */ sizeof("r2") -1 + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), sizeof("r2") -1, "r2", sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), tpm_daa_session_data->DAA_session.DAA_contextSeed, 0, NULL); } if (rc == 0) { rc = TPM_bin2bn(&yBignum, Y, DAA_SIZE_r2); } /* i. Set X = DAA_generic_S0 */ if (rc == 0) { printf("TPM_DAAJoin_Stage11_Sign_Stage4: Creating X\n"); rc = TPM_bin2bn(&xBignum, inputData0->buffer, inputData0->size); } /* j. Set n = DAA_generic_n */ if (rc == 0) { printf("TPM_DAAJoin_Stage11_Sign_Stage4: Creating n\n"); rc = TPM_bin2bn(&nBignum, inputData1->buffer, inputData1->size); } /* k. Set Z = DAA_session -> DAA_scratch */ if (rc == 0) { printf("TPM_DAAJoin_Stage11_Sign_Stage4: Creating Z\n"); rc = TPM_bin2bn(&zBignum, tpm_daa_session_data->DAA_session.DAA_scratch, sizeof(tpm_daa_session_data->DAA_session.DAA_scratch)); } /* l. Set DAA_session -> DAA_scratch = Z*(X^Y) mod n */ if (rc == 0) { rc = TPM_ComputeZxAexpPmodn(tpm_daa_session_data->DAA_session.DAA_scratch, sizeof(tpm_daa_session_data->DAA_session.DAA_scratch), zBignum, /* Z */ xBignum, /* A */ yBignum, /* P */ nBignum); /* N */ } /* m. set outputData = NULL */ /* NOTE Done by caller */ /* n. increment DAA_session -> DAA_stage by 1 */ /* NOTE Done by common code */ /* o. return TPM_SUCCESS */ free(Y); /* @1 */ TPM_BN_free(yBignum); /* @2 */ TPM_BN_free(xBignum); /* @3 */ TPM_BN_free(nBignum); /* @4 */ TPM_BN_free(zBignum); /* @5 */ return rc; } TPM_RESULT TPM_DAAJoin_Stage12(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0, TPM_SIZED_BUFFER *inputData1) { TPM_RESULT rc = 0; unsigned char *Y = NULL; /* freed @1 */ TPM_BIGNUM yBignum = NULL; /* freed @2 */ TPM_BIGNUM xBignum = NULL; /* freed @3 */ TPM_BIGNUM nBignum = NULL; /* freed @4 */ TPM_BIGNUM zBignum = NULL; /* freed @5 */ printf("TPM_DAAJoin_Stage12:\n"); tpm_state = tpm_state; /* not used */ /* a. Verify that DAA_session ->DAA_stage==12. Return TPM_DAA_STAGE and flush handle on mismatch */ /* NOTE Done by common code */ /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings ) and return error TPM_DAA_ISSUER_SETTINGS on mismatch */ /* NOTE Done by common code */ /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error TPM_DAA_TPM_SETTINGS on mismatch */ /* NOTE Done by common code */ /* d. Set DAA_generic_S1 = inputData0 */ /* e. Verify that SHA-1(DAA_generic_S1) == DAA_issuerSettings -> DAA_digest_S1 and return error TPM_DAA_INPUT_DATA0 on mismatch */ if (rc == 0) { printf("TPM_DAAJoin_Stage12: Checking DAA_generic_S1\n"); rc = TPM_SHA1_Check(tpm_daa_session_data->DAA_issuerSettings.DAA_digest_S1, /* expect */ inputData0->size, inputData0->buffer, /* DAA_generic_S1 */ 0, NULL); if (rc != 0) { rc = TPM_DAA_INPUT_DATA0; } } /* f. Set DAA_generic_n = inputData1 */ /* g. Verify that SHA-1(DAA_generic_n) == DAA_issuerSettings -> DAA_digest_n and return error TPM_DAA_INPUT_DATA1 on mismatch */ if (rc == 0) { printf("TPM_DAAJoin_Stage12: Checking DAA_digest_n\n"); rc = TPM_SHA1_Check(tpm_daa_session_data->DAA_issuerSettings.DAA_digest_n, /* expect */ inputData1->size, inputData1->buffer, /* DAA_generic_n */ 0, NULL); if (rc != 0) { rc = TPM_DAA_INPUT_DATA1; } } /* h. Obtain DAA_SIZE_r3 bytes using the MGF1 function and label them Y. "r3" || DAA_session -> DAA_contextSeed) is the Z seed. */ if (rc == 0) { printf("TPM_DAAJoin_Stage12: Creating Y\n"); rc = TPM_MGF1_GenerateArray(&Y, /* returned MGF1 array */ DAA_SIZE_r3, /* size of Y */ /* length of the entire seed */ sizeof("r3") -1 + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), sizeof("r3") -1, "r3", sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), tpm_daa_session_data->DAA_session.DAA_contextSeed, 0, NULL); } if (rc == 0) { rc = TPM_bin2bn(&yBignum, Y, DAA_SIZE_r3); } /* i. Set X = DAA_generic_S1 */ if (rc == 0) { printf("TPM_DAAJoin_Stage12: Creating X\n"); rc = TPM_bin2bn(&xBignum, inputData0->buffer, inputData0->size); } /* j. Set n = DAA_generic_n */ if (rc == 0) { printf("TPM_DAAJoin_Stage12: Creating n\n"); rc = TPM_bin2bn(&nBignum, inputData1->buffer, inputData1->size); } /* k. Set Z = DAA_session -> DAA_scratch */ if (rc == 0) { printf("TPM_DAAJoin_Stage12: Creating Z\n"); rc = TPM_bin2bn(&zBignum, tpm_daa_session_data->DAA_session.DAA_scratch, sizeof(tpm_daa_session_data->DAA_session.DAA_scratch)); } /* l. Set DAA_session -> DAA_scratch = Z*(X^Y) mod n */ if (rc == 0) { rc = TPM_ComputeZxAexpPmodn(tpm_daa_session_data->DAA_session.DAA_scratch, sizeof(tpm_daa_session_data->DAA_session.DAA_scratch), zBignum, /* Z */ xBignum, /* A */ yBignum, /* P */ nBignum); /* N */ } /* m. set outputData = DAA_session -> DAA_scratch */ if (rc == 0) { rc = TPM_SizedBuffer_Set(outputData, sizeof(tpm_daa_session_data->DAA_session.DAA_scratch), tpm_daa_session_data->DAA_session.DAA_scratch); } /* n. Set DAA_session -> DAA_scratch = NULL */ if (rc == 0) { tpm_daa_session_data->DAA_session.DAA_scratch_null = TRUE; } /* o. increment DAA_session -> DAA_stage by 1 */ /* NOTE Done by common code */ /* p. return TPM_SUCCESS */ free(Y); /* @1 */ TPM_BN_free(yBignum); /* @2 */ TPM_BN_free(xBignum); /* @3 */ TPM_BN_free(nBignum); /* @4 */ TPM_BN_free(zBignum); /* @5 */ return rc; } TPM_RESULT TPM_DAAJoin_Stage13_Sign_Stage6(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0, TPM_SIZED_BUFFER *inputData1) { TPM_RESULT rc = 0; TPM_BIGNUM wBignum = NULL; /* freed @1 */ TPM_BIGNUM qBignum = NULL; /* freed @2 */ TPM_BIGNUM nBignum = NULL; /* freed @3 */ TPM_BIGNUM w1Bignum = NULL; /* freed @4 */ printf("TPM_DAAJoin_Stage13_Sign_Stage6:\n"); tpm_state = tpm_state; /* not used */ outputData = outputData; /* not used */ /* a. Verify that DAA_session->DAA_stage==13. Return TPM_DAA_STAGE and flush handle on mismatch */ /* NOTE Done by common code */ /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS on mismatch */ /* NOTE Done by common code */ /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error TPM_DAA_TPM_SETTINGS on mismatch */ /* NOTE Done by common code */ /* d. Set DAA_generic_gamma = inputData0 */ /* e. Verify that SHA-1(DAA_generic_gamma) == DAA_issuerSettings -> DAA_digest_gamma and return error TPM_DAA_INPUT_DATA0 on mismatch */ if (rc == 0) { printf("TPM_DAAJoin_Stage13_Sign_Stage6: Checking DAA_generic_gamma\n"); rc = TPM_SHA1_Check(tpm_daa_session_data->DAA_issuerSettings.DAA_digest_gamma, /* expect */ inputData0->size, inputData0->buffer, /* DAA_generic_gamma */ 0, NULL); if (rc != 0) { rc = TPM_DAA_INPUT_DATA0; } } /* f. Verify that inputSize1 == DAA_SIZE_w and return error TPM_DAA_INPUT_DATA1 on mismatch */ if (rc == 0) { if (inputData1->size != DAA_SIZE_w) { printf("TPM_DAAJoin_Stage13_Sign_Stage6: Error, inputData1 size %u should be %u\n", inputData0->size, DAA_SIZE_w); rc = TPM_DAA_INPUT_DATA1; } } /* g. Set w = inputData1 */ if (rc == 0) { printf("TPM_DAAJoin_Stage13_Sign_Stage6: Creating w\n"); rc = TPM_bin2bn(&wBignum, inputData1->buffer, inputData1->size); } /* FIXME added Set q = DAA_issuerSettings -> DAA_generic_q */ if (rc == 0) { printf("TPM_DAAJoin_Stage13_Sign_Stage6: Creating q from DAA_generic_q\n"); rc = TPM_bin2bn(&qBignum, tpm_daa_session_data->DAA_issuerSettings.DAA_generic_q, sizeof(tpm_daa_session_data->DAA_issuerSettings.DAA_generic_q)); } /* FIXME Set n = DAA_generic_gamma */ if (rc == 0) { printf("TPM_DAAJoin_Stage13_Sign_Stage6: Creating n\n"); rc = TPM_bin2bn(&nBignum, inputData0->buffer, inputData0->size); } /* h. Set w1 = w^( DAA_issuerSettings -> DAA_generic_q) mod (DAA_generic_gamma) */ /* FIXME w1 = (w^q) mod n */ if (rc == 0) { rc = TPM_ComputeAexpPmodn(NULL, 0, &w1Bignum, /* R */ wBignum, /* A */ qBignum, /* P */ nBignum); /* n */ } /* i. If w1 != 1 (unity), return error TPM_DAA_WRONG_W */ if (rc == 0) { printf("TPM_DAAJoin_Stage13_Sign_Stage6: Testing w1\n"); rc = TPM_BN_is_one(w1Bignum); } /* j. Set DAA_session -> DAA_scratch = w */ if (rc == 0) { rc = TPM_ComputeDAAScratch(tpm_daa_session_data->DAA_session.DAA_scratch, sizeof(tpm_daa_session_data->DAA_session.DAA_scratch), wBignum); } /* k. set outputData = NULL */ /* NOTE Done by caller */ /* l. increment DAA_session -> DAA_stage by 1 */ /* NOTE Done by common code */ /* m. return TPM_SUCCESS. */ TPM_BN_free(wBignum); /* @1 */ TPM_BN_free(qBignum); /* @2 */ TPM_BN_free(nBignum); /* @3 */ TPM_BN_free(w1Bignum); /* @4 */ return rc; } TPM_RESULT TPM_DAAJoin_Stage14_Sign_Stage7(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0) { TPM_RESULT rc = 0; TPM_BIGNUM fBignum = NULL; /* freed @1 */ TPM_BIGNUM wBignum = NULL; /* freed @2 */ TPM_BIGNUM nBignum = NULL; /* freed @3 */ TPM_BIGNUM eBignum = NULL; /* freed @4 */ unsigned int numBytes; /* for debug */ printf("TPM_DAAJoin_Stage14_Sign_Stage7:\n"); tpm_state = tpm_state; /* not used */ /* a. Verify that DAA_session ->DAA_stage==14. Return TPM_DAA_STAGE and flush handle on mismatch */ /* NOTE Done by common code */ /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings ) and return error TPM_DAA_ISSUER_SETTINGS on mismatch */ /* NOTE Done by common code */ /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error TPM_DAA_TPM_SETTINGS on mismatch */ /* NOTE Done by common code */ /* d. Set DAA_generic_gamma = inputData0 */ /* e. Verify that SHA-1(DAA_generic_gamma) == DAA_issuerSettings -> DAA_digest_gamma and return error TPM_DAA_INPUT_DATA0 on mismatch */ if (rc == 0) { printf("TPM_DAAJoin_Stage14_Sign_Stage7: Checking DAA_generic_gamma\n"); rc = TPM_SHA1_Check(tpm_daa_session_data->DAA_issuerSettings.DAA_digest_gamma, /* expect */ inputData0->size, inputData0->buffer, /* DAA_generic_gamma */ 0, NULL); if (rc != 0) { rc = TPM_DAA_INPUT_DATA0; } } /* f. Set f = SHA-1(DAA_tpmSpecific -> DAA_rekey || DAA_tpmSpecific -> DAA_count || 0) || SHA-1(DAA_tpmSpecific -> DAA_rekey || DAA_tpmSpecific -> DAA_count || 1 ) mod DAA_issuerSettings -> DAA_generic_q. */ if (rc == 0) { printf("TPM_DAAJoin_Stage14_Sign_Stage7: Creating f\n"); rc = TPM_ComputeF(&fBignum, tpm_daa_session_data); /* freed @1 */ } if (rc == 0) { rc = TPM_BN_num_bytes(&numBytes, fBignum); printf("TPM_DAAJoin_Stage14_Sign_Stage7: f. f size %u\n", numBytes); } /* FIXME Set W = DAA_session -> DAA_scratch */ if (rc == 0) { printf("TPM_DAAJoin_Stage14_Sign_Stage7: Creating W\n"); rc = TPM_bin2bn(&wBignum, tpm_daa_session_data->DAA_session.DAA_scratch, sizeof(tpm_daa_session_data->DAA_session.DAA_scratch)); } if (rc == 0) { rc = TPM_BN_num_bytes(&numBytes, wBignum); printf("TPM_DAAJoin_Stage14_Sign_Stage7: W size %u\n", numBytes); } /* FIXME Set n = DAA_generic_gamma */ if (rc == 0) { printf("TPM_DAAJoin_Stage14_Sign_Stage7: Creating n\n"); rc = TPM_bin2bn(&nBignum, inputData0->buffer, inputData0->size); } if (rc == 0) { rc = TPM_BN_num_bytes(&numBytes, nBignum); printf("TPM_DAAJoin_Stage14_Sign_Stage7: n size %u\n", numBytes); } /* g. Set E = ((DAA_session -> DAA_scratch)^f) mod (DAA_generic_gamma). */ /* FIXME E = (w^f) mod n */ if (rc == 0) { rc = TPM_ComputeAexpPmodn(NULL, 0, &eBignum, /* R */ wBignum, /* A */ fBignum, /* P */ nBignum); /* n */ } /* h. Set outputData = E */ if (rc == 0) { printf("TPM_DAAJoin_Stage14_Sign_Stage7: Output E\n"); rc = TPM_bn2binMalloc(&(outputData->buffer), &(outputData->size), eBignum, 0); } /* i. increment DAA_session -> DAA_stage by 1 */ /* NOTE Done by common code */ /* j. return TPM_SUCCESS. */ TPM_BN_free(fBignum); /* @1 */ TPM_BN_free(wBignum); /* @2 */ TPM_BN_free(nBignum); /* @3 */ TPM_BN_free(eBignum); /* @4 */ return rc; } TPM_RESULT TPM_DAAJoin_Stage15_Sign_Stage8(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0) { TPM_RESULT rc = 0; unsigned char *r0 = NULL; /* freed @1 */ unsigned char *r1 = NULL; /* freed @2 */ TPM_BIGNUM r0Bignum = NULL; /* freed @3 */ TPM_BIGNUM r1Bignum = NULL; /* freed @4 */ TPM_BIGNUM r1sBignum = NULL; /* freed @5 */ TPM_BIGNUM rBignum = NULL; /* freed @6 */ TPM_BIGNUM e1Bignum = NULL; /* freed @7 */ TPM_BIGNUM qBignum = NULL; /* freed @8 */ TPM_BIGNUM nBignum = NULL; /* freed @9 */ TPM_BIGNUM wBignum = NULL; /* freed @10 */ printf("TPM_DAAJoin_Stage15_Sign_Stage8:\n"); tpm_state = tpm_state; /* not used */ /* a. Verify that DAA_session ->DAA_stage==15. Return TPM_DAA_STAGE and flush handle on mismatch */ /* NOTE Done by common code */ /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS on mismatch */ /* NOTE Done by common code */ /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error TPM_DAA_TPM_SETTINGS on mismatch */ /* NOTE Done by common code */ /* d. Set DAA_generic_gamma = inputData0 */ /* e. Verify that SHA-1(DAA_generic_gamma) == DAA_issuerSettings -> DAA_digest_gamma and return error TPM_DAA_INPUT_DATA0 on mismatch */ if (rc == 0) { printf("TPM_DAAJoin_Stage15_Sign_Stage8: Checking DAA_generic_gamma\n"); rc = TPM_SHA1_Check(tpm_daa_session_data->DAA_issuerSettings.DAA_digest_gamma, /* expect */ inputData0->size, inputData0->buffer, /* DAA_generic_gamma */ 0, NULL); if (rc != 0) { rc = TPM_DAA_INPUT_DATA0; } } /* f. Obtain DAA_SIZE_r0 bytes using the MGF1 function and label them r0. "r0" || DAA_session -> DAA_contextSeed) is the Z seed. */ if (rc == 0) { printf("TPM_DAAJoin_Stage15_Sign_Stage8: Creating r0\n"); rc = TPM_MGF1_GenerateArray(&r0, /* returned MGF1 array */ DAA_SIZE_r0, /* size of Y */ /* length of the entire seed */ sizeof("r0") -1 + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), sizeof("r0") -1, "r0", sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), tpm_daa_session_data->DAA_session.DAA_contextSeed, 0, NULL); } if (rc == 0) { rc = TPM_bin2bn(&r0Bignum, r0, DAA_SIZE_r0); } /* g. Obtain DAA_SIZE_r1 bytes using the MGF1 function and label them r1. "r1" || DAA_session -> DAA_contextSeedis the Z seed. */ if (rc == 0) { printf("TPM_DAAJoin_Stage15_Sign_Stage8: Creating r1\n"); rc = TPM_MGF1_GenerateArray(&r1, /* returned MGF1 array */ DAA_SIZE_r1, /* size of Y */ /* length of the entire seed */ sizeof("r1") -1 + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), sizeof("r1") -1, "r1", sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), tpm_daa_session_data->DAA_session.DAA_contextSeed, 0, NULL); } if (rc == 0) { rc = TPM_bin2bn(&r1Bignum, r1, DAA_SIZE_r1); } /* FIXME Set q = DAA_generic_q */ if (rc == 0) { printf("TPM_DAAJoin_Stage15_Sign_Stage8: Creating n from DAA_generic_q\n"); rc = TPM_bin2bn(&qBignum, tpm_daa_session_data->DAA_issuerSettings.DAA_generic_q, sizeof(tpm_daa_session_data->DAA_issuerSettings.DAA_generic_q)); } /* h. set r = r0 + 2^DAA_power0 * r1 mod (DAA_issuerSettings -> DAA_generic_q). */ /* FIXME added parentheses h. set r = (r0 + (2^DAA_power0 * r1)) mod (DAA_issuerSettings -> DAA_generic_q). h. set r = (r0 + (2^DAA_power0 * r1)) mod q */ if (rc == 0) { rc = TPM_BN_lshift(&r1sBignum, /* result, freed @5 */ r1Bignum, /* input */ DAA_power0); /* n */ } if (rc == 0) { rc = TPM_ComputeApBmodn(&rBignum, /* result, freed @6 */ r0Bignum, /* A */ r1sBignum, /* B */ qBignum); /* n */ } /* FIXME Set n = DAA_generic_gamma */ if (rc == 0) { printf("TPM_DAAJoin_Stage15_Sign_Stage8: Creating n1 from DAA_generic_gamma\n"); rc = TPM_bin2bn(&nBignum, inputData0->buffer, inputData0->size); } /* FIXME Set w = DAA_session -> DAA_scratch */ if (rc == 0) { printf("TPM_DAAJoin_Stage15_Sign_Stage8: Creating w from DAA_scratch\n"); rc = TPM_bin2bn(&wBignum, tpm_daa_session_data->DAA_session.DAA_scratch, sizeof(tpm_daa_session_data->DAA_session.DAA_scratch)); } /* i. set E1 = ((DAA_session -> DAA_scratch)^r) mod (DAA_generic_gamma). */ /* (w ^ r) mod n */ if (rc == 0) { rc = TPM_ComputeAexpPmodn(NULL, 0, &e1Bignum, /* R */ wBignum, /* A */ rBignum, /* P */ nBignum); /* n */ } /* j. Set DAA_session -> DAA_scratch = NULL */ if (rc == 0) { tpm_daa_session_data->DAA_session.DAA_scratch_null = TRUE; } /* k. Set outputData = E1 */ if (rc == 0) { rc = TPM_bn2binMalloc(&(outputData->buffer), &(outputData->size), e1Bignum, 0); } /* l. increment DAA_session -> DAA_stage by 1 */ /* NOTE Done by common code */ /* m. return TPM_SUCCESS. */ free(r0); /* @1 */ free(r1); /* @2 */ TPM_BN_free(r0Bignum); /* @3 */ TPM_BN_free(r1Bignum); /* @4 */ TPM_BN_free(r1sBignum); /* @5 */ TPM_BN_free(rBignum); /* @6 */ TPM_BN_free(e1Bignum); /* @7 */ TPM_BN_free(qBignum); /* @8 */ TPM_BN_free(nBignum); /* @9 */ TPM_BN_free(wBignum); /* @10 */ return rc; } TPM_RESULT TPM_DAAJoin_Stage16_Sign_Stage9(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0) { TPM_RESULT rc = 0; unsigned char *nt = NULL; /* freed @1 */ printf("TPM_DAAJoin_Stage16_Sign_Stage9:\n"); tpm_state = tpm_state; /* not used */ /* a. Verify that DAA_session ->DAA_stage==16. Return TPM_DAA_STAGE and flush handle on mismatch */ /* NOTE Done by common code */ /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS on mismatch */ /* NOTE Done by common code */ /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error TPM_DAA_TPM_SETTINGS on mismatch */ /* NOTE Done by common code */ /* d. Verify that inputSize0 == sizeOf(TPM_DIGEST) and return error TPM_DAA_INPUT_DATA0 on mismatch */ if (rc == 0) { if (inputData0->size != TPM_DIGEST_SIZE) { printf("TPM_DAAJoin_Stage16_Sign_Stage9: Error, inputData0 size %u should be %u\n", inputData0->size, TPM_DIGEST_SIZE); rc = TPM_DAA_INPUT_DATA0; } } /* e. Set DAA_session -> DAA_digest = inputData0 */ if (rc == 0) { /* e. Set DAA_session -> DAA_digest = inputData0 */ /* NOTE: This step is unnecessary, since the value is overridden in g. */ /* f. Obtain DAA_SIZE_NT bytes from the RNG and label them NT */ rc = TPM_Malloc(&nt, DAA_SIZE_NT); } if (rc == 0) { rc = TPM_Random(nt, DAA_SIZE_NT); } /* g. Set DAA_session -> DAA_digest to the SHA-1 ( DAA_session -> DAA_digest || NT ) */ if (rc == 0) { rc = TPM_SHA1(tpm_daa_session_data->DAA_session.DAA_digest, inputData0->size, inputData0->buffer, /* e. DAA_session -> DAA_digest */ DAA_SIZE_NT, nt, 0, NULL); } /* h. Set outputData = NT */ if (rc == 0) { rc = TPM_SizedBuffer_Set(outputData, DAA_SIZE_NT, nt); } /* i. increment DAA_session -> DAA_stage by 1 */ /* NOTE Done by common code */ /* j. return TPM_SUCCESS. */ free(nt); /* @1 */ return rc; } TPM_RESULT TPM_DAAJoin_Stage17_Sign_Stage11(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData) { TPM_RESULT rc = 0; unsigned char *r0 = NULL; /* freed @1 */ TPM_BIGNUM r0Bignum = NULL; /* freed @2 */ TPM_BIGNUM fBignum = NULL; /* freed @3 */ TPM_BIGNUM s0Bignum = NULL; /* freed @4 */ TPM_BIGNUM cBignum = NULL; /* freed @5 */ printf("TPM_DAAJoin_Stage17_Sign_Stage11:\n"); tpm_state = tpm_state; /* not used */ /* a. Verify that DAA_session ->DAA_stage==17. Return TPM_DAA_STAGE and flush handle on mismatch */ /* NOTE Done by common code */ /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS on mismatch */ /* NOTE Done by common code */ /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error TPM_DAA_TPM_SETTINGS on mismatch */ /* NOTE Done by common code */ /* d. Obtain DAA_SIZE_r0 bytes using the MGF1 function and label them r0. "r0" || DAA_session -> DAA_contextSeed is the Z seed. */ if (rc == 0) { printf("TPM_DAAJoin_Stage17_Sign_Stage11: Creating r0\n"); rc = TPM_MGF1_GenerateArray(&r0, /* returned MGF1 array */ DAA_SIZE_r0, /* size of Y */ /* length of the entire seed */ sizeof("r0") -1 + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), sizeof("r0") -1, "r0", sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), tpm_daa_session_data->DAA_session.DAA_contextSeed, 0, NULL); } if (rc == 0) { rc = TPM_bin2bn(&r0Bignum, r0, DAA_SIZE_r0); } /* e. Set f = SHA-1(DAA_tpmSpecific -> DAA_rekey || DAA_tpmSpecific -> DAA_count || 0) || SHA-1(DAA_tpmSpecific -> DAA_rekey || DAA_tpmSpecific -> DAA_count || 1 ) mod DAA_issuerSettings -> DAA_generic_q. */ if (rc == 0) { rc = TPM_ComputeF(&fBignum, tpm_daa_session_data); /* freed @3 */ } /* f. Set f0 = f mod 2^DAA_power0 (erase all but the lowest DAA_power0 bits of f) */ if (rc == 0) { rc = TPM_BN_mask_bits(fBignum, DAA_power0); /* f becomes f0 */ } /* FIXME Set c = DAA_session -> DAA_digest */ if (rc == 0) { printf("TPM_DAAJoin_Stage17_Sign_Stage11: Creating c from DAA_session -> DAA_digest\n"); rc = TPM_bin2bn(&cBignum, tpm_daa_session_data->DAA_session.DAA_digest, TPM_DIGEST_SIZE); } /* g. Set s0 = r0 + (DAA_session -> DAA_digest) * f0 in Z. Compute over the integers. The computation is not reduced with a modulus. */ /* s0 = r0 + (c * f0) */ if (rc == 0) { rc = TPM_ComputeApBxC(&s0Bignum, /* result */ r0Bignum, /* A */ cBignum, /* B */ fBignum); /* C */ } /* h. set outputData = s0 */ if (rc == 0) { rc = TPM_bn2binMalloc(&(outputData->buffer), &(outputData->size), s0Bignum, 0); } /* i. increment DAA_session -> DAA_stage by 1 */ /* NOTE Done by common code */ /* j. return TPM_SUCCESS */ free(r0); /* @1 */ TPM_BN_free(r0Bignum); /* @2 */ TPM_BN_free(fBignum); /* @3 */ TPM_BN_free(s0Bignum); /* @4 */ TPM_BN_free(cBignum); /* @5 */ return rc; } TPM_RESULT TPM_DAAJoin_Stage18_Sign_Stage12(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData) { TPM_RESULT rc = 0; unsigned char *r1 = NULL; /* freed @1 */ TPM_BIGNUM r1Bignum = NULL; /* freed @2 */ TPM_BIGNUM fBignum = NULL; /* freed @3 */ TPM_BIGNUM f1Bignum = NULL; /* freed @4 */ TPM_BIGNUM s1Bignum = NULL; /* freed @5 */ TPM_BIGNUM cBignum = NULL; /* freed @6 */ printf("TPM_DAAJoin_Stage18_Sign_Stage12:\n"); tpm_state = tpm_state; /* not used */ /* a. Verify that DAA_session ->DAA_stage==18. Return TPM_DAA_STAGE and flush handle on mismatch */ /* NOTE Done by common code */ /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS on mismatch */ /* NOTE Done by common code */ /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error TPM_DAA_TPM_SETTINGS on mismatch */ /* NOTE Done by common code */ /* d. Obtain DAA_SIZE_r1 bytes using the MGF1 function and label them r1. "r1" || DAA_session -> DAA_contextSeed is the Z seed. */ if (rc == 0) { printf("TPM_DAAJoin_Stage18_Sign_Stage12: Creating r1\n"); rc = TPM_MGF1_GenerateArray(&r1, /* returned MGF1 array */ DAA_SIZE_r1, /* size of Y */ /* length of the entire seed */ sizeof("r1") -1 + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), sizeof("r1") -1, "r1", sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), tpm_daa_session_data->DAA_session.DAA_contextSeed, 0, NULL); } if (rc == 0) { rc = TPM_bin2bn(&r1Bignum, r1, DAA_SIZE_r1); } /* e. Set f = SHA-1(DAA_tpmSpecific -> DAA_rekey || DAA_tpmSpecific -> DAA_count || 0) || SHA-1(DAA_tpmSpecific -> DAA_rekey || DAA_tpmSpecific -> DAA_count || 1 ) mod DAA_issuerSettings -> DAA_generic_q. */ if (rc == 0) { rc = TPM_ComputeF(&fBignum, tpm_daa_session_data); /* freed @3 */ } /* f. Shift f right by DAA_power0 bits (discard the lowest DAA_power0 bits) and label the result f1 */ if (rc == 0) { rc = TPM_BN_rshift(&f1Bignum, fBignum, DAA_power0); /* f becomes f1 */ } /* FIXME Set c = DAA_session -> DAA_digest */ if (rc == 0) { printf("TPM_DAAJoin_Stage18_Sign_Stage12: Creating c from DAA_session -> DAA_digest\n"); rc = TPM_bin2bn(&cBignum, tpm_daa_session_data->DAA_session.DAA_digest, TPM_DIGEST_SIZE); } /* g. Set s1 = r1 + (DAA_session -> DAA_digest)* f1 in Z. Compute over the integers. The computation is not reduced with a modulus. */ /* s1 = r1 + (c * f1) */ if (rc == 0) { rc = TPM_ComputeApBxC(&s1Bignum, /* result */ r1Bignum, /* A */ cBignum, /* B */ f1Bignum); /* C */ } /* h. set outputData = s1 */ if (rc == 0) { rc = TPM_bn2binMalloc(&(outputData->buffer), &(outputData->size), s1Bignum, 0); } /* i. increment DAA_session -> DAA_stage by 1 */ /* NOTE Done by common code */ /* j. return TPM_SUCCESS */ free(r1); /* @1 */ TPM_BN_free(r1Bignum); /* @2 */ TPM_BN_free(fBignum); /* @3 */ TPM_BN_free(f1Bignum); /* @4 */ TPM_BN_free(s1Bignum); /* @5 */ TPM_BN_free(cBignum); /* @6 */ return rc; } TPM_RESULT TPM_DAAJoin_Stage19(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData) { TPM_RESULT rc = 0; unsigned char *r2 = NULL; /* freed @1 */ TPM_BIGNUM r2Bignum = NULL; /* freed @2 */ TPM_BIGNUM s2Bignum = NULL; /* freed @3 */ TPM_BIGNUM cBignum = NULL; /* freed @4 */ TPM_BIGNUM u0Bignum = NULL; /* freed @5 */ printf("TPM_DAAJoin_Stage19:\n"); tpm_state = tpm_state; /* not used */ /* a. Verify that DAA_session ->DAA_stage==19. Return TPM_DAA_STAGE and flush handle on mismatch */ /* NOTE Done by common code */ /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS on mismatch */ /* NOTE Done by common code */ /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error TPM_DAA_TPM_SETTINGS on mismatch */ /* NOTE Done by common code */ /* d. Obtain DAA_SIZE_r2 bytes using the MGF1 function and label them r2. "r2" || DAA_session -> DAA_contextSeed is the Z seed. */ if (rc == 0) { printf("TPM_DAAJoin_Stage19: Creating r2\n"); rc = TPM_MGF1_GenerateArray(&r2, /* returned MGF1 array */ DAA_SIZE_r2, /* size of Y */ /* length of the entire seed */ sizeof("r2") -1 + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), sizeof("r2") -1, "r2", sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), tpm_daa_session_data->DAA_session.DAA_contextSeed, 0, NULL); } if (rc == 0) { rc = TPM_bin2bn(&r2Bignum, r2, DAA_SIZE_r2); } /* e. Set s2 = r2 + (DAA_session -> DAA_digest)*( DAA_joinSession -> DAA_join_u0) mod 2^DAA_power1 (Erase all but the lowest DAA_power1 bits of s2) */ /* FIXME Set c = DAA_session -> DAA_digest */ if (rc == 0) { printf("TPM_DAAJoin_Stage19: Creating c from DAA_session -> DAA_digest\n"); rc = TPM_bin2bn(&cBignum, tpm_daa_session_data->DAA_session.DAA_digest, TPM_DIGEST_SIZE); } /* FIXME Set u0 = DAA_joinSession -> DAA_join_u0 */ if (rc == 0) { printf("TPM_DAAJoin_Stage19: Creating u0 from DAA_joinSession -> DAA_join_u0\n"); rc = TPM_bin2bn(&u0Bignum, tpm_daa_session_data->DAA_joinSession.DAA_join_u0, sizeof(tpm_daa_session_data->DAA_joinSession.DAA_join_u0)); } /* s2 = (r2 + c * u0) mod_pow */ if (rc == 0) { rc = TPM_ComputeApBxC(&s2Bignum, /* result */ r2Bignum, /* A */ cBignum, /* B */ u0Bignum); /* C */ } if (rc == 0) { rc = TPM_BN_mask_bits(s2Bignum, DAA_power1); } /* f. set outputData = s2 */ if (rc == 0) { rc = TPM_bn2binMalloc(&(outputData->buffer), &(outputData->size), s2Bignum, 0); } /* insure that outputData is DAA_power1 bits */ if (rc == 0) { rc = TPM_SizedBuffer_ComputeEnlarge(outputData, DAA_power1 / 8); } /* g. increment DAA_session -> DAA_stage by 1 */ /* NOTE Done by common code */ /* h. return TPM_SUCCESS */ free(r2); /* @1 */ TPM_BN_free(r2Bignum); /* @2 */ TPM_BN_free(s2Bignum); /* @3 */ TPM_BN_free(cBignum); /* @4 */ TPM_BN_free(u0Bignum); /* @5 */ return rc; } TPM_RESULT TPM_DAAJoin_Stage20(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData) { TPM_RESULT rc = 0; unsigned char *r2 = NULL; /* freed @1 */ TPM_BIGNUM r2Bignum = NULL; /* freed @2 */ TPM_BIGNUM s12Bignum = NULL; /* freed @3 */ TPM_BIGNUM s12sBignum = NULL; /* freed @4 */ TPM_BIGNUM cBignum = NULL; /* freed @5 */ TPM_BIGNUM u0Bignum = NULL; /* freed @6 */ unsigned int numBytes; /* just for debug */ printf("TPM_DAAJoin_Stage20:\n"); tpm_state = tpm_state; /* not used */ /* a. Verify that DAA_session ->DAA_stage==20. Return TPM_DAA_STAGE and flush handle on mismatch */ /* NOTE Done by common code */ /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS on mismatch */ /* NOTE Done by common code */ /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error TPM_DAA_TPM_SETTINGS on mismatch */ /* NOTE Done by common code */ /* d. Obtain DAA_SIZE_r2 bytes using the MGF1 function and label them r2. "r2" || DAA_session -> DAA_contextSeed is the Z seed. */ if (rc == 0) { printf("TPM_DAAJoin_Stage20: Creating r2\n"); rc = TPM_MGF1_GenerateArray(&r2, /* returned MGF1 array */ DAA_SIZE_r2, /* size of Y */ /* length of the entire seed */ sizeof("r2") -1 + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), sizeof("r2") -1, "r2", sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), tpm_daa_session_data->DAA_session.DAA_contextSeed, 0, NULL); } if (rc == 0) { rc = TPM_bin2bn(&r2Bignum, r2, DAA_SIZE_r2); } /* e. Set s12 = r2 + (DAA_session -> DAA_digest)*( DAA_joinSession -> DAA_join_u0) */ /* FIXME Set c = DAA_session -> DAA_digest */ if (rc == 0) { printf("TPM_DAAJoin_Stage20: Creating c from DAA_session -> DAA_digest\n"); rc = TPM_bin2bn(&cBignum, tpm_daa_session_data->DAA_session.DAA_digest, TPM_DIGEST_SIZE); } /* FIXME Set u0 = DAA_joinSession -> DAA_join_u0 */ if (rc == 0) { printf("TPM_DAAJoin_Stage20: Creating u0 from DAA_joinSession -> DAA_join_u0\n"); rc = TPM_bin2bn(&u0Bignum, tpm_daa_session_data->DAA_joinSession.DAA_join_u0, sizeof(tpm_daa_session_data->DAA_joinSession.DAA_join_u0)); } /* s12 = (r2 + c * u0) mod_pow */ if (rc == 0) { rc = TPM_ComputeApBxC(&s12Bignum, /* result */ r2Bignum, /* A */ cBignum, /* B */ u0Bignum); /* C */ } /* FIXME for debug */ if (rc == 0) { rc = TPM_BN_num_bytes(&numBytes, s12Bignum); printf("TPM_DAAJoin_Stage20: e. s12 size %u\n", numBytes); } /* f. Shift s12 right by DAA_power1 bit (discard the lowest DAA_power1 bits). */ if (rc == 0) { rc = TPM_BN_rshift(&s12sBignum, s12Bignum, DAA_power1); /* s12 becomes s12s */ } if (rc == 0) { rc = TPM_BN_num_bytes(&numBytes, s12sBignum); printf("TPM_DAAJoin_Stage20: f. s12 size %u\n", numBytes); } /* g. Set DAA_session -> DAA_scratch = s12 */ if (rc == 0) { rc = TPM_ComputeDAAScratch(tpm_daa_session_data->DAA_session.DAA_scratch, sizeof(tpm_daa_session_data->DAA_session.DAA_scratch), s12sBignum); } /* h. Set outputData = DAA_session -> DAA_digest */ if (rc == 0) { rc = TPM_SizedBuffer_Set(outputData, TPM_DIGEST_SIZE, tpm_daa_session_data->DAA_session.DAA_digest); } /* i. increment DAA_session -> DAA_stage by 1 */ /* NOTE Done by common code */ /* j. return TPM_SUCCESS */ free(r2); /* @1 */ TPM_BN_free(r2Bignum); /* @2 */ TPM_BN_free(s12Bignum); /* @3 */ TPM_BN_free(s12sBignum); /* @4 */ TPM_BN_free(cBignum); /* @5 */ TPM_BN_free(u0Bignum); /* @6 */ return rc; } TPM_RESULT TPM_DAAJoin_Stage21(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData) { TPM_RESULT rc = 0; unsigned char *r3 = NULL; /* freed @1 */ TPM_BIGNUM r3Bignum = NULL; /* freed @2 */ TPM_BIGNUM s3Bignum = NULL; /* freed @3 */ TPM_BIGNUM cBignum = NULL; /* freed @4 */ TPM_BIGNUM u1Bignum = NULL; /* freed @5 */ TPM_BIGNUM s12Bignum = NULL; /* freed @6 */ unsigned int numBytes; /* just for debug */ printf("TPM_DAAJoin_Stage21:\n"); tpm_state = tpm_state; /* not used */ /* a. Verify that DAA_session ->DAA_stage==21. Return TPM_DAA_STAGE and flush handle on mismatch */ /* NOTE Done by common code */ /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS on mismatch */ /* NOTE Done by common code */ /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error TPM_DAA_TPM_SETTINGS on mismatch */ /* NOTE Done by common code */ /* d. Obtain DAA_SIZE_r3 bytes using the MGF1 function and label them r3. "r3" || DAA_session -> DAA_contextSeed) is the Z seed. */ if (rc == 0) { printf("TPM_DAAJoin_Stage21: Creating r3\n"); rc = TPM_MGF1_GenerateArray(&r3, /* returned MGF1 array */ DAA_SIZE_r3, /* size of r3 */ /* length of the entire seed */ sizeof("r3") -1 + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), sizeof("r3") -1, "r3", sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), tpm_daa_session_data->DAA_session.DAA_contextSeed, 0, NULL); } if (rc == 0) { rc = TPM_bin2bn(&r3Bignum, r3, DAA_SIZE_r3); } /* just for debug */ if (rc == 0) { rc = TPM_BN_num_bytes(&numBytes, r3Bignum); printf("TPM_DAAJoin_Stage21: r3 size %u\n", numBytes); } /* e. Set s3 = r3 + (DAA_session -> DAA_digest)*( DAA_joinSession -> DAA_join_u1) + (DAA_session -> DAA_scratch). */ /* FIXME Set c = DAA_session -> DAA_digest */ if (rc == 0) { printf("TPM_DAAJoin_Stage21: Creating c from DAA_session -> DAA_digest\n"); rc = TPM_bin2bn(&cBignum, tpm_daa_session_data->DAA_session.DAA_digest, TPM_DIGEST_SIZE); } /* just for debug */ if (rc == 0) { rc = TPM_BN_num_bytes(&numBytes, cBignum); printf("TPM_DAAJoin_Stage21: c size %u\n", numBytes); } /* FIXME Set u1 = DAA_joinSession -> DAA_join_u1 */ if (rc == 0) { printf("TPM_DAAJoin_Stage21: Creating u1 from DAA_joinSession -> DAA_join_u1\n"); rc = TPM_bin2bn(&u1Bignum, tpm_daa_session_data->DAA_joinSession.DAA_join_u1, sizeof(tpm_daa_session_data->DAA_joinSession.DAA_join_u1)); } /* just for debug */ if (rc == 0) { rc = TPM_BN_num_bytes(&numBytes, u1Bignum); printf("TPM_DAAJoin_Stage21: u1 size %u\n", numBytes); } /* FIXME Set s12 = DAA_session -> DAA_scratch */ if (rc == 0) { printf("TPM_DAAJoin_Stage21: Creating s12 from DAA_session -> DAA_scratch\n"); rc = TPM_bin2bn(&s12Bignum, tpm_daa_session_data->DAA_session.DAA_scratch, sizeof(tpm_daa_session_data->DAA_session.DAA_scratch)); } if (rc == 0) { rc = TPM_BN_num_bytes(&numBytes, s12Bignum); printf("TPM_DAAJoin_Stage21: s12 size %u\n", numBytes); } /* s3 = r3 + c * u1 + s12 */ if (rc == 0) { rc = TPM_ComputeApBxCpD(&s3Bignum, /* freed by caller */ r3Bignum, /* A */ cBignum, /* B */ u1Bignum, /* C */ s12Bignum); /* D */ } if (rc == 0) { rc = TPM_BN_num_bytes(&numBytes, s3Bignum); printf("TPM_DAAJoin_Stage21: s3 size %u\n", numBytes); } /* f. Set DAA_session -> DAA_scratch = NULL */ if (rc == 0) { tpm_daa_session_data->DAA_session.DAA_scratch_null = TRUE; } /* g. set outputData = s3 */ if (rc == 0) { rc = TPM_bn2binMalloc(&(outputData->buffer), &(outputData->size), s3Bignum, 0); } /* h. increment DAA_session -> DAA_stage by 1 */ /* NOTE Done by common code */ /* i. return TPM_SUCCESS */ free(r3); /* @1 */ TPM_BN_free(r3Bignum); /* @2 */ TPM_BN_free(s3Bignum); /* @3 */ TPM_BN_free(cBignum); /* @4 */ TPM_BN_free(u1Bignum); /* @5 */ TPM_BN_free(s12Bignum); /* @6 */ return rc; } TPM_RESULT TPM_DAAJoin_Stage22(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0) { TPM_RESULT rc = 0; TPM_BIGNUM v10Bignum = NULL; /* freed @1 */ TPM_BIGNUM v10sBignum = NULL; /* freed @2 */ TPM_BIGNUM u0Bignum = NULL; /* freed @3 */ TPM_BIGNUM u2Bignum = NULL; /* freed @4 */ TPM_BIGNUM v0Bignum = NULL; /* freed @5 */ TPM_DAA_SENSITIVE tpm_daa_sensitive; unsigned int numBytes; /* just for debug */ printf("TPM_DAAJoin_Stage22:\n"); TPM_DAASensitive_Init(&tpm_daa_sensitive); /* freed @6 */ /* a. Verify that DAA_session ->DAA_stage==22. Return TPM_DAA_STAGE and flush handle on mismatch */ /* NOTE Done by common code */ /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS on mismatch */ /* NOTE Done by common code */ /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error TPM_DAA_TPM_SETTINGS on mismatch */ /* NOTE Done by common code */ /* d. Verify inputSize0 == DAA_SIZE_v0 and return error TPM_DAA_INPUT_DATA0 on mismatch */ if (rc == 0) { if (inputData0->size != DAA_SIZE_v0) { printf("TPM_DAAJoin_Stage22: Error, inputData0 size %u should be %u\n", inputData0->size, DAA_SIZE_v0); rc = TPM_DAA_INPUT_DATA0; } } /* e. Set u2 = inputData0 */ if (rc == 0) { printf("TPM_DAAJoin_Stage22: Creating u2\n"); rc = TPM_bin2bn(&u2Bignum, inputData0->buffer, inputData0->size); } /* f. Set v0 = u2 + (DAA_joinSession -> DAA_join_u0) mod 2^DAA_power1 (Erase all but the lowest DAA_power1 bits of v0). */ /* FIXME Set u0 = DAA_joinSession -> DAA_join_u0 */ if (rc == 0) { printf("TPM_DAAJoin_Stage22: Creating u0 from DAA_joinSession -> DAA_join_u0\n"); rc = TPM_bin2bn(&u0Bignum, tpm_daa_session_data->DAA_joinSession.DAA_join_u0, sizeof(tpm_daa_session_data->DAA_joinSession.DAA_join_u0)); } /* FIXME factor this? */ if (rc == 0) { printf("TPM_DAAJoin_Stage22: Calculate v0\n"); rc = TPM_BN_new(&v0Bignum); } /* v0 = u2 + u0 */ if (rc == 0) { rc = TPM_BN_add(v0Bignum, u2Bignum, u0Bignum); } if (rc == 0) { rc = TPM_BN_num_bytes(&numBytes, v0Bignum); printf("TPM_DAAJoin_Stage22: f. v0 size before mask %u\n", numBytes); } /* v0 = v0 mod 2^DAA_power1 */ if (rc == 0) { rc = TPM_BN_mask_bits(v0Bignum, DAA_power1); } if (rc == 0) { rc = TPM_BN_num_bytes(&numBytes, v0Bignum); printf("TPM_DAAJoin_Stage22: f. v0 size after mask %u\n", numBytes); } /* g. Set DAA_tpmSpecific -> DAA_digest_v0 = SHA-1(v0) */ if (rc == 0) { rc = TPM_SHA1_BignumGenerate(tpm_daa_session_data->DAA_tpmSpecific.DAA_digest_v0, v0Bignum, (DAA_power1 + 7) / 8); /* canonicalize the number of bytes */ } /* h. Set v10 = u2 + (DAA_joinSession -> DAA_join_u0) in Z. Compute over the integers. The computation is not reduced with a modulus. */ if (rc == 0) { printf("TPM_DAAJoin_Stage22: Calculate v10\n"); rc = TPM_BN_new(&v10Bignum); } /* v0 = u2 + u0 */ if (rc == 0) { rc = TPM_BN_add(v10Bignum, u2Bignum, u0Bignum); } /* i. Shift v10 right by DAA_power1 bits (erase the lowest DAA_power1 bits). */ if (rc == 0) { rc = TPM_BN_rshift(&v10sBignum, v10Bignum, DAA_power1); } /* j. Set DAA_session -> DAA_scratch = v10 */ if (rc == 0) { rc = TPM_ComputeDAAScratch(tpm_daa_session_data->DAA_session.DAA_scratch, sizeof(tpm_daa_session_data->DAA_session.DAA_scratch), v10sBignum); } /* k. Set outputData */ /* i. Fill in TPM_DAA_BLOB with a type of TPM_RT_DAA_V0 and encrypt the v0 parameters using TPM_PERMANENT_DATA -> daaBlobKey */ /* Create a TPM_DAA_SENSITIVE structure */ if (rc == 0) { printf("TPM_DAAJoin_Stage22: Create TPM_DAA_SENSITIVE\n"); /* Set TPM_DAA_SENSITIVE -> internalData to v0Bignum */ rc = TPM_bn2binMalloc(&(tpm_daa_sensitive.internalData.buffer), &(tpm_daa_sensitive.internalData.size), v0Bignum, 0); } if (rc == 0) { rc = TPM_ComputeEncrypt(outputData, tpm_state, &tpm_daa_sensitive, TPM_RT_DAA_V0); } /* l. increment DAA_session -> DAA_stage by 1 */ /* NOTE Done by common code */ /* m. set DAA_session -> DAA_digestContext = SHA-1(DAA_tpmSpecific || DAA_joinSession) */ if (rc == 0) { rc = TPM_DAADigestContext_GenerateDigestJoin (tpm_daa_session_data->DAA_session.DAA_digestContext, tpm_daa_session_data); } /* n. return TPM_SUCCESS */ TPM_BN_free(v10Bignum); /* @1 */ TPM_BN_free(v10sBignum); /* @2 */ TPM_BN_free(u0Bignum); /* @3 */ TPM_BN_free(u2Bignum); /* @4 */ TPM_BN_free(v0Bignum); /* @5 */ TPM_DAASensitive_Delete(&tpm_daa_sensitive); /* @6 */ return rc; } TPM_RESULT TPM_DAAJoin_Stage23(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0) { TPM_RESULT rc = 0; TPM_BIGNUM u1Bignum = NULL; /* freed @1 */ TPM_BIGNUM u3Bignum = NULL; /* freed @2 */ TPM_BIGNUM v1Bignum = NULL; /* freed @3 */ TPM_BIGNUM v10Bignum = NULL; /* freed @4 */ TPM_DAA_SENSITIVE tpm_daa_sensitive; printf("TPM_DAAJoin_Stage23:\n"); TPM_DAASensitive_Init(&tpm_daa_sensitive); /* freed @5 */ /* a. Verify that DAA_session ->DAA_stage==23. Return TPM_DAA_STAGE and flush handle on mismatch */ /* NOTE Done by common code */ /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS on mismatch */ /* NOTE Done by common code */ /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error TPM_DAA_TPM_SETTINGS on mismatch */ /* NOTE Done by common code */ /* d. Verify inputSize0 == DAA_SIZE_v1 and return error TPM_DAA_INPUT_DATA0 on */ /* mismatch */ if (rc == 0) { if (inputData0->size != DAA_SIZE_v1) { printf("TPM_DAAJoin_Stage23: Error, inputData0 size %u should be %u\n", inputData0->size, DAA_SIZE_v1); rc = TPM_DAA_INPUT_DATA0; } } /* e. Set u3 = inputData0 */ if (rc == 0) { printf("TPM_DAAJoin_Stage23: Creating u3\n"); rc = TPM_bin2bn(&u3Bignum, inputData0->buffer, inputData0->size); } /* f. Set v1 = u3 + DAA_joinSession -> DAA_join_u1 + DAA_session -> DAA_scratch */ /* FIXME Set u1 = DAA_joinSession -> DAA_join_u1 */ if (rc == 0) { printf("TPM_DAAJoin_Stage23: Creating u1 from DAA_joinSession -> DAA_join_u1\n"); rc = TPM_bin2bn(&u1Bignum, tpm_daa_session_data->DAA_joinSession.DAA_join_u1, sizeof(tpm_daa_session_data->DAA_joinSession.DAA_join_u1)); } /* FIXME Set v10 = DAA_session -> DAA_scratch */ if (rc == 0) { printf("TPM_DAAJoin_Stage23: Creating v10\n"); rc = TPM_bin2bn(&v10Bignum, tpm_daa_session_data->DAA_session.DAA_scratch, sizeof(tpm_daa_session_data->DAA_session.DAA_scratch)); } if (rc == 0) { rc = TPM_BN_new(&v1Bignum); } /* f. Set v1 = u3 + u1 + v10 */ if (rc == 0) { rc = TPM_BN_add(v1Bignum, u3Bignum, u1Bignum); } if (rc == 0) { rc = TPM_BN_add(v1Bignum, v1Bignum,v10Bignum); } /* g. Set DAA_tpmSpecific -> DAA_digest_v1 = SHA-1(v1) */ if (rc == 0) { rc = TPM_SHA1_BignumGenerate(tpm_daa_session_data->DAA_tpmSpecific.DAA_digest_v1, v1Bignum, DAA_SIZE_v1); /* canonicalize the number of bytes */ } /* h. Set outputData */ /* i. Fill in TPM_DAA_BLOB with a type of TPM_RT_DAA_V1 and encrypt the v1 parameters using TPM_PERMANENT_DATA -> daaBlobKey */ /* Create a TPM_DAA_SENSITIVE structure */ if (rc == 0) { printf("TPM_DAAJoin_Stage23: Create TPM_DAA_SENSITIVE\n"); /* Set TPM_DAA_SENSITIVE -> internalData to v1Bignum */ rc = TPM_bn2binMalloc(&(tpm_daa_sensitive.internalData.buffer), &(tpm_daa_sensitive.internalData.size), v1Bignum, 0); } if (rc == 0) { rc = TPM_ComputeEncrypt(outputData, tpm_state, &tpm_daa_sensitive, TPM_RT_DAA_V1); } /* i. Set DAA_session -> DAA_scratch = NULL */ if (rc == 0) { tpm_daa_session_data->DAA_session.DAA_scratch_null = TRUE; } /* j. increment DAA_session -> DAA_stage by 1 */ /* NOTE Done by common code */ /* k. set DAA_session -> DAA_digestContext = SHA-1(DAA_tpmSpecific || DAA_joinSession) */ if (rc == 0) { rc = TPM_DAADigestContext_GenerateDigestJoin (tpm_daa_session_data->DAA_session.DAA_digestContext, tpm_daa_session_data); } /* l. return TPM_SUCCESS */ TPM_BN_free(u1Bignum); /* @1 */ TPM_BN_free(u3Bignum); /* @2 */ TPM_BN_free(v1Bignum); /* @3 */ TPM_BN_free(v10Bignum); /* @4 */ TPM_DAASensitive_Delete(&tpm_daa_sensitive); /* @5 */ return rc; } TPM_RESULT TPM_DAAJoin_Stage24(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData) { TPM_RESULT rc = 0; TPM_DAA_SENSITIVE tpm_daa_sensitive; printf("TPM_DAAJoin_Stage24:\n"); TPM_DAASensitive_Init(&tpm_daa_sensitive); /* freed @1 */ /* a. Verify that DAA_session ->DAA_stage==24. Return TPM_DAA_STAGE and flush handle on mismatch */ /* NOTE Done by common code */ /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS on mismatch */ /* NOTE Done by common code */ /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error TPM_DAA_TPM_SETTINGS on mismatch */ /* NOTE Done by common code */ /* d. set outputData = enc(DAA_tpmSpecific) using TPM_PERMANENT_DATA -> daaBlobKey */ /* Create a TPM_DAA_SENSITIVE structure */ if (rc == 0) { printf("TPM_DAAJoin_Stage24 Create TPM_DAA_SENSITIVE\n"); /* Set TPM_DAA_SENSITIVE -> internalData to DAA_tpmSpecific */ rc = TPM_SizedBuffer_SetStructure(&(tpm_daa_sensitive.internalData), &(tpm_daa_session_data->DAA_tpmSpecific), (TPM_STORE_FUNCTION_T)TPM_DAATpm_Store); } if (rc == 0) { rc = TPM_ComputeEncrypt(outputData, tpm_state, &tpm_daa_sensitive, TPM_RT_DAA_TPM); } /* e. return TPM_SUCCESS */ TPM_DAASensitive_Delete(&tpm_daa_sensitive); /* @2 */ return rc; } TPM_RESULT TPM_DAASign_Stage00(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA **tpm_daa_session_data, /* returns entry in array */ TPM_BOOL *daaHandleValid, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0) { TPM_RESULT rc = 0; unsigned char *stream; uint32_t stream_size; TPM_HANDLE daaHandle = 0; /* no preassigned handle */ printf("TPM_DAASign_Stage00:\n"); /* a. Determine that sufficient resources are available to perform a TPM_DAA_Sign. */ /* i. The TPM MUST support sufficient resources to perform one (1) TPM_DAA_Join/TPM_DAA_Sign. The TPM MAY support addition TPM_DAA_Join/ TPM_DAA_Sign sessions. */ /* ii. The TPM may share internal resources between the DAA operations and other variable resource requirements: */ /* iii. If there are insufficient resources within the stored key pool (and one or more keys need to be removed to permit the DAA operation to execute) return TPM_NOSPACE */ /* iv. If there are insufficient resources within the stored session pool (and one or more authorization or transport sessions need to be removed to permit the DAA operation to execute), return TPM_RESOURCES. */ if (rc == 0) { rc = TPM_DaaSessions_GetNewHandle(tpm_daa_session_data, /* returns entry in array */ &daaHandle, /* output */ daaHandleValid, /* output */ tpm_state->tpm_stclear_data.daaSessions); /* array */ } /* b. Set DAA_issuerSettings = inputData0 */ if (rc == 0) { stream = inputData0->buffer; stream_size = inputData0->size; rc = TPM_DAAIssuer_Load(&((*tpm_daa_session_data)->DAA_issuerSettings), &stream, &stream_size); if (rc != 0) { rc = TPM_DAA_INPUT_DATA0; } } /* c. Verify that all fields in DAA_issuerSettings are present and return error TPM_DAA_INPUT_DATA0 if not. */ if (rc == 0) { if (stream_size != 0) { printf("TPM_DAASign_Stage00: Error, bad input0 size %u\n", inputData0->size); rc = TPM_DAA_INPUT_DATA0; } } if (rc == 0) { /* d. set all fields in DAA_session = NULL */ /* e. Assign new handle for session */ /* NOTE Done by TPM_DaaSessions_GetNewHandle() */ printf("TPM_DAASign_Stage00: handle %08x\n", (*tpm_daa_session_data)->daaHandle); /* f. Set outputData to new handle */ /* i. The handle in outputData is included the output HMAC. */ rc = TPM_SizedBuffer_Append32(outputData, (*tpm_daa_session_data)->daaHandle); } /* g. set DAA_session -> DAA_stage = 1 */ /* NOTE Done by common code */ /* h. return TPM_SUCCESS */ return rc; } TPM_RESULT TPM_DAASign_Stage01(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0) { TPM_RESULT rc = 0; TPM_DAA_SENSITIVE tpm_daa_sensitive; unsigned char *stream; uint32_t stream_size; printf("TPM_DAASign_Stage01:\n"); outputData = outputData; /* not used */ TPM_DAASensitive_Init(&tpm_daa_sensitive); /* freed @1 */ /* a. Verify that DAA_session ->DAA_stage==1. Return TPM_DAA_STAGE and flush handle on mismatch */ /* NOTE Done by common code */ /* b. Set DAA_tpmSpecific = unwrap(inputData0) using TPM_PERMANENT_DATA -> daaBlobKey */ if (rc == 0) { rc = TPM_ComputeDecrypt(&tpm_daa_sensitive, /* output */ tpm_state, /* decryption and HMAC keys */ inputData0, /* encrypted stream */ TPM_RT_DAA_TPM); /* resourceType expected */ if (rc != 0) { rc = TPM_DAA_INPUT_DATA0; } } if (rc == 0) { stream = tpm_daa_sensitive.internalData.buffer; stream_size = tpm_daa_sensitive.internalData.size; rc = TPM_DAATpm_Load(&(tpm_daa_session_data->DAA_tpmSpecific), &stream, &stream_size); if (rc != 0) { rc = TPM_DAA_INPUT_DATA0; } } /* c. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS on mismatch */ /* NOTE Done by common code */ /* d. set DAA_session -> DAA_digestContext = SHA-1(DAA_tpmSpecific) */ if (rc == 0) { rc = TPM_SHA1_GenerateStructure(tpm_daa_session_data->DAA_session.DAA_digestContext, &(tpm_daa_session_data->DAA_tpmSpecific), (TPM_STORE_FUNCTION_T)TPM_DAATpm_Store); } /* e set outputData = NULL */ /* NOTE Done by caller */ /* f. set DAA_session -> DAA_stage =2 */ /* NOTE Done by common code */ /* g. return TPM_SUCCESS */ TPM_DAASensitive_Delete(&tpm_daa_sensitive); /* @1 */ return rc; } TPM_RESULT TPM_DAASign_Stage05(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0, TPM_SIZED_BUFFER *inputData1) { TPM_RESULT rc = 0; unsigned char *Y = NULL; /* freed @1 */ TPM_BIGNUM yBignum = NULL; /* freed @2 */ TPM_BIGNUM xBignum = NULL; /* freed @3 */ TPM_BIGNUM nBignum = NULL; /* freed @4 */ TPM_BIGNUM zBignum = NULL; /* freed @5 */ printf("TPM_DAASign_Stage05:\n"); tpm_state = tpm_state; /* not used */ /* a. Verify that DAA_session ->DAA_stage==5. Return TPM_DAA_STAGE and flush handle on mismatch */ /* NOTE Done by common code */ /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS on mismatch */ /* NOTE Done by common code */ /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific) and return error TPM_DAA_TPM_SETTINGS on mismatch */ /* NOTE Done by common code */ /* d. Set DAA_generic_S1 = inputData0 */ /* e. Verify that SHA-1(DAA_generic_S1) == DAA_issuerSettings -> DAA_digest_S1 and return error TPM_DAA_INPUT_DATA0 on mismatch */ if (rc == 0) { printf("TPM_DAASign_Stage05: Checking DAA_generic_S1\n"); rc = TPM_SHA1_Check(tpm_daa_session_data->DAA_issuerSettings.DAA_digest_S1, /* expect */ inputData0->size, inputData0->buffer, /* DAA_generic_S1 */ 0, NULL); if (rc != 0) { rc = TPM_DAA_INPUT_DATA0; } } /* f. Set DAA_generic_n = inputData1 */ /* g. Verify that SHA-1(DAA_generic_n) == DAA_issuerSettings -> DAA_digest_n and return error TPM_DAA_INPUT_DATA1 on mismatch */ if (rc == 0) { printf("TPM_DAASign_Stage05: Checking DAA_digest_n\n"); rc = TPM_SHA1_Check(tpm_daa_session_data->DAA_issuerSettings.DAA_digest_n, /* expect */ inputData1->size, inputData1->buffer, /* DAA_generic_n */ 0, NULL); if (rc != 0) { rc = TPM_DAA_INPUT_DATA1; } } /* h. Obtain DAA_SIZE_r4 bytes using the MGF1 function and label them Y. "r4" || DAA_session -> DAA_contextSeed is the Z seed. */ if (rc == 0) { printf("TPM_DAASign_Stage05: Creating Y\n"); rc = TPM_MGF1_GenerateArray(&Y, /* returned MGF1 array */ DAA_SIZE_r4, /* size of Y */ /* length of the entire seed */ sizeof("r4") -1 + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), sizeof("r4") -1, "r4", sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), tpm_daa_session_data->DAA_session.DAA_contextSeed, 0, NULL); } if (rc == 0) { rc = TPM_bin2bn(&yBignum, Y, DAA_SIZE_r4); } /* i. Set X = DAA_generic_S1 */ if (rc == 0) { printf("TPM_DAASign_Stage05 Creating X\n"); rc = TPM_bin2bn(&xBignum, inputData0->buffer, inputData0->size); } /* j. Set n = DAA_generic_n */ if (rc == 0) { printf("TPM_DAASign_Stage05: Creating n\n"); rc = TPM_bin2bn(&nBignum, inputData1->buffer, inputData1->size); } /* k. Set Z = DAA_session -> DAA_scratch */ if (rc == 0) { printf("TPM_DAASign_Stage05: Creating Z\n"); rc = TPM_bin2bn(&zBignum, tpm_daa_session_data->DAA_session.DAA_scratch, sizeof(tpm_daa_session_data->DAA_session.DAA_scratch)); } /* l. Set DAA_session -> DAA_scratch = Z*(X^Y) mod n */ if (rc == 0) { rc = TPM_ComputeZxAexpPmodn(tpm_daa_session_data->DAA_session.DAA_scratch, sizeof(tpm_daa_session_data->DAA_session.DAA_scratch), zBignum, /* Z */ xBignum, /* A */ yBignum, /* P */ nBignum); /* N */ } /* m. set outputData = DAA_session -> DAA_scratch */ if (rc == 0) { rc = TPM_SizedBuffer_Set(outputData, sizeof(tpm_daa_session_data->DAA_session.DAA_scratch), tpm_daa_session_data->DAA_session.DAA_scratch); } /* n. set DAA_session -> DAA_scratch = NULL */ if (rc == 0) { tpm_daa_session_data->DAA_session.DAA_scratch_null = TRUE; } /* o. increment DAA_session -> DAA_stage by 1 */ /* NOTE Done by common code */ /* p. return TPM_SUCCESS */ free(Y); /* @1 */ TPM_BN_free(yBignum); /* @2 */ TPM_BN_free(xBignum); /* @3 */ TPM_BN_free(nBignum); /* @4 */ TPM_BN_free(zBignum); /* @5 */ return rc; } TPM_RESULT TPM_DAASign_Stage10(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0, TPM_SIZED_BUFFER *inputData1) { TPM_RESULT rc = 0; unsigned char *stream; uint32_t stream_size; uint8_t selector; TPM_BOOL parentPCRStatus; TPM_KEY_HANDLE keyHandle; TPM_KEY *identityKey = NULL; /* the key specified by keyHandle */ printf("TPM_DAASign_Stage10:\n"); /* a. Verify that DAA_session ->DAA_stage==10. Return TPM_DAA_STAGE and flush handle on mismatch */ /* NOTE Done by common code */ /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS on mismatch */ /* NOTE Done by common code */ /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific) and return error TPM_DAA_TPM_SETTINGS on mismatch */ /* NOTE Done by common code */ /* d. Verify that inputSize0 == sizeOf(BYTE), and return error TPM_DAA_INPUT_DATA0 on mismatch */ /* e. Set selector = inputData0, verify that selector == 0 or 1, and return error TPM_DAA_INPUT_DATA0 on mismatch */ if (rc == 0) { stream = inputData0->buffer; stream_size = inputData0->size; rc = TPM_Load8(&selector, &stream, &stream_size); if (rc != 0) { rc = TPM_DAA_INPUT_DATA0; } } if (rc == 0) { if (stream_size != 0) { printf("TPM_DAASign_Stage10: Error, bad input0 size %u\n", inputData0->size); rc = TPM_DAA_INPUT_DATA0; } } if (rc == 0) { printf("TPM_DAASign_Stage10: selector %u\n", selector); switch (selector) { case 1: /* f. If selector == 1, verify that inputSize1 == sizeOf(TPM_DIGEST), and return error TPM_DAA_INPUT_DATA1 on mismatch */ if (rc == 0) { if (inputData1->size != TPM_DIGEST_SIZE) { printf("TPM_DAASign_Stage10: Error, bad input1 size %u\n", inputData1->size); rc = TPM_DAA_INPUT_DATA1; } } /* g. Set DAA_session -> DAA_digest to SHA-1 (DAA_session -> DAA_digest || 1 || inputData1) */ if (rc == 0) { rc = TPM_SHA1(tpm_daa_session_data->DAA_session.DAA_digest, TPM_DIGEST_SIZE, tpm_daa_session_data->DAA_session.DAA_digest, 1, &selector , inputData1->size, inputData1->buffer, 0, NULL); if (rc != 0) { rc = TPM_DAA_INPUT_DATA1; } } break; case 0: /* h. If selector == 0, verify that inputData1 is a handle to a TPM identity key (AIK), and return error TPM_DAA_INPUT_DATA1 on mismatch */ /* get the key handle */ if (rc == 0) { stream = inputData1->buffer; stream_size = inputData1->size; rc = TPM_Load32(&keyHandle, &stream, &stream_size); if (rc != 0) { rc = TPM_DAA_INPUT_DATA1; } } /* validate inputData1 */ if (rc == 0) { if (stream_size != 0) { printf("TPM_DAASign_Stage10: Error, bad input1 size %u\n", inputData1->size); rc = TPM_DAA_INPUT_DATA1; } } /* get the key */ if (rc == 0) { rc = TPM_KeyHandleEntries_GetKey(&identityKey, &parentPCRStatus, tpm_state, keyHandle, TRUE, /* read only */ FALSE, /* do not ignore PCRs */ FALSE); /* cannot use EK */ if (rc != 0) { rc = TPM_DAA_INPUT_DATA1; } } /* validate that it's an AIK */ if (rc == 0) { if (identityKey->keyUsage != TPM_KEY_IDENTITY) { printf("TPM_DAASign_Stage10: Error, " "key keyUsage %04hx must be TPM_KEY_IDENTITY\n", identityKey->keyUsage); rc = TPM_DAA_INPUT_DATA1; } } /* i. Set DAA_session -> DAA_digest to SHA-1 (DAA_session -> DAA_digest || 0 || n2) where n2 is the modulus of the AIK */ if (rc == 0) { rc = TPM_SHA1(tpm_daa_session_data->DAA_session.DAA_digest, TPM_DIGEST_SIZE, tpm_daa_session_data->DAA_session.DAA_digest, 1, &selector, identityKey->pubKey.size, identityKey->pubKey.buffer, 0, NULL); } break; default: printf("TPM_DAASign_Stage10: Error, bad selector %u\n", selector); rc = TPM_DAA_INPUT_DATA0; break; } } /* j. Set outputData = DAA_session -> DAA_digest */ if (rc == 0) { rc = TPM_SizedBuffer_Set(outputData, TPM_DIGEST_SIZE, tpm_daa_session_data->DAA_session.DAA_digest); } /* k. increment DAA_session -> DAA_stage by 1 */ /* NOTE Done by common code */ /* l. return TPM_SUCCESS. */ return rc; } TPM_RESULT TPM_DAASign_Stage13(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0) { TPM_RESULT rc = 0; unsigned char *r2 = NULL; /* freed @1 */ TPM_BIGNUM r2Bignum = NULL; /* freed @2 */ TPM_BIGNUM s2Bignum = NULL; /* freed @3 */ TPM_BIGNUM cBignum = NULL; /* freed @4 */ TPM_BIGNUM v0Bignum = NULL; /* freed @5 */ TPM_DAA_SENSITIVE tpm_daa_sensitive; printf("TPM_DAASign_Stage13:\n"); TPM_DAASensitive_Init(&tpm_daa_sensitive); /* freed @6 */ /* a. Verify that DAA_session ->DAA_stage==13. Return TPM_DAA_STAGE and flush handle on mismatch */ /* NOTE Done by common code */ /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS on mismatch */ /* NOTE Done by common code */ /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific) and return error TPM_DAA_TPM_SETTINGS on mismatch */ /* NOTE Done by common code */ /* d. Set DAA_private_v0= unwrap(inputData0) using TPM_PERMANENT_DATA -> daaBlobKey */ if (rc == 0) { printf("TPM_DAASign_Stage13: unwrapping to v0\n"); rc = TPM_ComputeDecrypt(&tpm_daa_sensitive, /* output */ tpm_state, /* decryption and HMAC keys */ inputData0, /* encrypted stream */ TPM_RT_DAA_V0); /* resourceType expected */ if (rc != 0) { rc = TPM_DAA_INPUT_DATA0; } } /* e. Verify that SHA-1(DAA_private_v0) == DAA_tpmSpecific -> DAA_digest_v0 and return error TPM_DAA_INPUT_DATA0 on mismatch */ if (rc == 0) { printf("TPM_DAASign_Stage13: Checking v0\n"); rc = TPM_SHA1_SizedBufferCheck(tpm_daa_session_data->DAA_tpmSpecific.DAA_digest_v0, &(tpm_daa_sensitive.internalData), (DAA_power1 + 7) / 8); if (rc != 0) { rc = TPM_DAA_INPUT_DATA0; } } /* f. Obtain DAA_SIZE_r2 bytes from the MGF1 function and label them r2. "r2" || DAA_session -> DAA_contextSeed) is the Z seed. */ if (rc == 0) { printf("TPM_DAASign_Stage13 Creating r2\n"); rc = TPM_MGF1_GenerateArray(&r2, /* returned MGF1 array */ DAA_SIZE_r2, /* size of Y */ /* length of the entire seed */ sizeof("r2") -1 + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), sizeof("r2") -1, "r2", sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), tpm_daa_session_data->DAA_session.DAA_contextSeed, 0, NULL); } if (rc == 0) { rc = TPM_bin2bn(&r2Bignum, r2, DAA_SIZE_r2); } /* g. Set s2 = r2 + (DAA_session -> DAA_digest)*( DAA_private_v0) mod 2^DAA_power1 */ /* (erase all but the lowest DAA_power1 bits of s2) */ /* FIXME Set c = DAA_session -> DAA_digest */ if (rc == 0) { printf("TPM_DAASign_Stage13: Creating c from DAA_session -> DAA_digest\n"); rc = TPM_bin2bn(&cBignum, tpm_daa_session_data->DAA_session.DAA_digest, TPM_DIGEST_SIZE); } /* FIXME Set v0 = DAA_private_v0 */ if (rc == 0) { rc = TPM_bin2bn(&v0Bignum, tpm_daa_sensitive.internalData.buffer, tpm_daa_sensitive.internalData.size); } /* s2 = r2 + c * v0 mod 2^DAA_power1 */ if (rc == 0) { rc = TPM_ComputeApBxC(&s2Bignum, /* result */ r2Bignum, /* A */ cBignum, /* B */ v0Bignum); /* C */ } if (rc == 0) { rc = TPM_BN_mask_bits(s2Bignum, DAA_power1); } /* h. set outputData = s2 */ if (rc == 0) { rc = TPM_bn2binMalloc(&(outputData->buffer), &(outputData->size), s2Bignum, 0); } /* i. increment DAA_session -> DAA_stage by 1 */ /* NOTE Done by common code */ /* j. return TPM_SUCCESS */ free(r2); /* @1 */ TPM_BN_free(r2Bignum); /* @2 */ TPM_BN_free(s2Bignum); /* @3 */ TPM_BN_free(cBignum); /* @4 */ TPM_BN_free(v0Bignum); /* @5 */ TPM_DAASensitive_Delete(&tpm_daa_sensitive); /* @6 */ return rc; } TPM_RESULT TPM_DAASign_Stage14(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0) { TPM_RESULT rc = 0; unsigned char *r2 = NULL; /* freed @1 */ TPM_BIGNUM r2Bignum = NULL; /* freed @2 */ TPM_BIGNUM s12Bignum = NULL; /* freed @3 */ TPM_BIGNUM s12sBignum = NULL; /* freed @4 */ TPM_BIGNUM cBignum = NULL; /* freed @5 */ TPM_BIGNUM v0Bignum = NULL; /* freed @6 */ TPM_DAA_SENSITIVE tpm_daa_sensitive; printf("TPM_DAASign_Stage14:\n"); outputData = outputData; /* not used */ TPM_DAASensitive_Init(&tpm_daa_sensitive); /* freed @7 */ /* a. Verify that DAA_session ->DAA_stage==14. Return TPM_DAA_STAGE and flush handle on mismatch */ /* NOTE Done by common code */ /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS on mismatch */ /* NOTE Done by common code */ /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific) and return error TPM_DAA_TPM_SETTINGS on mismatch */ /* NOTE Done by common code */ /* d. Set DAA_private_v0= unwrap(inputData0) using TPM_PERMANENT_DATA -> daaBlobKey */ if (rc == 0) { rc = TPM_ComputeDecrypt(&tpm_daa_sensitive, /* output */ tpm_state, /* decryption and HMAC keys */ inputData0, /* encrypted stream */ TPM_RT_DAA_V0); /* resourceType expected */ if (rc != 0) { rc = TPM_DAA_INPUT_DATA0; } } /* e. Verify that SHA-1(DAA_private_v0) == DAA_tpmSpecific -> DAA_digest_v0 and return error TPM_DAA_INPUT_DATA0 on mismatch */ if (rc == 0) { printf("TPM_DAASign_Stage14: Checking v0\n"); rc = TPM_SHA1_SizedBufferCheck(tpm_daa_session_data->DAA_tpmSpecific.DAA_digest_v0, &(tpm_daa_sensitive.internalData), (DAA_power1 + 7) / 8); if (rc != 0) { rc = TPM_DAA_INPUT_DATA0; } } /* f. Obtain DAA_SIZE_r2 bytes from the MGF1 function and label them r2. "r2" || DAA_session -> DAA_contextSeed is the Z seed. */ if (rc == 0) { printf("TPM_DAASign_Stage14: Creating r2\n"); rc = TPM_MGF1_GenerateArray(&r2, /* returned MGF1 array */ DAA_SIZE_r2, /* size of Y */ /* length of the entire seed */ sizeof("r2") -1 + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), sizeof("r2") -1, "r2", sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), tpm_daa_session_data->DAA_session.DAA_contextSeed, 0, NULL); } if (rc == 0) { rc = TPM_bin2bn(&r2Bignum, r2, DAA_SIZE_r2); } /* g. Set s12 = r2 + (DAA_session -> DAA_digest)*(DAA_private_v0). */ /* FIXME Set c = DAA_session -> DAA_digest */ if (rc == 0) { printf("TPM_DAASign_Stage14: Creating c from DAA_session -> DAA_digest\n"); rc = TPM_bin2bn(&cBignum, tpm_daa_session_data->DAA_session.DAA_digest, TPM_DIGEST_SIZE); } /* FIXME Set v0 = DAA_private_v0 */ if (rc == 0) { rc = TPM_bin2bn(&v0Bignum, tpm_daa_sensitive.internalData.buffer, tpm_daa_sensitive.internalData.size); } /* s12 = r2 + c * v0 */ if (rc == 0) { rc = TPM_ComputeApBxC(&s12Bignum, /* result */ r2Bignum, /* A */ cBignum, /* B */ v0Bignum); /* C */ } /* h. Shift s12 right by DAA_power1 bits (erase the lowest DAA_power1 bits). */ if (rc == 0) { rc = TPM_BN_rshift(&s12sBignum, s12Bignum, DAA_power1); /* f becomes f1 */ } /* i. Set DAA_session -> DAA_scratch = s12 */ if (rc == 0) { rc = TPM_ComputeDAAScratch(tpm_daa_session_data->DAA_session.DAA_scratch, sizeof(tpm_daa_session_data->DAA_session.DAA_scratch), s12sBignum); } /* j. set outputData = NULL */ /* NOTE Done by caller */ /* k. increment DAA_session -> DAA_stage by 1 */ /* NOTE Done by common code */ /* l. return TPM_SUCCESS */ free(r2); /* @1 */ TPM_BN_free(r2Bignum); /* @2 */ TPM_BN_free(s12Bignum); /* @3 */ TPM_BN_free(s12sBignum); /* @4 */ TPM_BN_free(cBignum); /* @5 */ TPM_BN_free(v0Bignum); /* @6 */ TPM_DAASensitive_Delete(&tpm_daa_sensitive); /* @7 */ return rc; } TPM_RESULT TPM_DAASign_Stage15(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0) { TPM_RESULT rc = 0; unsigned char *r4 = NULL; /* freed @1 */ TPM_BIGNUM r4Bignum = NULL; /* freed @2 */ TPM_BIGNUM s3Bignum = NULL; /* freed @3 */ TPM_BIGNUM cBignum = NULL; /* freed @4 */ TPM_BIGNUM v1Bignum = NULL; /* freed @5 */ TPM_BIGNUM s12Bignum = NULL; /* freed @6 */ TPM_DAA_SENSITIVE tpm_daa_sensitive; printf("TPM_DAASign_Stage15:\n"); TPM_DAASensitive_Init(&tpm_daa_sensitive); /* freed @7 */ /* a. Verify that DAA_session ->DAA_stage==15. Return TPM_DAA_STAGE and flush handle on mismatch */ /* NOTE Done by common code */ /* b. Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS on mismatch */ /* NOTE Done by common code */ /* c. Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific) and return error TPM_DAA_TPM_SETTINGS on mismatch */ /* NOTE Done by common code */ /* d. Set DAA_private_v1 = unwrap(inputData0) using TPM_PERMANENT_DATA -> daaBlobKey */ if (rc == 0) { rc = TPM_ComputeDecrypt(&tpm_daa_sensitive, /* output */ tpm_state, /* decryption and HMAC keys */ inputData0, /* encrypted stream */ TPM_RT_DAA_V1); /* resourceType expected */ if (rc != 0) { rc = TPM_DAA_INPUT_DATA0; } } /* e. Verify that SHA-1(DAA_private_v1) == DAA_tpmSpecific -> DAA_digest_v1 and return error TPM_DAA_INPUT_DATA0 on mismatch */ if (rc == 0) { printf("TPM_DAASign_Stage15: Checking v1\n"); rc = TPM_SHA1_SizedBufferCheck(tpm_daa_session_data->DAA_tpmSpecific.DAA_digest_v1, &(tpm_daa_sensitive.internalData), DAA_SIZE_v1); if (rc != 0) { rc = TPM_DAA_INPUT_DATA0; } } /* f. Obtain DAA_SIZE_r4 bytes from the MGF1 function and label them r4. "r4" || DAA_session -> DAA_contextSeed is the Z seed. */ if (rc == 0) { printf("TPM_DAASign_Stage15: Creating r4\n"); rc = TPM_MGF1_GenerateArray(&r4, /* returned MGF1 array */ DAA_SIZE_r4, /* size of Y */ /* length of the entire seed */ sizeof("r4") -1 + sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), sizeof("r4") -1, "r4", sizeof(tpm_daa_session_data->DAA_session.DAA_contextSeed), tpm_daa_session_data->DAA_session.DAA_contextSeed, 0, NULL); } if (rc == 0) { rc = TPM_bin2bn(&r4Bignum, r4, DAA_SIZE_r4); } /* g. Set s3 = r4 + (DAA_session -> DAA_digest)*(DAA_private_v1) + (DAA_session -> DAA_scratch). */ /* FIXME Set c = DAA_session -> DAA_digest */ if (rc == 0) { printf("TPM_DAASign_Stage15: Creating c from DAA_session -> DAA_digest\n"); rc = TPM_bin2bn(&cBignum, tpm_daa_session_data->DAA_session.DAA_digest, TPM_DIGEST_SIZE); } /* FIXME Set v1 = DAA_private_v1 */ if (rc == 0) { rc = TPM_bin2bn(&v1Bignum, tpm_daa_sensitive.internalData.buffer, tpm_daa_sensitive.internalData.size); } /* FIXME Set s12 = DAA_session -> DAA_scratch */ if (rc == 0) { printf("TPM_DAASign_Stage15: Creating s12 from DAA_session -> DAA_scratch\n"); rc = TPM_bin2bn(&s12Bignum, tpm_daa_session_data->DAA_session.DAA_scratch, sizeof(tpm_daa_session_data->DAA_session.DAA_scratch)); } /* s3 = r4 + c * v1 + s12 */ if (rc == 0) { rc = TPM_ComputeApBxCpD(&s3Bignum, /* freed by caller */ r4Bignum, /* A */ cBignum, /* B */ v1Bignum, /* C */ s12Bignum); /* D */ } /* h. Set DAA_session -> DAA_scratch = NULL */ if (rc == 0) { tpm_daa_session_data->DAA_session.DAA_scratch_null = TRUE; } /* i. set outputData = s3 */ if (rc == 0) { rc = TPM_bn2binMalloc(&(outputData->buffer), &(outputData->size), s3Bignum, 0); } /* j. Terminate the DAA session and all resources associated with the DAA sign session handle. */ /* NOTE Done by caller */ /* k. return TPM_SUCCESS */ free(r4); /* @1 */ TPM_BN_free(r4Bignum); /* @2 */ TPM_BN_free(s3Bignum); /* @3 */ TPM_BN_free(cBignum); /* @4 */ TPM_BN_free(v1Bignum); /* @5 */ TPM_BN_free(s12Bignum); /* @6 */ TPM_DAASensitive_Delete(&tpm_daa_sensitive); /* @7 */ return rc; } /* Stage Common Code */ /* TPM_DAADigestContext_GenerateDigestJoin() sets tpm_digest to SHA-1(DAA_tpmSpecific || DAA_joinSession)) */ TPM_RESULT TPM_DAADigestContext_GenerateDigestJoin(TPM_DIGEST tpm_digest, TPM_DAA_SESSION_DATA *tpm_daa_session_data) { TPM_RESULT rc = 0; TPM_STORE_BUFFER sbuffer; /* TPM_STORED_DATA serialization */ printf(" TPM_DAADigestContext_GenerateDigestJoin:\n"); TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ /* serialize DAA_tpmSpecific */ if (rc == 0) { rc = TPM_DAATpm_Store(&sbuffer, &(tpm_daa_session_data->DAA_tpmSpecific)); } /* serialize DAA_joinSession */ if (rc == 0) { rc = TPM_DAAJoindata_Store(&sbuffer, &(tpm_daa_session_data->DAA_joinSession)); } /* calculate and return the digest */ if (rc == 0) { rc = TPM_SHA1Sbuffer(tpm_digest, &sbuffer); } TPM_Sbuffer_Delete(&sbuffer); /* @1 */ return rc; } /* TPM_DAADigestContext_CheckDigestJoin() verifies that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession). Returns TPM_DAA_TPM_SETTINGS on mismatch */ TPM_RESULT TPM_DAADigestContext_CheckDigestJoin(TPM_DAA_SESSION_DATA *tpm_daa_session_data) { TPM_RESULT rc = 0; TPM_DIGEST tpm_digest; /* actual digest */ printf(" TPM_DAADigestContext_CheckDigestJoin:\n"); if (rc == 0) { rc = TPM_DAADigestContext_GenerateDigestJoin(tpm_digest, tpm_daa_session_data); } if (rc == 0) { rc = TPM_Digest_Compare(tpm_digest, tpm_daa_session_data->DAA_session.DAA_digestContext); if (rc != 0) { rc = TPM_DAA_TPM_SETTINGS; } } return rc; } /* TPM_ComputeF() computes the value F common to stages 4.j., 5.j., 14.f., 17.e., 18.e. j. Set f = SHA1(DAA_tpmSpecific -> DAA_rekey || DAA_tpmSpecific -> DAA_count || 0) || SHA1(DAA_tpmSpecific -> DAA_rekey || DAA_tpmSpecific -> DAA_count || 1 ) mod DAA_issuerSettings -> DAA_generic_q */ TPM_RESULT TPM_ComputeF(TPM_BIGNUM *fBignum, /* freed by caller */ TPM_DAA_SESSION_DATA *tpm_daa_session_data) { TPM_RESULT rc = 0; BYTE nZero = 0; BYTE nOne = 1; uint32_t nCount; /* DAA_count in nbo */ TPM_DIGEST digest0; /* first SHA1 calculation */ TPM_DIGEST digest1; /* second SHA1 calculation */ TPM_BIGNUM dividend; /* digest0 || digest1 as a BIGNUM */ TPM_BIGNUM modulus; /* DAA_generic_q as a BIGNUM */ printf(" TPM_ComputeF:\n"); modulus = NULL; /* freed @1 */ dividend = NULL; /* freed @2 */ if (rc == 0) { rc = TPM_BN_new(fBignum); } /* SHA1(DAA_tpmSpecific -> DAA_rekey || DAA_tpmSpecific -> DAA_count || 0) */ if (rc == 0) { printf(" TPM_ComputeF: Calculate digest0\n"); nCount = htonl(tpm_daa_session_data->DAA_tpmSpecific.DAA_count); rc = TPM_SHA1(digest0, TPM_DIGEST_SIZE, tpm_daa_session_data->DAA_tpmSpecific.DAA_rekey, sizeof(uint32_t), &nCount, sizeof(BYTE), &nZero, 0, NULL); } /* SHA1(DAA_tpmSpecific -> DAA_rekey || DAA_tpmSpecific -> DAA_count || 1 ) */ if (rc == 0) { printf(" TPM_ComputeF: Calculate digest1\n"); rc = TPM_SHA1(digest1, TPM_DIGEST_SIZE, tpm_daa_session_data->DAA_tpmSpecific.DAA_rekey, sizeof(uint32_t), &nCount, sizeof(BYTE), &nOne, 0, NULL); } /* Construct digest0 || digest1 as a positive BIGNUM */ if (rc == 0) { rc = TPM_2bin2bn(÷nd, digest0, TPM_DIGEST_SIZE, digest1, TPM_DIGEST_SIZE); } /* DAA_generic_q as a positive BIGNUM */ if (rc == 0) { rc = TPM_bin2bn(&modulus, tpm_daa_session_data->DAA_issuerSettings.DAA_generic_q, sizeof(tpm_daa_session_data->DAA_issuerSettings.DAA_generic_q)); } /* digest mod DAA_generic_q */ if (rc == 0) { rc = TPM_BN_mod(*fBignum, dividend, modulus); } TPM_BN_free(modulus); /* @1 */ TPM_BN_free(dividend); /* @2 */ return rc; } /* TPM_ComputeAexpPmodn() performs R = (A ^ P) mod n. rBignum is new'ed by this function and must be freed by the caller If DAA_scratch is not NULL, r is returned in DAA_scratch. */ TPM_RESULT TPM_ComputeAexpPmodn(BYTE *DAA_scratch, uint32_t DAA_scratch_size, TPM_BIGNUM *rBignum, /* freed by caller */ TPM_BIGNUM aBignum, TPM_BIGNUM pBignum, TPM_BIGNUM nBignum) { TPM_RESULT rc = 0; printf(" TPM_ComputeAexpPmodn:\n"); if (rc == 0) { rc = TPM_BN_new(rBignum); } if (rc == 0) { rc = TPM_BN_mod_exp(*rBignum, aBignum, pBignum, nBignum); } /* if the result should be returned in DAA_scratch */ if ((rc == 0) && (DAA_scratch != NULL)) { /* store the result in DAA_scratch */ rc = TPM_ComputeDAAScratch(DAA_scratch, DAA_scratch_size, *rBignum); } return rc; } /* TPM_ComputeZxAexpPmodn() performs DAA_scratch = Z * (A ^ P) mod n. */ TPM_RESULT TPM_ComputeZxAexpPmodn(BYTE *DAA_scratch, uint32_t DAA_scratch_size, TPM_BIGNUM zBignum, TPM_BIGNUM aBignum, TPM_BIGNUM pBignum, TPM_BIGNUM nBignum) { TPM_RESULT rc = 0; TPM_BIGNUM rBignum = NULL; /* freed @1 */ printf(" TPM_ComputeZxAexpPmodn:\n"); if (rc == 0) { printf(" TPM_ComputeZxAexpPmodn: Calculate R = A ^ P mod n\n"); rc = TPM_ComputeAexpPmodn(NULL, /* DAA_scratch */ 0, &rBignum, /* R */ aBignum, /* A */ pBignum, nBignum); } if (rc == 0) { printf(" TPM_ComputeZxAexpPmodn: Calculate R = Z * R mod n\n"); rc = TPM_BN_mod_mul(rBignum, zBignum, rBignum, nBignum); } /* store the result in DAA_scratch */ if (rc == 0) { rc = TPM_ComputeDAAScratch(DAA_scratch, DAA_scratch_size, rBignum); } TPM_BN_free(rBignum); /* @1 */ return rc; } /* TPM_ComputeApBmodn() performs R = A + B mod n */ TPM_RESULT TPM_ComputeApBmodn(TPM_BIGNUM *rBignum, /* freed by caller */ TPM_BIGNUM aBignum, TPM_BIGNUM bBignum, TPM_BIGNUM nBignum) { TPM_RESULT rc = 0; printf(" TPM_ComputeApBmodn:\n"); if (rc == 0) { rc = TPM_BN_new(rBignum); /* freed by caller */ } if (rc == 0) { rc = TPM_BN_mod_add(*rBignum, aBignum, bBignum, nBignum); } return rc; } /* TPM_ComputeApBxC() performs R = A + B * C */ TPM_RESULT TPM_ComputeApBxC(TPM_BIGNUM *rBignum, /* freed by caller */ TPM_BIGNUM aBignum, TPM_BIGNUM bBignum, TPM_BIGNUM cBignum) { TPM_RESULT rc = 0; printf(" TPM_ComputeApBxC:\n"); if (rc == 0) { rc = TPM_BN_new(rBignum); /* freed by caller */ } /* R = B * C */ if (rc == 0) { rc = TPM_BN_mul(*rBignum, bBignum, cBignum); } /* R = R + A */ if (rc == 0) { rc = TPM_BN_add(*rBignum, *rBignum, aBignum); } return rc; } /* TPM_ComputeApBxCpD() performs R = A + B * C + D */ TPM_RESULT TPM_ComputeApBxCpD(TPM_BIGNUM *rBignum, /* freed by caller */ TPM_BIGNUM aBignum, TPM_BIGNUM bBignum, TPM_BIGNUM cBignum, TPM_BIGNUM dBignum) { TPM_RESULT rc = 0; printf(" TPM_ComputeApBxCpD:\n"); /* R = A + B * C */ if (rc == 0) { rc = TPM_ComputeApBxC(rBignum, /* freed by caller */ aBignum, bBignum, cBignum); } /* R = R + D */ if (rc == 0) { rc = TPM_BN_add(*rBignum, *rBignum, dBignum); } return rc; } /* TPM_ComputeDAAScratch() stores 'bn' in DAA_scratch */ TPM_RESULT TPM_ComputeDAAScratch(BYTE *DAA_scratch, uint32_t DAA_scratch_size, TPM_BIGNUM bn) { TPM_RESULT rc = 0; printf(" TPM_ComputeDAAScratch:\n"); if (rc == 0) { rc = TPM_bn2binArray(DAA_scratch, DAA_scratch_size, bn); } return rc; } /* TPM_ComputeEnlarge() creates a buffer of size 'outSize' It copies 'outSize - inSize' zero bytes and then appends 'in' 'out' must be freed by the caller */ TPM_RESULT TPM_ComputeEnlarge(unsigned char **out, /* freed by caller */ uint32_t outSize, unsigned char *in, uint32_t inSize) { TPM_RESULT rc = 0; if (rc == 0) { if (outSize <= inSize) { printf("TPM_ComputeEnlarge: Error (fatal), inSize %u outSize %u\n", inSize, outSize); rc = TPM_FAIL; } } if (rc == 0) { rc = TPM_Malloc(out, outSize); } if (rc == 0) { memset(*out, 0, outSize - inSize); /* zero left bytes */ memcpy(*out + outSize - inSize, in, inSize); /* copy right bytes */ } return rc; } /* TPM_SizedBuffer_ComputeEnlarge() forces 'tpm_sized_buffer' to be 'size' bytes in length. If generally useful, this function should be moved to tpm_sizedbuffer.c */ TPM_RESULT TPM_SizedBuffer_ComputeEnlarge(TPM_SIZED_BUFFER *tpm_sized_buffer, uint32_t size) { TPM_RESULT rc = 0; unsigned char *newPtr; /* new buffer, enlarged */ newPtr = NULL; /* freed by caller */ /* if tpm_sized_buffer needs to be enlarged */ if (tpm_sized_buffer->size != size) { if (rc == 0) { /* copy the TPM_SIZED_BUFFER data. enlarged, to newPtr */ rc = TPM_ComputeEnlarge(&newPtr, size, /* output buffer */ tpm_sized_buffer->buffer, tpm_sized_buffer->size); } if (rc == 0) { /* after the copy, the old buffer is no longer needed */ free(tpm_sized_buffer->buffer); /* assign the with the enlarged buffer to the TPM_SIZED_BUFFER */ tpm_sized_buffer->buffer = newPtr; /* update size */ tpm_sized_buffer->size = size; } } return rc; } /* TPM_ComputeEncrypt() does join steps common to encrypting output data. It serializes the TPM_DAA_SENSITIVE, encrypts it to TPM_DAA_BLOB ->sensitiveData, adds the resourceType, generates the TPM_DAA_BLOB -> blobIntegrity HMAC using daaProof, and serializes the result to outputData. */ TPM_RESULT TPM_ComputeEncrypt(TPM_SIZED_BUFFER *outputData, tpm_state_t *tpm_state, TPM_DAA_SENSITIVE *tpm_daa_sensitive, TPM_RESOURCE_TYPE resourceType) { TPM_RESULT rc = 0; TPM_DAA_BLOB tpm_daa_blob; TPM_STORE_BUFFER daaSensitiveSbuffer; printf(" TPM_ComputeEncrypt:\n"); TPM_DAABlob_Init(&tpm_daa_blob); /* freed @1 */ TPM_Sbuffer_Init(&daaSensitiveSbuffer); /* freed @2 */ /* serialize the TPM_DAA_SENSITIVE */ if (rc == 0) { rc = TPM_DAASensitive_Store(&daaSensitiveSbuffer, tpm_daa_sensitive); } /* Create a TPM_DAA_BLOB structure */ if (rc == 0) { printf(" TPM_ComputeEncrypt: Create TPM_DAA_BLOB\n"); tpm_daa_blob.resourceType = resourceType; /* Set TPM_DAA_BLOB -> sensitiveData to the encryption of serialized TPM_DAA_SENSITIVE */ rc = TPM_SymmetricKeyData_EncryptSbuffer (&(tpm_daa_blob.sensitiveData), /* output buffer */ &daaSensitiveSbuffer, /* input buffer */ tpm_state->tpm_permanent_data.daaBlobKey); /* key */ } /* set TPM_DAA_BLOB -> blobIntegrity to the HMAC of TPM_DAA_BLOB using daaProof as the secret */ if (rc == 0) { rc = TPM_HMAC_GenerateStructure(tpm_daa_blob.blobIntegrity, /* HMAC */ tpm_state->tpm_permanent_data.daaProof, /* HMAC key */ &tpm_daa_blob, /* structure */ (TPM_STORE_FUNCTION_T)TPM_DAABlob_Store); /* store function */ } /* ii. set outputData to the encrypted TPM_DAA_BLOB */ if (rc == 0) { rc = TPM_SizedBuffer_SetStructure(outputData, &tpm_daa_blob, (TPM_STORE_FUNCTION_T )TPM_DAABlob_Store); } TPM_DAABlob_Delete(&tpm_daa_blob); /* @1 */ TPM_Sbuffer_Delete(&daaSensitiveSbuffer); /* @2 */ return rc; } /* TPM_ComputeDecrypt() does sign steps common to decrypting input data It deserializes 'inputData" to a TPM_DAA_BLOB, and validates the resourceType and blobIntegrity HMAC using daaProof. It decrypts TPM_DAA_BLOB ->sensitiveData and deserializes it to a TPM_DAA_SENSITIVE. tpm_daa_sensitive must be deleted by the caller */ TPM_RESULT TPM_ComputeDecrypt(TPM_DAA_SENSITIVE *tpm_daa_sensitive, tpm_state_t *tpm_state, TPM_SIZED_BUFFER *inputData, TPM_RESOURCE_TYPE resourceType) { TPM_RESULT rc = 0; TPM_DAA_BLOB tpm_daa_blob; unsigned char *stream; uint32_t stream_size; unsigned char *sensitiveStream; uint32_t sensitiveStreamSize; printf(" TPM_ComputeDecrypt:\n"); TPM_DAABlob_Init(&tpm_daa_blob); /* freed @1 */ sensitiveStream = NULL; /* freed @2 */ /* deserialize inputData to a TPM_DAA_BLOB */ if (rc == 0) { stream = inputData->buffer; stream_size = inputData->size; rc = TPM_DAABlob_Load(&tpm_daa_blob, &stream, &stream_size); } if (rc == 0) { if (stream_size != 0) { printf("TPM_ComputeDecrypt: Error, bad blob input size %u\n", inputData->size); rc = TPM_DAA_INPUT_DATA0; } } /* check blobIntegrity */ if (rc == 0) { rc = TPM_HMAC_CheckStructure(tpm_state->tpm_permanent_data.daaProof, /* HMAC key */ &tpm_daa_blob, /* structure */ tpm_daa_blob.blobIntegrity, /* expected */ (TPM_STORE_FUNCTION_T)TPM_DAABlob_Store, /* store function */ TPM_DAA_INPUT_DATA0); /* error code */ } /* check resourceType */ if (rc == 0) { if (tpm_daa_blob.resourceType != resourceType) { printf("TPM_ComputeDecrypt: Error, resourceType %08x\n", tpm_daa_blob.resourceType); rc = TPM_DAA_INPUT_DATA0; } } /* decrypt the TPM_DAA_BLOB -> sensitiveData */ if (rc == 0) { rc = TPM_SymmetricKeyData_Decrypt (&sensitiveStream, /* output, caller frees */ &sensitiveStreamSize, /* output */ tpm_daa_blob.sensitiveData.buffer, /* input */ tpm_daa_blob.sensitiveData.size, /* input */ tpm_state->tpm_permanent_data.daaBlobKey); /* dec key */ } if (rc == 0) { stream = sensitiveStream; stream_size = sensitiveStreamSize; rc = TPM_DAASensitive_Load(tpm_daa_sensitive, &stream, &stream_size); } if (rc == 0) { if (stream_size != 0) { printf("TPM_ComputeDecrypt: Error, bad sensitive input size %u\n", sensitiveStreamSize); rc = TPM_DAA_INPUT_DATA0; } } TPM_DAABlob_Delete(&tpm_daa_blob); /* @1 */ free(sensitiveStream); /* @2 */ return rc; } /* TPM_SHA1_BignumGenerate() converts the BIGNUM 'bn' to an array, enlarges the array to 'size', and computes the SHA-1 hash */ TPM_RESULT TPM_SHA1_BignumGenerate(TPM_DIGEST tpm_digest, TPM_BIGNUM bn, uint32_t size) { TPM_RESULT rc = 0; unsigned char *bin = NULL; /* freed @1 */ unsigned int bytes; unsigned char *newBin = NULL; /* freed @2, new buffer, enlarged */ if (rc == 0) { rc = TPM_bn2binMalloc(&bin, &bytes, bn, 0); /* freed @1 */ } if (rc == 0) { printf(" TPM_SHA1_BignumGenerate: enlarge to %u bytes, is %u bytes\n", size, bytes); if (bytes != size) { /* canonicalize the array size */ if (rc == 0) { rc = TPM_ComputeEnlarge(&newBin, size, /* output buffer */ bin, bytes ); /* inout buffer */ } if (rc == 0) { rc = TPM_SHA1(tpm_digest, size, newBin, 0, NULL); } } else { /* already canonicalized */ rc = TPM_SHA1(tpm_digest, bytes, bin, 0, NULL); } } free(bin); /* @1 */ free(newBin); /* @2 */ return rc; } /* TPM_SHA1_SizedBufferCheck() enlarges the TPM_SIZED_BUFFER to 'size', computes the SHA-1 hash, and validates the digest against 'tpm_digest' As a side effect, the TPM_SIZED_BUFFER may be enlarged. */ TPM_RESULT TPM_SHA1_SizedBufferCheck(TPM_DIGEST tpm_digest, TPM_SIZED_BUFFER *tpm_sized_buffer, uint32_t size) { TPM_RESULT rc = 0; if (rc == 0) { printf(" TPM_SHA1_SizedBufferCheck: enlarge to %u bytes, is %u bytes\n", size, tpm_sized_buffer->size); if (tpm_sized_buffer->size != size) { /* canonicalize the array size */ rc = TPM_SizedBuffer_ComputeEnlarge(tpm_sized_buffer, size); } } if (rc == 0) { rc = TPM_SHA1_Check(tpm_digest, tpm_sized_buffer->size, tpm_sized_buffer->buffer, 0, NULL); } return rc; } /* Processing functions */ /* 26.1 TPM_DAA_Join rev 99 TPM_DAA_Join is the process that establishes the DAA parameters in the TPM for a specific DAA issuing authority. outputSize and outputData are always included in the outParamDigest. This includes stage 0, where the outputData contains the DAA session handle. */ TPM_RESULT TPM_Process_DAAJoin(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, /* of remaining parameters*/ TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_HANDLE daaHandle; /* Session handle */ BYTE stage = 0; /* Processing stage of join */ TPM_SIZED_BUFFER inputData0; /* Data to be used by this capability */ TPM_SIZED_BUFFER inputData1; /* Data to be used by this capability */ TPM_AUTHHANDLE authHandle; /* The authorization session handle used for owner authentication */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* Continue use flag, TRUE if handle is still active */ TPM_AUTHDATA ownerAuth; /* The authorization session digest for inputs and owner. HMAC key: ownerAuth. */ /* processing */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_BOOL daaHandleValid = FALSE; TPM_AUTH_SESSION_DATA *auth_session_data; /* session data for authHandle */ TPM_SECRET *hmacKey; TPM_DAA_SESSION_DATA *tpm_daa_session_data; /* DAA session for handle */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_SIZED_BUFFER outputData; /* Data produced by this capability */ printf("TPM_Process_DAAJoin: Ordinal Entry\n"); TPM_SizedBuffer_Init(&inputData0); /* freed @1 */ TPM_SizedBuffer_Init(&inputData1); /* freed @2 */ TPM_SizedBuffer_Init(&outputData); /* freed @3 */ /* get inputs */ /* get handle */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&daaHandle, &command, ¶mSize); } /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get stage */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_DAAJoin: daaHandle %08x\n", daaHandle); returnCode = TPM_Load8(&stage, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_DAAJoin: stage %u\n", stage); /* For stages after stage 0, daaHandle is an input. Mark it valid so it can be terminated on error. */ if (stage > 0) { daaHandleValid = TRUE; } /* get inputData0 */ returnCode = TPM_SizedBuffer_Load(&inputData0, &command, ¶mSize); } /* get inputData1 */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_Load(&inputData1, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag1(tag); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, ownerAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_DAAJoin: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* 1. Use ownerAuth to verify that the Owner authorized all TPM_DAA_Join input parameters. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_OWNER, ordinal, NULL, &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ } if (returnCode == TPM_SUCCESS) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* owner HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, ownerAuth); /* Authorization digest for input */ } /* Common to most or all stages */ /* Validate the DAA session handle after stage 0, stage 0 assigns the handle */ if (returnCode == TPM_SUCCESS) { if (stage > 0) { returnCode = TPM_DaaSessions_GetEntry(&tpm_daa_session_data, /* returns entry in array */ tpm_state->tpm_stclear_data.daaSessions, /* array */ daaHandle); } } /* Verify that the input state is consistent with the current TPM state */ if (returnCode == TPM_SUCCESS) { if (stage > 0) { returnCode = TPM_DaaSessionData_CheckStage(tpm_daa_session_data, stage); } } /* Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error TPM_DAA_TPM_SETTINGS on mismatch */ if (returnCode == TPM_SUCCESS) { if (stage >= 1) { returnCode = TPM_DAADigestContext_CheckDigestJoin(tpm_daa_session_data); } } /* Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS on mismatch */ if (returnCode == TPM_SUCCESS) { if (stage >= 3) { returnCode = TPM_SHA1_CheckStructure(tpm_daa_session_data->DAA_tpmSpecific.DAA_digestIssuer, &(tpm_daa_session_data->DAA_issuerSettings), (TPM_STORE_FUNCTION_T)TPM_DAAIssuer_Store, TPM_DAA_ISSUER_SETTINGS); } } /* Stages */ if (returnCode == TPM_SUCCESS) { switch (stage) { case 0 : returnCode = TPM_DAAJoin_Stage00(tpm_state, &tpm_daa_session_data, /* entry in array */ &daaHandleValid, &outputData, &inputData0); if (daaHandleValid) { /* For stage 0, daaHandle may be generated. Extract it from the DAA session and mark it valid, so the session can be terminated on error. */ daaHandle = tpm_daa_session_data->daaHandle; } break; case 1 : returnCode = TPM_DAAJoin_Stage01(tpm_state, tpm_daa_session_data, &outputData, &inputData0, &inputData1); break; case 2 : returnCode = TPM_DAAJoin_Stage02(tpm_state, tpm_daa_session_data, &outputData, &inputData0, &inputData1); break; case 3 : returnCode = TPM_DAAJoin_Stage03(tpm_state, tpm_daa_session_data, &outputData, &inputData0); break; case 4 : returnCode = TPM_DAAJoin_Stage04(tpm_state, tpm_daa_session_data, &outputData, &inputData0, &inputData1); break; case 5 : returnCode = TPM_DAAJoin_Stage05(tpm_state, tpm_daa_session_data, &outputData, &inputData0, &inputData1); break; case 6 : returnCode = TPM_DAAJoin_Stage06(tpm_state, tpm_daa_session_data, &outputData, &inputData0, &inputData1); break; case 7 : returnCode = TPM_DAAJoin_Stage07(tpm_state, tpm_daa_session_data, &outputData, &inputData0, &inputData1); break; case 8 : returnCode = TPM_DAAJoin_Stage08(tpm_state, tpm_daa_session_data, &outputData, &inputData0); break; case 9 : returnCode = TPM_DAAJoin_Stage09_Sign_Stage2(tpm_state, tpm_daa_session_data, &outputData, &inputData0, &inputData1); break; case 10 : returnCode = TPM_DAAJoin_Stage10_Sign_Stage3(tpm_state, tpm_daa_session_data, &outputData, &inputData0, &inputData1); break; case 11 : returnCode = TPM_DAAJoin_Stage11_Sign_Stage4(tpm_state, tpm_daa_session_data, &outputData, &inputData0, &inputData1); break; case 12 : returnCode = TPM_DAAJoin_Stage12(tpm_state, tpm_daa_session_data, &outputData, &inputData0, &inputData1); break; case 13 : returnCode = TPM_DAAJoin_Stage13_Sign_Stage6(tpm_state, tpm_daa_session_data, &outputData, &inputData0, &inputData1); break; case 14 : returnCode = TPM_DAAJoin_Stage14_Sign_Stage7(tpm_state, tpm_daa_session_data, &outputData, &inputData0); break; case 15 : returnCode = TPM_DAAJoin_Stage15_Sign_Stage8(tpm_state, tpm_daa_session_data, &outputData, &inputData0); break; case 16 : returnCode = TPM_DAAJoin_Stage16_Sign_Stage9(tpm_state, tpm_daa_session_data, &outputData, &inputData0); break; case 17 : returnCode = TPM_DAAJoin_Stage17_Sign_Stage11(tpm_state, tpm_daa_session_data, &outputData); break; case 18 : returnCode = TPM_DAAJoin_Stage18_Sign_Stage12(tpm_state, tpm_daa_session_data, &outputData); break; case 19 : returnCode = TPM_DAAJoin_Stage19(tpm_state, tpm_daa_session_data, &outputData); break; case 20 : returnCode = TPM_DAAJoin_Stage20(tpm_state, tpm_daa_session_data, &outputData); break; case 21 : returnCode = TPM_DAAJoin_Stage21(tpm_state, tpm_daa_session_data, &outputData); break; case 22 : returnCode = TPM_DAAJoin_Stage22(tpm_state, tpm_daa_session_data, &outputData, &inputData0); break; case 23 : returnCode = TPM_DAAJoin_Stage23(tpm_state, tpm_daa_session_data, &outputData, &inputData0); break; case 24 : returnCode = TPM_DAAJoin_Stage24(tpm_state, tpm_daa_session_data, &outputData); break; default : printf("TPM_Process_DAAJoin: Error, Illegal stage\n"); returnCode = TPM_DAA_STAGE; } } /* Common to most or all stages */ if (returnCode == TPM_SUCCESS) { if (stage >= 2) { tpm_daa_session_data->DAA_session.DAA_stage++; } } /* 24.e.Terminate the DAA session and all resources associated with the DAA join session handle. */ if (returnCode == TPM_SUCCESS) { if (stage == 24) { printf("TPM_Process_DAAJoin: Stage 24, terminating DAA session %08x\n", tpm_daa_session_data->daaHandle); TPM_DaaSessionData_Delete(tpm_daa_session_data); } } /* 2. Any error return results in the TPM invalidating all resources associated with the join */ /* NOTE Done after response processing */ /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_DAAJoin: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* return outputData */ returnCode = TPM_SizedBuffer_Store(response, &outputData); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if (returnCode == TPM_SUCCESS) { /* no outParam's, set authorization response data */ returnCode = TPM_AuthParams_Set(response, *hmacKey, /* owner HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, terminate the session. */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* on error, terminate the DAA session */ if (((rcf != 0) || (returnCode != TPM_SUCCESS)) && daaHandleValid) { TPM_DaaSessions_TerminateHandle(tpm_state->tpm_stclear_data.daaSessions, daaHandle); } /* cleanup */ TPM_SizedBuffer_Delete(&inputData0); /* @1 */ TPM_SizedBuffer_Delete(&inputData1); /* @2 */ TPM_SizedBuffer_Delete(&outputData); /* @3 */ return rcf; } /* 26.2 TPM_DAA_Sign rev 99 TPM protected capability; user must provide authorizations from the TPM Owner. outputSize and outputData are always included in the outParamDigest. This includes stage 0, where the outputData contains the DAA session handle. */ TPM_RESULT TPM_Process_DAASign(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, /* of remaining parameters*/ TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_HANDLE daaHandle; /* Handle to the sign session */ BYTE stage = 0; /* Stage of the sign process */ TPM_SIZED_BUFFER inputData0; /* Data to be used by this capability */ TPM_SIZED_BUFFER inputData1; /* Data to be used by this capability */ TPM_AUTHHANDLE authHandle; /* The authorization session handle used for owner authentication */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* Continue use flag, TRUE if handle is still active */ TPM_AUTHDATA ownerAuth; /* The authorization session digest for inputs and owner. HMAC key: ownerAuth. */ /* processing */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_BOOL daaHandleValid = FALSE; TPM_AUTH_SESSION_DATA *auth_session_data; /* session data for authHandle */ TPM_SECRET *hmacKey; TPM_DAA_SESSION_DATA *tpm_daa_session_data; /* DAA session for handle */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_SIZED_BUFFER outputData; /* Data produced by this capability */ printf("TPM_Process_DAASign: Ordinal Entry\n"); TPM_SizedBuffer_Init(&inputData0); /* freed @1 */ TPM_SizedBuffer_Init(&inputData1); /* freed @2 */ TPM_SizedBuffer_Init(&outputData); /* freed @3 */ /* get inputs */ /* get handle */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&daaHandle, &command, ¶mSize); } /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get stage */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_DAASign: daaHandle %08x\n", daaHandle); returnCode = TPM_Load8(&stage, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_DAASign: stage %u\n", stage); /* For stages after stage 0, daaHandle is an input. Mark it valid so it can be terminated on error. */ if (stage > 0) { daaHandleValid = TRUE; } /* get inputData0 */ returnCode = TPM_SizedBuffer_Load(&inputData0, &command, ¶mSize); } /* get inputData1 */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_Load(&inputData1, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag1(tag); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, ownerAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_DAASign: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* 1. Use ownerAuth to verify that the Owner authorized all TPM_DAA_Sign input parameters. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_OWNER, ordinal, NULL, &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ } if (returnCode == TPM_SUCCESS) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* owner HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, ownerAuth); /* Authorization digest for input */ } /* Common to most or all stages */ /* Validate the DAA session handle after stage 0, stage 0 assigns the handle */ if (returnCode == TPM_SUCCESS) { if (stage > 0) { returnCode = TPM_DaaSessions_GetEntry(&tpm_daa_session_data, /* returns entry in array */ tpm_state->tpm_stclear_data.daaSessions, /* array */ daaHandle); } } /* Verify that the input state is consistent with the current TPM state */ if (returnCode == TPM_SUCCESS) { if (stage > 0) { returnCode = TPM_DaaSessionData_CheckStage(tpm_daa_session_data, stage); } } /* Verify that DAA_session -> DAA_digestContext == SHA-1(DAA_tpmSpecific) and return error TPM_DAA_TPM_SETTINGS on mismatch */ if (returnCode == TPM_SUCCESS) { if (stage >= 2) { returnCode = TPM_SHA1_CheckStructure(tpm_daa_session_data->DAA_session.DAA_digestContext, &(tpm_daa_session_data->DAA_tpmSpecific), (TPM_STORE_FUNCTION_T)TPM_DAATpm_Store, TPM_DAA_TPM_SETTINGS); } } /* Verify that DAA_tpmSpecific -> DAA_digestIssuer == SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS on mismatch */ if (returnCode == TPM_SUCCESS) { if (stage >= 2) { returnCode = TPM_SHA1_CheckStructure(tpm_daa_session_data->DAA_tpmSpecific.DAA_digestIssuer, &(tpm_daa_session_data->DAA_issuerSettings), (TPM_STORE_FUNCTION_T)TPM_DAAIssuer_Store, TPM_DAA_ISSUER_SETTINGS); } } /* Stages */ if (returnCode == TPM_SUCCESS) { switch (stage) { case 0 : returnCode = TPM_DAASign_Stage00(tpm_state, &tpm_daa_session_data, /* returns entry in array */ &daaHandleValid, &outputData, &inputData0); if (daaHandleValid) { /* For stage 0, daaHandle may be generated. Extract it from the DAA session and mark it valid, so the session can be terminated on error. */ daaHandle = tpm_daa_session_data->daaHandle; } break; case 1 : returnCode = TPM_DAASign_Stage01(tpm_state, tpm_daa_session_data, &outputData, &inputData0); break; case 2 : returnCode = TPM_DAAJoin_Stage09_Sign_Stage2(tpm_state, tpm_daa_session_data, &outputData, &inputData0, &inputData1); break; case 3 : returnCode = TPM_DAAJoin_Stage10_Sign_Stage3(tpm_state, tpm_daa_session_data, &outputData, &inputData0, &inputData1); break; case 4 : returnCode = TPM_DAAJoin_Stage11_Sign_Stage4(tpm_state, tpm_daa_session_data, &outputData, &inputData0, &inputData1); break; case 5 : returnCode = TPM_DAASign_Stage05(tpm_state, tpm_daa_session_data, &outputData, &inputData0, &inputData1); break; case 6 : returnCode = TPM_DAAJoin_Stage13_Sign_Stage6(tpm_state, tpm_daa_session_data, &outputData, &inputData0, &inputData1); break; case 7 : returnCode = TPM_DAAJoin_Stage14_Sign_Stage7(tpm_state, tpm_daa_session_data, &outputData, &inputData0); break; case 8 : returnCode = TPM_DAAJoin_Stage15_Sign_Stage8(tpm_state, tpm_daa_session_data, &outputData, &inputData0); break; case 9 : returnCode = TPM_DAAJoin_Stage16_Sign_Stage9(tpm_state, tpm_daa_session_data, &outputData, &inputData0); break; case 10 : returnCode = TPM_DAASign_Stage10(tpm_state, tpm_daa_session_data, &outputData, &inputData0, &inputData1); break; case 11 : returnCode = TPM_DAAJoin_Stage17_Sign_Stage11(tpm_state, tpm_daa_session_data, &outputData); break; case 12 : returnCode = TPM_DAAJoin_Stage18_Sign_Stage12(tpm_state, tpm_daa_session_data, &outputData); break; case 13 : returnCode = TPM_DAASign_Stage13(tpm_state, tpm_daa_session_data, &outputData, &inputData0); break; case 14 : returnCode = TPM_DAASign_Stage14(tpm_state, tpm_daa_session_data, &outputData, &inputData0); break; case 15 : returnCode = TPM_DAASign_Stage15(tpm_state, tpm_daa_session_data, &outputData, &inputData0); break; default : printf("TPM_Process_DAASign: Error, Illegal stage\n"); returnCode = TPM_DAA_STAGE; } } /* Common to most or all stages */ if (returnCode == TPM_SUCCESS) { tpm_daa_session_data->DAA_session.DAA_stage++; } /* 15.j. Terminate the DAA session and all resources associated with the DAA sign session handle. */ if (returnCode == TPM_SUCCESS) { if (stage == 15) { printf("TPM_Process_DAASign: Stage 15, terminating DAA session %08x\n", tpm_daa_session_data->daaHandle); TPM_DaaSessionData_Delete(tpm_daa_session_data); } } /* 2. Any error return results in the TPM invalidating all resources associated with the join */ /* NOTE Done after response processing */ /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_DAASign: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* return outputData */ returnCode = TPM_SizedBuffer_Store(response, &outputData); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if (returnCode == TPM_SUCCESS) { /* no outParam's, set authorization response data */ returnCode = TPM_AuthParams_Set(response, *hmacKey, /* owner HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, terminate the session. */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* on error, terminate the DAA session */ if (((rcf != 0) || (returnCode != TPM_SUCCESS)) && daaHandleValid) { TPM_DaaSessions_TerminateHandle(tpm_state->tpm_stclear_data.daaSessions, daaHandle); } /* cleanup */ TPM_SizedBuffer_Delete(&inputData0); /* @1 */ TPM_SizedBuffer_Delete(&inputData1); /* @2 */ TPM_SizedBuffer_Delete(&outputData); /* @3 */ return rcf; } libtpms-0.9.3/src/tpm12/tpm_daa.h000066400000000000000000000520601421143571500165130ustar00rootroot00000000000000/********************************************************************************/ /* */ /* DAA Functions */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_daa.h 4526 2011-03-24 21:14:42Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_DAA_H #define TPM_DAA_H #include "tpm_global.h" #include "tpm_store.h" /* TPM_DAA_SESSION_DATA (the entire array) */ void TPM_DaaSessions_Init(TPM_DAA_SESSION_DATA *daaSessions); TPM_RESULT TPM_DaaSessions_Load(TPM_DAA_SESSION_DATA *daaSessions, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_DaaSessions_Store(TPM_STORE_BUFFER *sbuffer, TPM_DAA_SESSION_DATA *daaSessions); void TPM_DaaSessions_Delete(TPM_DAA_SESSION_DATA *daaSessions); void TPM_DaaSessions_IsSpace(TPM_BOOL *isSpace, uint32_t *index, TPM_DAA_SESSION_DATA *daaSessions); void TPM_DaaSessions_GetSpace(uint32_t *space, TPM_DAA_SESSION_DATA *daaSessions); TPM_RESULT TPM_DaaSessions_StoreHandles(TPM_STORE_BUFFER *sbuffer, TPM_DAA_SESSION_DATA *daaSessions); TPM_RESULT TPM_DaaSessions_GetNewHandle(TPM_DAA_SESSION_DATA **tpm_daa_session_data, TPM_HANDLE *daaHandle, TPM_BOOL *daaHandleValid, TPM_DAA_SESSION_DATA *daaSessions); TPM_RESULT TPM_DaaSessions_GetEntry(TPM_DAA_SESSION_DATA **tpm_daa_session_data, TPM_DAA_SESSION_DATA *daaSessions, TPM_HANDLE daaHandle); TPM_RESULT TPM_DaaSessions_AddEntry(TPM_HANDLE *tpm_handle, TPM_BOOL keepHandle, TPM_DAA_SESSION_DATA *daaSessions, TPM_DAA_SESSION_DATA *tpm_daa_session_data); TPM_RESULT TPM_DaaSessions_TerminateHandle(TPM_DAA_SESSION_DATA *daaSessions, TPM_HANDLE daaHandle); /* TPM_DAA_SESSION_DATA (one element of the array) */ void TPM_DaaSessionData_Init(TPM_DAA_SESSION_DATA *tpm_daa_session_data); TPM_RESULT TPM_DaaSessionData_Load(TPM_DAA_SESSION_DATA *tpm_daa_session_data, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_DaaSessionData_Store(TPM_STORE_BUFFER *sbuffer, const TPM_DAA_SESSION_DATA *tpm_daa_session_data); void TPM_DaaSessionData_Delete(TPM_DAA_SESSION_DATA *tpm_daa_session_data); void TPM_DaaSessionData_Copy(TPM_DAA_SESSION_DATA *dest_daa_session_data, TPM_HANDLE tpm_handle, TPM_DAA_SESSION_DATA *src_daa_session_data); TPM_RESULT TPM_DaaSessionData_CheckStage(TPM_DAA_SESSION_DATA *tpm_daa_session_data, BYTE stage); /* TPM_DAA_ISSUER */ void TPM_DAAIssuer_Init(TPM_DAA_ISSUER *tpm_daa_issuer); TPM_RESULT TPM_DAAIssuer_Load(TPM_DAA_ISSUER *tpm_daa_issuer, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_DAAIssuer_Store(TPM_STORE_BUFFER *sbuffer, const TPM_DAA_ISSUER *tpm_daa_issuer); void TPM_DAAIssuer_Delete(TPM_DAA_ISSUER *tpm_daa_issuer); void TPM_DAAIssuer_Copy(TPM_DAA_ISSUER *dest_daa_issuer, TPM_DAA_ISSUER *src_daa_issuer); /* TPM_DAA_TPM */ void TPM_DAATpm_Init(TPM_DAA_TPM *tpm_daa_tpm); TPM_RESULT TPM_DAATpm_Load(TPM_DAA_TPM *tpm_daa_tpm, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_DAATpm_Store(TPM_STORE_BUFFER *sbuffer, const TPM_DAA_TPM *tpm_daa_tpm); void TPM_DAATpm_Delete(TPM_DAA_TPM *tpm_daa_tpm); void TPM_DAATpm_Copy(TPM_DAA_TPM *dest_daa_tpm, TPM_DAA_TPM *src_daa_tpm); /* TPM_DAA_CONTEXT */ void TPM_DAAContext_Init(TPM_DAA_CONTEXT *tpm_daa_context); TPM_RESULT TPM_DAAContext_Load(TPM_DAA_CONTEXT *tpm_daa_context, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_DAAContext_Store(TPM_STORE_BUFFER *sbuffer, const TPM_DAA_CONTEXT *tpm_daa_context); void TPM_DAAContext_Delete(TPM_DAA_CONTEXT *tpm_daa_context); void TPM_DAAContext_Copy(TPM_DAA_CONTEXT *dest_daa_context, TPM_DAA_CONTEXT *src_daa_context); /* TPM_DAA_JOINDATA */ void TPM_DAAJoindata_Init(TPM_DAA_JOINDATA *tpm_daa_joindata); TPM_RESULT TPM_DAAJoindata_Load(TPM_DAA_JOINDATA *tpm_daa_joindata, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_DAAJoindata_Store(TPM_STORE_BUFFER *sbuffer, const TPM_DAA_JOINDATA *tpm_daa_joindata); void TPM_DAAJoindata_Delete(TPM_DAA_JOINDATA *tpm_daa_joindata); void TPM_DAAJoindata_Copy(TPM_DAA_JOINDATA *dest_daa_joindata, TPM_DAA_JOINDATA *src_daa_joindata); /* TPM_DAA_BLOB */ void TPM_DAABlob_Init(TPM_DAA_BLOB *tpm_daa_blob); TPM_RESULT TPM_DAABlob_Load(TPM_DAA_BLOB *tpm_daa_blob, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_DAABlob_Store(TPM_STORE_BUFFER *sbuffer, const TPM_DAA_BLOB *tpm_daa_blob); void TPM_DAABlob_Delete(TPM_DAA_BLOB *tpm_daa_blob); /* TPM_DAA_SENSITIVE */ void TPM_DAASensitive_Init(TPM_DAA_SENSITIVE *tpm_daa_sensitive); TPM_RESULT TPM_DAASensitive_Load(TPM_DAA_SENSITIVE *tpm_daa_sensitive, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_DAASensitive_Store(TPM_STORE_BUFFER *sbuffer, const TPM_DAA_SENSITIVE *tpm_daa_sensitive); void TPM_DAASensitive_Delete(TPM_DAA_SENSITIVE *tpm_daa_sensitive); /* Stage Common Code */ TPM_RESULT TPM_DAADigestContext_GenerateDigestJoin(TPM_DIGEST tpm_digest, TPM_DAA_SESSION_DATA *tpm_daa_session_data); TPM_RESULT TPM_DAADigestContext_CheckDigestJoin(TPM_DAA_SESSION_DATA *tpm_daa_session_data); TPM_RESULT TPM_DAASession_CheckStage(TPM_DAA_SESSION_DATA *tpm_daa_session_data, BYTE stage); TPM_RESULT TPM_ComputeF(TPM_BIGNUM *fBignum, TPM_DAA_SESSION_DATA *tpm_daa_session_data); TPM_RESULT TPM_ComputeAexpPmodn(BYTE *DAA_scratch, uint32_t DAA_scratch_size, TPM_BIGNUM *rBignum, TPM_BIGNUM xBignum, TPM_BIGNUM fBignum, TPM_BIGNUM nBignum); TPM_RESULT TPM_ComputeZxAexpPmodn(BYTE *DAA_scratch, uint32_t DAA_scratch_size, TPM_BIGNUM zBignum, TPM_BIGNUM aBignum, TPM_BIGNUM pBignum, TPM_BIGNUM nBignum); TPM_RESULT TPM_ComputeApBmodn(TPM_BIGNUM *rBignum, TPM_BIGNUM aBignum, TPM_BIGNUM bBignum, TPM_BIGNUM nBignum); TPM_RESULT TPM_ComputeApBxC(TPM_BIGNUM *rBignum, TPM_BIGNUM aBignum, TPM_BIGNUM bBignum, TPM_BIGNUM cBignum); TPM_RESULT TPM_ComputeApBxCpD(TPM_BIGNUM *rBignum, TPM_BIGNUM aBignum, TPM_BIGNUM bBignum, TPM_BIGNUM cBignum, TPM_BIGNUM dBignum); TPM_RESULT TPM_ComputeDAAScratch(BYTE *DAA_scratch, uint32_t DAA_scratch_size, TPM_BIGNUM bn); TPM_RESULT TPM_ComputeEnlarge(unsigned char **out, uint32_t outSize, unsigned char *in, uint32_t inSize); TPM_RESULT TPM_SizedBuffer_ComputeEnlarge(TPM_SIZED_BUFFER *tpm_sized_buffer, uint32_t size); TPM_RESULT TPM_ComputeEncrypt(TPM_SIZED_BUFFER *outputData, tpm_state_t *tpm_state, TPM_DAA_SENSITIVE *tpm_daa_sensitive, TPM_RESOURCE_TYPE resourceType); TPM_RESULT TPM_ComputeDecrypt(TPM_DAA_SENSITIVE *tpm_daa_sensitive, tpm_state_t *tpm_state, TPM_SIZED_BUFFER *inputData, TPM_RESOURCE_TYPE resourceType); TPM_RESULT TPM_SHA1_BignumGenerate(TPM_DIGEST tpm_digest, TPM_BIGNUM bn, uint32_t size); TPM_RESULT TPM_SHA1_SizedBufferCheck(TPM_DIGEST tpm_digest, TPM_SIZED_BUFFER *tpm_sized_buffer, uint32_t size); /* Processing Common Functions */ TPM_RESULT TPM_DAAJoin_Stage00(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA **tpm_daa_session_data, TPM_BOOL *daaHandleValid, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0); TPM_RESULT TPM_DAAJoin_Stage01(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0, TPM_SIZED_BUFFER *inputData1); TPM_RESULT TPM_DAAJoin_Stage02(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0, TPM_SIZED_BUFFER *inputData1); TPM_RESULT TPM_DAAJoin_Stage03(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0); TPM_RESULT TPM_DAAJoin_Stage04(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0, TPM_SIZED_BUFFER *inputData1); TPM_RESULT TPM_DAAJoin_Stage05(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0, TPM_SIZED_BUFFER *inputData1); TPM_RESULT TPM_DAAJoin_Stage06(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0, TPM_SIZED_BUFFER *inputData1); TPM_RESULT TPM_DAAJoin_Stage07(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0, TPM_SIZED_BUFFER *inputData1); TPM_RESULT TPM_DAAJoin_Stage08(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0); TPM_RESULT TPM_DAAJoin_Stage09_Sign_Stage2(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0, TPM_SIZED_BUFFER *inputData1); TPM_RESULT TPM_DAAJoin_Stage10_Sign_Stage3(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0, TPM_SIZED_BUFFER *inputData1); TPM_RESULT TPM_DAAJoin_Stage11_Sign_Stage4(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0, TPM_SIZED_BUFFER *inputData1); TPM_RESULT TPM_DAAJoin_Stage12(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0, TPM_SIZED_BUFFER *inputData1); TPM_RESULT TPM_DAAJoin_Stage13_Sign_Stage6(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0, TPM_SIZED_BUFFER *inputData1); TPM_RESULT TPM_DAAJoin_Stage14_Sign_Stage7(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0); TPM_RESULT TPM_DAAJoin_Stage15_Sign_Stage8(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0); TPM_RESULT TPM_DAAJoin_Stage16_Sign_Stage9(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0); TPM_RESULT TPM_DAAJoin_Stage17_Sign_Stage11(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData); TPM_RESULT TPM_DAAJoin_Stage18_Sign_Stage12(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData); TPM_RESULT TPM_DAAJoin_Stage19(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData); TPM_RESULT TPM_DAAJoin_Stage20(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData); TPM_RESULT TPM_DAAJoin_Stage21(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData); TPM_RESULT TPM_DAAJoin_Stage22(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0); TPM_RESULT TPM_DAAJoin_Stage23(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0); TPM_RESULT TPM_DAAJoin_Stage24(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData); TPM_RESULT TPM_DAASign_Stage00(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA **tpm_daa_session_data, TPM_BOOL *daaHandleValid, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0); TPM_RESULT TPM_DAASign_Stage01(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0); TPM_RESULT TPM_DAASign_Stage05(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0, TPM_SIZED_BUFFER *inputData1); TPM_RESULT TPM_DAASign_Stage10(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0, TPM_SIZED_BUFFER *inputData1); TPM_RESULT TPM_DAASign_Stage13(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0); TPM_RESULT TPM_DAASign_Stage14(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0); TPM_RESULT TPM_DAASign_Stage15(tpm_state_t *tpm_state, TPM_DAA_SESSION_DATA *tpm_daa_session_data, TPM_SIZED_BUFFER *outputData, TPM_SIZED_BUFFER *inputData0); /* Processing functions */ TPM_RESULT TPM_Process_DAAJoin(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_DAASign(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); #endif libtpms-0.9.3/src/tpm12/tpm_delegate.c000066400000000000000000004307001421143571500175340ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Delegate Handler */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_delegate.c 4580 2011-06-10 17:55:41Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include #include #include "tpm_auth.h" #include "tpm_crypto.h" #include "tpm_cryptoh.h" #include "tpm_debug.h" #include "tpm_digest.h" #include "tpm_error.h" #include "tpm_key.h" #include "tpm_pcr.h" #include "tpm_permanent.h" #include "tpm_process.h" #include "tpm_secret.h" #include "tpm_delegate.h" /* TPM_DELEGATE_PUBLIC */ /* TPM_DelegatePublic_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_DelegatePublic_Init(TPM_DELEGATE_PUBLIC *tpm_delegate_public) { printf(" TPM_DelegatePublic_Init:\n"); tpm_delegate_public->rowLabel = 0; TPM_PCRInfoShort_Init(&(tpm_delegate_public->pcrInfo)); TPM_Delegations_Init(&(tpm_delegate_public->permissions)); tpm_delegate_public->familyID = 0; tpm_delegate_public->verificationCount = 0; return; } /* TPM_DelegatePublic_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes After use, call TPM_DelegatePublic_Delete() to free memory */ TPM_RESULT TPM_DelegatePublic_Load(TPM_DELEGATE_PUBLIC *tpm_delegate_public, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_DelegatePublic_Load:\n"); /* check the tag */ if (rc == 0) { rc = TPM_CheckTag(TPM_TAG_DELEGATE_PUBLIC, stream, stream_size); } /* load rowLabel */ if (rc == 0) { rc = TPM_Load8(&(tpm_delegate_public->rowLabel), stream, stream_size); } /* load pcrInfo */ if (rc == 0) { rc = TPM_PCRInfoShort_Load(&(tpm_delegate_public->pcrInfo), stream, stream_size, FALSE); } /* load permissions */ if (rc == 0) { rc = TPM_Delegations_Load(&(tpm_delegate_public->permissions), stream, stream_size); } /* load the familyID */ if (rc == 0) { rc = TPM_Load32(&(tpm_delegate_public->familyID), stream, stream_size); } /* load the verificationCount */ if (rc == 0) { rc = TPM_Load32(&(tpm_delegate_public->verificationCount), stream, stream_size); } return rc; } /* TPM_DelegatePublic_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_DelegatePublic_Store(TPM_STORE_BUFFER *sbuffer, const TPM_DELEGATE_PUBLIC *tpm_delegate_public) { TPM_RESULT rc = 0; printf(" TPM_DelegatePublic_Store:\n"); /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_DELEGATE_PUBLIC); } /* store rowLabel */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_delegate_public->rowLabel), sizeof(TPM_DELEGATE_LABEL)); } /* store pcrInfo */ if (rc == 0) { rc = TPM_PCRInfoShort_Store(sbuffer, &(tpm_delegate_public->pcrInfo), FALSE); } /* store permissions */ if (rc == 0) { rc = TPM_Delegations_Store(sbuffer, &(tpm_delegate_public->permissions)); } /* store familyID */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_delegate_public->familyID); } /* store verificationCount */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_delegate_public->verificationCount); } return rc; } /* TPM_DelegatePublic_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_DelegatePublic_Init to set members back to default values The object itself is not freed */ void TPM_DelegatePublic_Delete(TPM_DELEGATE_PUBLIC *tpm_delegate_public) { printf(" TPM_DeleteDelegatePublic:\n"); if (tpm_delegate_public != NULL) { TPM_PCRInfoShort_Delete(&(tpm_delegate_public->pcrInfo)); TPM_Delegations_Delete(&(tpm_delegate_public->permissions)); TPM_DelegatePublic_Init(tpm_delegate_public); } return; } /* TPM_DelegatePublic_Copy() copies the 'src' to the 'dest' structure */ TPM_RESULT TPM_DelegatePublic_Copy(TPM_DELEGATE_PUBLIC *dest, TPM_DELEGATE_PUBLIC *src) { TPM_RESULT rc = 0; printf(" TPM_DelegatePublic_Copy:\n"); if (rc == 0) { /* copy rowLabel */ dest->rowLabel = src->rowLabel; /* copy pcrInfo */ rc = TPM_PCRInfoShort_Copy(&(dest->pcrInfo), &(src->pcrInfo)); } if (rc == 0) { /* copy permissions */ TPM_Delegations_Copy(&(dest->permissions), &(src->permissions)); /* copy familyID */ dest->familyID = src->familyID; /* copy verificationCount */ dest->verificationCount = src->verificationCount; } return rc; } /* TPM_DELEGATE_SENSITIVE */ /* TPM_DelegateSensitive_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_DelegateSensitive_Init(TPM_DELEGATE_SENSITIVE *tpm_delegate_sensitive) { printf(" TPM_DelegateSensitive_Init:\n"); TPM_Secret_Init(tpm_delegate_sensitive->authValue); return; } /* TPM_DelegateSensitive_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes After use, call TPM_DelegateSensitive_Delete() to free memory */ TPM_RESULT TPM_DelegateSensitive_Load(TPM_DELEGATE_SENSITIVE *tpm_delegate_sensitive, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_DelegateSensitive_Load:\n"); /* check the tag */ if (rc == 0) { rc = TPM_CheckTag(TPM_TAG_DELEGATE_SENSITIVE, stream, stream_size); } /* load authValue */ if (rc == 0) { rc = TPM_Secret_Load(tpm_delegate_sensitive->authValue, stream, stream_size); } return rc; } /* TPM_DelegateSensitive_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_DelegateSensitive_Store(TPM_STORE_BUFFER *sbuffer, const TPM_DELEGATE_SENSITIVE *tpm_delegate_sensitive) { TPM_RESULT rc = 0; printf(" TPM_DelegateSensitive_Store:\n"); if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_DELEGATE_SENSITIVE); } if (rc == 0) { rc = TPM_Secret_Store(sbuffer, tpm_delegate_sensitive->authValue); } return rc; } /* TPM_DelegateSensitive_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_DelegateSensitive_Init to set members back to default values The object itself is not freed */ void TPM_DelegateSensitive_Delete(TPM_DELEGATE_SENSITIVE *tpm_delegate_sensitive) { printf(" TPM_DeleteDelegateSensitive:\n"); if (tpm_delegate_sensitive != NULL) { TPM_DelegateSensitive_Init(tpm_delegate_sensitive); } return; } /* TPM_DelegateSensitive_DecryptEncData() decrypts 'sensitiveArea' to a stream using 'delegateKey' and then deserializes the stream to a TPM_DELEGATE_SENSITIVE */ TPM_RESULT TPM_DelegateSensitive_DecryptEncData(TPM_DELEGATE_SENSITIVE *tpm_delegate_sensitive, TPM_SIZED_BUFFER *sensitiveArea, TPM_SYMMETRIC_KEY_TOKEN delegateKey) { TPM_RESULT rc = 0; unsigned char *s1; /* decrypted sensitive data */ uint32_t s1_length; unsigned char *stream; /* temp input stream */ uint32_t stream_size; printf(" TPM_DelegateSensitive_DecryptEncData:\n"); s1 = NULL; /* freed @1 */ if (rc == 0) { rc = TPM_SymmetricKeyData_Decrypt(&s1, /* decrypted data */ &s1_length, /* length decrypted data */ sensitiveArea->buffer, sensitiveArea->size, delegateKey); } if (rc == 0) { stream = s1; stream_size = s1_length; rc = TPM_DelegateSensitive_Load(tpm_delegate_sensitive, &stream, &stream_size); } free(s1); /* @1 */ return rc; } /* TPM_DELEGATIONS */ /* TPM_Delegations_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_Delegations_Init(TPM_DELEGATIONS *tpm_delegations) { printf(" TPM_Delegations_Init:\n"); tpm_delegations->delegateType = TPM_DEL_KEY_BITS; /* any legal value */ tpm_delegations->per1 = 0; tpm_delegations->per2 = 0; return; } /* TPM_Delegations_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes After use, call TPM_DeleteDelegations() to free memory */ TPM_RESULT TPM_Delegations_Load(TPM_DELEGATIONS *tpm_delegations, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_Delegations_Load:\n"); /* check tag */ if (rc == 0) { rc = TPM_CheckTag(TPM_TAG_DELEGATIONS, stream, stream_size); } /* load delegateType */ if (rc == 0) { rc = TPM_Load32(&(tpm_delegations->delegateType), stream, stream_size); } /* load per1 */ if (rc == 0) { rc = TPM_Load32(&(tpm_delegations->per1), stream, stream_size); } /* load per2 */ if (rc == 0) { rc = TPM_Load32(&(tpm_delegations->per2), stream, stream_size); } /* validate parameters */ if (rc == 0) { if (tpm_delegations->delegateType == TPM_DEL_OWNER_BITS) { if (tpm_delegations->per1 & ~TPM_DELEGATE_PER1_MASK) { printf("TPM_Delegations_Load: Error, owner per1 %08x\n", tpm_delegations->per1); rc = TPM_BAD_PARAMETER; } if (tpm_delegations->per2 & ~TPM_DELEGATE_PER2_MASK) { printf("TPM_Delegations_Load: Error, owner per2 %08x\n", tpm_delegations->per2); rc = TPM_BAD_PARAMETER; } } else if (tpm_delegations->delegateType == TPM_DEL_KEY_BITS) { if (tpm_delegations->per1 & ~TPM_KEY_DELEGATE_PER1_MASK) { printf("TPM_Delegations_Load: Error, key per1 %08x\n", tpm_delegations->per1); rc = TPM_BAD_PARAMETER; } if (tpm_delegations->per2 & ~TPM_KEY_DELEGATE_PER2_MASK) { printf("TPM_Delegations_Load: Error, key per2 %08x\n", tpm_delegations->per2); rc = TPM_BAD_PARAMETER; } } else { printf("TPM_Delegations_Load: Error, delegateType %08x\n", tpm_delegations->delegateType); rc = TPM_BAD_PARAMETER; } } return rc; } /* TPM_Delegations_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_Delegations_Store(TPM_STORE_BUFFER *sbuffer, const TPM_DELEGATIONS *tpm_delegations) { TPM_RESULT rc = 0; printf(" TPM_Delegations_Store:\n"); /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_DELEGATIONS); } /* store delegateType */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_delegations->delegateType); } /* store per1 */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_delegations->per1); } /* store per2 */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_delegations->per2); } return rc; } /* TPM_Delegations_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_Delegations_Init to set members back to default values The object itself is not freed */ void TPM_Delegations_Delete(TPM_DELEGATIONS *tpm_delegations) { printf(" TPM_Delegations_Delete:\n"); if (tpm_delegations != NULL) { TPM_Delegations_Init(tpm_delegations); } return; } /* TPM_Delegations_Copy() copies the source to the destination */ void TPM_Delegations_Copy(TPM_DELEGATIONS *dest, TPM_DELEGATIONS *src) { dest->delegateType = src->delegateType; dest->per1 = src->per1; dest->per2 = src->per2; return; } /* TPM_Delegations_CheckPermissionDelegation() verifies that the new delegation bits do not grant more permissions then currently delegated. Otherwise return error TPM_AUTHFAIL. An error occurs if a bit is set in newDelegations -> per and clear in currentDelegations -> per */ TPM_RESULT TPM_Delegations_CheckPermissionDelegation(TPM_DELEGATIONS *newDelegations, TPM_DELEGATIONS *currentDelegations) { TPM_RESULT rc = 0; printf(" TPM_Delegations_CheckPermissionDelegation:\n"); /* check per1 */ if (rc == 0) { if (newDelegations->per1 & ~currentDelegations->per1) { printf("TPM_Delegations_CheckPermissionDelegation: Error, " "new per1 %08x current per1 %08x\n", newDelegations->per1, currentDelegations->per1); rc = TPM_AUTHFAIL; } } /* check per2 */ if (rc == 0) { if (newDelegations->per2 & ~currentDelegations->per2) { printf("TPM_Delegations_CheckPermissionDelegation: Error, " "new per1 %08x current per1 %08x\n", newDelegations->per1, currentDelegations->per1); rc = TPM_AUTHFAIL; } } return rc; } /* TPM_Delegations_CheckPermission() verifies that the 'ordinal' has been delegated for execution based on the TPM_DELEGATE_PUBLIC. It verifies that the TPM_DELEGATIONS is appropriate for the entityType. Currently, only key or owner authorization can be delegated. It verifies that the TPM_DELEGATE_PUBLIC PCR's allow the delegation. */ TPM_RESULT TPM_Delegations_CheckPermission(tpm_state_t *tpm_state, TPM_DELEGATE_PUBLIC *delegatePublic, TPM_ENT_TYPE entityType, /* required */ TPM_COMMAND_CODE ordinal) { TPM_RESULT rc = 0; printf(" TPM_Delegations_CheckPermission: ordinal %08x\n", ordinal); if (rc == 0) { switch (entityType) { case TPM_ET_KEYHANDLE: rc = TPM_Delegations_CheckKeyPermission(&(delegatePublic->permissions), ordinal); break; case TPM_ET_OWNER: rc = TPM_Delegations_CheckOwnerPermission(&(delegatePublic->permissions), ordinal); break; default: printf("TPM_Delegations_CheckPermission: Error, " "DSAP session does not support entity type %02x\n", entityType); rc = TPM_AUTHFAIL; break; } } /* check that the TPM_DELEGATE_PUBLIC PCR's allow the delegation */ if (rc == 0) { rc = TPM_PCRInfoShort_CheckDigest(&(delegatePublic->pcrInfo), tpm_state->tpm_stclear_data.PCRS, tpm_state->tpm_stany_flags.localityModifier); } return rc; } /* TPM_Delegations_CheckOwnerPermission() verifies that the 'ordinal' has been delegated for execution based on the TPM_DELEGATIONS. */ TPM_RESULT TPM_Delegations_CheckOwnerPermission(TPM_DELEGATIONS *tpm_delegations, TPM_COMMAND_CODE ordinal) { TPM_RESULT rc = 0; uint16_t ownerPermissionBlock; /* 0:unused, 1:per1 2:per2 */ uint32_t ownerPermissionPosition; /* owner permission bit position */ printf(" TPM_Delegations_CheckOwnerPermission: ordinal %08x\n", ordinal); /* check that the TPM_DELEGATIONS structure is the correct type */ if (rc == 0) { if (tpm_delegations->delegateType != TPM_DEL_OWNER_BITS) { printf("TPM_Delegations_CheckOwnerPermission: Error," "Ordinal requires owner auth but delegateType is %08x\n", tpm_delegations->delegateType); rc = TPM_AUTHFAIL; } } /* get the block and position in the block from the ordinals table */ if (rc == 0) { rc = TPM_OrdinalTable_GetOwnerPermission(&ownerPermissionBlock, &ownerPermissionPosition, ordinal); } /* check that the permission bit is set in the TPM_DELEGATIONS bit map */ if (rc == 0) { printf(" TPM_Delegations_CheckOwnerPermission: block %u position %u\n", ownerPermissionBlock, ownerPermissionPosition); switch (ownerPermissionBlock) { case 1: /* per1 */ if (!(tpm_delegations->per1 & (1 << ownerPermissionPosition))) { printf("TPM_Delegations_CheckOwnerPermission: Error, per1 %08x\n", tpm_delegations->per1); rc = TPM_AUTHFAIL; } break; case 2: /* per2 */ if (!(tpm_delegations->per2 & (1 << ownerPermissionPosition))) { printf("TPM_Delegations_CheckOwnerPermission: Error, per2 %08x\n", tpm_delegations->per2); rc = TPM_AUTHFAIL; } break; default: printf("TPM_Delegations_CheckOwnerPermission: Error, block not 1 or 2\n"); rc = TPM_AUTHFAIL; break; } } return rc; } /* TPM_Delegations_CheckKeyPermission() verifies that the 'ordinal' has been delegated for execution based on the TPM_DELEGATIONS. */ TPM_RESULT TPM_Delegations_CheckKeyPermission(TPM_DELEGATIONS *tpm_delegations, TPM_COMMAND_CODE ordinal) { TPM_RESULT rc = 0; uint16_t keyPermissionBlock; /* 0:unused, 1:per1 2:per2 */ uint32_t keyPermissionPosition; /* key permission bit position */ printf(" TPM_Delegations_CheckKeyPermission: ordinal %08x\n", ordinal); /* check that the TPM_DELEGATIONS structure is the correct type */ if (rc == 0) { if (tpm_delegations->delegateType != TPM_DEL_KEY_BITS) { printf("TPM_Delegations_CheckKeyPermission: Error," "Ordinal requires key auth but delegateType is %08x\n", tpm_delegations->delegateType); rc = TPM_AUTHFAIL; } } /* get the block and position in the block from the ordinals table */ if (rc == 0) { rc = TPM_OrdinalTable_GetKeyPermission(&keyPermissionBlock, &keyPermissionPosition, ordinal); } /* check that the permission bit is set in the TPM_DELEGATIONS bit map */ if (rc == 0) { printf(" TPM_Delegations_CheckKeyPermission: block %u position %u\n", keyPermissionBlock, keyPermissionPosition); switch (keyPermissionBlock) { case 1: /* per1 */ if (!(tpm_delegations->per1 & (1 << keyPermissionPosition))) { printf("TPM_Delegations_CheckKeyPermission: Error, per1 %08x\n", tpm_delegations->per1); rc = TPM_AUTHFAIL; } break; case 2: /* per2 */ if (!(tpm_delegations->per2 & (1 << keyPermissionPosition))) { printf("TPM_Delegations_CheckKeyPermission: Error, per2 %08x\n", tpm_delegations->per2); rc = TPM_AUTHFAIL; } break; default: printf("TPM_Delegations_CheckKeyPermission: Error, block not 1 or 2\n"); rc = TPM_AUTHFAIL; break; } } return rc; } /* TPM_DELEGATE_OWNER_BLOB */ /* TPM_DelegateOwnerBlob_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_DelegateOwnerBlob_Init(TPM_DELEGATE_OWNER_BLOB *tpm_delegate_owner_blob) { printf(" TPM_DelegateOwnerBlob_Init:\n"); TPM_DelegatePublic_Init(&(tpm_delegate_owner_blob->pub)); TPM_Digest_Init(tpm_delegate_owner_blob->integrityDigest); TPM_SizedBuffer_Init(&(tpm_delegate_owner_blob->additionalArea)); TPM_SizedBuffer_Init(&(tpm_delegate_owner_blob->sensitiveArea)); return; } /* TPM_DelegateOwnerBlob_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_DelegateOwnerBlob_Init() After use, call TPM_DelegateOwnerBlob_Delete() to free memory */ TPM_RESULT TPM_DelegateOwnerBlob_Load(TPM_DELEGATE_OWNER_BLOB *tpm_delegate_owner_blob, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_DelegateOwnerBlob_Load:\n"); /* check tag */ if (rc == 0) { rc = TPM_CheckTag(TPM_TAG_DELEGATE_OWNER_BLOB, stream, stream_size); } /* load pub */ if (rc == 0) { rc = TPM_DelegatePublic_Load(&(tpm_delegate_owner_blob->pub), stream, stream_size); } /* check that permissions are owner */ if (rc == 0) { if (tpm_delegate_owner_blob->pub.permissions.delegateType != TPM_DEL_OWNER_BITS) { printf("TPM_DelegateOwnerBlob_Load: Error, delegateType expected %08x found %08x\n", TPM_DEL_OWNER_BITS, tpm_delegate_owner_blob->pub.permissions.delegateType); rc = TPM_INVALID_STRUCTURE; } } /* load integrityDigest */ if (rc == 0) { rc = TPM_Digest_Load(tpm_delegate_owner_blob->integrityDigest, stream, stream_size); } /* load additionalArea */ if (rc == 0) { rc = TPM_SizedBuffer_Load(&(tpm_delegate_owner_blob->additionalArea), stream, stream_size); } /* load sensitiveArea */ if (rc == 0) { rc = TPM_SizedBuffer_Load(&(tpm_delegate_owner_blob->sensitiveArea), stream, stream_size); } return rc; } /* TPM_DelegateOwnerBlob_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_DelegateOwnerBlob_Store(TPM_STORE_BUFFER *sbuffer, const TPM_DELEGATE_OWNER_BLOB *tpm_delegate_owner_blob) { TPM_RESULT rc = 0; printf(" TPM_DelegateOwnerBlob_Store:\n"); /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_DELEGATE_OWNER_BLOB); } /* store pub */ if (rc == 0) { rc = TPM_DelegatePublic_Store(sbuffer, &(tpm_delegate_owner_blob->pub)); } /* store integrityDigest */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_delegate_owner_blob->integrityDigest); } /* store additionalArea */ if (rc == 0) { rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_delegate_owner_blob->additionalArea)); } /* store sensitiveArea */ if (rc == 0) { rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_delegate_owner_blob->sensitiveArea)); } return rc; } /* TPM_DelegateOwnerBlob_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_DelegateOwnerBlob_Init to set members back to default values The object itself is not freed */ void TPM_DelegateOwnerBlob_Delete(TPM_DELEGATE_OWNER_BLOB *tpm_delegate_owner_blob) { printf(" TPM_DelegateOwnerBlob_Delete:\n"); if (tpm_delegate_owner_blob != NULL) { TPM_DelegatePublic_Delete(&(tpm_delegate_owner_blob->pub)); TPM_SizedBuffer_Delete(&(tpm_delegate_owner_blob->additionalArea)); TPM_SizedBuffer_Delete(&(tpm_delegate_owner_blob->sensitiveArea)); TPM_DelegateOwnerBlob_Init(tpm_delegate_owner_blob); } return; } /* TPM_DELEGATE_KEY_BLOB */ /* TPM_DelegateKeyBlob_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_DelegateKeyBlob_Init(TPM_DELEGATE_KEY_BLOB *tpm_delegate_key_blob) { printf(" TPM_DelegateKeyBlob_Init:\n"); TPM_DelegatePublic_Init(&(tpm_delegate_key_blob->pub)); TPM_Digest_Init(tpm_delegate_key_blob->integrityDigest); TPM_Digest_Init(tpm_delegate_key_blob->pubKeyDigest); TPM_SizedBuffer_Init(&(tpm_delegate_key_blob->additionalArea)); TPM_SizedBuffer_Init(&(tpm_delegate_key_blob->sensitiveArea)); return; } /* TPM_DelegateKeyBlob_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_DelegateKeyBlob_Init() After use, call TPM_DelegateKeyBlob_Delete() to free memory */ TPM_RESULT TPM_DelegateKeyBlob_Load(TPM_DELEGATE_KEY_BLOB *tpm_delegate_key_blob, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_DelegateKeyBlob_Load:\n"); /* check tag */ if (rc == 0) { rc = TPM_CheckTag(TPM_TAG_DELG_KEY_BLOB, stream, stream_size); } /* load pub */ if (rc == 0) { rc = TPM_DelegatePublic_Load(&(tpm_delegate_key_blob->pub), stream, stream_size); } /* check that permissions are key */ if (rc == 0) { if (tpm_delegate_key_blob->pub.permissions.delegateType != TPM_DEL_KEY_BITS) { printf("TPM_DelegateKeyBlob_Load: Error, delegateType expected %08x found %08x\n", TPM_DEL_KEY_BITS, tpm_delegate_key_blob->pub.permissions.delegateType); rc = TPM_INVALID_STRUCTURE; } } /* load integrityDigest */ if (rc == 0) { rc = TPM_Digest_Load(tpm_delegate_key_blob->integrityDigest, stream, stream_size); } /* load pubKeyDigest */ if (rc == 0) { rc = TPM_Digest_Load(tpm_delegate_key_blob->pubKeyDigest, stream, stream_size); } /* load additionalArea */ if (rc == 0) { rc = TPM_SizedBuffer_Load(&(tpm_delegate_key_blob->additionalArea), stream, stream_size); } /* load sensitiveArea */ if (rc == 0) { rc = TPM_SizedBuffer_Load(&(tpm_delegate_key_blob->sensitiveArea), stream, stream_size); } return rc; } /* TPM_DelegateKeyBlob_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_DelegateKeyBlob_Store(TPM_STORE_BUFFER *sbuffer, const TPM_DELEGATE_KEY_BLOB *tpm_delegate_key_blob) { TPM_RESULT rc = 0; printf(" TPM_DelegateKeyBlob_Store:\n"); /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_DELG_KEY_BLOB); } /* store pub */ if (rc == 0) { rc = TPM_DelegatePublic_Store(sbuffer, &(tpm_delegate_key_blob->pub)); } /* store integrityDigest */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_delegate_key_blob->integrityDigest); } /* store pubKeyDigest */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_delegate_key_blob->pubKeyDigest); } /* store additionalArea */ if (rc == 0) { rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_delegate_key_blob->additionalArea)); } /* store sensitiveArea */ if (rc == 0) { rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_delegate_key_blob->sensitiveArea)); } return rc; } /* TPM_DelegateKeyBlob_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_DelegateKeyBlob_Init to set members back to default values The object itself is not freed */ void TPM_DelegateKeyBlob_Delete(TPM_DELEGATE_KEY_BLOB *tpm_delegate_key_blob) { printf(" TPM_DelegateKeyBlob_Delete:\n"); if (tpm_delegate_key_blob != NULL) { TPM_DelegatePublic_Delete(&(tpm_delegate_key_blob->pub)); TPM_SizedBuffer_Delete(&(tpm_delegate_key_blob->additionalArea)); TPM_SizedBuffer_Delete(&(tpm_delegate_key_blob->sensitiveArea)); TPM_DelegateKeyBlob_Init(tpm_delegate_key_blob); } return; } /* TPM_FAMILY_TABLE */ /* TPM_FamilyTable_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_FamilyTable_Init(TPM_FAMILY_TABLE *tpm_family_table) { size_t i; printf(" TPM_FamilyTable_Init: Qty %u\n", TPM_NUM_FAMILY_TABLE_ENTRY_MIN); for (i = 0 ; i < TPM_NUM_FAMILY_TABLE_ENTRY_MIN ; i++) { TPM_FamilyTableEntry_Init(&(tpm_family_table->famTableRow[i])); } return; } /* TPM_FamilyTable_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_FamilyTable_Init() After use, call TPM_FamilyTable_Delete() to free memory */ TPM_RESULT TPM_FamilyTable_Load(TPM_FAMILY_TABLE *tpm_family_table, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; size_t i; printf(" TPM_FamilyTable_Load: Qty %u\n", TPM_NUM_FAMILY_TABLE_ENTRY_MIN); for (i = 0 ; (rc == 0) && (i < TPM_NUM_FAMILY_TABLE_ENTRY_MIN) ; i++) { rc = TPM_FamilyTableEntry_Load(&(tpm_family_table->famTableRow[i]), stream, stream_size); } return rc; } /* TPM_FamilyTable_Store() If store_tag is TRUE, the TPM_FAMILY_TABLE_ENTRY tag is stored. serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_FamilyTable_Store(TPM_STORE_BUFFER *sbuffer, const TPM_FAMILY_TABLE *tpm_family_table, TPM_BOOL store_tag) { TPM_RESULT rc = 0; size_t i; printf(" TPM_FamilyTable_Store: Qty %u\n", TPM_NUM_FAMILY_TABLE_ENTRY_MIN); for (i = 0 ; (rc == 0) && (i < TPM_NUM_FAMILY_TABLE_ENTRY_MIN) ; i++) { rc = TPM_FamilyTableEntry_Store(sbuffer, &(tpm_family_table->famTableRow[i]), store_tag); } return rc; } /* TPM_FamilyTable_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_FamilyTable_Init to set members back to default values The object itself is not freed */ void TPM_FamilyTable_Delete(TPM_FAMILY_TABLE *tpm_family_table) { size_t i; printf(" TPM_FamilyTable_Delete: Qty %u\n", TPM_NUM_FAMILY_TABLE_ENTRY_MIN); if (tpm_family_table != NULL) { for (i = 0 ; i < TPM_NUM_FAMILY_TABLE_ENTRY_MIN ; i++) { TPM_FamilyTableEntry_Delete(&(tpm_family_table->famTableRow[i])); } TPM_FamilyTable_Init(tpm_family_table); } return; } /* TPM_FamilyTable_GetEntry() searches all entries for the entry matching the familyID, and returns the TPM_FAMILY_TABLE_ENTRY associated with the familyID. Returns 0 for success TPM_BADINDEX if the familyID is not found */ TPM_RESULT TPM_FamilyTable_GetEntry(TPM_FAMILY_TABLE_ENTRY **tpm_family_table_entry, /* output */ TPM_FAMILY_TABLE *tpm_family_table, TPM_FAMILY_ID familyID) { TPM_RESULT rc = 0; size_t i; TPM_BOOL found; printf(" TPM_FamilyTable_GetEntry: familyID %08x\n", familyID); for (i = 0, found = FALSE ; (i < TPM_NUM_FAMILY_TABLE_ENTRY_MIN) && !found ; i++) { if (tpm_family_table->famTableRow[i].valid && (tpm_family_table->famTableRow[i].familyID == familyID)) { /* found */ found = TRUE; *tpm_family_table_entry = &(tpm_family_table->famTableRow[i]); } } if (!found) { printf("TPM_FamilyTable_GetEntry: Error, familyID %08x not found\n", familyID); rc = TPM_BADINDEX; } return rc; } /* TPM_FamilyTable_GetEnabledEntry() searches all entries for the entry matching the familyID, and returns the TPM_FAMILY_TABLE_ENTRY associated with the familyID. Similar to TPM_FamilyTable_GetEntry() but returns an error if the entry is disabled. Returns 0 for success TPM_BADINDEX if the familyID is not found TPM_DISABLED_CMD if the TPM_FAMILY_TABLE_ENTRY -> TPM_FAMFLAG_ENABLED is FALSE */ TPM_RESULT TPM_FamilyTable_GetEnabledEntry(TPM_FAMILY_TABLE_ENTRY **tpm_family_table_entry, TPM_FAMILY_TABLE *tpm_family_table, TPM_FAMILY_ID familyID) { TPM_RESULT rc = 0; printf(" TPM_FamilyTable_GetEnabledEntry: familyID %08x\n", familyID); if (rc == 0) { rc = TPM_FamilyTable_GetEntry(tpm_family_table_entry, tpm_family_table, familyID); } if (rc == 0) { if (!((*tpm_family_table_entry)->flags & TPM_FAMFLAG_ENABLED)) { printf("TPM_FamilyTable_GetEnabledEntry: Error, family %08x disabled\n", familyID); rc = TPM_DISABLED_CMD; } } return rc; } /* TPM_FamilyTable_IsSpace() returns success if an entry is available, an error if not. If success, 'family_table_entry' holds the first free family table row. */ TPM_RESULT TPM_FamilyTable_IsSpace(TPM_FAMILY_TABLE_ENTRY **tpm_family_table_entry, /* output */ TPM_FAMILY_TABLE *tpm_family_table) { size_t i; TPM_BOOL isSpace; TPM_RESULT rc = 0; printf(" TPM_FamilyTable_IsSpace:\n"); for (i = 0, isSpace = FALSE ; i < TPM_NUM_FAMILY_TABLE_ENTRY_MIN; i++) { *tpm_family_table_entry = &(tpm_family_table->famTableRow[i]); if (!((*tpm_family_table_entry)->valid)) { printf(" TPM_FamilyTable_IsSpace: Found space at %lu\n", (unsigned long)i); isSpace = TRUE; break; } } if (!isSpace) { printf(" TPM_FamilyTable_IsSpace: Error, no space found\n"); rc = TPM_RESOURCES; } return rc; } /* TPM_FamilyTable_StoreValid() stores only the valid (occupied) entries If store_tag is TRUE, the TPM_FAMILY_TABLE_ENTRY tag is stored. serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_FamilyTable_StoreValid(TPM_STORE_BUFFER *sbuffer, const TPM_FAMILY_TABLE *tpm_family_table, TPM_BOOL store_tag) { TPM_RESULT rc = 0; size_t i; printf(" TPM_FamilyTable_StoreValid: \n"); for (i = 0 ; (rc == 0) && (i < TPM_NUM_FAMILY_TABLE_ENTRY_MIN) ; i++) { /* store only the valid rows */ if (tpm_family_table->famTableRow[i].valid) { /* store only the publicly visible members */ printf(" TPM_FamilyTable_StoreValid: Entry %lu is valid\n", (unsigned long)i); printf(" TPM_FamilyTable_StoreValid: Entry family ID is %08x\n", tpm_family_table->famTableRow[i].familyID); rc = TPM_FamilyTableEntry_StorePublic(sbuffer, &(tpm_family_table->famTableRow[i]), store_tag); } } return rc; } /* TPM_FAMILY_TABLE_ENTRY */ /* TPM_FamilyTableEntry_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_FamilyTableEntry_Init(TPM_FAMILY_TABLE_ENTRY *tpm_family_table_entry) { printf(" TPM_FamilyTableEntry_Init:\n"); tpm_family_table_entry->familyLabel = 0; tpm_family_table_entry->familyID = 0; tpm_family_table_entry->verificationCount = 0; tpm_family_table_entry->flags = 0; tpm_family_table_entry->valid = FALSE; return; } /* TPM_FamilyTableEntry_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_FamilyTableEntry_Init() After use, call TPM_FamilyTableEntry_Delete() to free memory */ TPM_RESULT TPM_FamilyTableEntry_Load(TPM_FAMILY_TABLE_ENTRY *tpm_family_table_entry, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_FamilyTableEntry_Load:\n"); /* load tag */ /* the tag is not serialized when storing TPM_PERMANENT_DATA, to save NV space */ /* load familyLabel */ if (rc == 0) { rc = TPM_Load8(&(tpm_family_table_entry->familyLabel), stream, stream_size); } /* load familyID */ if (rc == 0) { rc = TPM_Load32(&(tpm_family_table_entry->familyID), stream, stream_size); } /* load verificationCount */ if (rc == 0) { rc = TPM_Load32(&(tpm_family_table_entry->verificationCount), stream, stream_size); } /* load flags */ if (rc == 0) { rc = TPM_Load32(&(tpm_family_table_entry->flags), stream, stream_size); } /* load valid */ if (rc == 0) { rc = TPM_LoadBool(&(tpm_family_table_entry->valid), stream, stream_size); } if (rc == 0) { printf(" TPM_FamilyTableEntry_Load: label %02x familyID %08x valid %u\n", tpm_family_table_entry->familyLabel, tpm_family_table_entry->familyID, tpm_family_table_entry->valid); } return rc; } /* TPM_FamilyTableEntry_Store() stores all members of the structure If store_tag is TRUE, the TPM_FAMILY_TABLE_ENTRY tag is stored. serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_FamilyTableEntry_Store(TPM_STORE_BUFFER *sbuffer, const TPM_FAMILY_TABLE_ENTRY *tpm_family_table_entry, TPM_BOOL store_tag) { TPM_RESULT rc = 0; printf(" TPM_FamilyTableEntry_Store:\n"); /* store public, visible members */ if (rc == 0) { rc = TPM_FamilyTableEntry_StorePublic(sbuffer, tpm_family_table_entry, store_tag); } /* store valid */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_family_table_entry->valid), sizeof(TPM_BOOL)); } return rc; } /* TPM_FamilyTableEntry_StorePublic() stores only the public, visible members of the structure If store_tag is TRUE, the TPM_FAMILY_TABLE_ENTRY tag is stored. serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_FamilyTableEntry_StorePublic(TPM_STORE_BUFFER *sbuffer, const TPM_FAMILY_TABLE_ENTRY *tpm_family_table_entry, TPM_BOOL store_tag) { TPM_RESULT rc = 0; printf(" TPM_FamilyTableEntry_StorePublic:\n"); /* store tag */ if ((rc == 0) && (store_tag)) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_FAMILY_TABLE_ENTRY); } /* store familyLabel */ if (rc == 0) { TPM_Sbuffer_Append(sbuffer, &(tpm_family_table_entry->familyLabel), sizeof(TPM_FAMILY_LABEL)); } /* store familyID */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_family_table_entry->familyID); } /* store verificationCount */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_family_table_entry->verificationCount); } /* store flags */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_family_table_entry->flags); } return rc; } /* TPM_FamilyTableEntry_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_FamilyTableEntry_Init to set members back to default values The object itself is not freed */ void TPM_FamilyTableEntry_Delete(TPM_FAMILY_TABLE_ENTRY *tpm_family_table_entry) { printf(" TPM_FamilyTableEntry_Delete:\n"); if (tpm_family_table_entry != NULL) { TPM_FamilyTableEntry_Init(tpm_family_table_entry); } return; } /* TPM_DELEGATE_TABLE */ /* TPM_DelegateTable_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_DelegateTable_Init(TPM_DELEGATE_TABLE *tpm_delegate_table) { size_t i; printf(" TPM_DelegateTable_Init: Qty %u\n", TPM_NUM_DELEGATE_TABLE_ENTRY_MIN); for (i = 0 ; i < TPM_NUM_DELEGATE_TABLE_ENTRY_MIN ; i++) { TPM_DelegateTableRow_Init(&(tpm_delegate_table->delRow[i])); } return; } /* TPM_DelegateTable_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_DelegateTable_Init() After use, call TPM_DelegateTable_Delete() to free memory */ TPM_RESULT TPM_DelegateTable_Load(TPM_DELEGATE_TABLE *tpm_delegate_table, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; size_t i; printf(" TPM_DelegateTable_Load: Qty %u\n", TPM_NUM_DELEGATE_TABLE_ENTRY_MIN); for (i = 0 ; (rc == 0) && (i < TPM_NUM_DELEGATE_TABLE_ENTRY_MIN) ; i++) { rc = TPM_DelegateTableRow_Load(&(tpm_delegate_table->delRow[i]), stream, stream_size); } return rc; } /* TPM_DelegateTable_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_DelegateTable_Store(TPM_STORE_BUFFER *sbuffer, const TPM_DELEGATE_TABLE *tpm_delegate_table) { TPM_RESULT rc = 0; size_t i; printf(" TPM_DelegateTable_Store: Qty %u\n", TPM_NUM_DELEGATE_TABLE_ENTRY_MIN); for (i = 0 ; (rc == 0) && (i < TPM_NUM_DELEGATE_TABLE_ENTRY_MIN) ; i++) { rc = TPM_DelegateTableRow_Store(sbuffer, &(tpm_delegate_table->delRow[i])); } return rc; } /* TPM_DelegateTable_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_DelegateTable_Init to set members back to default values The object itself is not freed */ void TPM_DelegateTable_Delete(TPM_DELEGATE_TABLE *tpm_delegate_table) { size_t i; printf(" TPM_DelegateTable_Delete: Qty %u\n", TPM_NUM_DELEGATE_TABLE_ENTRY_MIN); if (tpm_delegate_table != NULL) { for (i = 0 ; i < TPM_NUM_DELEGATE_TABLE_ENTRY_MIN ; i++) { TPM_DelegateTableRow_Delete(&(tpm_delegate_table->delRow[i])); } TPM_DelegateTable_Init(tpm_delegate_table); } return; } /* TPM_DelegateTable_StoreValid() store only the valid (occupied) entries. Each entry is prepended with it's index. serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_DelegateTable_StoreValid(TPM_STORE_BUFFER *sbuffer, const TPM_DELEGATE_TABLE *tpm_delegate_table) { TPM_RESULT rc = 0; uint32_t i; printf(" TPM_DelegateTable_StoreValid:\n"); for (i = 0 ; (rc == 0) && (i < TPM_NUM_DELEGATE_TABLE_ENTRY_MIN) ; i++) { /* store only the valid rows */ if (tpm_delegate_table->delRow[i].valid) { /* a. Write the TPM_DELEGATE_INDEX to delegateTable */ printf(" TPM_DelegateTable_StoreValid: Entry %u is valid\n", i); printf(" TPM_DelegateTable_StoreValid: Entry family ID is %08x\n", tpm_delegate_table->delRow[i].pub.familyID); if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, i); } /* b. Copy the TPM_DELEGATE_PUBLIC to delegateTable */ if (rc == 0) { rc = TPM_DelegatePublic_Store(sbuffer, &(tpm_delegate_table->delRow[i].pub)); } } } return rc; } /* TPM_DelegateTable_GetRow() maps 'rowIndex' to a TPM_DELEGATE_TABLE_ROW in the delegate table. The row may not have valid data. */ TPM_RESULT TPM_DelegateTable_GetRow(TPM_DELEGATE_TABLE_ROW **delegateTableRow, TPM_DELEGATE_TABLE *tpm_delegate_table, uint32_t rowIndex) { TPM_RESULT rc = 0; printf(" TPM_DelegateTable_GetRow: index %u\n", rowIndex); if (rc == 0) { if (rowIndex >= TPM_NUM_DELEGATE_TABLE_ENTRY_MIN) { printf("TPM_DelegateTable_GetRow: index %u out of range\n", rowIndex); rc = TPM_BADINDEX; } } if (rc == 0) { *delegateTableRow = &(tpm_delegate_table->delRow[rowIndex]); } return rc; } /* TPM_DelegateTable_GetValidRow() maps 'rowIndex' to a TPM_DELEGATE_TABLE_ROW in the delegate table. The row must have valid data. */ TPM_RESULT TPM_DelegateTable_GetValidRow(TPM_DELEGATE_TABLE_ROW **delegateTableRow, TPM_DELEGATE_TABLE *tpm_delegate_table, uint32_t rowIndex) { TPM_RESULT rc = 0; if (rc == 0) { rc = TPM_DelegateTable_GetRow(delegateTableRow, tpm_delegate_table, rowIndex); } if (rc == 0) { *delegateTableRow = &(tpm_delegate_table->delRow[rowIndex]); if (!(*delegateTableRow)->valid) { printf("TPM_DelegateTable_GetValidRow: index %u invalid\n", rowIndex); rc = TPM_BADINDEX; } } return rc; } /* TPM_DELEGATE_TABLE_ROW */ /* TPM_DelegateTableRow_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_DelegateTableRow_Init(TPM_DELEGATE_TABLE_ROW *tpm_delegate_table_row) { printf(" TPM_DelegateTableRow_Init:\n"); TPM_DelegatePublic_Init(&(tpm_delegate_table_row->pub)); TPM_Secret_Init(tpm_delegate_table_row->authValue); tpm_delegate_table_row->valid = FALSE; return; } /* TPM_DelegateTableRow_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_DelegateTableRow_Init() After use, call TPM_DelegateTableRow_Delete() to free memory */ TPM_RESULT TPM_DelegateTableRow_Load(TPM_DELEGATE_TABLE_ROW *tpm_delegate_table_row, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_DelegateTableRow_Load:\n"); /* check the tag */ if (rc == 0) { rc = TPM_CheckTag(TPM_TAG_DELEGATE_TABLE_ROW, stream, stream_size); } /* load pub */ if (rc == 0) { rc = TPM_DelegatePublic_Load(&(tpm_delegate_table_row->pub), stream, stream_size); } /* load authValue */ if (rc == 0) { rc = TPM_Secret_Load(tpm_delegate_table_row->authValue, stream, stream_size); } /* load valid */ if (rc == 0) { rc = TPM_LoadBool(&(tpm_delegate_table_row->valid), stream, stream_size); } return rc; } /* TPM_DelegateTableRow_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_DelegateTableRow_Store(TPM_STORE_BUFFER *sbuffer, const TPM_DELEGATE_TABLE_ROW *tpm_delegate_table_row) { TPM_RESULT rc = 0; printf(" TPM_DelegateTableRow_Store:\n"); /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_DELEGATE_TABLE_ROW); } /* store pub */ if (rc == 0) { rc = TPM_DelegatePublic_Store(sbuffer, &(tpm_delegate_table_row->pub)); } /* store authValue */ if (rc == 0) { rc = TPM_Secret_Store(sbuffer, tpm_delegate_table_row->authValue); } /* store valid */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_delegate_table_row->valid), sizeof(TPM_BOOL)); } return rc; } /* TPM_DelegateTableRow_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_DelegateTableRow_Init to set members back to default values The object itself is not freed */ void TPM_DelegateTableRow_Delete(TPM_DELEGATE_TABLE_ROW *tpm_delegate_table_row) { printf(" TPM_DelegateTableRow_Delete:\n"); if (tpm_delegate_table_row != NULL) { TPM_DelegatePublic_Delete(&(tpm_delegate_table_row->pub)); TPM_DelegateTableRow_Init(tpm_delegate_table_row); } return; } /* Processing Functions */ /* 19.1 TPM_Delegate_Manage rev 115 TPM_Delegate_Manage is the fundamental process for managing the Family tables, including enabling/disabling Delegation for a selected Family. Normally TPM_Delegate_Manage must be executed at least once (to create Family tables for a particular family) before any other type of Delegation command in that family can succeed. Delegate_Manage is authorized by the TPM Owner if an Owner is installed, because changing a table is a privileged Owner operation. If no Owner is installed, Delegate_Manage requires no privilege to execute. This does not disenfranchise an Owner, since there is no Owner, and simplifies loading of tables during platform manufacture or on first-boot. Burn-out of TPM non-volatile storage by inappropriate use is mitigated by the TPM's normal limits on NV-writes in the absence of an Owner. Tables can be locked after loading, to prevent subsequent tampering, and only unlocked by the Owner, his delegate, or the act of removing the Owner (even if there is no Owner). TPM_Delegate_Manage command is customized by opcode: (1) TPM_FAMILY_ENABLE enables/disables use of a family and all the rows of the delegate table belonging to that family, (2) TPM_FAMILY_ADMIN can be used to prevent further management of the Tables until an Owner is installed, or until the Owner is removed from the TPM. (Note that the Physical Presence command TPM_ForceClear always enables further management, even if TPM_ForceClear is used when no Owner is installed.) (3) TPM_FAMILY_CREATE creates a new family. (4) TPM_FAMILY_INVALIDATE invalidates an existing family. */ TPM_RESULT TPM_Process_DelegateManage(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_FAMILY_ID familyID; /* The familyID that is to be managed */ TPM_FAMILY_OPERATION opCode = 0; /* Operation to be performed by this command. */ TPM_SIZED_BUFFER opData; /* Data necessary to implement opCode */ TPM_AUTHHANDLE authHandle; /* The authorization session handle used for owner authentication. */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization session handle */ TPM_AUTHDATA ownerAuth; /* HMAC key: ownerAuth. */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ TPM_SECRET *hmacKey; TPM_SECRET savedAuth; /* saved copy for response */ TPM_DELEGATE_PUBLIC *delegatePublic; /* from DSAP session */ TPM_FAMILY_TABLE_ENTRY *familyRow = NULL; /* family table row containing familyID */ uint32_t nv1 = tpm_state->tpm_permanent_data.noOwnerNVWrite; /* temp for noOwnerNVWrite, initialize to silence compiler */ TPM_BOOL nv1Incremented = FALSE; /* flag that nv1 was incremented */ TPM_BOOL writeAllNV = FALSE; /* flag to write back data */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_STORE_BUFFER retData; /* Returned data */ printf("TPM_Process_DelegateManage: Ordinal Entry\n"); TPM_SizedBuffer_Init(&opData); /* freed @1 */ TPM_Sbuffer_Init(&retData); /* freed @2 */ /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get familyID parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&familyID, &command, ¶mSize); } /* get opCode parameter */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_DelegateManage: familyID %08x\n", familyID); returnCode = TPM_Load32(&opCode, &command, ¶mSize); } /* get opData parameter */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_DelegateManage: opCode %u\n", opCode); returnCode = TPM_SizedBuffer_Load(&opData, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag10(tag); } /* get the optional 'below the line' authorization parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, ownerAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_DelegateManage: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* 1. If opCode != TPM_FAMILY_CREATE */ /* a. Locate familyID in the TPM_FAMILY_TABLE and set familyRow to indicate row, return TPM_BADINDEX if not found */ /* b. Set FR, a TPM_FAMILY_TABLE_ENTRY, to TPM_FAMILY_TABLE. famTableRow[familyRow] */ if ((returnCode == TPM_SUCCESS) && (opCode != TPM_FAMILY_CREATE)) { printf("TPM_Process_DelegateManage: Not creating, get entry for familyID %08x\n", familyID); returnCode = TPM_FamilyTable_GetEntry(&familyRow, &(tpm_state->tpm_permanent_data.familyTable), familyID); } /* 2. If tag = TPM_TAG_RQU_AUTH1_COMMAND */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { /* a. Validate the command and parameters using ownerAuth, return TPM_AUTHFAIL on error */ returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_OWNER, ordinal, NULL, &(tpm_state->tpm_permanent_data.ownerAuth),/* OIAP */ tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ } if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { /* make a copy of the HMAC key for the response, since it MAY be invalidated */ TPM_Secret_Copy(savedAuth, *hmacKey); returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* owner HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, ownerAuth); /* Authorization digest for input */ } if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { /* b. If the command is delegated (authHandle session type is TPM_PID_DSAP or through ownerReference delegation) */ if ((auth_session_data->protocolID == TPM_PID_DSAP) || (tpm_state->tpm_stclear_data.ownerReference != TPM_KH_OWNER)) { /* i. If opCode = TPM_FAMILY_CREATE */ /* (1) The TPM MUST ignore familyID */ /* ii. Else */ if (opCode != TPM_FAMILY_CREATE) { /* get the TPM_DELEGATE_PUBLIC from the DSAP session */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessionData_GetDelegatePublic(&delegatePublic, auth_session_data); } /* (1) Verify that the familyID associated with authHandle matches the familyID parameter, return TPM_DELEGATE_FAMILY on error */ if (returnCode == TPM_SUCCESS) { if (delegatePublic->familyID != familyID) { printf("TPM_Process_DelegateManage: Error, familyID %08x should be %08x\n", familyID, delegatePublic->familyID); returnCode = TPM_DELEGATE_FAMILY; } } } } } /* 3. Else */ if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_AUTH1_COMMAND)) { /* a. If TPM_PERMANENT_DATA -> ownerAuth is valid, return TPM_AUTHFAIL */ if (tpm_state->tpm_permanent_data.ownerInstalled) { printf("TPM_Process_DelegateManage: Error, owner installed but no authorization\n"); returnCode = TPM_AUTHFAIL ; } } /* b. If opCode != TPM_FAMILY_CREATE and FR -> flags -> TPM_DELEGATE_ADMIN_LOCK is TRUE, return TPM_DELEGATE_LOCK */ if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_AUTH1_COMMAND)) { if ((opCode != TPM_FAMILY_CREATE) && (familyRow->flags & TPM_DELEGATE_ADMIN_LOCK)) { printf("TPM_Process_DelegateManage: Error, row locked\n"); returnCode = TPM_DELEGATE_LOCK; } } /* c. Validate max NV writes without an owner */ if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_AUTH1_COMMAND)) { /* i. Set NV1 to TPM_PERMANENT_DATA -> noOwnerNVWrite */ nv1 = tpm_state->tpm_permanent_data.noOwnerNVWrite; /* ii. Increment NV1 by 1 */ nv1++; /* iii. If NV1 > TPM_MAX_NV_WRITE_NOOWNER return TPM_MAXNVWRITES */ if (nv1 > TPM_MAX_NV_WRITE_NOOWNER) { printf("TPM_Process_DelegateManage: Error, max NV writes %d w/o owner reached\n", tpm_state->tpm_permanent_data.noOwnerNVWrite); returnCode = TPM_MAXNVWRITES; } if (returnCode == TPM_SUCCESS){ /* iv. Set TPM_PERMANENT_DATA -> noOwnerNVWrite to NV1 */ /* NOTE Don't update the noOwnerNVWrite value until determining that the write will be performed */ nv1Incremented = TRUE; } } /* 4. The TPM invalidates sessions */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_DelegateManage: Invalidate sessions\n"); /* a. MUST invalidate all DSAP sessions */ /* b. MUST invalidate all OSAP sessions associated with the delegation table */ /* d. MAY invalidate any other session */ TPM_AuthSessions_TerminatexSAP(&continueAuthSession, authHandle, tpm_state->tpm_stclear_data.authSessions); /* c. MUST set TPM_STCLEAR_DATA -> ownerReference to TPM_KH_OWNER */ tpm_state->tpm_stclear_data.ownerReference = TPM_KH_OWNER; } /* 5. If opCode == TPM_FAMILY_CREATE */ if ((returnCode == TPM_SUCCESS) && (opCode == TPM_FAMILY_CREATE)) { printf("TPM_Process_DelegateManage: Processing TPM_FAMILY_CREATE\n"); /* a. Validate that sufficient space exists within the TPM to store an additional family and map F2 to the newly allocated space. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_FamilyTable_IsSpace(&familyRow, /* output */ &(tpm_state->tpm_permanent_data.familyTable)); } /* b. Validate that opData is a TPM_FAMILY_LABEL */ if (returnCode == TPM_SUCCESS) { /* i. If opDataSize != sizeof(TPM_FAMILY_LABEL) return TPM_BAD_PARAM_SIZE */ if (opData.size != sizeof(TPM_FAMILY_LABEL)) { printf("TPM_Process_DelegateManage: Error, invalid opDataSize %u\n", opData.size); returnCode = TPM_BAD_PARAM_SIZE; } } /* c. Map F2 to a TPM_FAMILY_TABLE_ENTRY */ /* NOTE Done by TPM_FamilyTable_IsSpace() */ /* i. Set F2 -> tag to TPM_TAG_FAMILY_TABLE_ENTRY */ /* NOTE Done by TPM_FamilyTableEntry_Init() */ if (returnCode == TPM_SUCCESS) { /* ii. Set F2 -> familyLabel to opData */ familyRow->familyLabel = *(opData.buffer); /* d. Increment TPM_PERMANENT_DATA -> lastFamilyID by 1 */ tpm_state->tpm_permanent_data.lastFamilyID++; /* must write TPM_PERMANENT_DATA back to NVRAM, set this flag after NVRAM is written */ writeAllNV = TRUE; /* e. Set F2 -> familyID = TPM_PERMANENT_DATA -> lastFamilyID */ familyRow->familyID = tpm_state->tpm_permanent_data.lastFamilyID; /* f. Set F2 -> verificationCount = 1 */ familyRow->verificationCount = 1; /* g. Set F2 -> flags -> TPM_FAMFLAG_ENABLED to FALSE */ familyRow->flags &= ~TPM_FAMFLAG_ENABLED; /* h. Set F2 -> flags -> TPM_DELEGATE_ADMIN_LOCK to FALSE */ familyRow->flags &= ~TPM_DELEGATE_ADMIN_LOCK; /* i. Set retDataSize = 4 */ /* j. Set retData = F2 -> familyID */ printf("TPM_Process_DelegateManage: Created familyID %08x\n", familyRow->familyID); familyRow->valid = TRUE; returnCode = TPM_Sbuffer_Append32(&retData, familyRow->familyID); } /* k. Return TPM_SUCCESS */ } /* 6. If authHandle is of type DSAP then continueAuthSession MUST set to FALSE */ if ((returnCode == TPM_SUCCESS) && (opCode != TPM_FAMILY_CREATE) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { /* only if auth-1 */ if (auth_session_data->protocolID == TPM_PID_DSAP) { continueAuthSession = FALSE; } } /* 7. If opCode == TPM_FAMILY_ADMIN */ if ((returnCode == TPM_SUCCESS) && (opCode == TPM_FAMILY_ADMIN)) { printf("TPM_Process_DelegateManage: Processing TPM_FAMILY_ADMIN\n"); /* a. Validate that opDataSize == 1, and that opData is a Boolean value. */ if (returnCode == TPM_SUCCESS) { if (opData.size != sizeof(TPM_BOOL)) { printf("TPM_Process_DelegateManage: Error, invalid opDataSize %u\n", opData.size); returnCode = TPM_BAD_PARAM_SIZE; } } /* b. Set (FR -> flags -> TPM_DELEGATE_ADMIN_LOCK) = opData */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_DelegateManage: TPM_FAMILY_ADMIN opData %02x\n", opData.buffer[0]); if (*(TPM_BOOL *)(opData.buffer)) { familyRow->flags |= TPM_DELEGATE_ADMIN_LOCK; } else { familyRow->flags &= ~TPM_DELEGATE_ADMIN_LOCK; } printf("TPM_Process_DelegateManage: new TPM_FAMILY_TABLE_ENTRY.flags %08x\n", familyRow->flags); /* c. Set retDataSize = 0 */ /* NOTE Done by TPM_Sbuffer_Init() */ /* d. Return TPM_SUCCESS */ } if (returnCode == TPM_SUCCESS) { writeAllNV = TRUE; } } /* 8. else If opflag == TPM_FAMILY_ENABLE */ if ((returnCode == TPM_SUCCESS) && (opCode == TPM_FAMILY_ENABLE)) { printf("TPM_Process_DelegateManage: Processing TPM_FAMILY_ENABLE\n"); /* a. Validate that opDataSize == 1, and that opData is a Boolean value. */ if (returnCode == TPM_SUCCESS) { if (opData.size != sizeof(TPM_BOOL)) { printf("TPM_Process_DelegateManage: Error, invalid opDataSize %u\n", opData.size); returnCode = TPM_BAD_PARAM_SIZE; } } /* b. Set FR -> flags-> TPM_FAMFLAG_ENABLED = opData */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_DelegateManage: TPM_FAMILY_ENABLE opData %02x\n", opData.buffer[0]); if (*(TPM_BOOL *)(opData.buffer)) { familyRow->flags |= TPM_FAMFLAG_ENABLED; } else { familyRow->flags &= ~TPM_FAMFLAG_ENABLED; } printf("TPM_Process_DelegateManage: new TPM_FAMILY_TABLE_ENTRY.flags %08x\n", familyRow->flags); /* c. Set retDataSize = 0 */ /* NOTE Done by TPM_Sbuffer_Init() */ /* d. Return TPM_SUCCESS */ } if (returnCode == TPM_SUCCESS) { writeAllNV = TRUE; } } /* 9. else If opflag == TPM_FAMILY_INVALIDATE */ if ((returnCode == TPM_SUCCESS) && (opCode == TPM_FAMILY_INVALIDATE)) { printf("TPM_Process_DelegateManage: Processing TPM_FAMILY_INVALIDATE\n"); /* a. Invalidate all data associated with familyRow */ /* i. All data is all information pointed to by FR */ /* ii. return TPM_SELFTEST_FAILED on failure */ TPM_FamilyTableEntry_Delete(familyRow); /* b.The TPM MAY invalidate delegate rows that contain the same familyID. */ /* c. Set retDataSize = 0 */ /* NOTE Done by TPM_Sbuffer_Init() */ /* d. Return TPM_SUCCESS */ writeAllNV = TRUE; } /* 10. Else return TPM_BAD_PARAMETER */ if (returnCode == TPM_SUCCESS) { if ((opCode != TPM_FAMILY_CREATE) && (opCode != TPM_FAMILY_ADMIN) && (opCode != TPM_FAMILY_ENABLE) && (opCode != TPM_FAMILY_INVALIDATE)) { printf("TPM_Process_DelegateManage: Error, bad opCode %08x\n", opCode); returnCode = TPM_BAD_PARAMETER; } } /* if writing NV and this is a no owner NV write, update the count with the previously incremented value */ if (returnCode == TPM_SUCCESS) { if (writeAllNV && nv1Incremented) { printf("TPM_Process_DelegateManage: noOwnerNVWrite %u\n", nv1); tpm_state->tpm_permanent_data.noOwnerNVWrite = nv1; } } /* write back TPM_PERMANENT_DATA if required */ returnCode = TPM_PermanentAll_NVStore(tpm_state, writeAllNV, returnCode); /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_DelegateManage: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* append retDataSize and retData */ returnCode = TPM_Sbuffer_AppendAsSizedBuffer(response, &retData); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Set(response, savedAuth, /* saved HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ TPM_SizedBuffer_Delete(&opData); /* @1 */ TPM_Sbuffer_Delete(&retData); /* @2 */ return rcf; } /* 19.2 TPM_Delegate_CreateKeyDelegation rev 109 This command delegates privilege to use a key by creating a blob that can be used by TPM_DSAP. There is no check for appropriateness of the key's key usage against the key permission settings. If the key usage is incorrect, this command succeeds, but the delegated command will fail. These blobs CANNOT be used as input data for TPM_LoadOwnerDelegation because the internal TPM delegate table can store owner delegations only. (TPM_Delegate_CreateOwnerDelegation must be used to delegate Owner privilege.) The use restrictions that may be present on the key pointed to by keyHandle are not enforced for this command. Stated another way CreateKeyDelegation is not a use of the key. The publicInfo -> familyID can specify a disabled family row. The family row is checked when the key delegation is used in a DSAP session, not when it is created. */ TPM_RESULT TPM_Process_DelegateCreateKeyDelegation(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_KEY_HANDLE keyHandle; /* The keyHandle identifier of a loaded key. */ TPM_DELEGATE_PUBLIC publicInfo; /* The public information necessary to fill in the blob */ TPM_ENCAUTH delAuth; /* The encrypted new AuthData for the blob. The encryption key is the shared secret from the authorization session protocol.*/ TPM_AUTHHANDLE authHandle; /* The authorization session handle used for keyHandle authorization */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* Ignored */ TPM_AUTHDATA privAuth; /* The authorization session digest that authorizes the use of keyHandle. HMAC key: key.usageAuth */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ TPM_SECRET *hmacKey; TPM_BOOL parentPCRStatus; TPM_KEY *key = NULL; /* the key specified by keyHandle */ TPM_SECRET *keyUsageAuth; TPM_DELEGATE_PUBLIC *delegatePublic; /* from DSAP session */ TPM_FAMILY_TABLE_ENTRY *familyRow; /* family table row containing familyID */ TPM_DIGEST a1Auth; TPM_DELEGATE_SENSITIVE m1DelegateSensitive; TPM_STORE_BUFFER delegateSensitive_sbuffer; TPM_DELEGATE_KEY_BLOB p1DelegateKeyBlob; /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_STORE_BUFFER blobSbuffer; /* The partially encrypted delegation information. */ printf("TPM_Process_DelegateCreateKeyDelegation: Ordinal Entry\n"); TPM_DelegatePublic_Init(&publicInfo); /* freed @1 */ TPM_DelegateSensitive_Init(&m1DelegateSensitive); /* freed @2 */ TPM_Sbuffer_Init(&delegateSensitive_sbuffer); /* freed @3 */ TPM_DelegateKeyBlob_Init(&p1DelegateKeyBlob); /* freed @4 */ TPM_Sbuffer_Init(&blobSbuffer); /* freed @5 */ /* get inputs */ /* get keyHandle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&keyHandle, &command, ¶mSize); } /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get publicInfo parameter */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_DelegateCreateKeyDelegation: keyHandle %08x\n", keyHandle); returnCode = TPM_DelegatePublic_Load(&publicInfo, &command, ¶mSize); } /* get delAuth parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Authdata_Load(delAuth, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag1(tag); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, privAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_DelegateCreateKeyDelegation: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* 1. Verify AuthData for the command and parameters using privAuth */ /* get the key corresponding to the keyHandle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyHandleEntries_GetKey(&key, &parentPCRStatus, tpm_state, keyHandle, FALSE, /* not read-only */ FALSE, /* do not ignore PCRs */ FALSE); /* cannot use EK */ } /* get keyHandle -> usageAuth */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Key_GetUsageAuth(&keyUsageAuth, key); } /* get the session data */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_OSAP, TPM_ET_KEYHANDLE, ordinal, key, NULL, /* OIAP */ key->tpm_store_asymkey->pubDataDigest); /* OSAP */ } /* Validate the authorization */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, privAuth); /* Authorization digest for input */ } /* 2. Locate publicInfo -> familyID in the TPM_FAMILY_TABLE and set familyRow to indicate row, return TPM_BADINDEX if not found */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_FamilyTable_GetEntry(&familyRow, &(tpm_state->tpm_permanent_data.familyTable), publicInfo.familyID); } /* 3. If the key authentication is in fact a delegation, then the TPM SHALL validate the command and parameters using Delegation authorisation, then */ if ((returnCode == TPM_SUCCESS) && (auth_session_data->protocolID == TPM_PID_DSAP)) { printf("TPM_Process_DelegateCreateKeyDelegation: Authentication is a delegation\n"); /* get the TPM_DELEGATE_PUBLIC from the DSAP session */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessionData_GetDelegatePublic(&delegatePublic, auth_session_data); } /* a. Validate that authHandle -> familyID equals publicInfo -> familyID return TPM_DELEGATE_FAMILY on error */ if (returnCode == TPM_SUCCESS) { if (publicInfo.familyID != delegatePublic->familyID) { printf("TPM_Process_DelegateCreateKeyDelegation: Error, " "familyID %u should be %u\n", publicInfo.familyID, delegatePublic->familyID); returnCode = TPM_DELEGATE_FAMILY; } } /* b. If TPM_FAMILY_TABLE.famTableRow[ authHandle -> familyID] -> flags -> TPM_FAMFLAG_ENABLED is FALSE, return error TPM_DISABLED_CMD. */ if (returnCode == TPM_SUCCESS) { if (!(familyRow->flags & TPM_FAMFLAG_ENABLED)) { printf("TPM_Process_DelegateCreateKeyDelegation: Error, family %u disabled\n", publicInfo.familyID); returnCode = TPM_DISABLED_CMD; } } /* c. Verify that the delegation bits in publicInfo do not grant more permissions then currently delegated. Otherwise return error TPM_AUTHFAIL */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Delegations_CheckPermissionDelegation(&(publicInfo.permissions), &(delegatePublic->permissions)); } } /* 4. Check that publicInfo -> delegateType is TPM_DEL_KEY_BITS */ if (returnCode == TPM_SUCCESS) { if (publicInfo.permissions.delegateType != TPM_DEL_KEY_BITS) { printf("TPM_Process_DelegateCreateKeyDelegation: Error, " "delegateType %08x not a key delegation\n", publicInfo.permissions.delegateType); returnCode = TPM_BAD_PARAMETER; } } /* 5. Verify that authHandle indicates an OSAP or DSAP session return TPM_INVALID_AUTHHANDLE on error */ /* NOTE Done by TPM_AuthSessions_GetData() */ /* 6. Create a1 by decrypting delAuth according to the ADIP indicated by authHandle. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessionData_Decrypt(a1Auth, NULL, delAuth, auth_session_data, NULL, NULL, FALSE); /* even and odd */ } /* 7. Create h1 the SHA-1 of TPM_STORE_PUBKEY structure of the key pointed to by keyHandle */ if (returnCode == TPM_SUCCESS) { TPM_PrintFour("TPM_Process_DelegateCreateKeyDelegation: Decrypted a1", a1Auth); returnCode = TPM_SHA1_GenerateStructure(p1DelegateKeyBlob.pubKeyDigest, &(key->pubKey), (TPM_STORE_FUNCTION_T)TPM_SizedBuffer_Store); } /* 8. Create M1 a TPM_DELEGATE_SENSITIVE structure */ /* a. Set M1 -> tag to TPM_TAG_DELEGATE_SENSITIVE */ /* NOTE Done by TPM_DelegateSensitive_Init() */ /* b. Set M1 -> authValue to a1 */ if (returnCode == TPM_SUCCESS) { TPM_Secret_Copy(m1DelegateSensitive.authValue, a1Auth); /* c. The TPM MAY add additional information of a sensitive nature relative to the delegation */ /* 9. Create M2 the encryption of M1 using TPM_DELEGATE_KEY */ /* serialize M1 */ returnCode = TPM_DelegateSensitive_Store(&delegateSensitive_sbuffer, &m1DelegateSensitive); } /* encrypt with delegate key */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_DelegateCreateKeyDelegation: Encrypting TPM_DELEGATE_SENSITIVE\n"); returnCode = TPM_SymmetricKeyData_EncryptSbuffer(&(p1DelegateKeyBlob.sensitiveArea), &delegateSensitive_sbuffer, tpm_state->tpm_permanent_data.delegateKey); } /* 10. Create P1 a TPM_DELEGATE_KEY_BLOB */ /* a. Set P1 -> tag to TPM_TAG_DELG_KEY_BLOB */ /* NOTE Done by TPM_DelegateKeyBlob_Init() */ /* b. Set P1 -> pubKeyDigest to H1 */ /* NOTE Done by TPM_StorePubkey_GenerateDigest() */ /* c. Set P1 -> pub to PublicInfo */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_DelegatePublic_Copy(&(p1DelegateKeyBlob.pub), &publicInfo); } /* d. Set P1 -> pub -> verificationCount to familyRow -> verificationCount */ if (returnCode == TPM_SUCCESS) { p1DelegateKeyBlob.pub.verificationCount = familyRow->verificationCount; /* e. Set P1 -> integrityDigest to NULL */ /* NOTE Done by TPM_DelegateKeyBlob_Init() */ /* f. The TPM sets additionalArea and additionalAreaSize appropriate for this TPM. The information MAY include symmetric IV, symmetric mode of encryption and other data that allows the TPM to process the blob in the future. */ /* g. Set P1 -> sensitiveSize to the size of M2 */ /* h. Set P1 -> sensitiveArea to M2 */ /* NOTE Encrypted directly into p1DelegateKeyBlob.sensitiveArea */ /* 11. Calculate H2 the HMAC of P1 using tpmProof as the secret */ /* 12. Set P1 -> integrityDigest to H2 */ /* NOTE It is safe to HMAC directly into TPM_DELEGATE_KEY_BLOB, since the structure is serialized before the HMAC is performed */ returnCode = TPM_HMAC_GenerateStructure (p1DelegateKeyBlob.integrityDigest, /* HMAC */ tpm_state->tpm_permanent_data.tpmProof, /* HMAC key */ &p1DelegateKeyBlob, /* structure */ (TPM_STORE_FUNCTION_T)TPM_DelegateKeyBlob_Store); /* store function */ } /* 13. Ignore continueAuthSession on input set continueAuthSession to FALSE on output */ if (returnCode == TPM_SUCCESS) { continueAuthSession = FALSE; } /* 14. Return P1 as blob */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_DelegateKeyBlob_Store(&blobSbuffer, &p1DelegateKeyBlob); } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_DelegateCreateKeyDelegation: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* return blobSize and blob */ returnCode = TPM_Sbuffer_AppendAsSizedBuffer(response, &blobSbuffer); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ TPM_DelegatePublic_Delete(&publicInfo); /* @1 */ TPM_DelegateSensitive_Delete(&m1DelegateSensitive); /* @2 */ TPM_Sbuffer_Delete(&delegateSensitive_sbuffer); /* @3 */ TPM_DelegateKeyBlob_Delete(&p1DelegateKeyBlob); /* @4 */ TPM_Sbuffer_Delete(&blobSbuffer); /* @5 */ return rcf; } /* 19.3 TPM_Delegate_CreateOwnerDelegation rev 98 TPM_Delegate_CreateOwnerDelegation delegates the Owner's privilege to use a set of command ordinals, by creating a blob. Such blobs can be used as input data for TPM_DSAP or TPM_Delegate_LoadOwnerDelegation. TPM_Delegate_CreateOwnerDelegation includes the ability to void all existing delegations (by incrementing the verification count) before creating the new delegation. This ensures that the new delegation will be the only delegation that can operate at Owner privilege in this family. This new delegation could be used to enable a security monitor (a local separate entity, or remote separate entity, or local host entity) to reinitialize a family and perhaps perform external verification of delegation settings. Normally the ordinals for a delegated security monitor would include TPM_Delegate_CreateOwnerDelegation (this command) in order to permit the monitor to create further delegations, and TPM_Delegate_UpdateVerification to reactivate some previously voided delegations. If the verification count is incremented and the new delegation does not delegate any privileges (to any ordinals) at all, or uses an authorisation value that is then discarded, this family's delegations are all void and delegation must be managed using actual Owner authorisation. (TPM_Delegate_CreateKeyDelegation must be used to delegate privilege to use a key.) */ TPM_RESULT TPM_Process_DelegateCreateOwnerDelegation(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_BOOL increment; /* Flag dictates whether verificationCount will be incremented */ TPM_DELEGATE_PUBLIC publicInfo; /* The public parameters for the blob */ TPM_ENCAUTH delAuth; /* The encrypted new AuthData for the blob. The encryption key is the shared secret from the OSAP protocol.*/ TPM_AUTHHANDLE authHandle; /* The authorization session handle TPM Owner authentication */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* Ignored */ TPM_AUTHDATA ownerAuth; /* The authorization session digest. HMAC key:ownerAuth */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus = FALSE; /* audit the ordinal */ TPM_BOOL transportEncrypt = FALSE; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ TPM_SECRET *hmacKey; TPM_SECRET savedAuth; /* saved copy for response */ TPM_FAMILY_TABLE_ENTRY *familyRow; /* family table row containing familyID */ TPM_DELEGATE_PUBLIC *delegatePublic; /* from DSAP session */ TPM_BOOL writeAllNV = FALSE; TPM_DIGEST a1Auth; TPM_DELEGATE_SENSITIVE m1DelegateSensitive; TPM_STORE_BUFFER delegateSensitive_sbuffer; /* serialization of delegateSensitive */ TPM_DELEGATE_OWNER_BLOB b1DelegateOwnerBlob; /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_STORE_BUFFER blobSbuffer; /* The partially encrypted delegation information. */ printf("TPM_Process_DelegateCreateOwnerDelegation: Ordinal Entry\n"); TPM_DelegatePublic_Init(&publicInfo); /* freed @1 */ TPM_DelegateSensitive_Init(&m1DelegateSensitive); /* freed @2 */ TPM_Sbuffer_Init(&delegateSensitive_sbuffer); /* freed @3 */ TPM_DelegateOwnerBlob_Init(&b1DelegateOwnerBlob); /* freed @4 */ TPM_Sbuffer_Init(&blobSbuffer); /* freed @5 */ /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get increment parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_LoadBool(&increment, &command, ¶mSize); } /* get publicInfo parameter */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_DelegateCreateOwnerDelegation: increment %02x\n", increment); returnCode = TPM_DelegatePublic_Load(&publicInfo, &command, ¶mSize); } /* get delAuth parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Authdata_Load(delAuth, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag1(tag); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, ownerAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_DelegateCreateOwnerDelegation: Error, " "command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* 1. The TPM SHALL authenticate the command using TPM Owner authentication. Return TPM_AUTHFAIL on failure. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_OSAP, TPM_ET_OWNER, ordinal, NULL, NULL, /* OIAP */ tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ } if (returnCode == TPM_SUCCESS) { /* make a copy of the HMAC key for the response, since it MAY be invalidated */ TPM_Secret_Copy(savedAuth, *hmacKey); returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* owner HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, ownerAuth); /* Authorization digest for input */ } /* 2. Locate publicInfo -> familyID in the TPM_FAMILY_TABLE and set familyRow to indicate the row return TPM_BADINDEX if not found */ /* a. Set FR to TPM_FAMILY_TABLE.famTableRow[familyRow] */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_FamilyTable_GetEntry(&familyRow, &(tpm_state->tpm_permanent_data.familyTable), publicInfo.familyID); } /* 3. If the TPM Owner authentication is in fact a delegation, then the TPM SHALL validate the command and parameters using Delegation authorisation, then */ if ((returnCode == TPM_SUCCESS) && (auth_session_data->protocolID == TPM_PID_DSAP)) { /* get the TPM_DELEGATE_PUBLIC from the DSAP session */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessionData_GetDelegatePublic(&delegatePublic, auth_session_data); } /* a. Validate that authHandle -> familyID equals publicInfo -> familyID return TPM_DELEGATE_FAMILY */ if (returnCode == TPM_SUCCESS) { if (publicInfo.familyID != delegatePublic->familyID) { printf("TPM_Process_DelegateCreateOwnerDelegation: Error, " "familyID %u should be %u\n", publicInfo.familyID, delegatePublic->familyID); returnCode = TPM_DELEGATE_FAMILY; } } /* b. If FR -> flags -> TPM_FAMFLAG_ENABLED is FALSE, return error TPM_DISABLED_CMD. */ if (returnCode == TPM_SUCCESS) { if (!(familyRow->flags & TPM_FAMFLAG_ENABLED)) { printf("TPM_Process_DelegateCreateOwnerDelegation: Error, family %u disabled\n", publicInfo.familyID); returnCode = TPM_DISABLED_CMD; } } /* c. Verify that the delegation bits in publicInfo do not grant more permissions then currently delegated. Otherwise return error TPM_AUTHFAIL */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Delegations_CheckPermissionDelegation(&(publicInfo.permissions), &(delegatePublic->permissions)); } } /* 4. Check that publicInfo -> delegateType is TPM_DEL_OWNER_BITS */ if (returnCode == TPM_SUCCESS) { if (publicInfo.permissions.delegateType != TPM_DEL_OWNER_BITS) { printf("TPM_Process_DelegateCreateOwnerDelegation: Error, bad delegateType %08x\n", publicInfo.permissions.delegateType); returnCode = TPM_BAD_PARAMETER; } } /* 5. Verify that authHandle indicates an OSAP or DSAP session return TPM_INVALID_AUTHHANDLE on error */ /* NOTE Done by TPM_AuthSessions_GetData() */ /* 7. Create a1 by decrypting delAuth according to the ADIP indicated by authHandle */ /* NOTE 7. moved before 6. because it needs the session data */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessionData_Decrypt(a1Auth, NULL, delAuth, auth_session_data, NULL, NULL, FALSE); /* even and odd */ } /* 6. If increment == TRUE */ if ((returnCode == TPM_SUCCESS) && increment) { /* a. Increment FR -> verificationCount */ familyRow->verificationCount++; writeAllNV = TRUE; /* b. Set TPM_STCLEAR_DATA -> ownerReference to TPM_KH_OWNER */ tpm_state->tpm_stclear_data.ownerReference = TPM_KH_OWNER; /* c. The TPM invalidates sessions */ /* i. MUST invalidate all DSAP sessions */ /* ii. MUST invalidate all OSAP sessions associated with the delegation table */ /* iii. MAY invalidate any other session */ TPM_AuthSessions_TerminatexSAP(&continueAuthSession, authHandle, tpm_state->tpm_stclear_data.authSessions); } /* 8. Create M1 a TPM_DELEGATE_SENSITIVE structure */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_DelegateCreateOwnerDelegation: Creating TPM_DELEGATE_SENSITIVE\n"); /* a. Set M1 -> tag to TPM_TAG_DELEGATE_SENSITIVE */ /* NOTE Done by TPM_DelegateSensitive_Init() */ /* b. Set M1 -> authValue to a1 */ TPM_Secret_Copy(m1DelegateSensitive.authValue, a1Auth); /* c. Set other M1 fields as determined by the TPM vendor */ } /* 9. Create M2 the encryption of M1 using TPM_DELEGATE_KEY */ /* serialize M1 */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_DelegateSensitive_Store(&delegateSensitive_sbuffer, &m1DelegateSensitive); } /* encrypt with delegate key */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_DelegateCreateOwnerDelegation: Encrypting TPM_DELEGATE_SENSITIVE\n"); returnCode = TPM_SymmetricKeyData_EncryptSbuffer(&(b1DelegateOwnerBlob.sensitiveArea), &delegateSensitive_sbuffer, tpm_state->tpm_permanent_data.delegateKey); } /* 10. Create B1 a TPM_DELEGATE_OWNER_BLOB */ /* a. Set B1 -> tag to TPM_TAG_DELG_OWNER_BLOB */ /* NOTE Done by TPM_DelegateOwnerBlob_Init() */ /* b. Set B1 -> pub to publicInfo */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_DelegateCreateOwnerDelegation: Creating TPM_DELEGATE_OWNER_BLOB\n"); returnCode = TPM_DelegatePublic_Copy(&(b1DelegateOwnerBlob.pub), &publicInfo); } /* c. Set B1 -> sensitiveSize to the size of M2 */ /* d. Set B1 -> sensitiveArea to M2 */ /* NOTE Encrypted directly into b1DelegateOwnerBlob */ /* e. Set B1 -> integrityDigest to NULL */ /* NOTE Done by TPM_DelegateOwnerBlob_Init() */ if (returnCode == TPM_SUCCESS) { /* f. Set B1 pub -> verificationCount to FR -> verificationCount */ b1DelegateOwnerBlob.pub.verificationCount = familyRow->verificationCount; /* 11. The TPM sets additionalArea and additionalAreaSize appropriate for this TPM. The information MAY include symmetric IV, symmetric mode of encryption and other data that allows the TPM to process the blob in the future. */ /* 12. Create H1 the HMAC of B1 using tpmProof as the secret */ /* 13. Set B1 -> integrityDigest to H1 */ /* NOTE It is safe to HMAC directly into TPM_DELEGATE_OWNER_BLOB, since the structure is serialized before the HMAC is performed */ returnCode = TPM_HMAC_GenerateStructure (b1DelegateOwnerBlob.integrityDigest, /* HMAC */ tpm_state->tpm_permanent_data.tpmProof, /* HMAC key */ &b1DelegateOwnerBlob, /* structure */ (TPM_STORE_FUNCTION_T)TPM_DelegateOwnerBlob_Store); /* store function */ } /* 14. Ignore continueAuthSession on input set continueAuthSession to FALSE on output */ if (returnCode == TPM_SUCCESS) { continueAuthSession = FALSE; } /* 15. Return B1 as blob */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_DelegateOwnerBlob_Store(&blobSbuffer, &b1DelegateOwnerBlob); } /* write back TPM_PERMANENT_DATA if required */ returnCode = TPM_PermanentAll_NVStore(tpm_state, writeAllNV, returnCode); /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_DelegateCreateOwnerDelegation: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* return blobSize and blob */ returnCode = TPM_Sbuffer_AppendAsSizedBuffer(response, &blobSbuffer); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Set(response, savedAuth, /* saved HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ TPM_DelegatePublic_Delete(&publicInfo); /* @1 */ TPM_DelegateSensitive_Delete(&m1DelegateSensitive); /* @2 */ TPM_Sbuffer_Delete(&delegateSensitive_sbuffer); /* @3 */ TPM_DelegateOwnerBlob_Delete(&b1DelegateOwnerBlob); /* @4 */ TPM_Sbuffer_Delete(&blobSbuffer); /* @5 */ return rcf; } /* 19.4 TPM_Delegate_LoadOwnerDelegation rev 109 This command loads a delegate table row blob into a non-volatile delegate table row. Delegate_LoadOwnerDelegation can be used during manufacturing or on first boot (when no Owner is installed), or after an Owner is installed. If an Owner is installed, Delegate_LoadOwnerDelegation requires Owner authorisation, and sensitive information must be encrypted. Burn-out of TPM non-volatile storage by inappropriate use is mitigated by the TPM's normal limits on NV- writes in the absence of an Owner. Tables can be locked after loading using TPM_Delegate_Manage, to prevent subsequent tampering. A management system outside the TPM is expected to manage the delegate table rows stored on the TPM, and can overwrite any previously stored data. There is no way to explicitly delete a delegation entry. A new entry can overwrite an invalid entry. This command cannot be used to load key delegation blobs into the TPM */ TPM_RESULT TPM_Process_DelegateLoadOwnerDelegation(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_DELEGATE_INDEX index; /* The index of the delegate row to be written */ uint32_t blobSize; /* The size of the delegate blob */ TPM_DELEGATE_OWNER_BLOB d1Blob; /* Delegation information, including encrypted portions as appropriate */ TPM_AUTHHANDLE authHandle; /* The authorization session handle TPM Owner authentication */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization session handle */ TPM_AUTHDATA ownerAuth; /* The authorization session digest. HMAC key:ownerAuth */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus = FALSE; /* audit the ordinal */ TPM_BOOL transportEncrypt = FALSE; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ TPM_SECRET *hmacKey; TPM_SECRET savedAuth; /* saved copy for response */ TPM_DELEGATE_PUBLIC *delegatePublic; /* from DSAP session */ TPM_FAMILY_TABLE_ENTRY *familyRow; /* family table row containing familyID */ TPM_DELEGATE_SENSITIVE s1DelegateSensitive; TPM_DELEGATE_TABLE_ROW *delegateTableRow; unsigned char *stream; uint32_t stream_size; uint32_t nv1 = tpm_state->tpm_permanent_data.noOwnerNVWrite; /* temp for noOwnerNVWrite, initialize to silence compiler */ TPM_BOOL nv1Incremented = FALSE; /* flag that nv1 was incremented */ TPM_BOOL writeAllNV = FALSE; /* flag to write back data */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_DelegateLoadOwnerDelegation: Ordinal Entry\n"); TPM_DelegateOwnerBlob_Init(&d1Blob); /* freed @1 */ TPM_DelegateSensitive_Init(&s1DelegateSensitive); /* freed @2 */ /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get index parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&index, &command, ¶mSize); } /* get blobSize parameter */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_DelegateLoadOwnerDelegation: index %u\n", index); returnCode = TPM_Load32(&blobSize, &command, ¶mSize); } /* get blob parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_DelegateOwnerBlob_Load(&d1Blob, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag10(tag); } /* get the optional 'below the line' authorization parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, ownerAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_DelegateLoadOwnerDelegation: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* 1. Map blob to D1 a TPM_DELEGATE_OWNER_BLOB. */ /* a. Validate that D1 -> tag == TPM_TAG_DELEGATE_OWNER_BLOB */ /* Done by TPM_DelegateOwnerBlob_Load() */ /* 2. Locate D1 -> pub -> familyID in the TPM_FAMILY_TABLE and set familyRow to indicate row, return TPM_BADINDEX if not found */ /* 3. Set FR to TPM_FAMILY_TABLE -> famTableRow[familyRow] */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_FamilyTable_GetEnabledEntry(&familyRow, &(tpm_state->tpm_permanent_data.familyTable), d1Blob.pub.familyID); } /* 4. If TPM Owner is installed */ if ((returnCode == TPM_SUCCESS) && tpm_state->tpm_permanent_data.ownerInstalled) { /* a. Validate the command and parameters using TPM Owner authorization, return TPM_AUTHFAIL on error */ if (returnCode == TPM_SUCCESS) { if (tag != TPM_TAG_RQU_AUTH1_COMMAND) { printf("TPM_Process_DelegateLoadOwnerDelegation: Error, " "owner installed but no authorization\n"); returnCode = TPM_AUTHFAIL; } } if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_OWNER, ordinal, NULL, &(tpm_state->tpm_permanent_data.ownerAuth),/* OIAP */ tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ } if (returnCode == TPM_SUCCESS) { /* make a copy of the HMAC key for the response, since it MAY be invalidated */ TPM_Secret_Copy(savedAuth, *hmacKey); returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* owner HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, ownerAuth); /* Authorization digest for input */ } /* b. If the command is delegated (authHandle session type is TPM_PID_DSAP or through ownerReference delegation), verify that D1 -> pub -> familyID matches authHandle -> familyID, on error return TPM_DELEGATE_FAMILY */ if ((returnCode == TPM_SUCCESS) && ((auth_session_data->protocolID == TPM_PID_DSAP) || (tpm_state->tpm_stclear_data.ownerReference != TPM_KH_OWNER))) { /* get the TPM_DELEGATE_PUBLIC from the DSAP session */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessionData_GetDelegatePublic(&delegatePublic, auth_session_data); } if (returnCode == TPM_SUCCESS) { if (d1Blob.pub.familyID != delegatePublic->familyID) { printf("TPM_Process_DelegateLoadOwnerDelegation: Error, " "familyID %u should be %u\n", d1Blob.pub.familyID, delegatePublic->familyID); returnCode = TPM_DELEGATE_FAMILY; } } } } /* 5. Else */ if ((returnCode == TPM_SUCCESS) && !tpm_state->tpm_permanent_data.ownerInstalled) { /* a. If FR -> flags -> TPM_DELEGATE_ADMIN_LOCK is TRUE return TPM_DELEGATE_LOCK */ if (returnCode == TPM_SUCCESS) { if (familyRow->flags & TPM_DELEGATE_ADMIN_LOCK) { printf("TPM_Process_DelegateLoadOwnerDelegation: Error, row locked\n"); returnCode = TPM_DELEGATE_LOCK; } } /* b. Validate max NV writes without an owner */ if (returnCode == TPM_SUCCESS) { /* i. Set NV1 to PD -> noOwnerNVWrite */ nv1 = tpm_state->tpm_permanent_data.noOwnerNVWrite; /* ii. Increment NV1 by 1 */ nv1++; /* iii. If NV1 > TPM_MAX_NV_WRITE_NOOWNER return TPM_MAXNVWRITES */ if (nv1 > TPM_MAX_NV_WRITE_NOOWNER) { printf("TPM_Process_DelegateLoadOwnerDelegation: Error, " "max NV writes %d w/o owner reached\n", tpm_state->tpm_permanent_data.noOwnerNVWrite); returnCode = TPM_MAXNVWRITES; } } /* iv. Set PD -> noOwnerNVWrite to NV1 */ if (returnCode == TPM_SUCCESS) { /* NOTE Don't update the noOwnerNVWrite value until determining that the write will be performed */ nv1Incremented = TRUE; } } /* 6. If FR -> flags -> TPM_FAMFLAG_ENABLED is FALSE, return TPM_DISABLED_CMD */ /* NOTE Done by TPM_FamilyTable_GetEnabledEntry() */ /* 7. If TPM Owner is installed, validate the integrity of the blob */ if ((returnCode == TPM_SUCCESS) && tpm_state->tpm_permanent_data.ownerInstalled) { printf("TPM_Process_DelegateLoadOwnerDelegation: Checking integrityDigest\n"); /* a. Copy D1 -> integrityDigest to H2 */ /* b. Set D1 -> integrityDigest to NULL */ /* c. Create H3 the HMAC of D1 using tpmProof as the secret */ /* d. Compare H2 to H3, return TPM_AUTHFAIL on mismatch */ returnCode = TPM_HMAC_CheckStructure (tpm_state->tpm_permanent_data.tpmProof, /* key */ &d1Blob, /* structure */ d1Blob.integrityDigest, /* expected */ (TPM_STORE_FUNCTION_T)TPM_DelegateOwnerBlob_Store, /* store function */ TPM_AUTHFAIL); /* error code */ } /* 8. If TPM Owner is installed, create S1 a TPM_DELEGATE_SENSITIVE area by decrypting D1 -> sensitiveArea using TPM_DELEGATE_KEY. */ if ((returnCode == TPM_SUCCESS) && tpm_state->tpm_permanent_data.ownerInstalled) { if (returnCode == TPM_SUCCESS) { printf("TPM_Process_DelegateLoadOwnerDelegation: Decrypting sensitiveArea\n"); returnCode = TPM_DelegateSensitive_DecryptEncData(&s1DelegateSensitive, /* decrypted data */ &(d1Blob.sensitiveArea), /* encrypted */ tpm_state->tpm_permanent_data.delegateKey); } } /* 8. Otherwise set S1 = D1 -> sensitiveArea */ if ((returnCode == TPM_SUCCESS) && !tpm_state->tpm_permanent_data.ownerInstalled) { stream = d1Blob.sensitiveArea.buffer; stream_size = d1Blob.sensitiveArea.size; returnCode = TPM_DelegateSensitive_Load(&s1DelegateSensitive, &stream, &stream_size); } /* 9. Validate S1 */ /* a. Validate that S1 -> tag == TPM_TAG_DELEGATE_SENSITIVE, return TPM_INVALID_STRUCTURE on error */ /* NOTE Done by TPM_DelegateSensitive_Load() */ /* 10. Validate that index is a valid value for delegateTable, return TPM_BADINDEX on error */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_DelegateTable_GetRow(&delegateTableRow, &(tpm_state->tpm_permanent_data.delegateTable), index); } /* 11. The TPM invalidates sessions */ if (returnCode == TPM_SUCCESS) { /* a. MUST invalidate all DSAP sessions */ /* b. MUST invalidate all OSAP sessions associated with the delegation table */ /* c. MAY invalidate any other session */ TPM_AuthSessions_TerminatexSAP(&continueAuthSession, authHandle, tpm_state->tpm_stclear_data.authSessions); } /* 12. Copy data to the delegate table row */ if (returnCode == TPM_SUCCESS) { /* a. Copy the TPM_DELEGATE_PUBLIC from D1 -> pub to TPM_DELEGATE_TABLE -> delRow[index] -> pub. */ returnCode = TPM_DelegatePublic_Copy(&delegateTableRow->pub, &(d1Blob.pub)); writeAllNV = TRUE; } if (returnCode == TPM_SUCCESS) { delegateTableRow->valid = TRUE; /* b. Copy the TPM_SECRET from S1 -> authValue to TPM_DELEGATE_TABLE -> delRow[index] -> authValue. */ TPM_Secret_Copy(delegateTableRow->authValue, s1DelegateSensitive.authValue); /* c. Set TPM_STCLEAR_DATA-> ownerReference to TPM_KH_OWNER */ tpm_state->tpm_stclear_data.ownerReference = TPM_KH_OWNER; } if ((returnCode == TPM_SUCCESS) && tpm_state->tpm_permanent_data.ownerInstalled) { /* d. If authHandle is of type DSAP then continueAuthSession MUST set to FALSE */ if (auth_session_data->protocolID == TPM_PID_DSAP) { continueAuthSession = FALSE; } } /* if writing NV and this is a no owner NV write, update the count with the previously incremented value */ if (returnCode == TPM_SUCCESS) { if (writeAllNV && nv1Incremented) { printf("TPM_Process_DelegateLoadOwnerDelegation: noOwnerNVWrite %u\n", nv1); tpm_state->tpm_permanent_data.noOwnerNVWrite = nv1; } } /* write back TPM_PERMANENT_DATA */ returnCode = TPM_PermanentAll_NVStore(tpm_state, writeAllNV, returnCode); /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_DelegateLoadOwnerDelegation: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Set(response, savedAuth, /* saved HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ TPM_DelegateOwnerBlob_Delete(&d1Blob); /* @1 */ TPM_DelegateSensitive_Delete(&s1DelegateSensitive); /* @2 */ return rcf; } /* 19.5 TPM_Delegate_ReadTable rev 87 This command is used to read from the TPM the public contents of the family and delegate tables that are stored on the TPM. Such data is required during external verification of tables. There are no restrictions on the execution of this command; anyone can read this information regardless of the state of the PCRs, regardless of whether they know any specific AuthData value and regardless of whether or not the enable and admin bits are set one way or the other. */ TPM_RESULT TPM_Process_DelegateReadTable(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_STORE_BUFFER familySbuffer; /* Array of TPM_FAMILY_TABLE_ENTRY elements */ TPM_STORE_BUFFER delegateSbuffer; /* Array of TPM_DELEGATE_INDEX and TPM_DELEGATE_PUBLIC elements */ printf("TPM_Process_DelegateReadTable: Ordinal Entry\n"); TPM_Sbuffer_Init(&familySbuffer); /* freed @1 */ TPM_Sbuffer_Init(&delegateSbuffer); /* freed @2 */ /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_DelegateReadTable: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ /* 1. Set familyTableSize to the number of valid families on the TPM times sizeof(TPM_FAMILY_TABLE_ELEMENT). */ /* NOTE Done below by TPM_Sbuffer_AppendAsSizedBuffer() */ /* 2. Copy the valid entries in the internal family table to the output array familyTable */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_FamilyTable_StoreValid(&familySbuffer, &(tpm_state->tpm_permanent_data.familyTable), TRUE); /* standard, store the tag */ } /* 3. Set delegateTableSize to the number of valid delegate table entries on the TPM times (sizeof(TPM_DELEGATE_PUBLIC) + 4). */ /* NOTE Done below by TPM_Sbuffer_AppendAsSizedBuffer() */ /* 4. For each valid entry */ /* a. Write the TPM_DELEGATE_INDEX to delegateTable */ /* b. Copy the TPM_DELEGATE_PUBLIC to delegateTable */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_DelegateTable_StoreValid(&delegateSbuffer, &(tpm_state->tpm_permanent_data.delegateTable)); } /* 5. Return TPM_SUCCESS */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_DelegateReadTable: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* append familyTableSize and familyTable */ returnCode = TPM_Sbuffer_AppendAsSizedBuffer(response, &familySbuffer); } if (returnCode == TPM_SUCCESS) { /* append delegateTableSize and delegateTable */ returnCode = TPM_Sbuffer_AppendAsSizedBuffer(response, &delegateSbuffer); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* cleanup */ TPM_Sbuffer_Delete(&familySbuffer); /* @1 */ TPM_Sbuffer_Delete(&delegateSbuffer); /* @2 */ return rcf; } /* 19.6 TPM_Delegate_UpdateVerification rev 87 UpdateVerification sets the verificationCount in an entity (a blob or a delegation row) to the current family value, in order that the delegations represented by that entity will continue to be accepted by the TPM. */ TPM_RESULT TPM_Process_DelegateUpdateVerification(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_SIZED_BUFFER inputData; /* TPM_DELEGATE_KEY_BLOB or TPM_DELEGATE_OWNER_BLOB or TPM_DELEGATE_INDEX */ TPM_AUTHHANDLE authHandle; /* The authorization session handle used for owner authentication. */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization session handle */ TPM_AUTHDATA ownerAuth; /* Authorization HMAC key: ownerAuth. */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus = FALSE; /* audit the ordinal */ TPM_BOOL transportEncrypt = FALSE; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ TPM_SECRET *hmacKey = NULL; unsigned char *stream; /* temp input stream */ uint32_t stream_size; TPM_STRUCTURE_TAG d1Tag; /* input structure tag */ TPM_DELEGATE_INDEX d1DelegateIndex; TPM_DELEGATE_OWNER_BLOB d1DelegateOwnerBlob; TPM_DELEGATE_KEY_BLOB d1DelegateKeyBlob; TPM_DELEGATE_TABLE_ROW *d1DelegateTableRow = NULL; TPM_FAMILY_ID familyID = 0; TPM_FAMILY_TABLE_ENTRY *familyRow; /* family table row containing familyID */ TPM_DELEGATE_PUBLIC *delegatePublic; /* from DSAP session */ TPM_BOOL writeAllNV = FALSE; /* flag to write back NV */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_STORE_BUFFER outputDataSbuffer; /* TPM_DELEGATE_KEY_BLOB or TPM_DELEGATE_OWNER_BLOB */ printf("TPM_Process_DelegateUpdateVerification: Ordinal Entry\n"); TPM_SizedBuffer_Init(&inputData); /* freed @1 */ TPM_DelegateOwnerBlob_Init(&d1DelegateOwnerBlob); /* freed @2 */ TPM_DelegateKeyBlob_Init(&d1DelegateKeyBlob); /* freed @3 */ TPM_Sbuffer_Init(&outputDataSbuffer); /* freed @4 */ /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get inputData parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_Load(&inputData, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag1(tag); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, ownerAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_DelegateUpdateVerification: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* 1. Verify the TPM Owner, directly or indirectly through delegation, authorizes the command and parameters, on error return TPM_AUTHFAIL */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_OWNER, ordinal, NULL, &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ } if (returnCode == TPM_SUCCESS) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* owner HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, ownerAuth); /* Authorization digest for input */ } /* 2. Determine the type of inputData (TPM_DELEGATE_TABLE_ROW or TPM_DELEGATE_OWNER_BLOB or TPM_DELEGATE_KEY_BLOB) and map D1 to that structure */ if (returnCode == TPM_SUCCESS) { /* use a temporary copy so the original values are not moved */ stream = inputData.buffer; stream_size = inputData.size; /* the inputData is either a table index or a blob */ if (inputData.size == sizeof(TPM_DELEGATE_INDEX)) { /* if it's an index, get the index */ returnCode = TPM_Load32(&d1DelegateIndex, &stream, &stream_size); } else { /* if it's a blob, get the blob structure tag to determine the blob type */ returnCode = TPM_Load16(&d1Tag, &stream, &stream_size); } } if (returnCode == TPM_SUCCESS) { /* use a temporary copy so the original values are not moved */ stream = inputData.buffer; stream_size = inputData.size; /* if inputData is a table index */ if (inputData.size == sizeof(TPM_DELEGATE_INDEX)) { /* a. Mapping to TPM_DELEGATE_TABLE_ROW requires taking inputData as a tableIndex and locating the appropriate row in the table */ returnCode = TPM_DelegateTable_GetValidRow(&d1DelegateTableRow, &(tpm_state->tpm_permanent_data.delegateTable), d1DelegateIndex); familyID = d1DelegateTableRow->pub.familyID; } /* if inputData is a blob */ else { switch (d1Tag) { case TPM_TAG_DELEGATE_OWNER_BLOB: returnCode = TPM_DelegateOwnerBlob_Load(&d1DelegateOwnerBlob, &stream, &stream_size); familyID = d1DelegateOwnerBlob.pub.familyID; break; case TPM_TAG_DELG_KEY_BLOB: returnCode = TPM_DelegateKeyBlob_Load(&d1DelegateKeyBlob, &stream, &stream_size); familyID = d1DelegateKeyBlob.pub.familyID; break; default: printf("TPM_Process_DelegateUpdateVerification: Error, invalid tag %04hx\n", d1Tag); returnCode = TPM_BAD_PARAMETER; break; } } } /* 3. If D1 is TPM_DELEGATE_OWNER_BLOB or TPM_DELEGATE_KEY_BLOB Validate the integrity of D1 */ if ((returnCode == TPM_SUCCESS) && (inputData.size != sizeof(TPM_DELEGATE_INDEX))) { /* a. Copy D1 -> integrityDigest to H2 */ /* b. Set D1 -> integrityDigest to NULL */ /* c. Create H3 the HMAC of D1 using tpmProof as the secret */ /* d. Compare H2 to H3 return TPM_AUTHFAIL on mismatch */ switch (d1Tag) { case TPM_TAG_DELEGATE_OWNER_BLOB: returnCode = TPM_HMAC_CheckStructure (tpm_state->tpm_permanent_data.tpmProof, /* key */ &d1DelegateOwnerBlob, /* structure */ d1DelegateOwnerBlob.integrityDigest, /* expected */ (TPM_STORE_FUNCTION_T)TPM_DelegateOwnerBlob_Store, /* store function */ TPM_AUTHFAIL); /* error code */ break; case TPM_TAG_DELG_KEY_BLOB: returnCode = TPM_HMAC_CheckStructure (tpm_state->tpm_permanent_data.tpmProof, /* key */ &d1DelegateKeyBlob, /* structure */ d1DelegateKeyBlob.integrityDigest, /* expected */ (TPM_STORE_FUNCTION_T)TPM_DelegateKeyBlob_Store, /* store function */ TPM_AUTHFAIL); /* error code */ break; /* default error tested above */ } } /* 4. Locate (D1 -> pub -> familyID) in the TPM_FAMILY_TABLE and set familyRow to indicate row, return TPM_BADINDEX if not found */ /* 5. Set FR to TPM_FAMILY_TABLE.famTableRow[familyRow] */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_FamilyTable_GetEntry(&familyRow, &(tpm_state->tpm_permanent_data.familyTable), familyID); } if ((returnCode == TPM_SUCCESS) && (auth_session_data->protocolID == TPM_PID_DSAP)) { /* get the TPM_DELEGATE_PUBLIC from the DSAP session */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessionData_GetDelegatePublic(&delegatePublic, auth_session_data); } /* 6. If delegated, verify that family of the delegated Owner-auth is the same as D1: (authHandle -> familyID) == (D1 -> pub -> familyID); otherwise return error TPM_DELEGATE_FAMILY */ if (returnCode == TPM_SUCCESS) { if (familyID != delegatePublic->familyID) { printf("TPM_Process_DelegateUpdateVerification: Error, " "familyID %u should be %u\n", familyID, delegatePublic->familyID); returnCode = TPM_DELEGATE_FAMILY; } } /* 7. If delegated, verify that the family of the delegated Owner-auth is enabled: if (authHandle -> familyID -> flags TPM_FAMFLAG_ENABLED) is FALSE, return TPM_DISABLED_CMD */ if (returnCode == TPM_SUCCESS) { if (!(familyRow->flags & TPM_FAMFLAG_ENABLED)) { printf("TPM_Process_DelegateUpdateVerification: Error, family %u disabled\n", familyID); returnCode = TPM_DISABLED_CMD; } } } /* 8. Set D1 -> verificationCount to FR -> verificationCount */ if (returnCode == TPM_SUCCESS) { if (inputData.size == sizeof(TPM_DELEGATE_INDEX)) { d1DelegateTableRow->pub.verificationCount = familyRow->verificationCount; writeAllNV = TRUE; } else { switch (d1Tag) { case TPM_TAG_DELEGATE_OWNER_BLOB: d1DelegateOwnerBlob.pub.verificationCount = familyRow->verificationCount; break; case TPM_TAG_DELG_KEY_BLOB: d1DelegateKeyBlob.pub.verificationCount = familyRow->verificationCount; break; /* default error tested above */ } } } /* 9. If D1 is TPM_DELEGATE_OWNER_BLOB or TPM_DELEGATE_KEY_BLOB set the integrity of D1 */ if ((returnCode == TPM_SUCCESS) && (inputData.size != sizeof(TPM_DELEGATE_INDEX))) { /* a. Set D1 -> integrityDigest to NULL */ /* NOTE Done by TPM_HMAC_GenerateStructure() */ /* b. Create H1 the HMAC of D1 using tpmProof as the secret */ /* c. Set D1 -> integrityDigest to H1 */ /* NOTE It is safe to HMAC directly into the blob, since the structure is serialized before the HMAC is performed */ switch (d1Tag) { case TPM_TAG_DELEGATE_OWNER_BLOB: returnCode = TPM_HMAC_GenerateStructure (d1DelegateOwnerBlob.integrityDigest, /* HMAC */ tpm_state->tpm_permanent_data.tpmProof, /* HMAC key */ &d1DelegateOwnerBlob, /* structure */ (TPM_STORE_FUNCTION_T)TPM_DelegateOwnerBlob_Store); /* store function */ break; case TPM_TAG_DELG_KEY_BLOB: returnCode = TPM_HMAC_GenerateStructure (d1DelegateKeyBlob.integrityDigest, /* HMAC */ tpm_state->tpm_permanent_data.tpmProof, /* HMAC key */ &d1DelegateKeyBlob, /* structure */ (TPM_STORE_FUNCTION_T)TPM_DelegateKeyBlob_Store); /* store function */ break; } } /* If updating a delegate row, write back TPM_PERMANENT_DATA */ if (inputData.size == sizeof(TPM_DELEGATE_INDEX)) { returnCode = TPM_PermanentAll_NVStore(tpm_state, writeAllNV, returnCode); } /* 10. If D1 is a blob recreate the blob and return it */ else { if (returnCode == TPM_SUCCESS) { switch (d1Tag) { case TPM_TAG_DELEGATE_OWNER_BLOB: returnCode = TPM_DelegateOwnerBlob_Store(&outputDataSbuffer, &d1DelegateOwnerBlob); break; case TPM_TAG_DELG_KEY_BLOB: returnCode = TPM_DelegateKeyBlob_Store(&outputDataSbuffer, &d1DelegateKeyBlob); break; /* default error tested above */ } } } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_DelegateUpdateVerification: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* return outputSize and outputData */ returnCode = TPM_Sbuffer_AppendAsSizedBuffer(response, &outputDataSbuffer); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ TPM_SizedBuffer_Delete(&inputData); /* @1 */ TPM_DelegateOwnerBlob_Delete(&d1DelegateOwnerBlob); /* @2 */ TPM_DelegateKeyBlob_Delete(&d1DelegateKeyBlob); /* @3 */ TPM_Sbuffer_Delete(&outputDataSbuffer); /* @4 */ return rcf; } /* 19.7 TPM_Delegate_VerifyDelegation rev 105 VerifyDelegation interprets a delegate blob and returns success or failure, depending on whether the blob is currently valid. The delegate blob is NOT loaded into the TPM. */ TPM_RESULT TPM_Process_DelegateVerifyDelegation(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_SIZED_BUFFER delegation; /* TPM_DELEGATE_KEY_BLOB or TPM_DELEGATE_OWNER_BLOB */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ unsigned char *stream; /* temp input stream */ uint32_t stream_size; TPM_STRUCTURE_TAG d1Tag; /* input structure tag */ TPM_DELEGATE_OWNER_BLOB d1DelegateOwnerBlob; TPM_DELEGATE_KEY_BLOB d1DelegateKeyBlob; TPM_FAMILY_TABLE_ENTRY *familyRow; /* family table row containing familyID */ TPM_FAMILY_ID familyID; TPM_FAMILY_VERIFICATION verificationCount = 0; TPM_DELEGATE_SENSITIVE s1DelegateSensitive; /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_DelegateVerifyDelegation: Ordinal Entry\n"); TPM_SizedBuffer_Init(&delegation); /* freed @1 */ TPM_DelegateOwnerBlob_Init(&d1DelegateOwnerBlob); /* freed @2 */ TPM_DelegateKeyBlob_Init(&d1DelegateKeyBlob); /* freed @3 */ TPM_DelegateSensitive_Init(&s1DelegateSensitive); /* freed @4 */ /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get delegation parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_Load(&delegation, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_DelegateVerifyDelegation: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ /* 1. Determine the type of blob */ if (returnCode == TPM_SUCCESS) { /* use a temporary copy so the original values are not moved */ stream = delegation.buffer; stream_size = delegation.size; returnCode = TPM_Load16(&d1Tag, &stream, &stream_size); } if (returnCode == TPM_SUCCESS) { /* use a temporary copy so the original values are not moved */ stream = delegation.buffer; stream_size = delegation.size; switch (d1Tag) { /* 1. If delegation -> tag is equal to TPM_TAG_DELEGATE_OWNER_BLOB then */ case TPM_TAG_DELEGATE_OWNER_BLOB: /* a. Map D1 a TPM_DELEGATE_BLOB_OWNER to delegation */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_DelegateOwnerBlob_Load(&d1DelegateOwnerBlob, &stream, &stream_size); } if (returnCode == TPM_SUCCESS) { familyID = d1DelegateOwnerBlob.pub.familyID; verificationCount = d1DelegateOwnerBlob.pub.verificationCount; } break; /* 2. Else if delegation -> tag = TPM_TAG_DELG_KEY_BLOB */ case TPM_TAG_DELG_KEY_BLOB: /* a. Map D1 a TPM_DELEGATE_KEY_BLOB to delegation */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_DelegateKeyBlob_Load(&d1DelegateKeyBlob, &stream, &stream_size); } if (returnCode == TPM_SUCCESS) { familyID = d1DelegateKeyBlob.pub.familyID; verificationCount = d1DelegateKeyBlob.pub.verificationCount; } break; /* 3. Else return TPM_BAD_PARAMETER */ default: printf("TPM_Process_DelegateVerifyDelegation: Error, invalid tag %04hx\n", d1Tag); returnCode = TPM_BAD_PARAMETER; break; } } /* 4. Locate D1 -> familyID in the TPM_FAMILY_TABLE and set familyRow to indicate row, return TPM_BADINDEX if not found */ /* 5. Set FR to TPM_FAMILY_TABLE.famTableRow[familyRow] */ /* 6. If FR -> flags TPM_FAMFLAG_ENABLED is FALSE, return TPM_DISABLED_CMD */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_FamilyTable_GetEnabledEntry(&familyRow, &(tpm_state->tpm_permanent_data.familyTable), familyID); } /* 7. Validate that D1 -> pub -> verificationCount matches FR -> verificationCount, on mismatch return TPM_FAMILYCOUNT */ if (returnCode == TPM_SUCCESS) { if (verificationCount != familyRow->verificationCount) { printf("TPM_Process_DelegateVerifyDelegation: Error, " "verificationCount mismatch %u %u\n", verificationCount, familyRow->verificationCount); returnCode = TPM_FAMILYCOUNT; } } /* 8. Validate the integrity of D1 */ /* a. Copy D1 -> integrityDigest to H2 */ /* b. Set D1 -> integrityDigest to NULL */ /* c. Create H3 the HMAC of D1 using tpmProof as the secret */ /* d. Compare H2 to H3 return TPM_AUTHFAIL on mismatch */ if (returnCode == TPM_SUCCESS) { if (d1Tag == TPM_TAG_DELEGATE_OWNER_BLOB) { returnCode = TPM_HMAC_CheckStructure (tpm_state->tpm_permanent_data.tpmProof, /* key */ &d1DelegateOwnerBlob, /* structure */ d1DelegateOwnerBlob.integrityDigest, /* expected */ (TPM_STORE_FUNCTION_T)TPM_DelegateOwnerBlob_Store, /* store function */ TPM_AUTHFAIL); /* error code */ } else { returnCode = TPM_HMAC_CheckStructure (tpm_state->tpm_permanent_data.tpmProof, /* key */ &d1DelegateKeyBlob, /* structure */ d1DelegateKeyBlob.integrityDigest, /* expected */ (TPM_STORE_FUNCTION_T)TPM_DelegateKeyBlob_Store, /* store function */ TPM_AUTHFAIL); /* error code */ } } /* 9. Create S1 a TPM_DELEGATE_SENSITIVE area by decrypting D1 -> sensitiveArea using TPM_DELEGATE_KEY */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_DelegateVerifyDelegation: Decrypting sensitiveArea\n"); if (d1Tag == TPM_TAG_DELEGATE_OWNER_BLOB) { returnCode = TPM_DelegateSensitive_DecryptEncData(&s1DelegateSensitive, &(d1DelegateOwnerBlob.sensitiveArea), tpm_state->tpm_permanent_data.delegateKey); } else { returnCode = TPM_DelegateSensitive_DecryptEncData(&s1DelegateSensitive, &(d1DelegateKeyBlob.sensitiveArea), tpm_state->tpm_permanent_data.delegateKey); } } /* 10. Validate S1 values */ /* a. S1 -> tag is TPM_TAG_DELEGATE_SENSITIVE */ /* NOTE Done by TPM_DelegateSensitive_DecryptEncData() */ /* b. Return TPM_BAD_PARAMETER on error */ /* 11. Return TPM_SUCCESS */ /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_DelegateVerifyDelegation: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* cleanup */ TPM_SizedBuffer_Delete(&delegation); /* @1 */ TPM_DelegateOwnerBlob_Delete(&d1DelegateOwnerBlob); /* @2 */ TPM_DelegateKeyBlob_Delete(&d1DelegateKeyBlob); /* @3 */ TPM_DelegateSensitive_Delete(&s1DelegateSensitive); /* @4 */ return rcf; } libtpms-0.9.3/src/tpm12/tpm_delegate.h000066400000000000000000000331031421143571500175350ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Delegate Handler */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_delegate.h 4526 2011-03-24 21:14:42Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_DELEGATE_H #define TPM_DELEGATE_H #include "tpm_structures.h" /* TPM_DELEGATE_PUBLIC */ void TPM_DelegatePublic_Init(TPM_DELEGATE_PUBLIC *tpm_delegate_public); TPM_RESULT TPM_DelegatePublic_Load(TPM_DELEGATE_PUBLIC *tpm_delegate_public, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_DelegatePublic_Store(TPM_STORE_BUFFER *sbuffer, const TPM_DELEGATE_PUBLIC *tpm_delegate_public); void TPM_DelegatePublic_Delete(TPM_DELEGATE_PUBLIC *tpm_delegate_public); TPM_RESULT TPM_DelegatePublic_Copy(TPM_DELEGATE_PUBLIC *dest, TPM_DELEGATE_PUBLIC *src); /* TPM_DELEGATE_SENSITIVE */ void TPM_DelegateSensitive_Init(TPM_DELEGATE_SENSITIVE *tpm_delegate_sensitive); TPM_RESULT TPM_DelegateSensitive_Load(TPM_DELEGATE_SENSITIVE *tpm_delegate_sensitive, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_DelegateSensitive_Store(TPM_STORE_BUFFER *sbuffer, const TPM_DELEGATE_SENSITIVE *tpm_delegate_sensitive); void TPM_DelegateSensitive_Delete(TPM_DELEGATE_SENSITIVE *tpm_delegate_sensitive); TPM_RESULT TPM_DelegateSensitive_DecryptEncData(TPM_DELEGATE_SENSITIVE *tpm_delegate_sensitive, TPM_SIZED_BUFFER *sensitiveArea, TPM_SYMMETRIC_KEY_TOKEN delegateKey); /* TPM_DELEGATIONS */ void TPM_Delegations_Init(TPM_DELEGATIONS *tpm_delegations); TPM_RESULT TPM_Delegations_Load(TPM_DELEGATIONS *tpm_delegations, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_Delegations_Store(TPM_STORE_BUFFER *sbuffer, const TPM_DELEGATIONS *tpm_delegations); void TPM_Delegations_Delete(TPM_DELEGATIONS *tpm_delegations); void TPM_Delegations_Copy(TPM_DELEGATIONS *dest, TPM_DELEGATIONS *src); TPM_RESULT TPM_Delegations_CheckPermissionDelegation(TPM_DELEGATIONS *newDelegations, TPM_DELEGATIONS *currentDelegations); TPM_RESULT TPM_Delegations_CheckPermission(tpm_state_t *tpm_state, TPM_DELEGATE_PUBLIC *delegatePublic, TPM_ENT_TYPE entityType, TPM_COMMAND_CODE ordinal); TPM_RESULT TPM_Delegations_CheckOwnerPermission(TPM_DELEGATIONS *tpm_delegations, TPM_COMMAND_CODE ordinal); TPM_RESULT TPM_Delegations_CheckKeyPermission(TPM_DELEGATIONS *tpm_delegations, TPM_COMMAND_CODE ordinal); /* TPM_DELEGATE_OWNER_BLOB */ void TPM_DelegateOwnerBlob_Init(TPM_DELEGATE_OWNER_BLOB *tpm_delegate_owner_blob); TPM_RESULT TPM_DelegateOwnerBlob_Load(TPM_DELEGATE_OWNER_BLOB *tpm_delegate_owner_blob, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_DelegateOwnerBlob_Store(TPM_STORE_BUFFER *sbuffer, const TPM_DELEGATE_OWNER_BLOB *tpm_delegate_owner_blob); void TPM_DelegateOwnerBlob_Delete(TPM_DELEGATE_OWNER_BLOB *tpm_delegate_owner_blob); /* TPM_DELEGATE_KEY_BLOB */ void TPM_DelegateKeyBlob_Init(TPM_DELEGATE_KEY_BLOB *tpm_delegate_key_blob); TPM_RESULT TPM_DelegateKeyBlob_Load(TPM_DELEGATE_KEY_BLOB *tpm_delegate_key_blob, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_DelegateKeyBlob_Store(TPM_STORE_BUFFER *sbuffer, const TPM_DELEGATE_KEY_BLOB *tpm_delegate_key_blob); void TPM_DelegateKeyBlob_Delete(TPM_DELEGATE_KEY_BLOB *tpm_delegate_key_blob); /* TPM_FAMILY_TABLE */ void TPM_FamilyTable_Init(TPM_FAMILY_TABLE *tpm_family_table); TPM_RESULT TPM_FamilyTable_Load(TPM_FAMILY_TABLE *tpm_family_table, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_FamilyTable_Store(TPM_STORE_BUFFER *sbuffer, const TPM_FAMILY_TABLE *tpm_family_table, TPM_BOOL store_tag); void TPM_FamilyTable_Delete(TPM_FAMILY_TABLE *tpm_family_table); TPM_RESULT TPM_FamilyTable_StoreValid(TPM_STORE_BUFFER *sbuffer, const TPM_FAMILY_TABLE *tpm_family_table, TPM_BOOL store_tag); TPM_RESULT TPM_FamilyTable_GetEntry(TPM_FAMILY_TABLE_ENTRY **tpm_family_table_entry, TPM_FAMILY_TABLE *tpm_family_table, TPM_FAMILY_ID familyID); TPM_RESULT TPM_FamilyTable_GetEnabledEntry(TPM_FAMILY_TABLE_ENTRY **tpm_family_table_entry, TPM_FAMILY_TABLE *tpm_family_table, TPM_FAMILY_ID familyID); TPM_RESULT TPM_FamilyTable_IsSpace(TPM_FAMILY_TABLE_ENTRY **tpm_family_table_entry, TPM_FAMILY_TABLE *tpm_family_table); /* TPM_FAMILY_TABLE_ENTRY */ void TPM_FamilyTableEntry_Init(TPM_FAMILY_TABLE_ENTRY *tpm_family_table_entry); TPM_RESULT TPM_FamilyTableEntry_Load(TPM_FAMILY_TABLE_ENTRY *tpm_family_table_entry, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_FamilyTableEntry_Store(TPM_STORE_BUFFER *sbuffer, const TPM_FAMILY_TABLE_ENTRY *tpm_family_table_entry, TPM_BOOL store_tag); TPM_RESULT TPM_FamilyTableEntry_StorePublic(TPM_STORE_BUFFER *sbuffer, const TPM_FAMILY_TABLE_ENTRY *tpm_family_table_entry, TPM_BOOL store_tag); void TPM_FamilyTableEntry_Delete(TPM_FAMILY_TABLE_ENTRY *tpm_family_table_entry); /* TPM_DELEGATE_TABLE */ void TPM_DelegateTable_Init(TPM_DELEGATE_TABLE *tpm_delegate_table); TPM_RESULT TPM_DelegateTable_Load(TPM_DELEGATE_TABLE *tpm_delegate_table, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_DelegateTable_Store(TPM_STORE_BUFFER *sbuffer, const TPM_DELEGATE_TABLE *tpm_delegate_table); void TPM_DelegateTable_Delete(TPM_DELEGATE_TABLE *tpm_delegate_table); TPM_RESULT TPM_DelegateTable_StoreValid(TPM_STORE_BUFFER *sbuffer, const TPM_DELEGATE_TABLE *tpm_delegate_table); TPM_RESULT TPM_DelegateTable_GetRow(TPM_DELEGATE_TABLE_ROW **delegateTableRow, TPM_DELEGATE_TABLE *tpm_delegate_table, uint32_t rowIndex); TPM_RESULT TPM_DelegateTable_GetValidRow(TPM_DELEGATE_TABLE_ROW **delegateTableRow, TPM_DELEGATE_TABLE *tpm_delegate_table, uint32_t rowIndex); /* TPM_DELEGATE_TABLE_ROW */ void TPM_DelegateTableRow_Init(TPM_DELEGATE_TABLE_ROW *tpm_delegate_table_row); TPM_RESULT TPM_DelegateTableRow_Load(TPM_DELEGATE_TABLE_ROW *tpm_delegate_table_row, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_DelegateTableRow_Store(TPM_STORE_BUFFER *sbuffer, const TPM_DELEGATE_TABLE_ROW *tpm_delegate_table_row); void TPM_DelegateTableRow_Delete(TPM_DELEGATE_TABLE_ROW *tpm_delegate_table_row); /* Processing Functions */ TPM_RESULT TPM_Process_DelegateManage(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_DelegateCreateKeyDelegation(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_DelegateCreateOwnerDelegation(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_DelegateLoadOwnerDelegation(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_DelegateReadTable(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_DelegateUpdateVerification(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_DelegateVerifyDelegation(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); #endif libtpms-0.9.3/src/tpm12/tpm_digest.c000066400000000000000000000114621421143571500172410ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Digest Handler */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_digest.c 4071 2010-04-29 19:26:45Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include #include #include "tpm_debug.h" #include "tpm_error.h" #include "tpm_structures.h" #include "tpm_digest.h" /* TPM_Digest_Init resets a digest structure to zeros */ void TPM_Digest_Init(TPM_DIGEST tpm_digest) { printf(" TPM_Digest_Init:\n"); memset(tpm_digest, 0, TPM_DIGEST_SIZE); return; } /* TPM_Digest_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes */ TPM_RESULT TPM_Digest_Load(TPM_DIGEST tpm_digest, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_Digest_Load:\n"); rc = TPM_Loadn(tpm_digest, TPM_DIGEST_SIZE, stream, stream_size); return rc; } /* TPM_Digest_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes After use, call TPM_Sbuffer_Delete() to free memory */ TPM_RESULT TPM_Digest_Store(TPM_STORE_BUFFER *sbuffer, const TPM_DIGEST tpm_digest) { TPM_RESULT rc = 0; printf(" TPM_Digest_Store:\n"); rc = TPM_Sbuffer_Append(sbuffer, tpm_digest, TPM_DIGEST_SIZE); return rc; } void TPM_Digest_Set(TPM_DIGEST tpm_digest) { printf(" TPM_Digest_Set:\n"); memset(tpm_digest, 0xff, TPM_DIGEST_SIZE); } void TPM_Digest_Copy(TPM_DIGEST destination, const TPM_DIGEST source) { printf(" TPM_Digest_Copy:\n"); memcpy(destination, source, TPM_DIGEST_SIZE); return; } void TPM_Digest_XOR(TPM_DIGEST out, const TPM_DIGEST in1, const TPM_DIGEST in2) { size_t i; printf(" TPM_Digest_XOR:\n"); for (i = 0 ; i < TPM_DIGEST_SIZE ; i++) { out[i] = in1[i] ^ in2[i]; } return; } /* TPM_Digest_Compare() compares two digests, returning 0 if they are equal */ TPM_RESULT TPM_Digest_Compare(const TPM_DIGEST expect, const TPM_DIGEST actual) { TPM_RESULT rc = 0; printf(" TPM_Digest_Compare:\n"); rc = memcmp(expect, actual, TPM_DIGEST_SIZE); if (rc != 0) { printf("TPM_Digest_Compare: Error comparing digest\n"); TPM_PrintFour(" TPM_Digest_Compare: Expect", expect); TPM_PrintFour(" TPM_Digest_Compare: Actual", actual); rc = TPM_AUTHFAIL; } return rc; } void TPM_Digest_IsZero(TPM_BOOL *isZero, TPM_DIGEST tpm_digest) { size_t i; printf(" TPM_Digest_IsZero:\n"); for (i = 0, *isZero = TRUE ; (i < TPM_DIGEST_SIZE) && *isZero ; i++) { if (tpm_digest[i] != 0) { *isZero = FALSE; } } return; } #if 0 void TPM_Digest_IsMinusOne(TPM_BOOL *isMinusOne, TPM_DIGEST tpm_digest) { size_t i; printf(" TPM_Digest_IsMinusOne:\n"); for (i = 0, *isMinusOne = TRUE ; (i < TPM_DIGEST_SIZE) && *isMinusOne ; i++) { if (tpm_digest[i] != 0xff) { *isMinusOne = FALSE; } } return; } #endif libtpms-0.9.3/src/tpm12/tpm_digest.h000066400000000000000000000064221421143571500172460ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Digest Handler */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_digest.h 4071 2010-04-29 19:26:45Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_DIGEST_H #define TPM_DIGEST_H #include "tpm_structures.h" #include "tpm_store.h" void TPM_Digest_Init(TPM_DIGEST tpm_digest); TPM_RESULT TPM_Digest_Load(TPM_DIGEST tpm_digest, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_Digest_Store(TPM_STORE_BUFFER *sbuffer, const TPM_DIGEST tpm_digest); void TPM_Digest_Set(TPM_DIGEST tpm_digest); void TPM_Digest_Copy(TPM_DIGEST destination, const TPM_DIGEST source); void TPM_Digest_XOR(TPM_DIGEST out, const TPM_DIGEST in1, const TPM_DIGEST in2); TPM_RESULT TPM_Digest_Compare(const TPM_DIGEST expect, const TPM_DIGEST actual); void TPM_Digest_IsZero(TPM_BOOL *isZero, TPM_DIGEST tpm_digest); #if 0 void TPM_Digest_IsMinusOne(TPM_BOOL *isMinusOne, TPM_DIGEST tpm_digest); #endif #endif libtpms-0.9.3/src/tpm12/tpm_error.c000066400000000000000000000046361421143571500171200ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Error Response */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_error.c 4071 2010-04-29 19:26:45Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include #include "tpm_error.h" libtpms-0.9.3/src/tpm12/tpm_global.c000066400000000000000000000242041421143571500172200ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Global Variables */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_global.c 4621 2011-09-09 20:19:42Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include #include #include "tpm_crypto.h" #include "tpm_debug.h" #include "tpm_digest.h" #include "tpm_error.h" #include "tpm_io.h" #include "tpm_init.h" #include "tpm_key.h" #include "tpm_nvfile.h" #include "tpm_nvram.h" #include "tpm_permanent.h" #include "tpm_platform.h" #include "tpm_startup.h" #include "tpm_structures.h" #include "tpm_global.h" /* state for the TPM's */ tpm_state_t *tpm_instances[TPMS_MAX]; /* TPM_Global_Init initializes the tpm_state to default values. It does not load any data from or store data to NVRAM */ TPM_RESULT TPM_Global_Init(tpm_state_t *tpm_state) { TPM_RESULT rc = 0; printf("TPM_Global_Init: TPMs %lu\n", (unsigned long)sizeof(tpm_instances)/sizeof(tpm_state_t *)); /* initialize the TPM_STANY_FLAGS structure */ if (rc == 0) { /* set the structure to 0 for security, clean out old secrets */ memset(tpm_state, 0 , sizeof(tpm_state_t)); /* the virtual TPM number NOTE: This must be done early as it is used to construct nn.permall file names */ tpm_state->tpm_number = TPM_ILLEGAL_INSTANCE_HANDLE; /* initialize the TPM_PERMANENT_FLAGS structure */ printf("TPM_Global_Init: Initializing TPM_PERMANENT_FLAGS\n"); TPM_PermanentFlags_Init(&(tpm_state->tpm_permanent_flags)); /* initialize the TPM_STCLEAR_FLAGS structure */ printf("TPM_Global_Init: Initializing TPM_STCLEAR_FLAGS\n"); TPM_StclearFlags_Init(&(tpm_state->tpm_stclear_flags)); /* initialize the TPM_STANY_FLAGS structure */ printf("TPM_Global_Init: Initializing TPM_STANY_FLAGS\n"); TPM_StanyFlags_Init(&(tpm_state->tpm_stany_flags)); /* initialize TPM_PERMANENT_DATA structure */ printf("TPM_Global_Init: Initializing TPM_PERMANENT_DATA\n"); rc = TPM_PermanentData_Init(&(tpm_state->tpm_permanent_data), TRUE); } if (rc == 0) { /* initialize TPM_STCLEAR_DATA structure */ printf("TPM_Global_Init: Initializing TPM_STCLEAR_DATA\n"); TPM_StclearData_Init(&(tpm_state->tpm_stclear_data), tpm_state->tpm_permanent_data.pcrAttrib, TRUE); /* initialize the PCR's */ /* initialize TPM_STANY_DATA structure */ printf("TPM_Global_Init: Initializing TPM_STANY_DATA\n"); rc = TPM_StanyData_Init(&(tpm_state->tpm_stany_data)); } /* initialize the TPM_KEY_HANDLE_LIST structure */ if (rc == 0) { printf("TPM_Global_Init: Initializing TPM_KEY_HANDLE_LIST\n"); TPM_KeyHandleEntries_Init(tpm_state->tpm_key_handle_entries); /* initialize the SHA1 thread context */ tpm_state->sha1_context = NULL; /* initialize the TIS SHA1 thread context */ tpm_state->sha1_context_tis = NULL; tpm_state->transportHandle = 0; printf("TPM_Global_Init: Initializing TPM_NV_INDEX_ENTRIES\n"); TPM_NVIndexEntries_Init(&(tpm_state->tpm_nv_index_entries)); } /* comes up in limited operation mode */ /* shutdown is set on a self test failure, before calling TPM_Global_Init() */ if (rc == 0) { printf(" TPM_Global_Init: Set testState to %u \n", TPM_TEST_STATE_LIMITED); tpm_state->testState = TPM_TEST_STATE_LIMITED; } else { printf(" TPM_Global_Init: Set testState to %u \n", TPM_TEST_STATE_FAILURE); tpm_state->testState = TPM_TEST_STATE_FAILURE; } return rc; } #if 0 /* TPM_Global_Load() loads the tpm_state_t global structures for the TPM instance from NVRAM. tpm_state->tpm_number must be set by the caller. Returns 0 on success. TPM_FAIL on failure to load (fatal), since it should never occur */ TPM_RESULT TPM_Global_Load(tpm_state_t *tpm_state) { TPM_RESULT rc = 0; printf("TPM_Global_Load:\n"); /* TPM_PERMANENT_DATA, TPM_PERMANENT_FLAGS, owner evict keys, and NV defined space. */ if (rc == 0) { rc = TPM_PermanentAll_NVLoad(tpm_state); } if (rc == 0) { rc = TPM_VolatileAll_NVLoad(tpm_state); } return rc; } /* TPM_Global_Store() store the tpm_state_t global structure for the TPM instance to NVRAM tpm_state->tpm_number must be set by the caller. */ TPM_RESULT TPM_Global_Store(tpm_state_t *tpm_state) { TPM_RESULT rc = 0; printf(" TPM_Global_Store:\n"); if (rc == 0) { rc = TPM_PermanentAll_NVStore(tpm_state, TRUE, 0); } if (rc == 0) { rc = TPM_VolatileAll_NVStore(tpm_state); } return rc; } #endif /* TPM_Global_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_Global_Init to set members back to default values The object itself is not freed */ void TPM_Global_Delete(tpm_state_t *tpm_state) { printf(" TPM_Global_Delete:\n"); if (tpm_state != NULL) { /* TPM_PERMANENT_FLAGS have no allocated memory or secrets */ /* TPM_STCLEAR_FLAGS have no allocated memory or secrets */ /* TPM_STANY_FLAGS have no allocated memory or secrets */ printf(" TPM_Global_Delete: Deleting TPM_PERMANENT_DATA\n"); TPM_PermanentData_Delete(&(tpm_state->tpm_permanent_data), TRUE); printf(" TPM_Global_Delete: Deleting TPM_STCLEAR_DATA\n"); TPM_StclearData_Delete(&(tpm_state->tpm_stclear_data), tpm_state->tpm_permanent_data.pcrAttrib, TRUE); /* reset the PCR's */ printf(" TPM_Global_Delete: Deleting TPM_STANY_DATA\n"); TPM_StanyData_Delete(&(tpm_state->tpm_stany_data)); printf(" TPM_Global_Delete: Deleting key handle entries\n"); TPM_KeyHandleEntries_Delete(tpm_state->tpm_key_handle_entries); printf(" TPM_Global_Delete: Deleting SHA1 contexts\n"); TPM_SHA1Delete(&(tpm_state->sha1_context)); TPM_SHA1Delete(&(tpm_state->sha1_context_tis)); TPM_NVIndexEntries_Delete(&(tpm_state->tpm_nv_index_entries)); } return; } /* TPM_Global_GetPhysicalPresence() returns 'physicalPresence' TRUE if either TPM_STCLEAR_FLAGS -> physicalPresence is TRUE or hardware physical presence is indicated. The physicalPresenceHWEnable and physicalPresenceCMDEnable flags MUST mask their respective signals before further processing. The hardware signal, if enabled by the physicalPresenceHWEnable flag, MUST be logically ORed with the PhysicalPresence flag, if enabled, to obtain the final physical presence value used to allow or disallow local commands. */ TPM_RESULT TPM_Global_GetPhysicalPresence(TPM_BOOL *physicalPresence, const tpm_state_t *tpm_state) { TPM_RESULT rc = 0; *physicalPresence = FALSE; /* is CMD physical presence enabled */ printf(" TPM_Global_GetPhysicalPresence: physicalPresenceCMDEnable is %02x\n", tpm_state->tpm_permanent_flags.physicalPresenceCMDEnable); if (tpm_state->tpm_permanent_flags.physicalPresenceCMDEnable) { printf(" TPM_Global_GetPhysicalPresence: physicalPresence flag is %02x\n", tpm_state->tpm_stclear_flags.physicalPresence); /* if enabled, check for physicalPresence set by the command ordinal */ *physicalPresence = tpm_state->tpm_stclear_flags.physicalPresence; } /* if the software flag is true, result is true, no need to check the hardware */ /* if the TPM_STCLEAR_FLAGS flag is FALSE, check the hardware */ if (!(*physicalPresence)) { printf(" TPM_Global_GetPhysicalPresence: physicalPresenceHWEnable is %02x\n", tpm_state->tpm_permanent_flags.physicalPresenceHWEnable); /* if physicalPresenceHWEnable is FALSE, the hardware signal is disabled */ if (tpm_state->tpm_permanent_flags.physicalPresenceHWEnable) { /* if enabled, check the hardware signal */ rc = TPM_IO_GetPhysicalPresence(physicalPresence, tpm_state->tpm_number); printf(" TPM_Global_GetPhysicalPresence: physicalPresence HW is %02x\n", *physicalPresence); } } printf(" TPM_Global_GetPhysicalPresence: physicalPresence is %02x\n", *physicalPresence); return rc; } libtpms-0.9.3/src/tpm12/tpm_global.h000066400000000000000000000107201421143571500172230ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Global Variables */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_global.h 4285 2011-01-17 21:27:05Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_GLOBAL_H #define TPM_GLOBAL_H #include "tpm_nvram_const.h" #include "tpm_types.h" #include "tpm_structures.h" #define TPM_TEST_STATE_LIMITED 1 /* limited operation mode */ #define TPM_TEST_STATE_FULL 2 /* full operation mode */ #define TPM_TEST_STATE_FAILURE 3 /* failure mode */ typedef struct tdTPM_STATE { /* the number of the virtual TPM */ uint32_t tpm_number; /* 7.1 TPM_PERMANENT_FLAGS */ TPM_PERMANENT_FLAGS tpm_permanent_flags; /* 7.2 TPM_STCLEAR_FLAGS */ TPM_STCLEAR_FLAGS tpm_stclear_flags; /* 7.3 TPM_STANY_FLAGS */ TPM_STANY_FLAGS tpm_stany_flags; /* 7.4 TPM_PERMANENT_DATA */ TPM_PERMANENT_DATA tpm_permanent_data; /* 7.5 TPM_STCLEAR_DATA */ TPM_STCLEAR_DATA tpm_stclear_data; /* 7.6 TPM_STANY_DATA */ TPM_STANY_DATA tpm_stany_data; /* 5.6 TPM_KEY_HANDLE_ENTRY */ TPM_KEY_HANDLE_ENTRY tpm_key_handle_entries[TPM_KEY_HANDLES]; /* Context for SHA1 functions */ void *sha1_context; void *sha1_context_tis; TPM_TRANSHANDLE transportHandle; /* non-zero if the context was set up in a transport session */ /* self test shutdown */ uint32_t testState; /* NVRAM volatile data marker. Cleared at TPM_Startup(ST_Clear), it holds all indexes which have been read. The index not being present indicates that some volatile fields should be cleared at first read. */ TPM_NV_INDEX_ENTRIES tpm_nv_index_entries; /* NOTE: members added here should be initialized by TPM_Global_Init() and possibly added to TPM_SaveState_Load() and TPM_SaveState_Store() */ } tpm_state_t; /* state for the TPM */ extern tpm_state_t *tpm_instances[]; /* tpm_state_t */ TPM_RESULT TPM_Global_Init(tpm_state_t *tpm_state); #if 0 TPM_RESULT TPM_Global_Load(tpm_state_t *tpm_state); TPM_RESULT TPM_Global_Store(tpm_state_t *tpm_state); #endif void TPM_Global_Delete(tpm_state_t *tpm_state); TPM_RESULT TPM_Global_GetPhysicalPresence(TPM_BOOL *physicalPresence, const tpm_state_t *tpm_state); #endif libtpms-0.9.3/src/tpm12/tpm_identity.c000066400000000000000000001430541421143571500176160ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM Identity Handling */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_identity.c 4526 2011-03-24 21:14:42Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include #include #include "tpm_auth.h" #include "tpm_crypto.h" #include "tpm_cryptoh.h" #include "tpm_debug.h" #include "tpm_digest.h" #include "tpm_error.h" #include "tpm_io.h" #include "tpm_key.h" #include "tpm_memory.h" #include "tpm_pcr.h" #include "tpm_process.h" #include "tpm_secret.h" #include "tpm_storage.h" #include "tpm_ver.h" #include "tpm_identity.h" /* TPM_EK_BLOB */ /* TPM_EKBlob_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_EKBlob_Init(TPM_EK_BLOB *tpm_ek_blob) { printf(" TPM_EKBlob_Init:\n"); tpm_ek_blob->ekType = 0; TPM_SizedBuffer_Init(&(tpm_ek_blob->blob)); return; } /* TPM_EKBlob_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_EKBlob_Init() After use, call TPM_EKBlob_Delete() to free memory */ TPM_RESULT TPM_EKBlob_Load(TPM_EK_BLOB *tpm_ek_blob, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_EKBlob_Load:\n"); /* check the tag */ if (rc == 0) { rc = TPM_CheckTag(TPM_TAG_EK_BLOB, stream, stream_size); } /* load ekType */ if (rc == 0) { rc = TPM_Load16(&(tpm_ek_blob->ekType), stream, stream_size); } /* load blob */ if (rc == 0) { rc = TPM_SizedBuffer_Load(&(tpm_ek_blob->blob), stream, stream_size); } return rc; } #if 0 /* TPM_EKBlob_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_EKBlob_Store(TPM_STORE_BUFFER *sbuffer, const TPM_EK_BLOB *tpm_ek_blob) { TPM_RESULT rc = 0; printf(" TPM_EKBlob_Store:\n"); if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_EK_BLOB); } if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, tpm_ek_blob->ekType); } if (rc == 0) { rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_ek_blob->blob)); } return rc; } #endif /* TPM_EKBlob_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_EKBlob_Init to set members back to default values The object itself is not freed */ void TPM_EKBlob_Delete(TPM_EK_BLOB *tpm_ek_blob) { printf(" TPM_EKBlob_Delete:\n"); if (tpm_ek_blob != NULL) { TPM_SizedBuffer_Delete(&(tpm_ek_blob->blob)); TPM_EKBlob_Init(tpm_ek_blob); } return; } /* TPM_EK_BLOB_ACTIVATE */ /* TPM_EKBlobActivate_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_EKBlobActivate_Init(TPM_EK_BLOB_ACTIVATE *tpm_ek_blob_activate) { printf(" TPM_EKBlobActivate_Init:\n"); TPM_SymmetricKey_Init(&(tpm_ek_blob_activate->sessionKey)); TPM_Digest_Init(tpm_ek_blob_activate->idDigest); TPM_PCRInfoShort_Init(&(tpm_ek_blob_activate->pcrInfo)); return; } /* TPM_EKBlobActivate_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_EKBlobActivate_Init() After use, call TPM_EKBlobActivate_Delete() to free memory */ TPM_RESULT TPM_EKBlobActivate_Load(TPM_EK_BLOB_ACTIVATE *tpm_ek_blob_activate, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_EKBlobActivate_Load:\n"); /* check tag */ if (rc == 0) { rc = TPM_CheckTag(TPM_TAG_EK_BLOB_ACTIVATE, stream, stream_size); } /* load sessionKey */ if (rc == 0) { rc = TPM_SymmetricKey_Load(&(tpm_ek_blob_activate->sessionKey), stream, stream_size); } /* load idDigest */ if (rc == 0) { rc = TPM_Digest_Load(tpm_ek_blob_activate->idDigest, stream, stream_size); } /* load pcrInfo */ if (rc == 0) { rc = TPM_PCRInfoShort_Load(&(tpm_ek_blob_activate->pcrInfo), stream, stream_size, FALSE); } return rc; } #if 0 /* TPM_EKBlobActivate_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_EKBlobActivate_Store(TPM_STORE_BUFFER *sbuffer, const TPM_EK_BLOB_ACTIVATE *tpm_ek_blob_activate) { TPM_RESULT rc = 0; printf(" TPM_EKBlobActivate_Store:\n"); /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_EK_BLOB_ACTIVATE); } /* store sessionKey */ if (rc == 0) { rc = TPM_SymmetricKey_Store(sbuffer, &(tpm_ek_blob_activate->sessionKey)); } /* store idDigest */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_ek_blob_activate->idDigest); } /* store pcrInfo */ if (rc == 0) { rc = TPM_PCRInfoShort_Store(sbuffer, &(tpm_ek_blob_activate->pcrInfo), FALSE); } return rc; } #endif /* TPM_EKBlobActivate_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_EKBlobActivate_Init to set members back to default values The object itself is not freed */ void TPM_EKBlobActivate_Delete(TPM_EK_BLOB_ACTIVATE *tpm_ek_blob_activate) { printf(" TPM_EKBlobActivate_Delete:\n"); if (tpm_ek_blob_activate != NULL) { TPM_SymmetricKey_Delete(&(tpm_ek_blob_activate->sessionKey)); TPM_PCRInfoShort_Delete(&(tpm_ek_blob_activate->pcrInfo)); TPM_EKBlobActivate_Init(tpm_ek_blob_activate); } return; } /* TPM_EK_BLOB_AUTH */ #if 0 /* TPM_EKBlobAuth_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_EKBlobAuth_Init(TPM_EK_BLOB_AUTH *tpm_ek_blob_auth) { printf(" TPM_EKBlobAuth_Init:\n"); TPM_Secret_Init(tpm_ek_blob_auth->authValue); return; } /* TPM_EKBlobAuth_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_EKBlobAuth_Init() After use, call TPM_EKBlobAuth_Delete() to free memory */ TPM_RESULT TPM_EKBlobAuth_Load(TPM_EK_BLOB_AUTH *tpm_ek_blob_auth, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_EKBlobAuth_Load:\n"); /* check tag */ if (rc == 0) { rc = TPM_CheckTag(TPM_TAG_EK_BLOB_AUTH, stream, stream_size); } /* load authValue */ if (rc == 0) { rc = TPM_Secret_Load(tpm_ek_blob_auth->authValue, stream, stream_size); } return rc; } /* TPM_EKBlobAuth_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_EKBlobAuth_Store(TPM_STORE_BUFFER *sbuffer, const TPM_EK_BLOB_AUTH *tpm_ek_blob_auth) { TPM_RESULT rc = 0; printf(" TPM_EKBlobAuth_Store:\n"); if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_EK_BLOB_AUTH); } if (rc == 0) { rc = TPM_Secret_Store(sbuffer, tpm_ek_blob_auth->authValue); } return rc; } /* TPM_EKBlobAuth_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_EKBlobAuth_Init to set members back to default values The object itself is not freed */ void TPM_EKBlobAuth_Delete(TPM_EK_BLOB_AUTH *tpm_ek_blob_auth) { printf(" TPM_EKBlobAuth_Delete:\n"); if (tpm_ek_blob_auth != NULL) { TPM_EKBlobAuth_Init(tpm_ek_blob_auth); } return; } #endif /* TPM_IDENTITY_CONTENTS */ /* TPM_IdentityContents_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_IdentityContents_Init(TPM_IDENTITY_CONTENTS *tpm_identity_contents) { printf(" TPM_IdentityContents_Init:\n"); TPM_StructVer_Init(&(tpm_identity_contents->ver)); tpm_identity_contents->ordinal = TPM_ORD_MakeIdentity; TPM_Digest_Init(tpm_identity_contents->labelPrivCADigest); TPM_Pubkey_Init(&(tpm_identity_contents->identityPubKey)); return; } /* TPM_IdentityContents_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_IdentityContents_Init() After use, call TPM_IdentityContents_Delete() to free memory NOTE: Never called. */ #if 0 TPM_RESULT TPM_IdentityContents_Load(TPM_IDENTITY_CONTENTS *tpm_identity_contents, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_IdentityContents_Load:\n"); /* load ver */ if (rc == 0) { rc = TPM_StructVer_Load(&(tpm_identity_contents->ver), stream, stream_size); } /* check ver immediately to ease debugging */ if (rc == 0) { rc = TPM_StructVer_CheckVer(&(tpm_identity_contents->ver)); } /* load ordinal */ if (rc == 0) { rc = TPM_Load32(&(tpm_identity_contents->ordinal), stream, stream_size); } /* load labelPrivCADigest */ if (rc == 0) { rc = TPM_Digest_Load(tpm_identity_contents->labelPrivCADigest, stream, stream_size); } /* load identityPubKey */ if (rc == 0) { rc = TPM_Pubkey_Load(&(tpm_identity_contents->identityPubKey), stream, stream_size); } return rc; } #endif /* TPM_IdentityContents_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_IdentityContents_Store(TPM_STORE_BUFFER *sbuffer, TPM_IDENTITY_CONTENTS *tpm_identity_contents) { TPM_RESULT rc = 0; printf(" TPM_IdentityContents_Store:\n"); /* store ver */ if (rc == 0) { rc = TPM_StructVer_Store(sbuffer, &(tpm_identity_contents->ver)); } /* store ordinal */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_identity_contents->ordinal); } /* store labelPrivCADigest */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_identity_contents->labelPrivCADigest); } /* store identityPubKey */ if (rc == 0) { rc = TPM_Pubkey_Store(sbuffer, &(tpm_identity_contents->identityPubKey)); } return rc; } /* TPM_IdentityContents_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_IdentityContents_Init to set members back to default values The object itself is not freed */ void TPM_IdentityContents_Delete(TPM_IDENTITY_CONTENTS *tpm_identity_contents) { printf(" TPM_IdentityContents_Delete:\n"); if (tpm_identity_contents != NULL) { TPM_Pubkey_Delete(&(tpm_identity_contents->identityPubKey)); TPM_IdentityContents_Init(tpm_identity_contents); } return; } /* TPM_ASYM_CA_CONTENTS */ /* TPM_AsymCaContents_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_AsymCaContents_Init(TPM_ASYM_CA_CONTENTS *tpm_asym_ca_contents) { printf(" TPM_AsymCaContents_Init:\n"); TPM_SymmetricKey_Init(&(tpm_asym_ca_contents->sessionKey)); TPM_Digest_Init(tpm_asym_ca_contents->idDigest); return; } /* TPM_AsymCaContents_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_AsymCaContents_Init() After use, call TPM_AsymCaContents_Delete() to free memory */ TPM_RESULT TPM_AsymCaContents_Load(TPM_ASYM_CA_CONTENTS *tpm_asym_ca_contents, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_AsymCaContents_Load:\n"); if (rc == 0) { rc = TPM_SymmetricKey_Load(&(tpm_asym_ca_contents->sessionKey), stream, stream_size); } if (rc == 0) { rc = TPM_Digest_Load(tpm_asym_ca_contents->idDigest, stream, stream_size); } return rc; } #if 0 /* TPM_AsymCaContents_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_AsymCaContents_Store(TPM_STORE_BUFFER *sbuffer, const TPM_ASYM_CA_CONTENTS *tpm_asym_ca_contents) { TPM_RESULT rc = 0; printf(" TPM_AsymCaContents_Store:\n"); if (rc == 0) { rc = TPM_SymmetricKey_Store(sbuffer, &(tpm_asym_ca_contents->sessionKey)); } if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_asym_ca_contents->idDigest); } return rc; } #endif /* TPM_AsymCaContents_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_AsymCaContents_Init to set members back to default values The object itself is not freed */ void TPM_AsymCaContents_Delete(TPM_ASYM_CA_CONTENTS *tpm_asym_ca_contents) { printf(" TPM_AsymCaContents_Delete:\n"); if (tpm_asym_ca_contents != NULL) { TPM_SymmetricKey_Delete(&(tpm_asym_ca_contents->sessionKey)); TPM_AsymCaContents_Init(tpm_asym_ca_contents); } return; } /* Processing Functions */ /* 15.1 TPM_MakeIdentity rev 114 Generate a new Attestation Identity Key (AIK) labelPrivCADigest identifies the privacy CA that the owner expects to be the target CA for the AIK. The selection is not enforced by the TPM. It is advisory only. It is included because the TSS cannot be trusted to send the AIK to the correct privacy CA. The privacy CA can use this parameter to validate that it is the target privacy CA and label intended by the TPM owner at the time the key was created. The label can be used to indicate an application purpose. The public key of the new TPM identity SHALL be identityPubKey. The private key of the new TPM identity SHALL be tpm_signature_key. Properties of the new identity TPM_PUBKEY identityPubKey This SHALL be the public key of a previously unused asymmetric key pair. TPM_STORE_ASYMKEY tpm_signature_key This SHALL be the private key that forms a pair with identityPubKey and SHALL be extant only in a TPM-shielded location. This capability also generates a TPM_KEY containing the tpm_signature_key. If identityPubKey is stored on a platform it SHALL exist only in storage to which access is controlled and is available to authorized entities. */ TPM_RESULT TPM_Process_MakeIdentity(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_ENCAUTH identityAuth; /* Encrypted usage authorization data for the new identity */ TPM_CHOSENID_HASH labelPrivCADigest; /* The digest of the identity label and privacy CA chosen for the new TPM identity. */ TPM_KEY idKeyParams; /* Structure containing all parameters of new identity key. pubKey.keyLength & idKeyParams.encData are both 0 MAY be TPM_KEY12 */ TPM_AUTHHANDLE srkAuthHandle; /* The authorization handle used for SRK authorization. */ TPM_NONCE srknonceOdd; /* Nonce generated by system associated with srkAuthHandle */ TPM_BOOL continueSrkSession = TRUE; /* Ignored */ TPM_AUTHDATA srkAuth; /* The authorization digest for the inputs and the SRK. HMAC key: srk.usageAuth. */ TPM_AUTHHANDLE authHandle; /* The authorization handle used for owner authorization. Session type MUST be OSAP. */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* Ignored */ TPM_AUTHDATA ownerAuth; /* The authorization digest for inputs and owner. HMAC key: ownerAuth. */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL srkAuthHandleValid = FALSE; TPM_BOOL authHandleValid = FALSE; TPM_AUTH_SESSION_DATA *srk_auth_session_data = NULL; /* session data for authHandle */ TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for dataAuthHandle */ TPM_SECRET *srkHmacKey; TPM_SECRET *hmacKey; TPM_SECRET a1Auth; TPM_STORE_ASYMKEY *idKeyStoreAsymkey; TPM_IDENTITY_CONTENTS idContents; TPM_DIGEST h1Digest; /* digest of TPM_IDENTITY_CONTENTS structure */ int ver; /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_KEY idKey; /* The newly created identity key. MAY be TPM_KEY12 */ TPM_SIZED_BUFFER identityBinding; /* Signature of TPM_IDENTITY_CONTENTS using idKey.private. */ printf("TPM_Process_MakeIdentity: Ordinal Entry\n"); TPM_Key_Init(&idKeyParams); /* freed @1 */ TPM_Key_Init(&idKey); /* freed @2 */ TPM_SizedBuffer_Init(&identityBinding); /* freed @3 */ TPM_IdentityContents_Init(&idContents); /* freed @4 */ /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get identityAuth parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Authdata_Load(identityAuth, &command, ¶mSize); } /* get labelPrivCADigest parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Digest_Load(labelPrivCADigest, &command, ¶mSize); } /* get idKeyParams parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Key_Load(&idKeyParams, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag21(tag); } /* get the optional 'below the line' authorization parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { returnCode = TPM_AuthParams_Get(&srkAuthHandle, &srkAuthHandleValid, srknonceOdd, &continueSrkSession, srkAuth, &command, ¶mSize); printf("TPM_Process_MakeIdentity: srkAuthHandle %08x\n", srkAuthHandle); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, ownerAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_MakeIdentity: authHandle %08x\n", authHandle); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_MakeIdentity: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { srkAuthHandleValid = FALSE; authHandleValid = FALSE; } /* Processing */ /* 1. Validate the idKeyParams parameters for the key description */ /* a. If the algorithm type is RSA the key length MUST be a minimum of 2048 and MUST use the default exponent. For interoperability the key length SHOULD be 2048 */ /* b. If the algorithm type is other than RSA the strength provided by the key MUST be comparable to RSA 2048 */ /* c. If the TPM is not designed to create a key of the requested type, return the error code TPM_BAD_KEY_PROPERTY */ /* d. If TPM_PERMANENT_FLAGS -> FIPS is TRUE then */ /* i. If authDataUsage specifies TPM_AUTH_NEVER return TPM_NOTFIPS */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Key_CheckProperties(&ver, &idKeyParams, 2048, tpm_state->tpm_permanent_flags.FIPS); printf("TPM_Process_MakeIdentity: key parameters v = %d\n", ver); } /* 2. Use authHandle to verify that the Owner authorized all TPM_MakeIdentity input parameters. */ /* get the session data */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_OSAP, TPM_ET_OWNER, ordinal, NULL, NULL, tpm_state->tpm_permanent_data.ownerAuth); } /* Validate the authorization to use the key pointed to by keyHandle */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Auth2data_Check(tpm_state, *hmacKey, /* HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, ownerAuth); /* Authorization digest for input */ } /* 3. Use srkAuthHandle to verify that the SRK owner authorized all TPM_MakeIdentity input parameters. */ /* get the session data */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { returnCode = TPM_AuthSessions_GetData (&srk_auth_session_data, &srkHmacKey, tpm_state, srkAuthHandle, TPM_PID_NONE, TPM_ET_KEYHANDLE, ordinal, &(tpm_state->tpm_permanent_data.srk), /* OIAP */ &(tpm_state->tpm_permanent_data.srk.tpm_store_asymkey->usageAuth), /* OSAP */ tpm_state->tpm_permanent_data.srk.tpm_store_asymkey->pubDataDigest); } /* Validate the authorization to use the key pointed to by keyHandle */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { returnCode = TPM_Authdata_Check(tpm_state, *srkHmacKey, /* HMAC key */ inParamDigest, srk_auth_session_data, /* authorization session */ srknonceOdd, /* Nonce generated by system associated with authHandle */ continueSrkSession, srkAuth); /* Authorization digest for input */ } /* if there is no SRK authorization, check that the SRK authDataUsage is TPM_AUTH_NEVER */ if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_AUTH2_COMMAND)) { if (tpm_state->tpm_permanent_data.srk.authDataUsage != TPM_AUTH_NEVER) { printf("TPM_Process_MakeIdentity: Error, SRK authorization required\n"); returnCode = TPM_AUTHFAIL; } } /* 4. Verify that idKeyParams -> keyUsage is TPM_KEY_IDENTITY. If it is not, return TPM_INVALID_KEYUSAGE */ /* NOTE: TPM_KEY_IDENTITY keys must use TPM_SS_RSASSAPKCS1v15_SHA1 */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_MakeIdentity: Checking key parameters\n"); if (idKeyParams.keyUsage != TPM_KEY_IDENTITY) { printf("TPM_Process_MakeIdentity: Error, " "idKeyParams keyUsage %08x should be TPM_KEY_IDENTITY\n", idKeyParams.keyUsage); returnCode = TPM_INVALID_KEYUSAGE; } } /* 5. Verify that idKeyParams -> keyFlags -> migratable is FALSE. If it is not, return TPM_INVALID_KEYUSAGE */ if (returnCode == TPM_SUCCESS) { if (idKeyParams.keyFlags & TPM_MIGRATABLE) { printf("TPM_Process_MakeIdentity: Error, " "idKeyParams keyFlags %08x cannot be migratable\n", idKeyParams.keyFlags); returnCode = TPM_INVALID_KEYUSAGE; } } /* 6. Create a1 by decrypting identityAuth according to the ADIP indicated by authHandle. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessionData_Decrypt(a1Auth, NULL, identityAuth, auth_session_data, NULL, NULL, FALSE); /* even and odd */ } /* 7. Set continueAuthSession and continueSRKSession to FALSE. */ if (returnCode == TPM_SUCCESS) { continueAuthSession = FALSE; continueSrkSession = FALSE; /* 8. Determine the structure version */ /* a. If idKeyParams -> tag is TPM_TAG_KEY12 */ /* i. Set V1 to 2 */ /* ii. Create idKey a TPM_KEY12 structure using idKeyParams as the default values for the structure */ /* b. If idKeyParams -> ver is 1.1 */ /* i. Set V1 to 1 */ /* ii. Create idKey a TPM_KEY structure using idKeyParams as the default values for the structure */ /* NOTE Done by TPM_Key_CheckProperties() */ /* NOTE The creation determination is done by TPM_Key_GenerateRSA() */ } /* 9. Set the digestAtCreation values for pcrInfo */ /* NOTE Done as the key is generated */ /* a. For PCR_INFO_LONG include the locality of the current command */ /* 10. Create an asymmetric key pair (identityPubKey and tpm_signature_key) using a TPM-protected capability, in accordance with the algorithm specified in idKeyParams */ if (returnCode == TPM_SUCCESS) { /* generate the key pair, create the tpm_store_asymkey cache, copy key parameters, create tpm_pcr_info cache, copies pcr parameters, sets digestAtCreation, sets pubKey, serializes pcrInfo does not set encData */ printf("TPM_Process_MakeIdentity: Generating key\n"); returnCode = TPM_Key_GenerateRSA(&idKey, tpm_state, &(tpm_state->tpm_permanent_data.srk), /* parent key */ tpm_state->tpm_stclear_data.PCRS, /* PCR array */ ver, idKeyParams.keyUsage, idKeyParams.keyFlags, idKeyParams.authDataUsage, /* TPM_AUTH_DATA_USAGE */ &(idKeyParams.algorithmParms), /* TPM_KEY_PARMS */ idKeyParams.tpm_pcr_info, /* TPM_PCR_INFO */ idKeyParams.tpm_pcr_info_long);/* TPM_PCR_INFO_LONG */ } /* 11. Ensure that the authorization information in A1 is properly stored in the idKey as usageAuth. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Key_GetStoreAsymkey(&idKeyStoreAsymkey, &idKey); } if (returnCode == TPM_SUCCESS) { TPM_Secret_Copy(idKeyStoreAsymkey->usageAuth, a1Auth); /* 12. Attach identityPubKey and tpm_signature_key to idKey */ /* Note: Done as the key is generated */ /* 13. Set idKey -> migrationAuth to TPM_PERMANENT_DATA -> tpmProof */ TPM_Secret_Copy(idKeyStoreAsymkey->migrationAuth, tpm_state->tpm_permanent_data.tpmProof); /* 14. Ensure that all TPM_PAYLOAD_TYPE structures identity this key as TPM_PT_ASYM */ /* NOTE Done as the key is generated */ } /* 15. Encrypt the private portion of idKey using the SRK as the parent key */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_MakeIdentity: Encrypting key private part with SRK\n"); returnCode = TPM_Key_GenerateEncData(&idKey, &(tpm_state->tpm_permanent_data.srk)); } /* 16. Create a TPM_IDENTITY_CONTENTS structure named idContents using labelPrivCADigest and the information from idKey */ if (returnCode == TPM_SUCCESS) { TPM_Digest_Copy(idContents.labelPrivCADigest, labelPrivCADigest); returnCode = TPM_Pubkey_Set(&(idContents.identityPubKey), &idKey); } /* 17. Sign idContents using tpm_signature_key and TPM_SS_RSASSAPKCS1v15_SHA1. Store the result in identityBinding. */ /* NOTE: TPM_Key_CheckProperties() verified TPM_SS_RSASSAPKCS1v15_SHA1 */ /* serialize tpm_identity_contents and hash the results*/ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SHA1_GenerateStructure(h1Digest, &idContents, (TPM_STORE_FUNCTION_T)TPM_IdentityContents_Store); } /* sign the digest */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_MakeIdentity: Signing digest of TPM_IDENTITY_CONTENTS\n"); returnCode = TPM_RSASignToSizedBuffer(&identityBinding, h1Digest, TPM_DIGEST_SIZE, &idKey); } #if 0 /* NOTE Debug code to reverse the signature */ if (returnCode == TPM_SUCCESS) { unsigned char *message = NULL; unsigned char *narr = NULL; uint32_t nbytes; unsigned char *earr = NULL; uint32_t ebytes; if (returnCode == 0) { returnCode = TPM_Malloc(&message, identityBinding.size); /* freed @10 */ } if (returnCode == 0) { returnCode = TPM_Key_GetPublicKey(&nbytes, &narr, &idKey); } if (returnCode == 0) { returnCode = TPM_Key_GetExponent(&ebytes, &earr, &idKey); } if (returnCode == 0) { returnCode = TPM_RSAPublicEncryptRaw(message, /* output */ identityBinding.size, identityBinding.buffer, /* input */ identityBinding.size, narr, /* public modulus */ nbytes, earr, /* public exponent */ ebytes); } free(message); /* @10 */ } #endif /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_MakeIdentity: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* return idKey */ returnCode = TPM_Key_Store(response, &idKey); } if (returnCode == TPM_SUCCESS) { /* return identityBinding */ returnCode = TPM_SizedBuffer_Store(response, &identityBinding); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { returnCode = TPM_AuthParams_Set(response, *srkHmacKey, /* owner HMAC key */ srk_auth_session_data, outParamDigest, srknonceOdd, continueSrkSession); } /* calculate and set the below the line parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* owner HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueSrkSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueSrkSession) && srkAuthHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, srkAuthHandle); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ TPM_Key_Delete(&idKeyParams); /* freed @1 */ TPM_Key_Delete(&idKey); /* freed @2 */ TPM_SizedBuffer_Delete(&identityBinding); /* freed @3 */ TPM_IdentityContents_Delete(&idContents); /* freed @4 */ return rcf; } /* 15.2 TPM_ActivateIdentity rev 107 The purpose of TPM_ActivateIdentity is to twofold. The first purpose is to obtain assurance that the credential in the TPM_SYM_CA_ATTESTATION is for this TPM. The second purpose is to obtain the session key used to encrypt the TPM_IDENTITY_CREDENTIAL. The command TPM_ActivateIdentity activates a TPM identity created using the command TPM_MakeIdentity. The command assumes the availability of the private key associated with the identity. The command will verify the association between the keys during the process. The command will decrypt the input blob and extract the session key and verify the connection between the public and private keys. The input blob can be in 1.1 or 1.2 format. */ TPM_RESULT TPM_Process_ActivateIdentity(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_KEY_HANDLE idKeyHandle; /* handle of identity key to be activated */ TPM_SIZED_BUFFER blob; /* The encrypted ASYM_CA_CONTENTS or TPM_EK_BLOB */ TPM_AUTHHANDLE idKeyAuthHandle; /* The authorization handle used for ID key authorization. */ TPM_NONCE idKeynonceOdd; /* Nonce generated by system associated with idKeyAuthHandle */ TPM_BOOL continueIdKeySession = TRUE; /* Continue usage flag for idKeyAuthHandle. */ TPM_AUTHDATA idKeyAuth; /* The authorization digest for the inputs and ID key. HMAC key: idKey.usageAuth. */ TPM_AUTHHANDLE authHandle; /* The authorization handle used for owner authorization. */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization handle */ TPM_AUTHDATA ownerAuth; /* The authorization digest for inputs and owner. HMAC key: ownerAuth. */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL idKeyAuthHandleValid = FALSE; TPM_BOOL authHandleValid = FALSE; TPM_AUTH_SESSION_DATA *id_key_auth_session_data = NULL; /* session data for authHandle */ TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for dataAuthHandle */ TPM_SECRET *idKeyHmacKey; TPM_SECRET *hmacKey; TPM_KEY *idKey; /* Identity key to be activated */ TPM_SECRET *idKeyUsageAuth; TPM_BOOL idPCRStatus; TPM_DIGEST h1Digest; /* digest of public key in idKey */ unsigned char *b1Blob = NULL; /* decrypted blob */ uint32_t b1BlobLength = 0; /* actual valid data */ TPM_STRUCTURE_TAG hTag; /* b1 tag in host byte order */ int vers = 0; /* version of blob */ unsigned char *stream; uint32_t stream_size; TPM_EK_BLOB b1EkBlob; TPM_ASYM_CA_CONTENTS b1AsymCaContents; TPM_SYMMETRIC_KEY *k1 = NULL; TPM_EK_BLOB_ACTIVATE a1; /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_SYMMETRIC_KEY symmetricKey; /* The decrypted symmetric key. */ printf("TPM_Process_ActivateIdentity: Ordinal Entry\n"); TPM_SizedBuffer_Init(&blob); /* freed @1 */ TPM_SymmetricKey_Init(&symmetricKey); /* freed @2 */ TPM_AsymCaContents_Init(&b1AsymCaContents); /* freed @4 */ TPM_EKBlob_Init(&b1EkBlob); /* freed @5 */ TPM_EKBlobActivate_Init(&a1); /* freed @6 */ /* get inputs */ /* get idKey parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&idKeyHandle, &command, ¶mSize); } /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get blob parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_Load(&blob, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag21(tag); } /* get the optional 'below the line' authorization parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { returnCode = TPM_AuthParams_Get(&idKeyAuthHandle, &idKeyAuthHandleValid, idKeynonceOdd, &continueIdKeySession, idKeyAuth, &command, ¶mSize); printf("TPM_Process_ActivateIdentity: idKeyAuthHandle %08x\n", idKeyAuthHandle); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, ownerAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_ActivateIdentity: authHandle %08x\n", authHandle); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_ActivateIdentity: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { idKeyAuthHandleValid = FALSE; authHandleValid = FALSE; } /* Processing */ /* 1. Using the authHandle field, validate the owner's authorization to execute the command and all of the incoming parameters. */ /* get the session data */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_OWNER, ordinal, NULL, &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ } /* Validate the authorization to use the key pointed to by keyHandle */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, ownerAuth); /* Authorization digest for input */ } /* 2. Using the idKeyAuthHandle, validate the authorization to execute command and all of the incoming parameters */ /* get the idKey */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyHandleEntries_GetKey(&idKey, &idPCRStatus, tpm_state, idKeyHandle, FALSE, /* not r/o, using to authenticate */ FALSE, /* do not ignore PCRs */ FALSE); /* cannot use EK */ } /* get keyHandle -> usageAuth */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Key_GetUsageAuth(&idKeyUsageAuth, idKey); } /* get the session data */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { returnCode = TPM_AuthSessions_GetData(&id_key_auth_session_data, &idKeyHmacKey, tpm_state, idKeyAuthHandle, TPM_PID_NONE, TPM_ET_KEYHANDLE, ordinal, idKey, idKeyUsageAuth, /* OIAP */ idKey->tpm_store_asymkey->pubDataDigest); /* OSAP */ } /* Validate the authorization to use the key pointed to by keyHandle */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { returnCode = TPM_Auth2data_Check(tpm_state, *idKeyHmacKey, /* HMAC key */ inParamDigest, id_key_auth_session_data, /* authorization session */ idKeynonceOdd, /* Nonce generated by system associated with authHandle */ continueIdKeySession, idKeyAuth); /* Authorization digest for input */ } /* if there is no idKey authorization, check that the idKey -> authDataUsage is TPM_AUTH_NEVER */ if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_AUTH2_COMMAND)) { if (idKey->authDataUsage != TPM_AUTH_NEVER) { printf("TPM_Process_ActivateIdentity: Error, ID key authorization required\n"); returnCode = TPM_AUTHFAIL; } } /* 3. Validate that the idKey is the public key of a valid TPM identity by checking that idKeyHandle -> keyUsage is TPM_KEY_IDENTITY. Return TPM_BAD_PARAMETER on mismatch */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_ActivateIdentity: Checking for identity key\n"); if (idKey->keyUsage != TPM_KEY_IDENTITY) { printf("TPM_Process_ActivateIdentity: Error, keyUsage %04hx must be TPM_KEY_IDENTITY\n", idKey->keyUsage); returnCode = TPM_BAD_PARAMETER; } } /* 4. Create H1 the digest of a TPM_PUBKEY derived from idKey */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Key_GeneratePubkeyDigest(h1Digest, idKey); } /* 5. Decrypt blob creating B1 using PRIVEK as the decryption key */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_ActivateIdentity: Decrypting blob with EK\n"); returnCode = TPM_RSAPrivateDecryptMalloc(&b1Blob, /* decrypted data */ &b1BlobLength, /* actual size of b1 data */ blob.buffer, blob.size, &(tpm_state->tpm_permanent_data.endorsementKey)); } /* 6. Determine the type and version of B1 */ if (returnCode == TPM_SUCCESS) { stream = b1Blob; /* b1 must be preserved for the free */ stream_size = b1BlobLength; /* convert possible tag to uint16_t */ hTag = ntohs(*(TPM_STRUCTURE_TAG *)b1Blob); /* a. If B1 -> tag is TPM_TAG_EK_BLOB then */ if (hTag == TPM_TAG_EK_BLOB) { /* i. B1 is a TPM_EK_BLOB */ printf("TPM_Process_ActivateIdentity: b1 is TPM_EK_BLOB\n"); vers = 2; returnCode = TPM_EKBlob_Load(&b1EkBlob, &stream, &stream_size); } /* b. Else */ else { /* i. B1 is a TPM_ASYM_CA_CONTENTS. As there is no tag for this structure it is possible for the TPM to make a mistake here but other sections of the structure undergo validation */ printf("TPM_Process_ActivateIdentity: b1 is TPM_ASYM_CA_CONTENTS\n"); vers = 1; returnCode = TPM_AsymCaContents_Load(&b1AsymCaContents, &stream, &stream_size); } } /* 7. If B1 is a version 1.1 TPM_ASYM_CA_CONTENTS then */ if ((returnCode == TPM_SUCCESS) && (vers == 1)) { /* a. Compare H1 to B1 -> idDigest on mismatch return TPM_BAD_PARAMETER */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Digest_Compare(h1Digest, b1AsymCaContents.idDigest); if (returnCode != 0) { printf("TPM_Process_ActivateIdentity: Error " "comparing TPM_ASYM_CA_CONTENTS idDigest\n"); returnCode = TPM_BAD_PARAMETER; } } /* b. Set K1 to B1 -> sessionKey */ if (returnCode == TPM_SUCCESS) { k1 = &(b1AsymCaContents.sessionKey); } } /* 8. If B1 is a TPM_EK_BLOB then */ if ((returnCode == TPM_SUCCESS) && (vers == 2)) { /* a. Validate that B1 -> ekType is TPM_EK_TYPE_ACTIVATE, return TPM_BAD_TYPE if not. */ if (returnCode == TPM_SUCCESS) { if (b1EkBlob.ekType != TPM_EK_TYPE_ACTIVATE) { printf("TPM_Process_ActivateIdentity: Error, " "TPM_EK_BLOB not ekType TPM_EK_TYPE_ACTIVATE\n"); returnCode = TPM_BAD_TYPE; } } /* b. Assign A1 as a TPM_EK_BLOB_ACTIVATE structure from B1 -> blob */ if (returnCode == TPM_SUCCESS) { stream = b1EkBlob.blob.buffer; stream_size = b1EkBlob.blob.size; returnCode = TPM_EKBlobActivate_Load(&a1, &stream, &stream_size); } /* c. Compare H1 to A1 -> idDigest on mismatch return TPM_BAD_PARAMETER */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Digest_Compare(h1Digest, a1.idDigest); if (returnCode != 0) { printf("TPM_Process_ActivateIdentity: Error " "comparing TPM_EK_TYPE_ACTIVATE idDigest\n"); returnCode = TPM_BAD_PARAMETER; } } /* d. If A1 -> pcrSelection is not NULL */ /* i. Compute a composite hash C1 using the PCR selection A1 -> pcrSelection */ /* ii. Compare C1 to A1 -> pcrInfo -> digestAtRelease and return TPM_WRONGPCRVAL on a mismatch */ /* e. If A1 -> pcrInfo specifies a locality ensure that the appropriate locality has been asserted, return TPM_BAD_LOCALITY on error */ if (returnCode == TPM_SUCCESS) { if (returnCode == TPM_SUCCESS) { returnCode = TPM_PCRInfoShort_CheckDigest(&(a1.pcrInfo), tpm_state->tpm_stclear_data.PCRS, /* PCR array */ tpm_state->tpm_stany_flags.localityModifier); } } /* f. Set K1 to A1 -> symmetricKey */ if (returnCode == TPM_SUCCESS) { k1 = &(a1.sessionKey); } } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_ActivateIdentity: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* 9. Return K1 */ returnCode = TPM_SymmetricKey_Store(response, k1); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { returnCode = TPM_AuthParams_Set(response, *idKeyHmacKey, /* owner HMAC key */ id_key_auth_session_data, outParamDigest, idKeynonceOdd, continueIdKeySession); } /* calculate and set the below the line parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* owner HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueIdKeySession) && idKeyAuthHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, idKeyAuthHandle); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ TPM_SizedBuffer_Delete(&blob); /* @1 */ TPM_SymmetricKey_Delete(&symmetricKey); /* @2 */ free(b1Blob); /* @3 */ TPM_AsymCaContents_Delete(&b1AsymCaContents); /* @4 */ TPM_EKBlob_Delete(&b1EkBlob); /* @5 */ TPM_EKBlobActivate_Delete(&a1); /* @6 */ return rcf; } libtpms-0.9.3/src/tpm12/tpm_identity.h000066400000000000000000000135631421143571500176240ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM Identity Handling */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_identity.h 4071 2010-04-29 19:26:45Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_IDENTITY_H #define TPM_IDENTITY_H #include "tpm_global.h" /* TPM_EK_BLOB */ void TPM_EKBlob_Init(TPM_EK_BLOB *tpm_ek_blob); TPM_RESULT TPM_EKBlob_Load(TPM_EK_BLOB *tpm_ek_blob, unsigned char **stream, uint32_t *stream_size); #if 0 TPM_RESULT TPM_EKBlob_Store(TPM_STORE_BUFFER *sbuffer, const TPM_EK_BLOB *tpm_ek_blob); #endif void TPM_EKBlob_Delete(TPM_EK_BLOB *tpm_ek_blob); /* TPM_EK_BLOB_ACTIVATE */ void TPM_EKBlobActivate_Init(TPM_EK_BLOB_ACTIVATE *tpm_ek_blob_activate); TPM_RESULT TPM_EKBlobActivate_Load(TPM_EK_BLOB_ACTIVATE *tpm_ek_blob_activate, unsigned char **stream, uint32_t *stream_size); #if 0 TPM_RESULT TPM_EKBlobActivate_Store(TPM_STORE_BUFFER *sbuffer, const TPM_EK_BLOB_ACTIVATE *tpm_ek_blob_activate); #endif void TPM_EKBlobActivate_Delete(TPM_EK_BLOB_ACTIVATE *tpm_ek_blob_activate); /* TPM_EK_BLOB_AUTH */ #if 0 void TPM_EKBlobAuth_Init(TPM_EK_BLOB_AUTH *tpm_ek_blob_auth); TPM_RESULT TPM_EKBlobAuth_Load(TPM_EK_BLOB_AUTH *tpm_ek_blob_auth, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_EKBlobAuth_Store(TPM_STORE_BUFFER *sbuffer, const TPM_EK_BLOB_AUTH *tpm_ek_blob_auth); void TPM_EKBlobAuth_Delete(TPM_EK_BLOB_AUTH *tpm_ek_blob_auth); #endif /* TPM_IDENTITY_CONTENTS */ void TPM_IdentityContents_Init(TPM_IDENTITY_CONTENTS *tpm_identity_contents); #if 0 TPM_RESULT TPM_IdentityContents_Load(TPM_IDENTITY_CONTENTS *tpm_identity_contents, unsigned char **stream, uint32_t *stream_size); #endif TPM_RESULT TPM_IdentityContents_Store(TPM_STORE_BUFFER *sbuffer, TPM_IDENTITY_CONTENTS *tpm_identity_contents); void TPM_IdentityContents_Delete(TPM_IDENTITY_CONTENTS *tpm_identity_contents); /* TPM_ASYM_CA_CONTENTS */ void TPM_AsymCaContents_Init(TPM_ASYM_CA_CONTENTS *tpm_asym_ca_contents); TPM_RESULT TPM_AsymCaContents_Load(TPM_ASYM_CA_CONTENTS *tpm_asym_ca_contents, unsigned char **stream, uint32_t *stream_size); #if 0 TPM_RESULT TPM_AsymCaContents_Store(TPM_STORE_BUFFER *sbuffer, const TPM_ASYM_CA_CONTENTS *tpm_asym_ca_contents); #endif void TPM_AsymCaContents_Delete(TPM_ASYM_CA_CONTENTS *tpm_asym_ca_contents); /* Processing Functions */ TPM_RESULT TPM_Process_MakeIdentity(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_ActivateIdentity(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); #endif libtpms-0.9.3/src/tpm12/tpm_init.c000066400000000000000000001163501421143571500167270ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM Initialization */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_init.c 4623 2011-09-28 15:15:09Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include #include #include #include #include "tpm_admin.h" #include "tpm_cryptoh.h" #include "tpm_crypto.h" #include "tpm_daa.h" #include "tpm_debug.h" #include "tpm_digest.h" #include "tpm_error.h" #include "tpm_io.h" #include "tpm_memory.h" #include "tpm_nonce.h" #include "tpm_nvfile.h" #include "tpm_pcr.h" #include "tpm_process.h" #include "tpm_permanent.h" #include "tpm_platform.h" #include "tpm_session.h" #include "tpm_startup.h" #include "tpm_structures.h" #include "tpm_ticks.h" #include "tpm_transport.h" #include "tpm_init.h" /* local prototypes */ static TPM_RESULT TPM_CheckTypes(void); /* TPM_Init transitions the TPM from a power-off state to one where the TPM begins an initialization process. TPM_Init could be the result of power being applied to the platform or a hard reset. TPM_Init sets an internal flag to indicate that the TPM is undergoing initialization. The TPM must complete initialization before it is operational. The completion of initialization requires the receipt of the TPM_Startup command. This is different from the debug function TPM_Process_Init(), which initializes a TPM. The call tree for initialization is as follows: main() TPM_MainInit() TPM_IO_Init() - initializes the TPM I/O interface TPM_Crypto_Init() - initializes cryptographic libraries TPM_NVRAM_Init() - get NVRAM path once TPM_LimitedSelfTest() - as per the specification TPM_Global_Init() - initializes the TPM state Returns: 0 on success non-zero on a fatal error where the TPM should not continue. These are fatal errors where the TPM just exits. It can't even enter shutdown. A self test error may cause one or all TPM's to enter shutdown, but is not fatal. */ TPM_RESULT TPM_MainInit(void) { TPM_RESULT rc = 0; /* results for common code, fatal errors */ uint32_t i; TPM_RESULT testRc = 0; /* temporary place to hold common self tests failure before the tpm state is created */ tpm_state_t *tpm_state; /* TPM instance state */ bool has_cached_state = false; tpm_state = NULL; /* freed @1 */ /* preliminary check that platform specific sizes are correct */ if (rc == 0) { rc = TPM_CheckTypes(); } /* initialize the TPM to host interface */ if (rc == 0) { printf("TPM_MainInit: Initialize the TPM to host interface\n"); rc = TPM_IO_Init(); } /* initialize cryptographic functions */ if (rc == 0) { printf("TPM_MainInit: Initialize the TPM crypto support\n"); rc = TPM_Crypto_Init(); } /* initialize NVRAM static variables. This must be called before the global TPM state is loaded */ if (rc == 0) { printf("TPM_MainInit: Initialize the TPM NVRAM\n"); rc = TPM_NVRAM_Init(); } /* run the initial subset of self tests once */ if (rc == 0) { printf("TPM_MainInit: Run common limited self tests\n"); /* an error is a fatal error, causes a shutdown of the TPM */ testRc = TPM_LimitedSelfTestCommon(); } /* initialize the global structure for the TPM */ for (i = 0 ; (rc == 0) && (i < TPMS_MAX) ; i++) { printf("TPM_MainInit: Initializing global TPM %lu\n", (unsigned long)i); /* Need to malloc and init a TPM state if this is the first time through or if the state was saved in the array. Otherwise, the malloc'ed structure from the previous time through the loop can be reused. */ if ((rc == 0) && (tpm_state == NULL)) { if (rc == 0) { rc = TPM_Malloc((unsigned char **)&tpm_state, sizeof(tpm_state_t)); } /* initialize the global instance state */ if (rc == 0) { rc = TPM_Global_Init(tpm_state); /* freed @2 */ } } if (rc == 0) { has_cached_state = HasCachedState(TPMLIB_STATE_PERMANENT); /* record the TPM number in the state */ tpm_state->tpm_number = i; /* If the instance exists in NVRAM, it it initialized and saved in the tpm_instances[] array. Restores TPM_PERMANENT_FLAGS and TPM_PERMANENT_DATA to in-memory structures. */ /* Returns TPM_RETRY on non-existent file */ rc = TPM_PermanentAll_NVLoad(tpm_state); } /* If there was no state for TPM 0 (instance 0 does not exist), initialize state for the first time using TPM_Global_Init() above. It is created and set to default values. */ if ((rc == TPM_RETRY) && (i == 0)) { /* save the state for TPM 0 (first time through) */ rc = TPM_PermanentAll_NVStore(tpm_state, TRUE, /* write NV */ 0); /* no roll back */ } #ifdef TPM_VOLATILE_LOAD /* if volatile state exists at startup, load it. This is used for fail-over restart. */ if (rc == 0) { rc = TPM_VolatileAll_NVLoad(tpm_state); } #endif /* TPM_VOLATILE_LOAD */ /* libtpms: due to the SetState() API we have to write the permanent state back to a file now */ if (rc == 0 && has_cached_state) { rc = TPM_PermanentAll_NVStore(tpm_state, TRUE, /* write NV */ 0); /* no roll back */ } /* if permanent state was loaded successfully (or stored successfully for TPM 0 the first time) */ if (rc == 0) { printf("TPM_MainInit: Creating global TPM instance %lu\n", (unsigned long)i); /* set the testState for the TPM based on the common selftest result */ if (testRc != 0) { /* a. When the TPM detects a failure during any self-test, it SHOULD delete values preserved by TPM_SaveState. */ TPM_SaveState_NVDelete(tpm_state, FALSE); /* ignore error if the state does not exist */ printf(" TPM_MainInit: Set testState to %u \n", TPM_TEST_STATE_FAILURE); tpm_state->testState = TPM_TEST_STATE_FAILURE; } /* save state in array */ tpm_instances[i] = tpm_state; tpm_state = NULL; /* flag that the malloc'ed structure was used. It should not be freed, and a new instance is needed the next time through the loop */ } /* If there was the non-fatal error TPM_RETRY, the instance does not exist. If instance > 0 does not exist, the array entry is set to NULL. Continue */ else if (rc == TPM_RETRY) { printf("TPM_MainInit: Not Creating global TPM %lu\n", (unsigned long)i); tpm_instances[i] = NULL; /* flag that the instance does not exist */ rc = 0; /* Instance does not exist, not fatal error */ } } /* run individual self test on a TPM */ for (i = 0 ; (rc == 0) && (i < TPMS_MAX) && (tpm_instances[i] != NULL) && (tpm_instances[i]->testState != TPM_TEST_STATE_FAILURE) ; /* don't continue if already error */ i++) { printf("TPM_MainInit: Run limited self tests on TPM %lu\n", (unsigned long)i); testRc = TPM_LimitedSelfTestTPM(tpm_instances[i]); if (testRc != 0) { /* a. When the TPM detects a failure during any self-test, it SHOULD delete values preserved by TPM_SaveState. */ TPM_SaveState_NVDelete(tpm_state, FALSE); /* ignore error if the state does not exist */ } } /* the _Delete(), free() clean up if the last created instance was not required */ TPM_Global_Delete(tpm_state); /* @2 */ free(tpm_state); /* @1 */ return rc; } /* TPM_CheckTypes() checks that the assumed TPM types are correct for the platform */ static TPM_RESULT TPM_CheckTypes(void) { TPM_RESULT rc = 0; /* fatal errors */ /* These should be removed at compile time */ if (rc == 0) { if (sizeof(uint16_t) != 2) { printf("TPM_CheckTypes: Error (fatal), uint16_t size %lu not supported\n", (unsigned long)sizeof(uint16_t)); rc = TPM_FAIL; } } if (rc == 0) { if (sizeof(uint32_t) != 4) { printf("TPM_CheckTypes: Error (fatal), uint32_t size %lu not supported\n", (unsigned long)sizeof(uint32_t)); rc = TPM_FAIL; } } if (rc == 0) { if ((sizeof(time_t) != 4) && /* for 32-bit machines */ (sizeof(time_t) != 8)) { /* for 64-bit machines */ printf("TPM_CheckTypes: Error (fatal), time_t size %lu not supported\n", (unsigned long)sizeof(time_t)); rc = TPM_FAIL; } } return rc; } /* TPM_STANY_FLAGS */ /* TPM_StanyFlags_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_StanyFlags_Init(TPM_STANY_FLAGS *tpm_stany_flags) { printf(" TPM_StanyFlags_Init:\n"); tpm_stany_flags->postInitialise = TRUE; tpm_stany_flags->localityModifier = 0; tpm_stany_flags->transportExclusive = 0; tpm_stany_flags->TOSPresent = FALSE; /* NOTE added */ tpm_stany_flags->stateSaved = FALSE; return; } /* TPM_StanyFlags_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_StanyFlags_Init() */ TPM_RESULT TPM_StanyFlags_Load(TPM_STANY_FLAGS *tpm_stany_flags, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_StanyFlags_Load:\n"); /* check tag */ if (rc == 0) { rc = TPM_CheckTag(TPM_TAG_STANY_FLAGS, stream, stream_size); } /* load postInitialise*/ if (rc == 0) { rc = TPM_LoadBool(&(tpm_stany_flags->postInitialise), stream, stream_size); } /* load localityModifier */ if (rc == 0) { rc = TPM_Load32(&(tpm_stany_flags->localityModifier), stream, stream_size); } /* load transportExclusive */ if (rc == 0) { rc = TPM_Load32(&(tpm_stany_flags->transportExclusive), stream, stream_size); } /* load TOSPresent */ if (rc == 0) { rc = TPM_LoadBool(&(tpm_stany_flags->TOSPresent), stream, stream_size); } /* load stateSaved */ if (rc == 0) { rc = TPM_LoadBool(&(tpm_stany_flags->stateSaved), stream, stream_size); } return rc; } /* TPM_StanyFlags_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_StanyFlags_Store(TPM_STORE_BUFFER *sbuffer, TPM_STANY_FLAGS *tpm_stany_flags) { TPM_RESULT rc = 0; printf(" TPM_StanyFlags_Store:\n"); /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_STANY_FLAGS); } /* store postInitialise*/ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_stany_flags->postInitialise), sizeof(TPM_BOOL)); } /* store localityModifier */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_stany_flags->localityModifier); } /* store transportExclusive */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_stany_flags->transportExclusive); } /* store TOSPresent */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_stany_flags->TOSPresent), sizeof(TPM_BOOL)); } /* store stateSaved */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_stany_flags->stateSaved), sizeof(TPM_BOOL)); } return rc; } /* TPM_STCLEAR_FLAGS */ /* TPM_StclearFlags_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_StclearFlags_Init(TPM_STCLEAR_FLAGS *tpm_stclear_flags) { printf(" TPM_StclearFlags_Init:\n"); /* tpm_stclear_flags->deactivated; no default state */ tpm_stclear_flags->disableForceClear = FALSE; tpm_stclear_flags->physicalPresence = FALSE; tpm_stclear_flags->physicalPresenceLock = FALSE; tpm_stclear_flags->bGlobalLock = FALSE; return; } /* TPM_StclearFlags_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_StclearFlags_Init() */ TPM_RESULT TPM_StclearFlags_Load(TPM_STCLEAR_FLAGS *tpm_stclear_flags, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_StclearFlags_Load:\n"); /* check tag */ if (rc == 0) { rc = TPM_CheckTag(TPM_TAG_STCLEAR_FLAGS, stream, stream_size); } /* load deactivated */ if (rc == 0) { rc = TPM_LoadBool(&(tpm_stclear_flags->deactivated), stream, stream_size); } /* load disableForceClear */ if (rc == 0) { rc = TPM_LoadBool(&(tpm_stclear_flags->disableForceClear), stream, stream_size); } /* load physicalPresence */ if (rc == 0) { rc = TPM_LoadBool(&(tpm_stclear_flags->physicalPresence), stream, stream_size); } /* load physicalPresenceLock */ if (rc == 0) { rc = TPM_LoadBool(&(tpm_stclear_flags->physicalPresenceLock), stream, stream_size); } /* load bGlobalLock */ if (rc == 0) { rc = TPM_LoadBool(&(tpm_stclear_flags->bGlobalLock), stream, stream_size); } return rc; } /* TPM_StclearFlags_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_StclearFlags_Store(TPM_STORE_BUFFER *sbuffer, const TPM_STCLEAR_FLAGS *tpm_stclear_flags) { TPM_RESULT rc = 0; printf(" TPM_StclearFlags_Store:\n"); /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_STCLEAR_FLAGS); } /* store deactivated */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_stclear_flags->deactivated), sizeof(TPM_BOOL)); } /* store disableForceClear */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_stclear_flags->disableForceClear), sizeof(TPM_BOOL)); } /* store physicalPresence */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_stclear_flags->physicalPresence), sizeof(TPM_BOOL)); } /* store physicalPresenceLock */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_stclear_flags->physicalPresenceLock), sizeof(TPM_BOOL)); } /* store bGlobalLock */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_stclear_flags->bGlobalLock), sizeof(TPM_BOOL)); } return rc; } /* TPM_StclearFlags_StoreBitmap() serializes TPM_STCLEAR_FLAGS structure into a bit map */ TPM_RESULT TPM_StclearFlags_StoreBitmap(uint32_t *tpm_bitmap, const TPM_STCLEAR_FLAGS *tpm_stclear_flags) { TPM_RESULT rc = 0; uint32_t pos = 0; /* position in bitmap */ printf(" TPM_StclearFlags_StoreBitmap:\n"); *tpm_bitmap = 0; /* store deactivated */ if (rc == 0) { rc = TPM_Bitmap_Store(tpm_bitmap, tpm_stclear_flags->deactivated, &pos); } /* store disableForceClear */ if (rc == 0) { rc = TPM_Bitmap_Store(tpm_bitmap, tpm_stclear_flags->disableForceClear, &pos); } /* store physicalPresence */ if (rc == 0) { rc = TPM_Bitmap_Store(tpm_bitmap, tpm_stclear_flags->physicalPresence, &pos); } /* store physicalPresenceLock */ if (rc == 0) { rc = TPM_Bitmap_Store(tpm_bitmap, tpm_stclear_flags->physicalPresenceLock, &pos); } /* store bGlobalLock */ if (rc == 0) { rc = TPM_Bitmap_Store(tpm_bitmap, tpm_stclear_flags->bGlobalLock, &pos); } return rc; } /* TPM_STANY_DATA */ /* TPM_StanyData_Init() sets members to default values sets all pointers to NULL and sizes to 0 */ TPM_RESULT TPM_StanyData_Init(TPM_STANY_DATA *tpm_stany_data) { TPM_RESULT rc = 0; printf(" TPM_StanyData_Init:\n"); if (rc == 0) { /* The tpm_stany_data->currentTicks holds the time of day at initialization. Both nonce generation and current time of day can return an error */ TPM_CurrentTicks_Init(&(tpm_stany_data->currentTicks)); rc = TPM_CurrentTicks_Start(&(tpm_stany_data->currentTicks)); } return rc; } /* TPM_StanyData_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_StanyData_Init() After use, call TPM_StanyData_Delete() to free memory */ TPM_RESULT TPM_StanyData_Load(TPM_STANY_DATA *tpm_stany_data, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_StanyData_Load:\n"); tpm_stany_data = tpm_stany_data; /* check tag */ if (rc == 0) { rc = TPM_CheckTag(TPM_TAG_STANY_DATA, stream, stream_size); } /* load currentTicks */ if (rc == 0) { rc = TPM_CurrentTicks_LoadAll(&(tpm_stany_data->currentTicks), stream, stream_size); } return rc; } /* TPM_StanyData_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_StanyData_Store(TPM_STORE_BUFFER *sbuffer, TPM_STANY_DATA *tpm_stany_data) { TPM_RESULT rc = 0; printf(" TPM_StanyData_Store:\n"); tpm_stany_data = tpm_stany_data; /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_STANY_DATA); } /* store currentTicks*/ if (rc == 0) { rc = TPM_CurrentTicks_StoreAll(sbuffer, &(tpm_stany_data->currentTicks)); } return rc; } /* TPM_StanyData_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL set members back to default values The object itself is not freed */ void TPM_StanyData_Delete(TPM_STANY_DATA *tpm_stany_data) { printf(" TPM_StanyData_Delete:\n"); /* nothing to free */ tpm_stany_data = tpm_stany_data; return; } /* TPM_STCLEAR_DATA */ /* TPM_StclearData_Init() If pcrInit is TRUE, resets the PCR's sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_StclearData_Init(TPM_STCLEAR_DATA *tpm_stclear_data, TPM_PCR_ATTRIBUTES *pcrAttrib, TPM_BOOL pcrInit) { printf(" TPM_StclearData_Init:\n"); TPM_Nonce_Init(tpm_stclear_data->contextNonceKey); tpm_stclear_data->countID = TPM_COUNT_ID_NULL; /* NULL value - unselected counter */ tpm_stclear_data->ownerReference = TPM_KH_OWNER; tpm_stclear_data->disableResetLock = FALSE; /* initialize PCR's */ if (pcrInit) { printf("TPM_StclearData_Init: Initializing PCR's\n"); TPM_PCRs_Init(tpm_stclear_data->PCRS, pcrAttrib); } #if (TPM_REVISION >= 103) /* added for rev 103 */ tpm_stclear_data->deferredPhysicalPresence = 0; #endif tpm_stclear_data->authFailCount = 0; tpm_stclear_data->authFailTime = 0; /* initialize authorization, transport, DAA sessions, and saved sessions */ TPM_StclearData_SessionInit(tpm_stclear_data); TPM_Digest_Init(tpm_stclear_data->auditDigest); TPM_Sbuffer_Init(&(tpm_stclear_data->ordinalResponse)); return; } /* TPM_StclearData_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_StclearData_Init() After use, call TPM_StclearData_Delete() to free memory */ TPM_RESULT TPM_StclearData_Load(TPM_STCLEAR_DATA *tpm_stclear_data, unsigned char **stream, uint32_t *stream_size, TPM_PCR_ATTRIBUTES *pcrAttrib) { TPM_RESULT rc = 0; TPM_STRUCTURE_TAG tag = 0; printf(" TPM_StclearData_Load:\n"); /* get tag */ if (rc == 0) { rc = TPM_Load16(&tag, stream, stream_size); } /* check tag */ if (rc == 0) { printf(" TPM_StclearData_Load: stream version %04hx\n", tag); switch (tag) { case TPM_TAG_STCLEAR_DATA: case TPM_TAG_STCLEAR_DATA_V2: break; default: printf("TPM_StclearData_Load: Error (fatal), version %04x unsupported\n", tag); rc = TPM_FAIL; break; } } /* load contextNonceKey */ if (rc == 0) { rc = TPM_Nonce_Load(tpm_stclear_data->contextNonceKey, stream, stream_size); } /* load countID */ if (rc == 0) { rc = TPM_Load32(&(tpm_stclear_data->countID), stream, stream_size); } /* load ownerReference */ if (rc == 0) { rc = TPM_Load32(&(tpm_stclear_data->ownerReference), stream, stream_size); } /* load disableResetLock */ if (rc == 0) { rc = TPM_LoadBool(&(tpm_stclear_data->disableResetLock), stream, stream_size); } /* load PCR's */ if (rc == 0) { rc = TPM_PCRs_Load(tpm_stclear_data->PCRS, pcrAttrib, stream, stream_size); } #if (TPM_REVISION >= 103) /* added for rev 103 */ /* load deferredPhysicalPresence */ if (rc == 0) { rc = TPM_Load32(&(tpm_stclear_data->deferredPhysicalPresence), stream, stream_size); } #endif /* load authFailCount */ if (rc == 0) { rc = TPM_Load32(&(tpm_stclear_data->authFailCount), stream, stream_size); } /* load authFailTime */ if (rc == 0) { rc = TPM_Load32(&(tpm_stclear_data->authFailTime), stream, stream_size); } /* load authorization sessions */ if (rc == 0) { rc = TPM_AuthSessions_Load(tpm_stclear_data->authSessions, stream, stream_size); } /* load transport sessions */ if (rc == 0) { rc = TPM_TransportSessions_Load(tpm_stclear_data->transSessions, stream, stream_size); } /* load DAA sessions */ if (rc == 0) { rc = TPM_DaaSessions_Load(tpm_stclear_data->daaSessions, stream, stream_size); } /* load contextNonceSession */ if (rc == 0) { rc = TPM_Nonce_Load(tpm_stclear_data->contextNonceSession, stream, stream_size); } /* load contextCount */ if (rc == 0) { rc = TPM_Load32(&(tpm_stclear_data->contextCount), stream, stream_size); } /* load contextList */ if (rc == 0) { rc = TPM_ContextList_Load(tpm_stclear_data->contextList, stream, stream_size); } /* load auditDigest */ if (rc == 0) { rc = TPM_Digest_Load(tpm_stclear_data->auditDigest, stream, stream_size); TPM_PrintFour(" TPM_StclearData_Load: auditDigest", tpm_stclear_data->auditDigest); } /* no need to store and load ordinalResponse */ if (tag == TPM_TAG_STCLEAR_DATA) { /* but it's there for some versions */ if (rc == 0) { TPM_STORE_BUFFER ordinalResponse; TPM_Sbuffer_Init(&ordinalResponse); rc = TPM_Sbuffer_Load(&ordinalResponse, stream, stream_size); TPM_Sbuffer_Delete(&ordinalResponse); } if (rc == 0) { uint32_t responseCount; rc = TPM_Load32(&responseCount, stream, stream_size); } } return rc; } /* TPM_StclearData_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_StclearData_Store(TPM_STORE_BUFFER *sbuffer, TPM_STCLEAR_DATA *tpm_stclear_data, TPM_PCR_ATTRIBUTES *pcrAttrib) { TPM_RESULT rc = 0; printf(" TPM_StclearData_Store:\n"); /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_STCLEAR_DATA_V2); } /* store contextNonceKey */ if (rc == 0) { rc = TPM_Nonce_Store(sbuffer, tpm_stclear_data->contextNonceKey); } /* store countID */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_stclear_data->countID); } /* store ownerReference */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_stclear_data->ownerReference); } /* store disableResetLock */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_stclear_data->disableResetLock), sizeof(TPM_BOOL)); } /* store PCR's */ if (rc == 0) { rc = TPM_PCRs_Store(sbuffer, tpm_stclear_data->PCRS, pcrAttrib); } #if (TPM_REVISION >= 103) /* added for rev 103 */ /* store deferredPhysicalPresence */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_stclear_data->deferredPhysicalPresence); } #endif /* store authFailCount */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_stclear_data->authFailCount); } /* store authFailTime */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_stclear_data->authFailTime); } /* store authorization sessions */ if (rc == 0) { rc = TPM_AuthSessions_Store(sbuffer, tpm_stclear_data->authSessions); } /* store transport sessions */ if (rc == 0) { rc = TPM_TransportSessions_Store(sbuffer, tpm_stclear_data->transSessions); } /* store DAA sessions */ if (rc == 0) { rc = TPM_DaaSessions_Store(sbuffer, tpm_stclear_data->daaSessions); } /* store contextNonceSession */ if (rc == 0) { rc = TPM_Nonce_Store(sbuffer, tpm_stclear_data->contextNonceSession); } /* store contextCount */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_stclear_data->contextCount); } /* store contextList */ if (rc == 0) { rc = TPM_ContextList_Store(sbuffer, tpm_stclear_data->contextList); } /* store auditDigest */ if (rc == 0) { TPM_PrintFour(" TPM_StclearData_Store: auditDigest", tpm_stclear_data->auditDigest); rc = TPM_Digest_Store(sbuffer, tpm_stclear_data->auditDigest); } /* no need to store and load ordinalResponse */ return rc; } /* TPM_StclearData_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_StclearData_Init to set members back to default values The object itself is not freed */ /* TPM_StclearData_Delete() frees any memory associated with TPM_STCLEAR_DATA, and then reinitializes the structure. If pcrInit is TRUE, the PCR's are initialized. */ void TPM_StclearData_Delete(TPM_STCLEAR_DATA *tpm_stclear_data, TPM_PCR_ATTRIBUTES *pcrAttrib, TPM_BOOL pcrInit) { printf(" TPM_StclearData_Delete:\n"); if (tpm_stclear_data != NULL) { TPM_StclearData_SessionDelete(tpm_stclear_data);/* authorization, transport, and DAA sessions */ TPM_Sbuffer_Delete(&(tpm_stclear_data->ordinalResponse)); TPM_StclearData_Init(tpm_stclear_data, pcrAttrib, pcrInit); } return; } /* TPM_StclearData_SessionInit() initializes the structure members associated with authorization, transport, and DAA sessions. It must be called whenever the sessions are invalidated. */ void TPM_StclearData_SessionInit(TPM_STCLEAR_DATA *tpm_stclear_data) { printf(" TPM_StclearData_SessionInit:\n"); /* active sessions */ TPM_AuthSessions_Init(tpm_stclear_data->authSessions); TPM_TransportSessions_Init(tpm_stclear_data->transSessions); TPM_DaaSessions_Init(tpm_stclear_data->daaSessions); /* saved sessions */ TPM_Nonce_Init(tpm_stclear_data->contextNonceSession); tpm_stclear_data->contextCount = 0; TPM_ContextList_Init(tpm_stclear_data->contextList); return; } /* TPM_StclearData_SessionDelete() deletes the structure members associated with authorization, transport, and DAA sessions. It must be called whenever the sessions are invalidated. */ void TPM_StclearData_SessionDelete(TPM_STCLEAR_DATA *tpm_stclear_data) { printf(" TPM_StclearData_SessionDelete:\n"); /* active and saved authorization sessions, the authSessions table and the 3 contextList entries */ TPM_StclearData_AuthSessionDelete(tpm_stclear_data); /* loaded transport sessions */ TPM_TransportSessions_Delete(tpm_stclear_data->transSessions); /* loaded DAA sessions */ TPM_DaaSessions_Delete(tpm_stclear_data->daaSessions); return; } /* TPM_StclearData_AuthSessionDelete() deletes the structure members associated with authorization sessions. It clears the authSessions table and the 3 contextList members. It must be called whenever the sessions are invalidated. */ void TPM_StclearData_AuthSessionDelete(TPM_STCLEAR_DATA *tpm_stclear_data) { printf(" TPM_StclearData_AuthSessionDelete:\n"); /* active sessions */ TPM_AuthSessions_Delete(tpm_stclear_data->authSessions); /* saved sessions */ TPM_Nonce_Init(tpm_stclear_data->contextNonceSession); tpm_stclear_data->contextCount = 0; TPM_ContextList_Init(tpm_stclear_data->contextList); return; } /* TPM_InitCmd() executes the actions of the TPM_Init 'ordinal' */ TPM_RESULT TPM_InitCmd(tpm_state_t *tpm_state) { TPM_RESULT rc = 0; uint32_t tpm_number; printf(" TPM_Init:\n"); /* Release all resources for the TPM and reinitialize */ if (rc == TPM_SUCCESS) { tpm_number = tpm_state->tpm_number; /* save the TPM value */ TPM_Global_Delete(tpm_state); /* delete all the state */ rc = TPM_Global_Init(tpm_state); /* re-allocate the state */ } /* Reload non-volatile memory */ if (rc == TPM_SUCCESS) { tpm_state->tpm_number = tpm_number; /* restore the TPM number */ /* Returns TPM_RETRY on non-existent file */ rc = TPM_PermanentAll_NVLoad(tpm_state); /* reload the state */ if (rc == TPM_RETRY) { printf("TPM_Init: Error (fatal), non-existent instance\n"); rc = TPM_FAIL; } } return rc; } /* TPM_Handle_GenerateHandle() is a utility function that returns an unused handle. It's really not an initialization function, but as the handle arrays are typically in TPM_STCLEAR_DATA, it's a reasonable home. If 'tpm_handle' is non-zero, it is the first value tried. If 'keepHandle' is TRUE, it is the only value tried. If 'tpm_handle' is zero, a random value is assigned. If 'keepHandle' is TRUE, an error returned, as zero is an illegal handle value. If 'isKeyHandle' is TRUE, special checking is performed to avoid reserved values. 'getEntryFunction' is a function callback to check whether the handle has already been assigned to an entry in the appropriate handle list. */ TPM_RESULT TPM_Handle_GenerateHandle(TPM_HANDLE *tpm_handle, void *tpm_handle_entries, TPM_BOOL keepHandle, TPM_BOOL isKeyHandle, TPM_GETENTRY_FUNCTION_T getEntryFunction) { TPM_RESULT rc = 0; TPM_RESULT getRc = 0; unsigned int timeout; /* collision timeout */ void *used_handle_entry; /* place holder for discarded entry */ TPM_BOOL done; printf(" TPM_Handle_GenerateHandle: handle %08x, keepHandle %u\n", *tpm_handle, keepHandle); /* if the input value must be used */ if (keepHandle) { /* 0 is illegal and cannot be kept */ if (rc == 0) { if (*tpm_handle == 0) { printf("TPM_Handle_GenerateHandle: Error, cannot keep handle 0\n"); rc = TPM_BAD_HANDLE; } } /* key handles beginning with 0x40 are reserved special values */ if (rc == 0) { if (isKeyHandle) { if ((*tpm_handle & 0xff000000) == 0x40000000) { printf("TPM_Handle_GenerateHandle: Error, cannot keep reserved key handle\n"); rc = TPM_BAD_HANDLE; } } } /* check if the handle is already used */ if (rc == 0) { getRc = getEntryFunction(&used_handle_entry, /* discarded entry */ tpm_handle_entries, /* handle array */ *tpm_handle); /* search for handle */ /* success mean the handle has already been assigned */ if (getRc == 0) { printf("TPM_Handle_GenerateHandle: Error handle already in use\n"); rc = TPM_BAD_HANDLE; } } } /* input value is recommended but not required */ else { /* implement a crude timeout in case the random number generator fails and there are too many collisions */ for (done = FALSE, timeout = 0 ; (rc == 0) && !done && (timeout < 1000) ; timeout++) { /* If no handle has been assigned, try a random value. If a handle has been assigned, try it first */ if (rc == 0) { if (*tpm_handle == 0) { rc = TPM_Random((BYTE *)tpm_handle, sizeof(uint32_t)); } } /* if the random value is 0, reject it immediately */ if (rc == 0) { if (*tpm_handle == 0) { printf(" TPM_Handle_GenerateHandle: Random value 0 rejected\n"); continue; } } /* if the value is a reserved key handle, reject it immediately */ if (rc == 0) { if (isKeyHandle) { if ((*tpm_handle & 0xff000000) == 0x40000000) { printf(" TPM_Handle_GenerateHandle: Random value %08x rejected\n", *tpm_handle); *tpm_handle = 0; /* ignore the assigned value */ continue; } } } /* test if the handle has already been used */ if (rc == 0) { getRc = getEntryFunction(&used_handle_entry, /* discarded entry */ tpm_handle_entries, /* handle array */ *tpm_handle); /* search for handle */ if (getRc != 0) { /* not found, done */ printf(" TPM_Handle_GenerateHandle: Assigned Handle %08x\n", *tpm_handle); done = TRUE; } else { /* found, try again */ *tpm_handle = 0; /* ignore the assigned value */ printf(" TPM_Handle_GenerateHandle: Handle %08x already used\n", *tpm_handle); } } } if (!done) { printf("TPM_Handle_GenerateHandle: Error (fatal), random number generator failed\n"); rc = TPM_FAIL; } } return rc; } /* Processing Functions */ /* TPM_Init This ordinal should not be implemented, since it allows software to imitate a reboot. That would be a major security hole, since the PCR's are reset. It is only here for regression tests. */ TPM_RESULT TPM_Process_Init(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ printf("TPM_Process_Init: Ordinal Entry\n"); ordinal = ordinal; /* not used */ command = command; /* not used */ transportInternal = transportInternal; /* not used */ /* check state */ /* NOTE: Allow at any time. */ /* get inputs */ /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_Init: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ if (returnCode == TPM_SUCCESS) { #ifdef TPM_TEST returnCode = TPM_InitCmd(tpm_state); #else tpm_state = tpm_state; /* to quiet the compiler */ printf("TPM_Process_Init: Error, bad ordinal\n"); returnCode = TPM_BAD_ORDINAL; #endif } /* response */ if (rcf == 0) { printf("TPM_Process_Init: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } return rcf; } libtpms-0.9.3/src/tpm12/tpm_init.h000066400000000000000000000135751421143571500167410ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM Initialization */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_init.h 4403 2011-02-08 18:28:22Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_INIT_H #define TPM_INIT_H #include "tpm_global.h" #include "tpm_store.h" #include "tpm_structures.h" /* Power up initialization */ TPM_RESULT TPM_MainInit(void); /* TPM_STANY_FLAGS */ void TPM_StanyFlags_Init(TPM_STANY_FLAGS *tpm_stany_flags); TPM_RESULT TPM_StanyFlags_Load(TPM_STANY_FLAGS *tpm_stany_flags, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_StanyFlags_Store(TPM_STORE_BUFFER *sbuffer, TPM_STANY_FLAGS *tpm_stany_flags); /* TPM_STCLEAR_FLAGS */ void TPM_StclearFlags_Init(TPM_STCLEAR_FLAGS *tpm_stclear_flags); TPM_RESULT TPM_StclearFlags_Load(TPM_STCLEAR_FLAGS *tpm_stclear_flags, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_StclearFlags_Store(TPM_STORE_BUFFER *sbuffer, const TPM_STCLEAR_FLAGS *tpm_stclear_flags); TPM_RESULT TPM_StclearFlags_StoreBitmap(uint32_t *tpm_bitmap, const TPM_STCLEAR_FLAGS *tpm_stclear_flags); /* TPM_STANY_DATA */ TPM_RESULT TPM_StanyData_Init(TPM_STANY_DATA *tpm_stany_data); TPM_RESULT TPM_StanyData_Load(TPM_STANY_DATA *tpm_stany_data, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_StanyData_Store(TPM_STORE_BUFFER *sbuffer, TPM_STANY_DATA *tpm_stany_data); void TPM_StanyData_Delete(TPM_STANY_DATA *tpm_stany_data); /* TPM_STCLEAR_DATA */ void TPM_StclearData_Init(TPM_STCLEAR_DATA *tpm_stclear_data, TPM_PCR_ATTRIBUTES *pcrAttrib, TPM_BOOL pcrInit); TPM_RESULT TPM_StclearData_Load(TPM_STCLEAR_DATA *tpm_stclear_data, unsigned char **stream, uint32_t *stream_size, TPM_PCR_ATTRIBUTES *pcrAttrib); TPM_RESULT TPM_StclearData_Store(TPM_STORE_BUFFER *sbuffer, TPM_STCLEAR_DATA *tpm_stclear_data, TPM_PCR_ATTRIBUTES *pcrAttrib); void TPM_StclearData_Delete(TPM_STCLEAR_DATA *tpm_stclear_data, TPM_PCR_ATTRIBUTES *pcrAttrib, TPM_BOOL pcrInit); void TPM_StclearData_SessionInit(TPM_STCLEAR_DATA *tpm_stclear_data); void TPM_StclearData_SessionDelete(TPM_STCLEAR_DATA *tpm_stclear_data); void TPM_StclearData_AuthSessionDelete(TPM_STCLEAR_DATA *tpm_stclear_data); /* Actions */ TPM_RESULT TPM_InitCmd(tpm_state_t *tpm_state); /* Processing Functions */ TPM_RESULT TPM_Process_Init(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); /* generic function prototype for a handle array getEntry callback function */ typedef TPM_RESULT (*TPM_GETENTRY_FUNCTION_T )(void **entry, void *entries, TPM_HANDLE handle); TPM_RESULT TPM_Handle_GenerateHandle(TPM_HANDLE *tpm_handle, void *tpm_handle_entries, TPM_BOOL keepHandle, TPM_BOOL isKeyHandle, TPM_GETENTRY_FUNCTION_T getEntryFunction); #endif libtpms-0.9.3/src/tpm12/tpm_io.h000066400000000000000000000065571421143571500164070ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM Host IO */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_io.h 4211 2010-11-22 21:07:24Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_IO_H #define TPM_IO_H #include "tpm_types.h" /* non-portable structure to pass around IO file descriptor */ typedef struct TPM_CONNECTION_FD { #ifdef TPM_POSIX int fd; /* for socket, just an int */ #endif } TPM_CONNECTION_FD; TPM_RESULT TPM_IO_IsNotifyAvailable(TPM_BOOL *isAvailable); TPM_RESULT TPM_IO_Connect(TPM_CONNECTION_FD *connection_fd, void *mainLoopArgs); TPM_RESULT TPM_IO_Read(TPM_CONNECTION_FD *connection_fd, unsigned char *buffer, uint32_t *paramSize, size_t buffer_size, void *mainLoopArgs); TPM_RESULT TPM_IO_Write(TPM_CONNECTION_FD *connection_fd, const unsigned char *buffer, size_t buffer_length); TPM_RESULT TPM_IO_Disconnect(TPM_CONNECTION_FD *connection_fd); /* function for notifying listener(s) about PCRExtend events */ TPM_RESULT TPM_IO_ClientSendNotification(const void *buf, size_t count); #endif libtpms-0.9.3/src/tpm12/tpm_key.c000066400000000000000000005533301421143571500165570ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Key Handler */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_key.c 4655 2011-12-21 21:03:15Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include #include #include #include "tpm_auth.h" #include "tpm_commands.h" #include "tpm_crypto.h" #include "tpm_cryptoh.h" #include "tpm_debug.h" #include "tpm_digest.h" #include "tpm_error.h" #include "tpm_init.h" #include "tpm_io.h" #include "tpm_load.h" #include "tpm_memory.h" #include "tpm_nonce.h" #include "tpm_nvfile.h" #include "tpm_nvram.h" #include "tpm_owner.h" #include "tpm_pcr.h" #include "tpm_sizedbuffer.h" #include "tpm_store.h" #include "tpm_structures.h" #include "tpm_startup.h" #include "tpm_permanent.h" #include "tpm_process.h" #include "tpm_ver.h" #include "tpm_key.h" /* The default RSA exponent */ unsigned char tpm_default_rsa_exponent[] = {0x01, 0x00, 0x01}; /* local prototypes */ static TPM_RESULT TPM_Key_CheckTag(TPM_KEY12 *tpm_key12); /* TPM_KEY, TPM_KEY12 These functions generally handle either a TPM_KEY or TPM_KEY12. Where structure members differ, the function checks the version or tag and adapts the processing to the structure type. This handling is opaque to the caller. */ /* TPM_Key_Init initializes a key structure. The default is TPM_KEY. Typically, a TPM_Key_Set() or TPM_Key_Load() will adjust to TPM_KEY or TPM_KEY12 */ void TPM_Key_Init(TPM_KEY *tpm_key) { printf(" TPM_Key_Init:\n"); TPM_StructVer_Init(&(tpm_key->ver)); tpm_key->keyUsage = TPM_KEY_UNINITIALIZED; tpm_key->keyFlags = 0; tpm_key->authDataUsage = 0; TPM_KeyParms_Init(&(tpm_key->algorithmParms)); TPM_SizedBuffer_Init(&(tpm_key->pcrInfo)); TPM_SizedBuffer_Init(&(tpm_key->pubKey)); TPM_SizedBuffer_Init(&(tpm_key->encData)); tpm_key->tpm_pcr_info = NULL; tpm_key->tpm_pcr_info_long = NULL; tpm_key->tpm_store_asymkey = NULL; tpm_key->tpm_migrate_asymkey = NULL; return; } /* TPM_Key_InitTag12() alters the tag and fill from TPM_KEY to TPM_KEY12 */ void TPM_Key_InitTag12(TPM_KEY *tpm_key) { printf(" TPM_Key_InitTag12:\n"); ((TPM_KEY12 *)tpm_key)->tag = TPM_TAG_KEY12; ((TPM_KEY12 *)tpm_key)->fill = 0x0000; return; } /* TPM_Key_Set() sets a TPM_KEY structure to the specified values. The tpm_pcr_info digestAtCreation is calculated. It serializes the tpm_pcr_info or tpm_pcr_info_long cache to pcrInfo. One or the other may be specified, but not both. The tag/version is set correctly. If the parent_key is NULL, encData is set to the clear text serialization of the tpm_store_asymkey member. If parent_key is not NULL, encData is not set yet, since further processing may be done before encryption. Must call TPM_Key_Delete() to free */ TPM_RESULT TPM_Key_Set(TPM_KEY *tpm_key, /* output created key */ tpm_state_t *tpm_state, TPM_KEY *parent_key, /* NULL for root keys */ TPM_DIGEST *tpm_pcrs, /* points to the TPM PCR array */ int ver, /* TPM_KEY or TPM_KEY12 */ TPM_KEY_USAGE keyUsage, /* input */ TPM_KEY_FLAGS keyFlags, /* input */ TPM_AUTH_DATA_USAGE authDataUsage, /* input */ TPM_KEY_PARMS *tpm_key_parms, /* input */ TPM_PCR_INFO *tpm_pcr_info, /* must copy */ TPM_PCR_INFO_LONG *tpm_pcr_info_long, /* must copy */ uint32_t keyLength, /* public key length in bytes */ BYTE* publicKey, /* public key byte array */ TPM_STORE_ASYMKEY *tpm_store_asymkey, /* cache TPM_STORE_ASYMKEY */ TPM_MIGRATE_ASYMKEY *tpm_migrate_asymkey) /* cache TPM_MIGRATE_ASYMKEY */ { TPM_RESULT rc = 0; TPM_STORE_BUFFER sbuffer; printf(" TPM_Key_Set:\n"); TPM_Sbuffer_Init(&sbuffer); /* version must be TPM_KEY or TPM_KEY12 */ if (rc == 0) { if ((ver != 1) && (ver != 2)) { printf("TPM_Key_Set: Error (fatal), " "TPM_KEY version %d is not 1 or 2\n", ver); rc = TPM_FAIL; /* should never occur */ } } /* either tpm_pcr_info != NULL for TPM_KEY or tpm_pcr_info_long != NULL for TPM_KEY12, but not both */ if (rc == 0) { if ((ver == 1) && (tpm_pcr_info_long != NULL)) { printf("TPM_Key_Set: Error (fatal), " "TPM_KEY and TPM_PCR_INFO_LONG both specified\n"); rc = TPM_FAIL; /* should never occur */ } } if (rc == 0) { if ((ver == 2) && (tpm_pcr_info != NULL)) { printf("TPM_Key_Set: Error (fatal), " "TPM_KEY12 and TPM_PCR_INFO both specified\n"); rc = TPM_FAIL; /* should never occur */ } } if (rc == 0) { TPM_Key_Init(tpm_key); if (ver == 2) { TPM_Key_InitTag12(tpm_key); /* change tag to TPM_KEY12 */ } tpm_key->keyUsage = keyUsage; tpm_key->keyFlags = keyFlags; tpm_key->authDataUsage = authDataUsage; rc = TPM_KeyParms_Copy(&(tpm_key->algorithmParms), /* freed by caller */ tpm_key_parms); } /* The pcrInfo serialization is deferred, since PCR data is be altered after the initial 'set'. */ if (rc == 0) { /* generate the TPM_PCR_INFO member cache, directly copying from the tpm_pcr_info */ if (tpm_pcr_info != NULL) { /* TPM_KEY */ rc = TPM_PCRInfo_CreateFromInfo(&(tpm_key->tpm_pcr_info), tpm_pcr_info); } /* generate the TPM_PCR_INFO_LONG member cache, directly copying from the tpm_pcr_info_long */ else if (tpm_pcr_info_long != NULL) { /* TPM_KEY12 */ rc = TPM_PCRInfoLong_CreateFromInfoLong(&(tpm_key->tpm_pcr_info_long), tpm_pcr_info_long); } } if (rc == 0) { /* if there are PCR's specified, set the digestAtCreation */ if (tpm_pcr_info != NULL) { rc = TPM_PCRInfo_SetDigestAtCreation(tpm_key->tpm_pcr_info, tpm_pcrs); } /* if there are PCR's specified, set the localityAtCreation, digestAtCreation */ else if (tpm_pcr_info_long != NULL) { /* TPM_KEY12 */ if (rc == 0) { rc = TPM_Locality_Set(&(tpm_key->tpm_pcr_info_long->localityAtCreation), tpm_state->tpm_stany_flags.localityModifier); } if (rc == 0) { rc = TPM_PCRInfoLong_SetDigestAtCreation(tpm_key->tpm_pcr_info_long, tpm_pcrs); } } } /* set TPM_SIZED_BUFFER pubKey */ if (rc == 0) { rc = TPM_SizedBuffer_Set(&(tpm_key->pubKey), keyLength, /* in bytes */ publicKey); } if (rc == 0) { if (tpm_store_asymkey == NULL) { printf("TPM_Key_Set: Error (fatal), No TPM_STORE_ASYMKEY supplied\n"); rc = TPM_FAIL; /* should never occur */ } } /* sanity check, currently no need to set TPM_MIGRATE_ASYMKEY */ if (rc == 0) { if (tpm_migrate_asymkey != NULL) { printf("TPM_Key_Set: Error (fatal), TPM_MIGRATE_ASYMKEY supplied\n"); rc = TPM_FAIL; /* should never occur */ } } if (rc == 0) { /* root key, no parent, just serialize the TPM_STORE_ASYMKEY structure */ if (parent_key == NULL) { if (rc == 0) { rc = TPM_StoreAsymkey_Store(&sbuffer, FALSE, tpm_store_asymkey); /* freed @1 */ } if (rc == 0) { rc = TPM_SizedBuffer_SetFromStore(&(tpm_key->encData), &sbuffer); } } } if (rc == 0) { tpm_key->tpm_store_asymkey = tpm_store_asymkey; /* cache TPM_STORE_ASYMKEY */ tpm_key->tpm_migrate_asymkey = tpm_migrate_asymkey; /* cache TPM_MIGRATE_ASYMKEY */ } /* Generate the TPM_STORE_ASYMKEY -> pubDataDigest. Serializes pcrInfo as a side effect. */ if (rc == 0) { rc = TPM_Key_GeneratePubDataDigest(tpm_key); } TPM_Sbuffer_Delete(&sbuffer); /* @1 */ return rc; } /* TPM_Key_Copy() copies the source TPM_KEY to the destination. The destination should be initialized before the call. */ TPM_RESULT TPM_Key_Copy(TPM_KEY *tpm_key_dest, TPM_KEY *tpm_key_src, TPM_BOOL copyEncData) { TPM_RESULT rc = 0; if (rc == 0) { TPM_StructVer_Copy(&(tpm_key_dest->ver), &(tpm_key_src->ver)); /* works for TPM_KEY12 also */ tpm_key_dest->keyUsage = tpm_key_src->keyUsage; tpm_key_dest->keyFlags = tpm_key_src->keyFlags; tpm_key_dest->authDataUsage = tpm_key_src->authDataUsage; rc = TPM_KeyParms_Copy(&(tpm_key_dest->algorithmParms), &(tpm_key_src->algorithmParms)); } if (rc == 0) { rc = TPM_SizedBuffer_Copy(&(tpm_key_dest->pcrInfo), &(tpm_key_src->pcrInfo)); } /* copy TPM_PCR_INFO cache */ if (rc == 0) { if (tpm_key_src->tpm_pcr_info != NULL) { /* TPM_KEY */ rc = TPM_PCRInfo_CreateFromInfo(&(tpm_key_dest->tpm_pcr_info), tpm_key_src->tpm_pcr_info); } else if (tpm_key_src->tpm_pcr_info_long != NULL) { /* TPM_KEY12 */ rc = TPM_PCRInfoLong_CreateFromInfoLong(&(tpm_key_dest->tpm_pcr_info_long), tpm_key_src->tpm_pcr_info_long); } } /* copy pubKey */ if (rc == 0) { rc = TPM_SizedBuffer_Copy(&(tpm_key_dest->pubKey), &(tpm_key_src->pubKey)); } /* copy encData */ if (rc == 0) { if (copyEncData) { rc = TPM_SizedBuffer_Copy(&(tpm_key_dest->encData), &(tpm_key_src->encData)); } } return rc; } /* TPM_Key_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes The TPM_PCR_INFO or TPM_PCR_INFO_LONG cache is set from the deserialized pcrInfo stream. After use, call TPM_Key_Delete() to free memory */ TPM_RESULT TPM_Key_Load(TPM_KEY *tpm_key, /* result */ unsigned char **stream, /* pointer to next parameter */ uint32_t *stream_size) /* stream size left */ { TPM_RESULT rc = 0; printf(" TPM_Key_Load:\n"); /* load public data, and create PCR cache */ if (rc == 0) { rc = TPM_Key_LoadPubData(tpm_key, FALSE, stream, stream_size); } /* load encDataSize and encData */ if (rc == 0) { rc = TPM_SizedBuffer_Load(&(tpm_key->encData), stream, stream_size); } return rc; } /* TPM_Key_LoadClear() load a serialized key where the TPM_STORE_ASYMKEY structure is serialized in clear text. The TPM_PCR_INFO or TPM_PCR_INFO_LONG cache is set from the deserialized pcrInfo stream. This function is used to load internal keys (e.g. EK, SRK, owner evict keys) or keys saved as part of a save state. */ TPM_RESULT TPM_Key_LoadClear(TPM_KEY *tpm_key, /* result */ TPM_BOOL isEK, /* key being loaded is EK */ unsigned char **stream, /* pointer to next parameter */ uint32_t *stream_size) /* stream size left */ { TPM_RESULT rc = 0; uint32_t storeAsymkeySize; printf(" TPM_Key_LoadClear:\n"); /* load public data */ if (rc == 0) { rc = TPM_Key_LoadPubData(tpm_key, isEK, stream, stream_size); } /* load TPM_STORE_ASYMKEY size */ if (rc == 0) { rc = TPM_Load32(&storeAsymkeySize, stream, stream_size); } /* The size might be 0 for an uninitialized internal key. That case is not an error. */ if ((rc == 0) && (storeAsymkeySize > 0)) { rc = TPM_Key_LoadStoreAsymKey(tpm_key, isEK, stream, stream_size); } return rc; } /* TPM_Key_LoadPubData() deserializes a TPM_KEY or TPM_KEY12 structure, excluding encData, to 'tpm_key'. The TPM_PCR_INFO or TPM_PCR_INFO_LONG cache is set from the deserialized pcrInfo stream. If the pcrInfo stream is empty, the caches remain NULL. deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes After use, call TPM_Key_Delete() to free memory */ TPM_RESULT TPM_Key_LoadPubData(TPM_KEY *tpm_key, /* result */ TPM_BOOL isEK, /* key being loaded is EK */ unsigned char **stream, /* pointer to next parameter */ uint32_t *stream_size) /* stream size left */ { TPM_RESULT rc = 0; printf(" TPM_Key_LoadPubData:\n"); /* peek at the first byte */ if (rc == 0) { /* TPM_KEY[0] is major (non zero) */ if ((*stream)[0] != 0) { /* load ver */ if (rc == 0) { rc = TPM_StructVer_Load(&(tpm_key->ver), stream, stream_size); } /* check ver immediately to ease debugging */ if (rc == 0) { rc = TPM_StructVer_CheckVer(&(tpm_key->ver)); } } else { /* TPM_KEY12 is tag (zero) */ /* load tag */ if (rc == 0) { rc = TPM_Load16(&(((TPM_KEY12 *)tpm_key)->tag), stream, stream_size); } /* load fill */ if (rc == 0) { rc = TPM_Load16(&(((TPM_KEY12 *)tpm_key)->fill), stream, stream_size); } if (rc == 0) { rc = TPM_Key_CheckTag((TPM_KEY12 *)tpm_key); } } } /* load keyUsage */ if (rc == 0) { rc = TPM_Load16(&(tpm_key->keyUsage), stream, stream_size); } /* load keyFlags */ if (rc == 0) { rc = TPM_KeyFlags_Load(&(tpm_key->keyFlags), stream, stream_size); } /* load authDataUsage */ if (rc == 0) { rc = TPM_Load8(&(tpm_key->authDataUsage), stream, stream_size); } /* load algorithmParms */ if (rc == 0) { rc = TPM_KeyParms_Load(&(tpm_key->algorithmParms), stream, stream_size); } /* load PCRInfo */ if ((rc == 0) && !isEK) { rc = TPM_SizedBuffer_Load(&(tpm_key->pcrInfo), stream, stream_size); } /* set TPM_PCR_INFO tpm_pcr_info cache from PCRInfo stream. If the stream is empty, a NULL is returned. */ if ((rc == 0) && !isEK) { if (((TPM_KEY12 *)tpm_key)->tag != TPM_TAG_KEY12) { /* TPM_KEY */ rc = TPM_PCRInfo_CreateFromBuffer(&(tpm_key->tpm_pcr_info), &(tpm_key->pcrInfo)); } else { /* TPM_KEY12 */ rc = TPM_PCRInfoLong_CreateFromBuffer(&(tpm_key->tpm_pcr_info_long), &(tpm_key->pcrInfo)); } } /* load pubKey */ if (rc == 0) { rc = TPM_SizedBuffer_Load(&(tpm_key->pubKey), stream, stream_size); } return rc; } /* TPM_Key_StorePubData() serializes a TPM_KEY or TPM_KEY12 structure, excluding encData, appending results to 'sbuffer'. As a side effect, it serializes the tpm_pcr_info cache to pcrInfo. */ TPM_RESULT TPM_Key_StorePubData(TPM_STORE_BUFFER *sbuffer, TPM_BOOL isEK, TPM_KEY *tpm_key) { TPM_RESULT rc = 0; printf(" TPM_Key_StorePubData:\n"); if (rc == 0) { /* store ver */ if (((TPM_KEY12 *)tpm_key)->tag != TPM_TAG_KEY12) { /* TPM_KEY */ rc = TPM_StructVer_Store(sbuffer, &(tpm_key->ver)); } else { /* TPM_KEY12 */ /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_KEY12); } /* store fill */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, 0x0000); } } } /* store keyUsage */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, tpm_key->keyUsage); } /* store keyFlags */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_key->keyFlags); } /* store authDataUsage */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_key->authDataUsage), sizeof(TPM_AUTH_DATA_USAGE)); } /* store algorithmParms */ if (rc == 0) { rc = TPM_KeyParms_Store(sbuffer, &(tpm_key->algorithmParms)); } /* store pcrInfo */ if ((rc == 0) && !isEK) { /* copy cache to pcrInfo */ if (((TPM_KEY12 *)tpm_key)->tag != TPM_TAG_KEY12) { /* TPM_KEY */ rc = TPM_SizedBuffer_SetStructure(&(tpm_key->pcrInfo), tpm_key->tpm_pcr_info, (TPM_STORE_FUNCTION_T)TPM_PCRInfo_Store); } else { /* TPM_KEY12 */ rc = TPM_SizedBuffer_SetStructure(&(tpm_key->pcrInfo), tpm_key->tpm_pcr_info_long, (TPM_STORE_FUNCTION_T)TPM_PCRInfoLong_Store); } } /* copy pcrInfo to sbuffer */ if ((rc == 0) && !isEK) { rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_key->pcrInfo)); } /* store pubKey */ if (rc == 0) { rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_key->pubKey)); } return rc; } /* TPM_Key_Store() serializes a TPM_KEY structure, appending results to 'sbuffer' As a side effect, it serializes the tpm_pcr_info cache to pcrInfo. */ TPM_RESULT TPM_Key_Store(TPM_STORE_BUFFER *sbuffer, TPM_KEY *tpm_key) { TPM_RESULT rc = 0; printf(" TPM_Key_Store:\n"); /* store the pubData */ if (rc == 0) { rc = TPM_Key_StorePubData(sbuffer, FALSE, tpm_key); } /* store encDataSize and encData */ if (rc == 0) { rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_key->encData)); } return rc; } /* TPM_Key_StoreClear() serializes a TPM_KEY structure, appending results to 'sbuffer' TPM_Key_StoreClear() serializes the tpm_store_asymkey member as cleartext. It is used for keys such as the SRK, which never leave the TPM. It is also used for saving state, where the entire blob is encrypted. As a side effect, it serializes the tpm_pcr_info cache to pcrInfo. */ TPM_RESULT TPM_Key_StoreClear(TPM_STORE_BUFFER *sbuffer, TPM_BOOL isEK, /* key being stored is EK */ TPM_KEY *tpm_key) { TPM_RESULT rc = 0; TPM_STORE_BUFFER asymSbuffer; const unsigned char *asymBuffer; uint32_t asymLength; printf(" TPM_Key_StoreClear:\n"); TPM_Sbuffer_Init(&asymSbuffer); /* freed @1 */ /* store the pubData */ if (rc == 0) { rc = TPM_Key_StorePubData(sbuffer, isEK, tpm_key); } /* store TPM_STORE_ASYMKEY cache as cleartext */ if (rc == 0) { /* if the TPM_STORE_ASYMKEY cache exists */ if (tpm_key->tpm_store_asymkey != NULL) { /* , serialize it */ if (rc == 0) { rc = TPM_StoreAsymkey_Store(&asymSbuffer, isEK, tpm_key->tpm_store_asymkey); } /* get the result */ TPM_Sbuffer_Get(&asymSbuffer, &asymBuffer, &asymLength); /* store the result as a sized buffer */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, asymLength); } if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, asymBuffer, asymLength); } } /* If there is no TPM_STORE_ASYMKEY cache, mark it empty. This can occur for an internal key that has not been created yet. */ else { rc = TPM_Sbuffer_Append32(sbuffer, 0); } } TPM_Sbuffer_Delete(&asymSbuffer); /* @1 */ return rc; } /* TPM_KEY_StorePubkey() gets (as a stream) the TPM_PUBKEY derived from a TPM_KEY There is no need to actually assemble the structure, since only the serialization of its two members are needed. The stream is returned as a TPM_STORE_BUFFER (that must be initialized and deleted by the caller), and it's components (buffer and size). */ TPM_RESULT TPM_Key_StorePubkey(TPM_STORE_BUFFER *pubkeyStream, /* output */ const unsigned char **pubkeyStreamBuffer, /* output */ uint32_t *pubkeyStreamLength, /* output */ TPM_KEY *tpm_key) /* input */ { TPM_RESULT rc = 0; printf(" TPM_Key_StorePubkey:\n"); /* the first part is a TPM_KEY_PARMS */ if (rc == 0) { rc = TPM_KeyParms_Store(pubkeyStream, &(tpm_key->algorithmParms)); } /* the second part is the TPM_SIZED_BUFFER pubKey */ if (rc == 0) { rc = TPM_SizedBuffer_Store(pubkeyStream, &(tpm_key->pubKey)); } /* retrieve the resulting pubkey stream */ if (rc == 0) { TPM_Sbuffer_Get(pubkeyStream, pubkeyStreamBuffer, pubkeyStreamLength); } return rc; } /* TPM_Key_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_Key_Init to set members back to default values The TPM_KEY itself is not freed The key is not freed because it might be a local variable rather than a malloc'ed pointer. */ void TPM_Key_Delete(TPM_KEY *tpm_key) { if (tpm_key != NULL) { printf(" TPM_Key_Delete:\n"); TPM_KeyParms_Delete(&(tpm_key->algorithmParms)); /* pcrInfo */ TPM_SizedBuffer_Delete(&(tpm_key->pcrInfo)); /* pcr caches */ TPM_PCRInfo_Delete(tpm_key->tpm_pcr_info); free(tpm_key->tpm_pcr_info); TPM_PCRInfoLong_Delete(tpm_key->tpm_pcr_info_long); free(tpm_key->tpm_pcr_info_long); TPM_SizedBuffer_Delete(&(tpm_key->pubKey)); TPM_SizedBuffer_Delete(&(tpm_key->encData)); TPM_StoreAsymkey_Delete(tpm_key->tpm_store_asymkey); free(tpm_key->tpm_store_asymkey); TPM_MigrateAsymkey_Delete(tpm_key->tpm_migrate_asymkey); free(tpm_key->tpm_migrate_asymkey); TPM_Key_Init(tpm_key); } return; } /* TPM_Key_CheckStruct() verifies that the 'tpm_key' has either a TPM_KEY -> ver of a TPM_KEY12 tag and fill */ TPM_RESULT TPM_Key_CheckStruct(int *ver, TPM_KEY *tpm_key) { TPM_RESULT rc = 0; /* The key can be either a TPM_KEY or TPM_KEY12 */ if (*(unsigned char *)tpm_key == 0x01) { *ver = 1; rc = TPM_StructVer_CheckVer(&(tpm_key->ver)); /* check for TPM_KEY */ if (rc == 0) { /* if found TPM_KEY */ printf(" TPM_Key_CheckStruct: TPM_KEY version %u.%u\n", tpm_key->ver.major, tpm_key->ver.minor); } } else { /* else check for TPM_KEY12 */ *ver = 2; rc = TPM_Key_CheckTag((TPM_KEY12 *)tpm_key); if (rc == 0) { printf(" TPM_Key_CheckStruct: TPM_KEY12\n"); } else { /* not TPM_KEY or TPM_KEY12 */ printf("TPM_Key_CheckStruct: Error checking structure, bytes 0:3 %02x %02x %02x %02x\n", tpm_key->ver.major, tpm_key->ver.minor, tpm_key->ver.revMajor, tpm_key->ver.revMinor); rc = TPM_BAD_KEY_PROPERTY; } } return rc; } /* TPM_Key_CheckTag() checks that the TPM_KEY12 tag is correct */ static TPM_RESULT TPM_Key_CheckTag(TPM_KEY12 *tpm_key12) { TPM_RESULT rc = 0; if (rc == 0) { if (tpm_key12->tag != TPM_TAG_KEY12) { printf("TPM_Key_CheckTag: Error, TPM_KEY12 tag %04x should be TPM_TAG_KEY12\n", tpm_key12->tag); rc = TPM_BAD_KEY_PROPERTY; } } if (rc == 0) { if (tpm_key12->fill != 0x0000) { printf("TPM_Key_CheckTag: Error, TPM_KEY12 fill %04x should be 0x0000\n", tpm_key12->fill); rc = TPM_BAD_KEY_PROPERTY; } } return rc; } /* TPM_Key_CheckProperties() checks that the TPM can generate a key of the type requested in 'tpm_key'. if keyLength is non-zero, checks that the tpm_key specifies the correct key length. If keyLength is 0, any tpm_key key length is accepted. Returns TPM_BAD_KEY_PROPERTY on error. */ TPM_RESULT TPM_Key_CheckProperties(int *ver, TPM_KEY *tpm_key, uint32_t keyLength, /* in bits */ TPM_BOOL FIPS) { TPM_RESULT rc = 0; printf(" TPM_Key_CheckProperties:\n"); /* check the version */ if (rc == 0) { rc = TPM_Key_CheckStruct(ver, tpm_key); } /* if FIPS */ if ((rc == 0) && FIPS) { /* b. If keyInfo -> authDataUsage specifies TPM_AUTH_NEVER return TPM_NOTFIPS */ if (tpm_key->authDataUsage == TPM_AUTH_NEVER) { printf("TPM_Key_CheckProperties: Error, FIPS authDataUsage TPM_AUTH_NEVER\n"); rc = TPM_NOTFIPS; } } /* most of the work is done by TPM_KeyParms_CheckProperties() */ if (rc == 0) { printf(" TPM_Key_CheckProperties: authDataUsage %02x\n", tpm_key->authDataUsage); rc = TPM_KeyParms_CheckProperties(&(tpm_key->algorithmParms), tpm_key->keyUsage, keyLength, /* in bits */ FIPS); } return rc; } /* TPM_Key_LoadStoreAsymKey() deserializes a stream to a TPM_STORE_ASYMKEY structure and stores it in the TPM_KEY cache. Call this function when a key is loaded, either from the host (stream is decrypted encData) or from permanent data or saved state (stream was clear text). */ TPM_RESULT TPM_Key_LoadStoreAsymKey(TPM_KEY *tpm_key, TPM_BOOL isEK, unsigned char **stream, /* decrypted encData (clear text) */ uint32_t *stream_size) { TPM_RESULT rc = 0; /* This function should never be called when the TPM_STORE_ASYMKEY structure has already been loaded. This indicates an internal error. */ printf(" TPM_Key_LoadStoreAsymKey:\n"); if (rc == 0) { if (tpm_key->tpm_store_asymkey != NULL) { printf("TPM_Key_LoadStoreAsymKey: Error (fatal), TPM_STORE_ASYMKEY already loaded\n"); rc = TPM_FAIL; /* should never occur */ } } /* If the stream size is 0, there is an internal error. */ if (rc == 0) { if (*stream_size == 0) { printf("TPM_Key_LoadStoreAsymKey: Error (fatal), stream size is 0\n"); rc = TPM_FAIL; /* should never occur */ } } /* allocate memory for the structure */ if (rc == 0) { rc = TPM_Malloc((unsigned char **)&(tpm_key->tpm_store_asymkey), sizeof(TPM_STORE_ASYMKEY)); } if (rc == 0) { TPM_StoreAsymkey_Init(tpm_key->tpm_store_asymkey); rc = TPM_StoreAsymkey_Load(tpm_key->tpm_store_asymkey, isEK, stream, stream_size, &(tpm_key->algorithmParms), &(tpm_key->pubKey)); TPM_PrintFour(" TPM_Key_LoadStoreAsymKey: usageAuth", tpm_key->tpm_store_asymkey->usageAuth); } return rc; } /* TPM_Key_GetStoreAsymkey() gets the TPM_STORE_ASYMKEY from a TPM_KEY cache. */ TPM_RESULT TPM_Key_GetStoreAsymkey(TPM_STORE_ASYMKEY **tpm_store_asymkey, TPM_KEY *tpm_key) { TPM_RESULT rc = 0; printf(" TPM_Key_GetStoreAsymkey:\n"); if (rc == 0) { /* return the cached structure */ *tpm_store_asymkey = tpm_key->tpm_store_asymkey; if (tpm_key->tpm_store_asymkey == NULL) { printf("TPM_Key_GetStoreAsymkey: Error (fatal), no cache\n"); rc = TPM_FAIL; /* indicate no cache */ } } return rc; } /* TPM_Key_GetMigrateAsymkey() gets the TPM_MIGRATE_ASYMKEY from a TPM_KEY cache. */ TPM_RESULT TPM_Key_GetMigrateAsymkey(TPM_MIGRATE_ASYMKEY **tpm_migrate_asymkey, TPM_KEY *tpm_key) { TPM_RESULT rc = 0; printf(" TPM_Key_GetMigrateAsymkey:\n"); if (rc == 0) { /* return the cached structure */ *tpm_migrate_asymkey = tpm_key->tpm_migrate_asymkey; if (tpm_key->tpm_migrate_asymkey == NULL) { printf("TPM_Key_GetMigrateAsymkey: Error (fatal), no cache\n"); rc = TPM_FAIL; /* indicate no cache */ } } return rc; } /* TPM_Key_GetUsageAuth() gets the usageAuth from the TPM_STORE_ASYMKEY or TPM_MIGRATE_ASYMKEY contained in a TPM_KEY */ TPM_RESULT TPM_Key_GetUsageAuth(TPM_SECRET **usageAuth, TPM_KEY *tpm_key) { TPM_RESULT rc = 0; TPM_STORE_ASYMKEY *tpm_store_asymkey; TPM_MIGRATE_ASYMKEY *tpm_migrate_asymkey; printf(" TPM_Key_GetUsageAuth:\n"); /* check that the TPM_KEY_USAGE indicates a valid key */ if (rc == 0) { if ((tpm_key == NULL) || (tpm_key->keyUsage == TPM_KEY_UNINITIALIZED)) { printf("TPM_Key_GetUsageAuth: Error, key not initialized\n"); rc = TPM_INVALID_KEYUSAGE; } } /* get the TPM_STORE_ASYMKEY object */ if (rc == 0) { rc = TPM_Key_GetStoreAsymkey(&tpm_store_asymkey, tpm_key); /* found a TPM_STORE_ASYMKEY */ if (rc == 0) { *usageAuth = &(tpm_store_asymkey->usageAuth); } /* get the TPM_MIGRATE_ASYMKEY object */ else { rc = TPM_Key_GetMigrateAsymkey(&tpm_migrate_asymkey, tpm_key); /* found a TPM_MIGRATE_ASYMKEY */ if (rc == 0) { *usageAuth = &(tpm_migrate_asymkey->usageAuth); } } } if (rc != 0) { printf("TPM_Key_GetUsageAuth: Error (fatal), " "could not get TPM_STORE_ASYMKEY or TPM_MIGRATE_ASYMKEY\n"); rc = TPM_FAIL; /* should never occur */ } /* get the usageAuth element */ if (rc == 0) { TPM_PrintFour(" TPM_Key_GetUsageAuth: Auth", **usageAuth); } return rc; } /* TPM_Key_GetPublicKey() gets the public key from the TPM_STORE_PUBKEY contained in a TPM_KEY */ TPM_RESULT TPM_Key_GetPublicKey(uint32_t *nbytes, unsigned char **narr, TPM_KEY *tpm_key) { TPM_RESULT rc = 0; printf(" TPM_Key_GetPublicKey:\n"); if (rc == 0) { *nbytes = tpm_key->pubKey.size; *narr = tpm_key->pubKey.buffer; } return rc; } /* TPM_Key_GetPrimeFactorP() gets the prime factor p from the TPM_STORE_ASYMKEY contained in a TPM_KEY */ TPM_RESULT TPM_Key_GetPrimeFactorP(uint32_t *pbytes, unsigned char **parr, TPM_KEY *tpm_key) { TPM_RESULT rc = 0; TPM_STORE_ASYMKEY *tpm_store_asymkey; printf(" TPM_Key_GetPrimeFactorP:\n"); if (rc == 0) { rc = TPM_Key_GetStoreAsymkey(&tpm_store_asymkey, tpm_key); } if (rc == 0) { *pbytes = tpm_store_asymkey->privKey.p_key.size; *parr = tpm_store_asymkey->privKey.p_key.buffer; } return rc; } /* TPM_Key_GetPrivateKey() gets the private key from the TPM_STORE_ASYMKEY contained in a TPM_KEY */ TPM_RESULT TPM_Key_GetPrivateKey(uint32_t *dbytes, unsigned char **darr, TPM_KEY *tpm_key) { TPM_RESULT rc = 0; TPM_STORE_ASYMKEY *tpm_store_asymkey; printf(" TPM_Key_GetPrivateKey:\n"); if (rc == 0) { rc = TPM_Key_GetStoreAsymkey(&tpm_store_asymkey, tpm_key); } if (rc == 0) { *dbytes = tpm_store_asymkey->privKey.d_key.size; *darr = tpm_store_asymkey->privKey.d_key.buffer; } return rc; } /* TPM_Key_GetExponent() gets the exponent key from the TPM_RSA_KEY_PARMS contained in a TPM_KEY */ TPM_RESULT TPM_Key_GetExponent(uint32_t *ebytes, unsigned char **earr, TPM_KEY *tpm_key) { TPM_RESULT rc = 0; printf(" TPM_Key_GetExponent:\n"); if (rc == 0) { rc = TPM_KeyParms_GetExponent(ebytes, earr, &(tpm_key->algorithmParms)); } return rc; } /* TPM_Key_GetPCRUsage() returns 'pcrUsage' TRUE if any bit is set in the pcrSelect bit mask. 'start_pcr' indicates the starting byte index into pcrSelect[] */ TPM_RESULT TPM_Key_GetPCRUsage(TPM_BOOL *pcrUsage, TPM_KEY *tpm_key, size_t start_index) { TPM_RESULT rc = 0; printf(" TPM_Key_GetPCRUsage: Start %lu\n", (unsigned long)start_index); if (((TPM_KEY12 *)tpm_key)->tag != TPM_TAG_KEY12) { /* TPM_KEY */ rc = TPM_PCRInfo_GetPCRUsage(pcrUsage, tpm_key->tpm_pcr_info, start_index); } else { /* TPM_KEY12 */ rc = TPM_PCRInfoLong_GetPCRUsage(pcrUsage, tpm_key->tpm_pcr_info_long, start_index); } return rc; } /* TPM_Key_GetLocalityAtRelease() the localityAtRelease for a TPM_PCR_INFO_LONG. For a TPM_PCR_INFO is returns TPM_LOC_ALL (all localities). */ TPM_RESULT TPM_Key_GetLocalityAtRelease(TPM_LOCALITY_SELECTION *localityAtRelease, TPM_KEY *tpm_key) { TPM_RESULT rc = 0; printf(" TPM_Key_GetLocalityAtRelease:\n"); if (((TPM_KEY12 *)tpm_key)->tag != TPM_TAG_KEY12) { /* TPM_KEY */ /* locality not used for TPM_PCR_INFO */ *localityAtRelease = TPM_LOC_ALL; } /* TPM_KEY12 */ else if (tpm_key->tpm_pcr_info_long == NULL) { /* locality not used if TPM_PCR_INFO_LONG was not specified */ *localityAtRelease = TPM_LOC_ALL; } else { *localityAtRelease = tpm_key->tpm_pcr_info_long->localityAtRelease; } return rc; } /* TPM_Key_GenerateRSA() generates a TPM_KEY using TPM_KEY_PARMS. The tag/version is set correctly. The TPM_STORE_ASYMKEY member cache is set. pcrInfo is set as a serialized tpm_pcr_info or tpm_pcr_info_long. For exported keys, encData is not set yet. It later becomes the encryption of TPM_STORE_ASYMKEY. For internal 'root' keys (endorsement key, srk), encData is stored as clear text. It returns the TPM_KEY object. Call tree: local - sets tpm_store_asymkey->privkey TPM_Key_Set - sets keyUsage, keyFlags, authDataUsage, algorithmParms tpm_pcr_info cache, digestAtCreation, pubKey, TPM_Key_GeneratePubDataDigest - pubDataDigest TPM_Key_Store TPM_Key_StorePubData - serializes tpm_pcr_info cache */ TPM_RESULT TPM_Key_GenerateRSA(TPM_KEY *tpm_key, /* output created key */ tpm_state_t *tpm_state, TPM_KEY *parent_key, /* NULL for root keys */ TPM_DIGEST *tpm_pcrs, /* PCR array from state */ int ver, /* TPM_KEY or TPM_KEY12 */ TPM_KEY_USAGE keyUsage, /* input */ TPM_KEY_FLAGS keyFlags, /* input */ TPM_AUTH_DATA_USAGE authDataUsage, /* input */ TPM_KEY_PARMS *tpm_key_parms, /* input */ TPM_PCR_INFO *tpm_pcr_info, /* input */ TPM_PCR_INFO_LONG *tpm_pcr_info_long) /* input */ { TPM_RESULT rc = 0; TPM_RSA_KEY_PARMS *tpm_rsa_key_parms; unsigned char *earr; /* public exponent */ uint32_t ebytes; /* generated RSA key */ unsigned char *n = NULL; /* public key */ unsigned char *p = NULL; /* prime factor */ unsigned char *q = NULL; /* prime factor */ unsigned char *d = NULL; /* private key */ printf(" TPM_Key_GenerateRSA:\n"); /* extract the TPM_RSA_KEY_PARMS from TPM_KEY_PARMS */ if (rc == 0) { rc = TPM_KeyParms_GetRSAKeyParms(&tpm_rsa_key_parms, tpm_key_parms); } /* get the public exponent, with conversion */ if (rc == 0) { rc = TPM_RSAKeyParms_GetExponent(&ebytes, &earr, tpm_rsa_key_parms); } /* allocate storage for TPM_STORE_ASYMKEY. The structure is not freed. It is cached in the TPM_KEY->TPM_STORE_ASYMKEY member and freed when they are deleted. */ if (rc == 0) { rc = TPM_Malloc((unsigned char **)&(tpm_key->tpm_store_asymkey), sizeof(TPM_STORE_ASYMKEY)); } if (rc == 0) { TPM_StoreAsymkey_Init(tpm_key->tpm_store_asymkey); } /* generate the key pair */ if (rc == 0) { rc = TPM_RSAGenerateKeyPair(&n, /* public key (modulus) freed @3 */ &p, /* private prime factor freed @4 */ &q, /* private prime factor freed @5 */ &d, /* private key (private exponent) freed @6 */ tpm_rsa_key_parms->keyLength, /* key size in bits */ earr, /* public exponent */ ebytes); } /* construct the TPM_STORE_ASYMKEY member */ if (rc == 0) { TPM_PrintFour(" TPM_Key_GenerateRSA: Public key n", n); TPM_PrintAll(" TPM_Key_GenerateRSA: Exponent", earr, ebytes); TPM_PrintFour(" TPM_Key_GenerateRSA: Private prime p", p); TPM_PrintFour(" TPM_Key_GenerateRSA: Private prime q", q); TPM_PrintFour(" TPM_Key_GenerateRSA: Private key d", d); /* add the private primes and key to the TPM_STORE_ASYMKEY object */ rc = TPM_SizedBuffer_Set(&(tpm_key->tpm_store_asymkey->privKey.d_key), tpm_rsa_key_parms->keyLength/CHAR_BIT, d); } if (rc == 0) { rc = TPM_SizedBuffer_Set(&(tpm_key->tpm_store_asymkey->privKey.p_key), tpm_rsa_key_parms->keyLength/(CHAR_BIT * 2), p); } if (rc == 0) { rc = TPM_SizedBuffer_Set(&(tpm_key->tpm_store_asymkey->privKey.q_key), tpm_rsa_key_parms->keyLength/(CHAR_BIT * 2), q); } if (rc == 0) { rc = TPM_Key_Set(tpm_key, tpm_state, parent_key, tpm_pcrs, ver, /* TPM_KEY or TPM_KEY12 */ keyUsage, /* TPM_KEY_USAGE */ keyFlags, /* TPM_KEY_FLAGS */ authDataUsage, /* TPM_AUTH_DATA_USAGE */ tpm_key_parms, /* TPM_KEY_PARMS */ tpm_pcr_info, /* TPM_PCR_INFO */ tpm_pcr_info_long, /* TPM_PCR_INFO_LONG */ tpm_rsa_key_parms->keyLength/CHAR_BIT, /* TPM_STORE_PUBKEY.keyLength */ n, /* TPM_STORE_PUBKEY.key (public key) */ /* FIXME redundant */ tpm_key->tpm_store_asymkey, /* cache the TPM_STORE_ASYMKEY structure */ NULL); /* TPM_MIGRATE_ASYMKEY */ } free(n); /* @3 */ free(p); /* @4 */ free(q); /* @5 */ free(d); /* @6 */ return rc; } /* TPM_Key_GeneratePubkeyDigest() serializes a TPM_PUBKEY derived from the TPM_KEY and calculates its digest. */ TPM_RESULT TPM_Key_GeneratePubkeyDigest(TPM_DIGEST tpm_digest, TPM_KEY *tpm_key) { TPM_RESULT rc = 0; TPM_STORE_BUFFER pubkeyStream; /* from tpm_key */ const unsigned char *pubkeyStreamBuffer; uint32_t pubkeyStreamLength; printf(" TPM_Key_GeneratePubkeyDigest:\n"); TPM_Sbuffer_Init(&pubkeyStream); /* freed @1 */ /* serialize a TPM_PUBKEY derived from the TPM_KEY */ if (rc == 0) { rc = TPM_Key_StorePubkey(&pubkeyStream, /* output */ &pubkeyStreamBuffer, /* output */ &pubkeyStreamLength, /* output */ tpm_key); /* input */ } if (rc == 0) { rc = TPM_SHA1(tpm_digest, pubkeyStreamLength, pubkeyStreamBuffer, 0, NULL); } TPM_Sbuffer_Delete(&pubkeyStream); /* @1 */ return rc; } /* TPM_Key_ComparePubkey() serializes and hashes the TPM_PUBKEY derived from a TPM_KEY and a TPM_PUBKEY and compares the results */ TPM_RESULT TPM_Key_ComparePubkey(TPM_KEY *tpm_key, TPM_PUBKEY *tpm_pubkey) { TPM_RESULT rc = 0; TPM_DIGEST key_digest; TPM_DIGEST pubkey_digest; if (rc == 0) { rc = TPM_Key_GeneratePubkeyDigest(key_digest, tpm_key); } if (rc == 0) { rc = TPM_SHA1_GenerateStructure(pubkey_digest, tpm_pubkey, (TPM_STORE_FUNCTION_T)TPM_Pubkey_Store); } if (rc == 0) { rc = TPM_Digest_Compare(key_digest, pubkey_digest); } return rc; } /* TPM_Key_GeneratePubDataDigest() generates and stores a TPM_STORE_ASYMKEY -> pubDataDigest As a side effect, it serializes the tpm_pcr_info cache to pcrInfo. */ TPM_RESULT TPM_Key_GeneratePubDataDigest(TPM_KEY *tpm_key) { TPM_RESULT rc = 0; TPM_STORE_BUFFER sbuffer; /* TPM_KEY serialization */ TPM_STORE_ASYMKEY *tpm_store_asymkey; printf(" TPM_Key_GeneratePubDataDigest:\n"); TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ /* serialize the TPM_KEY excluding the encData fields */ if (rc == 0) { rc = TPM_Key_StorePubData(&sbuffer, FALSE, tpm_key); } /* get the TPM_STORE_ASYMKEY structure */ if (rc == 0) { rc = TPM_Key_GetStoreAsymkey(&tpm_store_asymkey, tpm_key); } /* hash the serialized buffer to tpm_digest */ if (rc == 0) { rc = TPM_SHA1Sbuffer(tpm_store_asymkey->pubDataDigest, &sbuffer); } TPM_Sbuffer_Delete(&sbuffer); /* @1 */ return rc; } /* TPM_Key_CheckPubDataDigest() generates a TPM_STORE_ASYMKEY -> pubDataDigest and compares it to the stored value. Returns: Error id */ TPM_RESULT TPM_Key_CheckPubDataDigest(TPM_KEY *tpm_key) { TPM_RESULT rc = 0; TPM_STORE_BUFFER sbuffer; /* TPM_KEY serialization */ TPM_STORE_ASYMKEY *tpm_store_asymkey; TPM_DIGEST tpm_digest; /* calculated pubDataDigest */ printf(" TPM_Key_CheckPubDataDigest:\n"); TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ /* serialize the TPM_KEY excluding the encData fields */ if (rc == 0) { rc = TPM_Key_StorePubData(&sbuffer, FALSE, tpm_key); } /* get the TPM_STORE_ASYMKEY structure */ if (rc == 0) { rc = TPM_Key_GetStoreAsymkey(&tpm_store_asymkey, tpm_key); } if (rc == 0) { rc = TPM_SHA1Sbuffer(tpm_digest, &sbuffer); } if (rc == 0) { rc = TPM_Digest_Compare(tpm_store_asymkey->pubDataDigest, tpm_digest); } TPM_Sbuffer_Delete(&sbuffer); /* @1 */ return rc; } /* TPM_Key_GenerateEncData() generates an TPM_KEY -> encData structure member by serializing the cached TPM_KEY -> TPM_STORE_ASYMKEY member and encrypting the result using the parent_key public key. */ TPM_RESULT TPM_Key_GenerateEncData(TPM_KEY *tpm_key, TPM_KEY *parent_key) { TPM_RESULT rc = 0; TPM_STORE_ASYMKEY *tpm_store_asymkey; printf(" TPM_Key_GenerateEncData;\n"); /* get the TPM_STORE_ASYMKEY structure */ if (rc == 0) { rc = TPM_Key_GetStoreAsymkey(&tpm_store_asymkey, tpm_key); } if (rc == 0) { rc = TPM_StoreAsymkey_GenerateEncData(&(tpm_key->encData), tpm_store_asymkey, parent_key); } return rc; } /* TPM_Key_DecryptEncData() decrypts the TPM_KEY -> encData using the parent private key. The result is deserialized and stored in the TPM_KEY -> TPM_STORE_ASYMKEY cache. */ TPM_RESULT TPM_Key_DecryptEncData(TPM_KEY *tpm_key, /* result */ TPM_KEY *parent_key) /* parent for decrypting encData */ { TPM_RESULT rc = 0; unsigned char *decryptData = NULL; /* freed @1 */ uint32_t decryptDataLength = 0; /* actual valid data */ unsigned char *stream; uint32_t stream_size; printf(" TPM_Key_DecryptEncData\n"); /* allocate space for the decrypted data */ if (rc == 0) { rc = TPM_RSAPrivateDecryptMalloc(&decryptData, /* decrypted data */ &decryptDataLength, /* actual size of decrypted data */ tpm_key->encData.buffer, /* encrypted data */ tpm_key->encData.size, /* encrypted data size */ parent_key); } /* load the TPM_STORE_ASYMKEY cache from the 'encData' member stream */ if (rc == 0) { stream = decryptData; stream_size = decryptDataLength; rc = TPM_Key_LoadStoreAsymKey(tpm_key, FALSE, &stream, &stream_size); } free(decryptData); /* @1 */ return rc; } /* TPM_Key_GeneratePCRDigest() generates a digest based on the current PCR state and the PCR's specified with the key. The key can be either TPM_KEY or TPM_KEY12. This function assumes that TPM_Key_GetPCRUsage() has determined that PCR's are in use, so a NULL PCR cache will return an error here. See Part 1 25.1 */ TPM_RESULT TPM_Key_CheckPCRDigest(TPM_KEY *tpm_key, tpm_state_t *tpm_state) { TPM_RESULT rc = 0; printf(" TPM_Key_GeneratePCRDigest:\n"); if (((TPM_KEY12 *)tpm_key)->tag != TPM_TAG_KEY12) { /* TPM_KEY */ /* i. Calculate H1 a TPM_COMPOSITE_HASH of the PCR selected by LK -> pcrInfo -> releasePCRSelection */ /* ii. Compare H1 to LK -> pcrInfo -> digestAtRelease on mismatch return TPM_WRONGPCRVAL */ if (rc == 0) { rc = TPM_PCRInfo_CheckDigest(tpm_key->tpm_pcr_info, tpm_state->tpm_stclear_data.PCRS); /* array of PCR's */ } } else { /* TPM_KEY12 */ /* i. Calculate H1 a TPM_COMPOSITE_HASH of the PCR selected by LK -> pcrInfo -> releasePCRSelection */ /* ii. Compare H1 to LK -> pcrInfo -> digestAtRelease on mismatch return TPM_WRONGPCRVAL */ if (rc == 0) { rc = TPM_PCRInfoLong_CheckDigest(tpm_key->tpm_pcr_info_long, tpm_state->tpm_stclear_data.PCRS, /* array of PCR's */ tpm_state->tpm_stany_flags.localityModifier); } } /* 4. Allow use of the key */ if (rc != 0) { printf("TPM_Key_CheckPCRDigest: Error, wrong digestAtRelease value\n"); rc = TPM_WRONGPCRVAL; } return rc; } /* TPM_Key_CheckRestrictDelegate() checks the restrictDelegate data against the TPM_KEY properties. It determines how the TPM responds to delegated requests to use a certified migration key. Called from TPM_AuthSessions_GetData() if it's a DSAP session using a key entity.. TPM_PERMANENT_DATA -> restrictDelegate is used as follows: 1. If the session type is TPM_PID_DSAP and TPM_KEY -> keyFlags -> migrateAuthority is TRUE a. If TPM_KEY_USAGE is TPM_KEY_SIGNING and restrictDelegate -> TPM_CMK_DELEGATE_SIGNING is TRUE, or TPM_KEY_USAGE is TPM_KEY_STORAGE and restrictDelegate -> TPM_CMK_DELEGATE_STORAGE is TRUE, or TPM_KEY_USAGE is TPM_KEY_BIND and restrictDelegate -> TPM_CMK_DELEGATE_BIND is TRUE, or TPM_KEY_USAGE is TPM_KEY_LEGACY and restrictDelegate -> TPM_CMK_DELEGATE_LEGACY is TRUE, or TPM_KEY_USAGE is TPM_KEY_MIGRATE and restrictDelegate -> TPM_CMK_DELEGATE_MIGRATE is TRUE then the key can be used. b. Else return TPM_INVALID_KEYUSAGE. */ TPM_RESULT TPM_Key_CheckRestrictDelegate(TPM_KEY *tpm_key, TPM_CMK_DELEGATE restrictDelegate) { TPM_RESULT rc = 0; printf("TPM_Key_CheckRestrictDelegate:\n"); if (rc == 0) { if (tpm_key == NULL) { printf("TPM_Key_CheckRestrictDelegate: Error (fatal), key NULL\n"); rc = TPM_FAIL; /* internal error, should never occur */ } } /* if it's a certified migration key */ if (rc == 0) { if (tpm_key->keyFlags & TPM_MIGRATEAUTHORITY) { if (!( ((restrictDelegate & TPM_CMK_DELEGATE_SIGNING) && (tpm_key->keyUsage == TPM_KEY_SIGNING)) || ((restrictDelegate & TPM_CMK_DELEGATE_STORAGE) && (tpm_key->keyUsage == TPM_KEY_STORAGE)) || ((restrictDelegate & TPM_CMK_DELEGATE_BIND) && (tpm_key->keyUsage == TPM_KEY_BIND)) || ((restrictDelegate & TPM_CMK_DELEGATE_LEGACY) && (tpm_key->keyUsage == TPM_KEY_LEGACY)) || ((restrictDelegate & TPM_CMK_DELEGATE_MIGRATE) && (tpm_key->keyUsage == TPM_KEY_MIGRATE)) )) { printf("TPM_Key_CheckRestrictDelegate: Error, " "invalid keyUsage %04hx restrictDelegate %08x\n", tpm_key->keyUsage, restrictDelegate); rc = TPM_INVALID_KEYUSAGE; } } } return rc; } /* TPM_KEY_FLAGS */ /* TPM_KeyFlags_Load() deserializes a TPM_KEY_FLAGS value and checks for a legal value. */ TPM_RESULT TPM_KeyFlags_Load(TPM_KEY_FLAGS *tpm_key_flags, /* result */ unsigned char **stream, /* pointer to next parameter */ uint32_t *stream_size) /* stream size left */ { TPM_RESULT rc = 0; /* load keyFlags */ if (rc == 0) { rc = TPM_Load32(tpm_key_flags, stream, stream_size); } /* check TPM_KEY_FLAGS validity, look for extra bits set */ if (rc == 0) { if (*tpm_key_flags & ~TPM_KEY_FLAGS_MASK) { printf("TPM_KeyFlags_Load: Error, illegal keyFlags value %08x\n", *tpm_key_flags); rc = TPM_BAD_KEY_PROPERTY; } } return rc; } /* TPM_KEY_PARMS */ void TPM_KeyParms_Init(TPM_KEY_PARMS *tpm_key_parms) { printf(" TPM_KeyParms_Init:\n"); tpm_key_parms->algorithmID = 0; tpm_key_parms->encScheme = TPM_ES_NONE; tpm_key_parms->sigScheme = TPM_SS_NONE; TPM_SizedBuffer_Init(&(tpm_key_parms->parms)); tpm_key_parms->tpm_rsa_key_parms = NULL; return; } #if 0 /* TPM_KeyParms_SetRSA() is a 'Set' version specific to RSA keys */ TPM_RESULT TPM_KeyParms_SetRSA(TPM_KEY_PARMS *tpm_key_parms, TPM_ALGORITHM_ID algorithmID, TPM_ENC_SCHEME encScheme, TPM_SIG_SCHEME sigScheme, uint32_t keyLength, /* in bits */ TPM_SIZED_BUFFER *exponent) { TPM_RESULT rc = 0; printf(" TPM_KeyParms_SetRSA:\n"); /* copy the TPM_KEY_PARMS members */ if (rc == 0) { tpm_key_parms->algorithmID = algorithmID; tpm_key_parms->encScheme = encScheme; tpm_key_parms->sigScheme = sigScheme; /* construct the TPM_RSA_KEY_PARMS cache member object */ rc = TPM_RSAKeyParms_New(&tpm_key_parms->tpm_rsa_key_parms); } if (rc == 0) { /* copy the TPM_RSA_KEY_PARMS members */ tpm_key_parms->tpm_rsa_key_parms->keyLength = keyLength; tpm_key_parms->tpm_rsa_key_parms->numPrimes = 2; rc = TPM_SizedBuffer_Copy(&(tpm_key_parms->tpm_rsa_key_parms->exponent), exponent); } /* serialize the TPM_RSA_KEY_PARMS object back to TPM_KEY_PARMS */ if (rc == 0) { rc = TPM_SizedBuffer_SetStructure(&(tpm_key_parms->parms), tpm_key_parms->tpm_rsa_key_parms, (TPM_STORE_FUNCTION_T)TPM_RSAKeyParms_Store); } return rc; } #endif /* TPM_KeyParms_Copy() copies the source to the destination. If the algorithmID is TPM_ALG_RSA, the tpm_rsa_key_parms cache is allocated and copied. Must be freed by TPM_KeyParms_Delete() after use */ TPM_RESULT TPM_KeyParms_Copy(TPM_KEY_PARMS *tpm_key_parms_dest, TPM_KEY_PARMS *tpm_key_parms_src) { TPM_RESULT rc = 0; printf(" TPM_KeyParms_Copy:\n"); if (rc == 0) { tpm_key_parms_dest->algorithmID = tpm_key_parms_src->algorithmID; tpm_key_parms_dest->encScheme = tpm_key_parms_src->encScheme; tpm_key_parms_dest->sigScheme = tpm_key_parms_src->sigScheme; rc = TPM_SizedBuffer_Copy(&(tpm_key_parms_dest->parms), &(tpm_key_parms_src->parms)); } /* if there is a destination TPM_RSA_KEY_PARMS cache */ if ((rc == 0) && (tpm_key_parms_dest->algorithmID == TPM_ALG_RSA)) { /* construct the TPM_RSA_KEY_PARMS cache member object */ if (rc == 0) { rc = TPM_RSAKeyParms_New(&(tpm_key_parms_dest->tpm_rsa_key_parms)); } /* copy the TPM_RSA_KEY_PARMS member */ if (rc == 0) { rc = TPM_RSAKeyParms_Copy(tpm_key_parms_dest->tpm_rsa_key_parms, tpm_key_parms_src->tpm_rsa_key_parms); } } return rc; } /* TPM_KeyParms_Load deserializes a stream to a TPM_KEY_PARMS structure. Must be freed by TPM_KeyParms_Delete() after use */ TPM_RESULT TPM_KeyParms_Load(TPM_KEY_PARMS *tpm_key_parms, /* result */ unsigned char **stream, /* pointer to next parameter */ uint32_t *stream_size) /* stream size left */ { TPM_RESULT rc = 0; unsigned char *parms_stream; uint32_t parms_stream_size; printf(" TPM_KeyParms_Load:\n"); /* load algorithmID */ if (rc == 0) { rc = TPM_Load32(&(tpm_key_parms->algorithmID), stream, stream_size); } /* load encScheme */ if (rc == 0) { rc = TPM_Load16(&(tpm_key_parms->encScheme), stream, stream_size); } /* load sigScheme */ if (rc == 0) { rc = TPM_Load16(&(tpm_key_parms->sigScheme), stream, stream_size); } /* load parmSize and parms */ if (rc == 0) { rc = TPM_SizedBuffer_Load(&(tpm_key_parms->parms), stream, stream_size); } if (rc == 0) { switch (tpm_key_parms->algorithmID) { /* Allow load of uninitialized structures */ case 0: break; case TPM_ALG_RSA: /* load the TPM_RSA_KEY_PARMS cache if the algorithmID indicates an RSA key */ if (rc == 0) { rc = TPM_RSAKeyParms_New(&(tpm_key_parms->tpm_rsa_key_parms)); } /* deserialize the parms stream, but don't move the pointer */ if (rc == 0) { parms_stream = tpm_key_parms->parms.buffer; parms_stream_size = tpm_key_parms->parms.size; rc = TPM_RSAKeyParms_Load(tpm_key_parms->tpm_rsa_key_parms, &parms_stream, &parms_stream_size); } break; /* NOTE Only handles TPM_RSA_KEY_PARMS, could handle TPM_SYMMETRIC_KEY_PARMS */ case TPM_ALG_AES128: case TPM_ALG_AES192: case TPM_ALG_AES256: default: printf("TPM_KeyParms_Load: Cannot handle algorithmID %08x\n", tpm_key_parms->algorithmID); rc = TPM_BAD_KEY_PROPERTY; break; } } return rc; } TPM_RESULT TPM_KeyParms_GetExponent(uint32_t *ebytes, unsigned char **earr, TPM_KEY_PARMS *tpm_key_parms) { TPM_RESULT rc = 0; TPM_RSA_KEY_PARMS *tpm_rsa_key_parms; printf(" TPM_KeyParms_GetExponent:\n"); if (rc == 0) { rc = TPM_KeyParms_GetRSAKeyParms(&tpm_rsa_key_parms, tpm_key_parms); } if (rc == 0) { rc = TPM_RSAKeyParms_GetExponent(ebytes, earr, tpm_rsa_key_parms); } return rc; } /* TPM_KeyParms_Store serializes a TPM_KEY_PARMS structure, appending results to 'sbuffer' */ TPM_RESULT TPM_KeyParms_Store(TPM_STORE_BUFFER *sbuffer, TPM_KEY_PARMS *tpm_key_parms) { TPM_RESULT rc = 0; printf(" TPM_KeyParms_Store:\n"); /* store algorithmID */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_key_parms->algorithmID); } /* store encScheme */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, tpm_key_parms->encScheme); } /* store sigScheme */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, tpm_key_parms->sigScheme); } /* copy cache to parms */ if (rc == 0) { switch (tpm_key_parms->algorithmID) { /* Allow store of uninitialized structures */ case 0: break; case TPM_ALG_RSA: rc = TPM_SizedBuffer_SetStructure(&(tpm_key_parms->parms), tpm_key_parms->tpm_rsa_key_parms, (TPM_STORE_FUNCTION_T)TPM_RSAKeyParms_Store); break; /* NOTE Only handles TPM_RSA_KEY_PARMS, could handle TPM_SYMMETRIC_KEY_PARMS */ case TPM_ALG_AES128: case TPM_ALG_AES192: case TPM_ALG_AES256: default: printf("TPM_KeyParms_Store: Cannot handle algorithmID %08x\n", tpm_key_parms->algorithmID); rc = TPM_BAD_KEY_PROPERTY; break; } } /* store parms */ if (rc == 0) { rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_key_parms->parms)); } return rc; } /* TPM_KeyParms_Delete frees any member allocated memory */ void TPM_KeyParms_Delete(TPM_KEY_PARMS *tpm_key_parms) { printf(" TPM_KeyParms_Delete:\n"); if (tpm_key_parms != NULL) { TPM_SizedBuffer_Delete(&(tpm_key_parms->parms)); TPM_RSAKeyParms_Delete(tpm_key_parms->tpm_rsa_key_parms); free(tpm_key_parms->tpm_rsa_key_parms); TPM_KeyParms_Init(tpm_key_parms); } return; } /* TPM_KeyParms_GetRSAKeyParms() gets the TPM_RSA_KEY_PARMS from a TPM_KEY_PARMS cache. Returns an error if the cache is NULL, since the cache should always be set when the TPM_KEY_PARMS indicates an RSA key. */ TPM_RESULT TPM_KeyParms_GetRSAKeyParms(TPM_RSA_KEY_PARMS **tpm_rsa_key_parms, TPM_KEY_PARMS *tpm_key_parms) { TPM_RESULT rc = 0; printf(" TPM_KeyParms_GetRSAKeyParms:\n"); /* algorithmID must be RSA */ if (rc == 0) { if (tpm_key_parms->algorithmID != TPM_ALG_RSA) { printf("TPM_KeyParms_GetRSAKeyParms: Error, incorrect algorithmID %08x\n", tpm_key_parms->algorithmID); rc = TPM_BAD_KEY_PROPERTY; } } /* if the TPM_RSA_KEY_PARMS structure has not been cached, deserialize it */ if (rc == 0) { if (tpm_key_parms->tpm_rsa_key_parms == NULL) { printf("TPM_KeyParms_GetRSAKeyParms: Error (fatal), cache is NULL\n"); /* This should never occur. The cache is loaded when the TPM_KEY_PARMS is loaded. */ rc = TPM_FAIL; } } /* return the cached structure */ if (rc == 0) { *tpm_rsa_key_parms = tpm_key_parms->tpm_rsa_key_parms; } return rc; } /* TPM_KeyParms_CheckProperties() checks that the TPM can generate a key of the type requested in 'tpm_key_parms' if' keyLength' is non-zero, checks that the tpm_key specifies the correct key length. If keyLength is 0, any tpm_key key length is accepted. */ TPM_RESULT TPM_KeyParms_CheckProperties(TPM_KEY_PARMS *tpm_key_parms, TPM_KEY_USAGE tpm_key_usage, uint32_t keyLength, /* in bits */ TPM_BOOL FIPS) { TPM_RESULT rc = 0; TPM_RSA_KEY_PARMS *tpm_rsa_key_parms = NULL;/* used if algorithmID indicates RSA */ printf(" TPM_KeyParms_CheckProperties: keyUsage %04hx\n", tpm_key_usage); printf(" TPM_KeyParms_CheckProperties: sigScheme %04hx\n", tpm_key_parms->sigScheme); printf(" TPM_KeyParms_CheckProperties: encScheme %04hx\n", tpm_key_parms->encScheme); if (rc == 0) { /* the code currently only supports RSA */ if (tpm_key_parms->algorithmID != TPM_ALG_RSA) { printf("TPM_KeyParms_CheckProperties: Error, algorithmID not TPM_ALG_RSA\n"); rc = TPM_BAD_KEY_PROPERTY; } } /* get the TPM_RSA_KEY_PARMS structure from the TPM_KEY_PARMS structure */ /* NOTE: for now only support RSA keys */ if (rc == 0) { rc = TPM_KeyParms_GetRSAKeyParms(&tpm_rsa_key_parms, tpm_key_parms); } /* check key length if specified as input parameter */ if ((rc == 0) && (keyLength != 0)) { if (tpm_rsa_key_parms->keyLength != keyLength) { /* in bits */ printf("TPM_KeyParms_CheckProperties: Error, Bad keyLength should be %u, was %u\n", keyLength, tpm_rsa_key_parms->keyLength); rc = TPM_BAD_KEY_PROPERTY; } } if (rc == 0) { if (tpm_rsa_key_parms->keyLength > TPM_RSA_KEY_LENGTH_MAX) { /* in bits */ printf("TPM_KeyParms_CheckProperties: Error, Bad keyLength max %u, was %u\n", TPM_RSA_KEY_LENGTH_MAX, tpm_rsa_key_parms->keyLength); rc = TPM_BAD_KEY_PROPERTY; } } /* kgold - Support only 2 primes */ if (rc == 0) { if (tpm_rsa_key_parms->numPrimes != 2) { printf("TPM_KeyParms_CheckProperties: Error, numPrimes %u should be 2\n", tpm_rsa_key_parms->numPrimes); rc = TPM_BAD_KEY_PROPERTY; } } /* if FIPS */ if ((rc == 0) && FIPS) { /* a. If keyInfo -> keySize is less than 1024 return TPM_NOTFIPS */ if (tpm_rsa_key_parms->keyLength < 1024) { printf("TPM_KeyParms_CheckProperties: Error, Invalid FIPS key length %u\n", tpm_rsa_key_parms->keyLength); rc = TPM_NOTFIPS; } /* c. If keyInfo -> keyUsage specifies TPM_KEY_LEGACY return TPM_NOTFIPS */ else if (tpm_key_usage == TPM_KEY_LEGACY) { printf("TPM_KeyParms_CheckProperties: Error, FIPS authDataUsage TPM_AUTH_NEVER\n"); rc = TPM_NOTFIPS; } } /* From Part 2 5.7.1 Mandatory Key Usage Schemes and TPM_CreateWrapKey, TPM_LoadKey */ if (rc == 0) { switch (tpm_key_usage) { case TPM_KEY_UNINITIALIZED: printf("TPM_KeyParms_CheckProperties: Error, keyUsage TPM_KEY_UNINITIALIZED\n"); rc = TPM_BAD_KEY_PROPERTY; break; case TPM_KEY_SIGNING: if (tpm_key_parms->encScheme != TPM_ES_NONE) { printf("TPM_KeyParms_CheckProperties: Error, " "Signing encScheme %04hx is not TPM_ES_NONE\n", tpm_key_parms->encScheme); rc = TPM_BAD_KEY_PROPERTY; } #ifdef TPM_V12 else if ((tpm_key_parms->sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1) && (tpm_key_parms->sigScheme != TPM_SS_RSASSAPKCS1v15_DER) && (tpm_key_parms->sigScheme != TPM_SS_RSASSAPKCS1v15_INFO)) { #else /* TPM 1.1 */ else if (tpm_key_parms->sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1) { #endif printf("TPM_KeyParms_CheckProperties: Error, " "Signing sigScheme %04hx is not DER, SHA1, INFO\n", tpm_key_parms->sigScheme); rc = TPM_BAD_KEY_PROPERTY; } break; case TPM_KEY_STORAGE: if (tpm_key_parms->encScheme != TPM_ES_RSAESOAEP_SHA1_MGF1) { printf("TPM_KeyParms_CheckProperties: Error, " "Storage encScheme %04hx is not TPM_ES_RSAESOAEP_SHA1_MGF1\n", tpm_key_parms->encScheme); rc = TPM_BAD_KEY_PROPERTY; } else if (tpm_key_parms->sigScheme != TPM_SS_NONE) { printf("TPM_KeyParms_CheckProperties: Error, " "Storage sigScheme %04hx is not TPM_SS_NONE\n", tpm_key_parms->sigScheme); rc = TPM_BAD_KEY_PROPERTY; } else if (tpm_key_parms->algorithmID != TPM_ALG_RSA) { /*constant condition*/ printf("TPM_KeyParms_CheckProperties: Error, " "Storage algorithmID %08x is not TPM_ALG_RSA\n", tpm_key_parms->algorithmID); rc = TPM_BAD_KEY_PROPERTY; } /* interoperable TPM only supports 2048 */ else if (tpm_rsa_key_parms->keyLength < 2048) { printf("TPM_KeyParms_CheckProperties: Error, " "Storage keyLength %d is less than 2048\n", tpm_rsa_key_parms->keyLength); rc = TPM_BAD_KEY_PROPERTY; } else { rc = TPM_KeyParams_CheckDefaultExponent(&(tpm_rsa_key_parms->exponent)); } break; case TPM_KEY_IDENTITY: if (tpm_key_parms->encScheme != TPM_ES_NONE) { printf("TPM_KeyParms_CheckProperties: Error, " "Identity encScheme %04hx is not TPM_ES_NONE\n", tpm_key_parms->encScheme); rc = TPM_BAD_KEY_PROPERTY; } else if (tpm_key_parms->sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1) { printf("TPM_KeyParms_CheckProperties: Error, " "Identity sigScheme %04hx is not %04x\n", tpm_key_parms->sigScheme, TPM_SS_RSASSAPKCS1v15_SHA1); rc = TPM_BAD_KEY_PROPERTY; } else if (tpm_key_parms->algorithmID != TPM_ALG_RSA) { /*constant condition*/ printf("TPM_KeyParms_CheckProperties: Error, " "Identity algorithmID %08x is not TPM_ALG_RSA\n", tpm_key_parms->algorithmID); rc = TPM_BAD_KEY_PROPERTY; } /* interoperable TPM only supports 2048 */ else if (tpm_rsa_key_parms->keyLength < 2048) { printf("TPM_KeyParms_CheckProperties: Error, " "Identity keyLength %d is less than 2048\n", tpm_rsa_key_parms->keyLength); rc = TPM_BAD_KEY_PROPERTY; } else { rc = TPM_KeyParams_CheckDefaultExponent(&(tpm_rsa_key_parms->exponent)); } break; case TPM_KEY_AUTHCHANGE: if (tpm_key_parms->encScheme != TPM_ES_RSAESOAEP_SHA1_MGF1) { printf("TPM_KeyParms_CheckProperties: Error, " "Authchange encScheme %04hx is not TPM_ES_RSAESOAEP_SHA1_MGF1\n", tpm_key_parms->encScheme); rc = TPM_BAD_KEY_PROPERTY; } else if (tpm_key_parms->sigScheme != TPM_SS_NONE) { printf("TPM_KeyParms_CheckProperties: Error, " "Authchange sigScheme %04hx is not TPM_SS_NONE\n", tpm_key_parms->sigScheme); rc = TPM_BAD_KEY_PROPERTY; } else if (tpm_rsa_key_parms->keyLength < 512) { printf("TPM_KeyParms_CheckProperties: Error, " "Authchange keyLength %d is less than 512\n", tpm_rsa_key_parms->keyLength); rc = TPM_BAD_KEY_PROPERTY; } break; case TPM_KEY_BIND: if ((tpm_key_parms->encScheme != TPM_ES_RSAESOAEP_SHA1_MGF1) && (tpm_key_parms->encScheme != TPM_ES_RSAESPKCSv15)) { printf("TPM_KeyParms_CheckProperties: Error, " "Bind encScheme %04hx is not %04x or %04x\n", tpm_key_parms->encScheme, TPM_ES_RSAESOAEP_SHA1_MGF1, TPM_ES_RSAESPKCSv15); rc = TPM_BAD_KEY_PROPERTY; } else if (tpm_key_parms->sigScheme != TPM_SS_NONE) { printf("TPM_KeyParms_CheckProperties: Error, " "Bind sigScheme %04hx is not TPM_SS_NONE\n", tpm_key_parms->sigScheme); rc = TPM_BAD_KEY_PROPERTY; } break; case TPM_KEY_LEGACY: if ((tpm_key_parms->encScheme != TPM_ES_RSAESOAEP_SHA1_MGF1) && (tpm_key_parms->encScheme != TPM_ES_RSAESPKCSv15)) { printf("TPM_KeyParms_CheckProperties: Error, " "Legacy encScheme %04hx is not %04x or %04x\n", tpm_key_parms->encScheme, TPM_ES_RSAESOAEP_SHA1_MGF1, TPM_ES_RSAESPKCSv15); rc = TPM_BAD_KEY_PROPERTY; } else if ((tpm_key_parms->sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1) && (tpm_key_parms->sigScheme != TPM_SS_RSASSAPKCS1v15_DER)) { printf("TPM_KeyParms_CheckProperties: Error, " "Legacy sigScheme %04hx is not %04x or %04x\n", tpm_key_parms->sigScheme, TPM_SS_RSASSAPKCS1v15_SHA1, TPM_SS_RSASSAPKCS1v15_DER); rc = TPM_BAD_KEY_PROPERTY; } break; case TPM_KEY_MIGRATE: if (tpm_key_parms->encScheme != TPM_ES_RSAESOAEP_SHA1_MGF1) { printf("TPM_KeyParms_CheckProperties: Error, " "Migrate encScheme %04hx is not TPM_ES_RSAESOAEP_SHA1_MGF1\n", tpm_key_parms->encScheme); rc = TPM_BAD_KEY_PROPERTY; } else if (tpm_key_parms->sigScheme != TPM_SS_NONE) { printf("TPM_KeyParms_CheckProperties: Error, " "Migrate sigScheme %04hx is not TPM_SS_NONE\n", tpm_key_parms->sigScheme); rc = TPM_BAD_KEY_PROPERTY; } else if (tpm_key_parms->algorithmID != TPM_ALG_RSA) { /*constant condition*/ printf("TPM_KeyParms_CheckProperties: Error, " "Migrate algorithmID %08x is not TPM_ALG_RSA\n", tpm_key_parms->algorithmID); rc = TPM_BAD_KEY_PROPERTY; } /* interoperable TPM only supports 2048 */ else if (tpm_rsa_key_parms->keyLength < 2048) { printf("TPM_KeyParms_CheckProperties: Error, " "Migrate keyLength %d is less than 2048\n", tpm_rsa_key_parms->keyLength); rc = TPM_BAD_KEY_PROPERTY; } else { rc = TPM_KeyParams_CheckDefaultExponent(&(tpm_rsa_key_parms->exponent)); } break; default: printf("TPM_KeyParms_CheckProperties: Error, Unknown keyUsage %04hx\n", tpm_key_usage); rc = TPM_BAD_KEY_PROPERTY; break; } } return rc; } TPM_RESULT TPM_KeyParams_CheckDefaultExponent(TPM_SIZED_BUFFER *exponent) { TPM_RESULT rc = 0; uint32_t i; if ((rc == 0) && (exponent->size != 0)) { /* 0 is the default */ printf(" TPM_KeyParams_CheckDefaultExponent: exponent size %u\n", exponent->size); if (rc == 0) { if (exponent->size < 3) { printf("TPM_KeyParams_CheckDefaultExponent: Error, exponent size is %u\n", exponent->size); rc = TPM_BAD_KEY_PROPERTY; } } if (rc == 0) { for (i = 3 ; i < exponent->size ; i++) { if (exponent->buffer[i] != 0) { printf("TPM_KeyParams_CheckDefaultExponent: Error, exponent[%u] is %02x\n", i, exponent->buffer[i]); rc = TPM_BAD_KEY_PROPERTY; } } } if (rc == 0) { if ((exponent->buffer[0] != tpm_default_rsa_exponent[0]) || (exponent->buffer[1] != tpm_default_rsa_exponent[1]) || (exponent->buffer[2] != tpm_default_rsa_exponent[2])) { printf("TPM_KeyParams_CheckDefaultExponent: Error, exponent is %02x %02x %02x\n", exponent->buffer[2], exponent->buffer[1], exponent->buffer[0]); rc = TPM_BAD_KEY_PROPERTY; } } } return rc; } /* TPM_STORE_ASYMKEY */ void TPM_StoreAsymkey_Init(TPM_STORE_ASYMKEY *tpm_store_asymkey) { printf(" TPM_StoreAsymkey_Init:\n"); tpm_store_asymkey->payload = TPM_PT_ASYM; TPM_Secret_Init(tpm_store_asymkey->usageAuth); TPM_Secret_Init(tpm_store_asymkey->migrationAuth); TPM_Digest_Init(tpm_store_asymkey->pubDataDigest); TPM_StorePrivkey_Init(&(tpm_store_asymkey->privKey)); return; } /* TPM_StoreAsymkey_Load() deserializes the TPM_STORE_ASYMKEY structure. The serialized structure contains the private factor p. Normally, 'tpm_key_parms' and tpm_store_pubkey are not NULL and the private key d is derived from p and the public key n and exponent e. In some cases, a TPM_STORE_ASYMKEY is being manipulated without the rest of the TPM_KEY structure. When 'tpm_key' is NULL, p is left intact, and the resulting structure cannot be used as a private key. */ TPM_RESULT TPM_StoreAsymkey_Load(TPM_STORE_ASYMKEY *tpm_store_asymkey, TPM_BOOL isEK, unsigned char **stream, uint32_t *stream_size, TPM_KEY_PARMS *tpm_key_parms, TPM_SIZED_BUFFER *pubKey) { TPM_RESULT rc = 0; printf(" TPM_StoreAsymkey_Load:\n"); /* load payload */ if ((rc == 0) && !isEK) { rc = TPM_Load8(&(tpm_store_asymkey->payload), stream, stream_size); } /* check payload value to ease debugging */ if ((rc == 0) && !isEK) { if ( /* normal key */ (tpm_store_asymkey->payload != TPM_PT_ASYM) && /* TPM_CMK_CreateKey payload */ (tpm_store_asymkey->payload != TPM_PT_MIGRATE_RESTRICTED) && /* TPM_CMK_ConvertMigration payload */ (tpm_store_asymkey->payload != TPM_PT_MIGRATE_EXTERNAL) ) { printf("TPM_StoreAsymkey_Load: Error, invalid payload %02x\n", tpm_store_asymkey->payload); rc = TPM_INVALID_STRUCTURE; } } /* load usageAuth */ if ((rc == 0) && !isEK) { rc = TPM_Secret_Load(tpm_store_asymkey->usageAuth, stream, stream_size); } /* load migrationAuth */ if ((rc == 0) && !isEK) { rc = TPM_Secret_Load(tpm_store_asymkey->migrationAuth, stream, stream_size); } /* load pubDataDigest */ if (rc == 0) { rc = TPM_Digest_Load(tpm_store_asymkey->pubDataDigest, stream, stream_size); } /* load privKey - actually prime factor p */ if (rc == 0) { rc = TPM_SizedBuffer_Load((&(tpm_store_asymkey->privKey.p_key)), stream, stream_size); } /* convert prime factor p to the private key */ if ((rc == 0) && (tpm_key_parms != NULL) && (pubKey != NULL)) { rc = TPM_StorePrivkey_Convert(tpm_store_asymkey, tpm_key_parms, pubKey); } return rc; } #if 0 static TPM_RESULT TPM_StoreAsymkey_LoadTest(TPM_KEY *tpm_key) { TPM_RESULT rc = 0; int irc; /* actual */ unsigned char *narr; unsigned char *earr; unsigned char *parr; unsigned char *qarr; unsigned char *darr; uint32_t nbytes; uint32_t ebytes; uint32_t pbytes; uint32_t qbytes; uint32_t dbytes; /* computed */ unsigned char *q1arr = NULL; unsigned char *d1arr = NULL; uint32_t q1bytes; uint32_t d1bytes; printf(" TPM_StoreAsymkey_LoadTest:\n"); /* actual data */ if (rc == 0) { narr = tpm_key->pubKey.key; darr = tpm_key->tpm_store_asymkey->privKey.d_key; parr = tpm_key->tpm_store_asymkey->privKey.p_key; qarr = tpm_key->tpm_store_asymkey->privKey.q_key; nbytes = tpm_key->pubKey.keyLength; dbytes = tpm_key->tpm_store_asymkey->privKey.d_keyLength; pbytes = tpm_key->tpm_store_asymkey->privKey.p_keyLength; qbytes = tpm_key->tpm_store_asymkey->privKey.q_keyLength; rc = TPM_Key_GetPublicKey(&nbytes, &narr, tpm_key); } if (rc == 0) { rc = TPM_Key_GetExponent(&ebytes, &earr, tpm_key); } if (rc == 0) { rc = TPM_Key_GetPrimeFactorP(&pbytes, &parr, tpm_key); } /* computed data */ if (rc == 0) { rc = TPM_RSAGetPrivateKey(&q1bytes, &q1arr, /* freed @1 */ &d1bytes, &d1arr, /* freed @2 */ nbytes, narr, ebytes, earr, pbytes, parr); } /* compare q */ if (rc == 0) { if (qbytes != q1bytes) { printf("TPM_StoreAsymkey_LoadTest: Error (fatal), qbytes %u q1bytes %u\n", qbytes, q1bytes); rc = TPM_FAIL; } } if (rc == 0) { irc = memcmp(qarr, q1arr, qbytes); if (irc != 0) { printf("TPM_StoreAsymkey_LoadTest: Error (fatal), qarr mismatch\n"); rc = TPM_FAIL; } } /* compare d */ if (rc == 0) { if (dbytes != d1bytes) { printf("TPM_StoreAsymkey_LoadTest: Error (fatal), dbytes %u d1bytes %u\n", dbytes, d1bytes); rc = TPM_FAIL; } } if (rc == 0) { irc = memcmp(darr, d1arr, dbytes); if (irc != 0) { printf("TPM_StoreAsymkey_LoadTest: Error (fatal), darr mismatch\n"); rc = TPM_FAIL; } } free(q1arr); /* @1 */ free(d1arr); /* @2 */ return rc; } #endif TPM_RESULT TPM_StoreAsymkey_Store(TPM_STORE_BUFFER *sbuffer, TPM_BOOL isEK, const TPM_STORE_ASYMKEY *tpm_store_asymkey) { TPM_RESULT rc = 0; printf(" TPM_StoreAsymkey_Store:\n"); /* store payload */ if ((rc == 0) && !isEK) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_store_asymkey->payload), sizeof(TPM_PAYLOAD_TYPE)); } /* store usageAuth */ if ((rc == 0) && !isEK) { rc = TPM_Secret_Store(sbuffer, tpm_store_asymkey->usageAuth); } /* store migrationAuth */ if ((rc == 0) && !isEK) { rc = TPM_Secret_Store(sbuffer, tpm_store_asymkey->migrationAuth); } /* store pubDataDigest */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_store_asymkey->pubDataDigest); } /* store privKey */ if (rc == 0) { rc = TPM_StorePrivkey_Store(sbuffer, &(tpm_store_asymkey->privKey)); } return rc; } void TPM_StoreAsymkey_Delete(TPM_STORE_ASYMKEY *tpm_store_asymkey) { printf(" TPM_StoreAsymkey_Delete:\n"); if (tpm_store_asymkey != NULL) { TPM_Secret_Delete(tpm_store_asymkey->usageAuth); TPM_Secret_Delete(tpm_store_asymkey->migrationAuth); TPM_StorePrivkey_Delete(&(tpm_store_asymkey->privKey)); TPM_StoreAsymkey_Init(tpm_store_asymkey); } return; } TPM_RESULT TPM_StoreAsymkey_GenerateEncData(TPM_SIZED_BUFFER *encData, TPM_STORE_ASYMKEY *tpm_store_asymkey, TPM_KEY *parent_key) { TPM_RESULT rc = 0; TPM_STORE_BUFFER sbuffer; /* TPM_STORE_ASYMKEY serialization */ printf(" TPM_StoreAsymkey_GenerateEncData;\n"); TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ /* serialize the TPM_STORE_ASYMKEY member */ if (rc == 0) { rc = TPM_StoreAsymkey_Store(&sbuffer, FALSE, tpm_store_asymkey); } if (rc == 0) { rc = TPM_RSAPublicEncryptSbuffer_Key(encData, &sbuffer, parent_key); } TPM_Sbuffer_Delete(&sbuffer); /* @1 */ return rc; } /* TPM_StoreAsymkey_GetPrimeFactorP() gets the prime factor p from the TPM_STORE_ASYMKEY */ TPM_RESULT TPM_StoreAsymkey_GetPrimeFactorP(uint32_t *pbytes, unsigned char **parr, TPM_STORE_ASYMKEY *tpm_store_asymkey) { TPM_RESULT rc = 0; printf(" TPM_StoreAsymkey_GetPrimeFactorP:\n"); if (rc == 0) { *pbytes = tpm_store_asymkey->privKey.p_key.size; *parr = tpm_store_asymkey->privKey.p_key.buffer; TPM_PrintFour(" TPM_StoreAsymkey_GetPrimeFactorP:", *parr); } return rc; } /* TPM_StoreAsymkey_GetO1Size() calculates the destination o1 size for a TPM_STORE_ASYMKEY Used for creating a migration blob, TPM_STORE_ASYMKEY -> TPM_MIGRATE_ASYMKEY. */ void TPM_StoreAsymkey_GetO1Size(uint32_t *o1_size, TPM_STORE_ASYMKEY *tpm_store_asymkey) { *o1_size = tpm_store_asymkey->privKey.p_key.size + /* private key */ sizeof(uint32_t) - /* private key length */ TPM_DIGEST_SIZE + /* - k1 -> k2 TPM_MIGRATE_ASYMKEY -> partPrivKey */ sizeof(uint32_t) + /* TPM_MIGRATE_ASYMKEY -> partPrivKeyLen */ sizeof(TPM_PAYLOAD_TYPE) + /* TPM_MIGRATE_ASYMKEY -> payload */ TPM_SECRET_SIZE + /* TPM_MIGRATE_ASYMKEY -> usageAuth */ TPM_DIGEST_SIZE + /* TPM_MIGRATE_ASYMKEY -> pubDataDigest */ TPM_DIGEST_SIZE + /* OAEP pHash */ TPM_DIGEST_SIZE + /* OAEP seed */ 1; /* OAEP 0x01 byte */ printf(" TPM_StoreAsymkey_GetO1Size: key size %u o1 size %u\n", tpm_store_asymkey->privKey.p_key.size, *o1_size); } /* TPM_StoreAsymkey_CheckO1Size() verifies the destination o1_size against the source k1k2 array length This is a currently just a sanity check on the TPM_StoreAsymkey_GetO1Size() function. */ TPM_RESULT TPM_StoreAsymkey_CheckO1Size(uint32_t o1_size, uint32_t k1k2_length) { TPM_RESULT rc = 0; /* sanity check the TPM_MIGRATE_ASYMKEY size against the requested o1 size */ /* K1 K2 are the length and value of the private key, 4 + 128 bytes for a 2048-bit key */ if (o1_size < (k1k2_length - TPM_DIGEST_SIZE + /* k1 k2, the first 20 bytes are used as the OAEP seed */ sizeof(TPM_PAYLOAD_TYPE) + /* TPM_MIGRATE_ASYMKEY -> payload */ TPM_SECRET_SIZE + /* TPM_MIGRATE_ASYMKEY -> usageAuth */ TPM_DIGEST_SIZE + /* TPM_MIGRATE_ASYMKEY -> pubDataDigest */ sizeof(uint32_t) + /* TPM_MIGRATE_ASYMKEY -> partPrivKeyLen */ TPM_DIGEST_SIZE + /* OAEP pHash */ TPM_DIGEST_SIZE + /* OAEP seed */ 1)) { /* OAEP 0x01 byte */ printf(" TPM_StoreAsymkey_CheckO1Size: Error (fatal) k1k2_length %d too large for o1 %u\n", k1k2_length, o1_size); rc = TPM_FAIL; } return rc; } /* TPM_StoreAsymkey_StoreO1() creates an OAEP encoded TPM_MIGRATE_ASYMKEY from a TPM_STORE_ASYMKEY. It does the common steps of constructing the TPM_MIGRATE_ASYMKEY, serializing it, and OAEP padding. */ TPM_RESULT TPM_StoreAsymkey_StoreO1(BYTE *o1, uint32_t o1_size, TPM_STORE_ASYMKEY *tpm_store_asymkey, TPM_DIGEST pHash, TPM_PAYLOAD_TYPE payload_type, TPM_SECRET usageAuth) { TPM_RESULT rc = 0; TPM_STORE_BUFFER k1k2_sbuffer; /* serialization of TPM_STORE_ASYMKEY -> privKey -> key */ const unsigned char *k1k2; /* serialization results */ uint32_t k1k2_length; TPM_MIGRATE_ASYMKEY tpm_migrate_asymkey; TPM_STORE_BUFFER tpm_migrate_asymkey_sbuffer; /* serialized tpm_migrate_asymkey */ const unsigned char *tpm_migrate_asymkey_buffer; uint32_t tpm_migrate_asymkey_length; printf(" TPM_StoreAsymkey_StoreO1:\n"); TPM_Sbuffer_Init(&k1k2_sbuffer); /* freed @1 */ TPM_MigrateAsymkey_Init(&tpm_migrate_asymkey); /* freed @2 */ TPM_Sbuffer_Init(&tpm_migrate_asymkey_sbuffer); /* freed @3 */ /* NOTE Comments from TPM_CreateMigrationBlob rev 81 */ /* a. Build two byte arrays, K1 and K2: */ /* i. K1 = TPM_STORE_ASYMKEY.privKey[0..19] (TPM_STORE_ASYMKEY.privKey.keyLength + 16 bytes of TPM_STORE_ASYMKEY.privKey.key), sizeof(K1) = 20 */ /* ii. K2 = TPM_STORE_ASYMKEY.privKey[20..131] (position 16-127 of TPM_STORE_ASYMKEY. privKey.key), sizeof(K2) = 112 */ if (rc == 0) { rc = TPM_SizedBuffer_Store(&k1k2_sbuffer, &(tpm_store_asymkey->privKey.p_key)); } if (rc == 0) { TPM_Sbuffer_Get(&k1k2_sbuffer, &k1k2, &k1k2_length); /* sanity check the TPM_STORE_ASYMKEY -> privKey -> key size against the requested o1 size */ rc = TPM_StoreAsymkey_CheckO1Size(o1_size, k1k2_length); } /* b. Build M1 a TPM_MIGRATE_ASYMKEY structure */ /* i. TPM_MIGRATE_ASYMKEY.payload = TPM_PT_MIGRATE */ /* ii. TPM_MIGRATE_ASYMKEY.usageAuth = TPM_STORE_ASYMKEY.usageAuth */ /* iii. TPM_MIGRATE_ASYMKEY.pubDataDigest = TPM_STORE_ASYMKEY. pubDataDigest */ /* iv. TPM_MIGRATE_ASYMKEY.partPrivKeyLen = 112 - 127. */ /* v. TPM_MIGRATE_ASYMKEY.partPrivKey = K2 */ if (rc == 0) { tpm_migrate_asymkey.payload = payload_type; TPM_Secret_Copy(tpm_migrate_asymkey.usageAuth, usageAuth); TPM_Digest_Copy(tpm_migrate_asymkey.pubDataDigest, tpm_store_asymkey->pubDataDigest); TPM_PrintFour(" TPM_StoreAsymkey_StoreO1: k1 -", k1k2); TPM_PrintFour(" TPM_StoreAsymkey_StoreO1: k2 -", k1k2 + TPM_DIGEST_SIZE); rc = TPM_SizedBuffer_Set(&(tpm_migrate_asymkey.partPrivKey), k1k2_length - TPM_DIGEST_SIZE, /* k2 length 112 for 2048 bit key */ k1k2 + TPM_DIGEST_SIZE); /* k2 */ } /* c. Create o1 (which SHALL be 198 bytes for a 2048 bit RSA key) by performing the OAEP encoding of m using OAEP parameters of */ /* i. m = M1 the TPM_MIGRATE_ASYMKEY structure */ /* ii. pHash = d1->migrationAuth */ /* iii. seed = s1 = K1 */ if (rc == 0) { /* serialize TPM_MIGRATE_ASYMKEY m */ rc = TPM_MigrateAsymkey_Store(&tpm_migrate_asymkey_sbuffer, &tpm_migrate_asymkey); } if (rc == 0) { /* get the serialization result */ TPM_Sbuffer_Get(&tpm_migrate_asymkey_sbuffer, &tpm_migrate_asymkey_buffer, &tpm_migrate_asymkey_length); TPM_PrintFour(" TPM_StoreAsymkey_StoreO1: pHash -", pHash); rc = TPM_RSA_padding_add_PKCS1_OAEP(o1, /* output */ o1_size, tpm_migrate_asymkey_buffer, /* message */ tpm_migrate_asymkey_length, pHash, k1k2); /* k1, seed */ TPM_PrintFour(" TPM_StoreAsymkey_StoreO1: o1 -", o1); } TPM_Sbuffer_Delete(&k1k2_sbuffer); /* @1 */ TPM_MigrateAsymkey_Delete(&tpm_migrate_asymkey); /* @2 */ TPM_Sbuffer_Delete(&tpm_migrate_asymkey_sbuffer); /* @3 */ return rc; } /* TPM_StoreAsymkey_LoadO1() extracts TPM_STORE_ASYMKEY from the OAEP encoded TPM_MIGRATE_ASYMKEY. It does the common steps OAEP depadding, deserializing the TPM_MIGRATE_ASYMKEY, and reconstructing the TPM_STORE_ASYMKEY. It sets these, which may or may not be correct at a higher level TPM_STORE_ASYMKEY -> payload = TPM_MIGRATE_ASYMKEY -> payload TPM_STORE_ASYMKEY -> usageAuth = TPM_MIGRATE_ASYMKEY -> usageAuth TPM_STORE_ASYMKEY -> migrationAuth = pHash TPM_STORE_ASYMKEY -> pubDataDigest = TPM_MIGRATE_ASYMKEY -> pubDataDigest TPM_STORE_ASYMKEY -> privKey = seed + TPM_MIGRATE_ASYMKEY -> partPrivKey */ TPM_RESULT TPM_StoreAsymkey_LoadO1(TPM_STORE_ASYMKEY *tpm_store_asymkey, /* output */ BYTE *o1, /* input */ uint32_t o1_size) /* input */ { TPM_RESULT rc = 0; BYTE *tpm_migrate_asymkey_buffer; uint32_t tpm_migrate_asymkey_length; TPM_DIGEST seed; TPM_DIGEST pHash; unsigned char *stream; /* for deserializing structures */ uint32_t stream_size; TPM_MIGRATE_ASYMKEY tpm_migrate_asymkey; TPM_STORE_BUFFER k1k2_sbuffer; const unsigned char *k1k2_buffer; uint32_t k1k2_length; printf(" TPM_StoreAsymkey_LoadO1:\n"); TPM_MigrateAsymkey_Init(&tpm_migrate_asymkey); /* freed @1 */ TPM_Sbuffer_Init(&k1k2_sbuffer); /* freed @2 */ tpm_migrate_asymkey_buffer = NULL; /* freed @3 */ /* allocate memory for TPM_MIGRATE_ASYMKEY after removing OAEP pad from o1 */ if (rc == 0) { rc = TPM_Malloc(&tpm_migrate_asymkey_buffer, o1_size); } if (rc == 0) { TPM_PrintFour(" TPM_StoreAsymkey_LoadO1: o1 -", o1); /* 5. Create m1, seed and pHash by OAEP decoding o1 */ printf(" TPM_StoreAsymkey_LoadO1: Depadding\n"); rc = TPM_RSA_padding_check_PKCS1_OAEP(tpm_migrate_asymkey_buffer, /* out: to */ &tpm_migrate_asymkey_length, /* out: to length */ o1_size, /* to size */ o1, o1_size, /* from, from length */ pHash, seed); TPM_PrintFour(" TPM_StoreAsymkey_LoadO1: tpm_migrate_asymkey_buffer -", tpm_migrate_asymkey_buffer); printf(" TPM_StoreAsymkey_LoadO1: tpm_migrate_asymkey_length %u\n", tpm_migrate_asymkey_length); TPM_PrintFour(" TPM_StoreAsymkey_LoadO1: - pHash", pHash); TPM_PrintFour(" TPM_StoreAsymkey_LoadO1: - seed", seed); } /* deserialize the buffer back to a TPM_MIGRATE_ASYMKEY */ if (rc == 0) { stream = tpm_migrate_asymkey_buffer; stream_size = tpm_migrate_asymkey_length; rc = TPM_MigrateAsymkey_Load(&tpm_migrate_asymkey, &stream, &stream_size); printf(" TPM_StoreAsymkey_LoadO1: partPrivKey length %u\n", tpm_migrate_asymkey.partPrivKey.size); TPM_PrintFourLimit(" TPM_StoreAsymkey_LoadO1: partPrivKey -", tpm_migrate_asymkey.partPrivKey.buffer, tpm_migrate_asymkey.partPrivKey.size); } /* create k1k2 by combining seed (k1) and TPM_MIGRATE_ASYMKEY.partPrivKey (k2) field */ if (rc == 0) { rc = TPM_Digest_Store(&k1k2_sbuffer, seed); } if (rc == 0) { rc = TPM_Sbuffer_Append(&k1k2_sbuffer, tpm_migrate_asymkey.partPrivKey.buffer, tpm_migrate_asymkey.partPrivKey.size); } /* assemble the TPM_STORE_ASYMKEY structure */ if (rc == 0) { tpm_store_asymkey->payload = tpm_migrate_asymkey.payload; TPM_Digest_Copy(tpm_store_asymkey->usageAuth, tpm_migrate_asymkey.usageAuth); TPM_Digest_Copy(tpm_store_asymkey->migrationAuth, pHash); TPM_Digest_Copy(tpm_store_asymkey->pubDataDigest, tpm_migrate_asymkey.pubDataDigest); TPM_Sbuffer_Get(&k1k2_sbuffer, &k1k2_buffer, &k1k2_length); printf(" TPM_StoreAsymkey_LoadO1: k1k2 length %u\n", k1k2_length); TPM_PrintFourLimit(" TPM_StoreAsymkey_LoadO1: k1k2", k1k2_buffer, k1k2_length); rc = TPM_SizedBuffer_Load(&(tpm_store_asymkey->privKey.p_key), (unsigned char **)&k1k2_buffer, &k1k2_length); } TPM_MigrateAsymkey_Delete(&tpm_migrate_asymkey); /* @1 */ TPM_Sbuffer_Delete(&k1k2_sbuffer); /* @2 */ free(tpm_migrate_asymkey_buffer); /* @3 */ return rc; } /* TPM_MIGRATE_ASYMKEY */ /* TPM_MigrateAsymkey_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_MigrateAsymkey_Init(TPM_MIGRATE_ASYMKEY *tpm_migrate_asymkey) { printf(" TPM_MigrateAsymkey_Init:\n"); tpm_migrate_asymkey->payload = TPM_PT_MIGRATE; TPM_Secret_Init(tpm_migrate_asymkey->usageAuth); TPM_Digest_Init(tpm_migrate_asymkey->pubDataDigest); TPM_SizedBuffer_Init(&(tpm_migrate_asymkey->partPrivKey)); return; } /* TPM_MigrateAsymkey_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_MigrateAsymkey_Init() After use, call TPM_MigrateAsymkey_Delete() to free memory */ TPM_RESULT TPM_MigrateAsymkey_Load(TPM_MIGRATE_ASYMKEY *tpm_migrate_asymkey, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_MigrateAsymkey_Load:\n"); /* load payload */ if (rc == 0) { rc = TPM_Load8(&(tpm_migrate_asymkey->payload), stream, stream_size); } /* check payload value to ease debugging */ if (rc == 0) { if ((tpm_migrate_asymkey->payload != TPM_PT_MIGRATE) && (tpm_migrate_asymkey->payload != TPM_PT_MAINT) && (tpm_migrate_asymkey->payload != TPM_PT_CMK_MIGRATE)) { printf("TPM_MigrateAsymkey_Load: Error illegal payload %02x\n", tpm_migrate_asymkey->payload); rc = TPM_INVALID_STRUCTURE; } } /* load usageAuth */ if (rc == 0) { rc = TPM_Secret_Load(tpm_migrate_asymkey->usageAuth, stream, stream_size); } /* load pubDataDigest */ if (rc == 0) { rc = TPM_Digest_Load(tpm_migrate_asymkey->pubDataDigest, stream, stream_size); } /* load partPrivKey */ if (rc == 0) { rc = TPM_SizedBuffer_Load(&(tpm_migrate_asymkey->partPrivKey), stream, stream_size); } return rc; } /* TPM_MigrateAsymkey_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_MigrateAsymkey_Store(TPM_STORE_BUFFER *sbuffer, const TPM_MIGRATE_ASYMKEY *tpm_migrate_asymkey) { TPM_RESULT rc = 0; printf(" TPM_MigrateAsymkey_Store:\n"); /* store payload */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_migrate_asymkey->payload), sizeof(TPM_PAYLOAD_TYPE)); } /* store usageAuth */ if (rc == 0) { rc = TPM_Secret_Store(sbuffer, tpm_migrate_asymkey->usageAuth); } /* store pubDataDigest */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_migrate_asymkey->pubDataDigest); } /* store partPrivKey */ if (rc == 0) { rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_migrate_asymkey->partPrivKey)); } return rc; } /* TPM_MigrateAsymkey_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_MigrateAsymkey_Init to set members back to default values The object itself is not freed */ void TPM_MigrateAsymkey_Delete(TPM_MIGRATE_ASYMKEY *tpm_migrate_asymkey) { printf(" TPM_MigrateAsymkey_Delete:\n"); if (tpm_migrate_asymkey != NULL) { TPM_Secret_Delete(tpm_migrate_asymkey->usageAuth); TPM_SizedBuffer_Zero(&(tpm_migrate_asymkey->partPrivKey)); TPM_SizedBuffer_Delete(&(tpm_migrate_asymkey->partPrivKey)); TPM_MigrateAsymkey_Init(tpm_migrate_asymkey); } return; } /* TPM_STORE_PRIVKEY */ void TPM_StorePrivkey_Init(TPM_STORE_PRIVKEY *tpm_store_privkey) { printf(" TPM_StorePrivkey_Init:\n"); TPM_SizedBuffer_Init(&(tpm_store_privkey->d_key)); TPM_SizedBuffer_Init(&(tpm_store_privkey->p_key)); TPM_SizedBuffer_Init(&(tpm_store_privkey->q_key)); return; } /* TPM_StorePrivkey_Convert() sets the prime factor q and private key d based on the prime factor p and the public key and exponent. */ TPM_RESULT TPM_StorePrivkey_Convert(TPM_STORE_ASYMKEY *tpm_store_asymkey, /* I/O result */ TPM_KEY_PARMS *tpm_key_parms, /* to get exponent */ TPM_SIZED_BUFFER *pubKey) /* to get public key */ { TPM_RESULT rc = 0; /* computed data */ unsigned char *narr; unsigned char *earr; unsigned char *parr; unsigned char *qarr = NULL; unsigned char *darr = NULL; uint32_t nbytes; uint32_t ebytes; uint32_t pbytes; uint32_t qbytes; uint32_t dbytes; printf(" TPM_StorePrivkey_Convert:\n"); if (rc == 0) { TPM_PrintFour(" TPM_StorePrivkey_Convert: p", tpm_store_asymkey->privKey.p_key.buffer); nbytes = pubKey->size; narr = pubKey->buffer; rc = TPM_KeyParms_GetExponent(&ebytes, &earr, tpm_key_parms); } if (rc == 0) { rc = TPM_StoreAsymkey_GetPrimeFactorP(&pbytes, &parr, tpm_store_asymkey); } if (rc == 0) { rc = TPM_RSAGetPrivateKey(&qbytes, &qarr, /* freed @1 */ &dbytes, &darr, /* freed @2 */ nbytes, narr, ebytes, earr, pbytes, parr); } if (rc == 0) { TPM_PrintFour(" TPM_StorePrivkey_Convert: q", qarr); TPM_PrintFour(" TPM_StorePrivkey_Convert: d", darr); rc = TPM_SizedBuffer_Set((&(tpm_store_asymkey->privKey.q_key)), qbytes, qarr); } if (rc == 0) { rc = TPM_SizedBuffer_Set((&(tpm_store_asymkey->privKey.d_key)), dbytes, darr); } free(qarr); /* @1 */ free(darr); /* @2 */ return rc; } /* TPM_StorePrivkey_Store serializes a TPM_STORE_PRIVKEY structure, appending results to 'sbuffer' Only the prime factor p is stored. The other prime factor q and the private key d are recalculated after a load. */ TPM_RESULT TPM_StorePrivkey_Store(TPM_STORE_BUFFER *sbuffer, const TPM_STORE_PRIVKEY *tpm_store_privkey) { TPM_RESULT rc = 0; printf(" TPM_StorePrivkey_Store:\n"); if (rc == 0) { TPM_PrintFour(" TPM_StorePrivkey_Store: p", tpm_store_privkey->p_key.buffer); rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_store_privkey->p_key)); } return rc; } void TPM_StorePrivkey_Delete(TPM_STORE_PRIVKEY *tpm_store_privkey) { printf(" TPM_StorePrivkey_Delete:\n"); if (tpm_store_privkey != NULL) { TPM_SizedBuffer_Zero(&(tpm_store_privkey->d_key)); TPM_SizedBuffer_Zero(&(tpm_store_privkey->p_key)); TPM_SizedBuffer_Zero(&(tpm_store_privkey->q_key)); TPM_SizedBuffer_Delete(&(tpm_store_privkey->d_key)); TPM_SizedBuffer_Delete(&(tpm_store_privkey->p_key)); TPM_SizedBuffer_Delete(&(tpm_store_privkey->q_key)); TPM_StorePrivkey_Init(tpm_store_privkey); } return; } /* TPM_PUBKEY */ void TPM_Pubkey_Init(TPM_PUBKEY *tpm_pubkey) { printf(" TPM_Pubkey_Init:\n"); TPM_KeyParms_Init(&(tpm_pubkey->algorithmParms)); TPM_SizedBuffer_Init(&(tpm_pubkey->pubKey)); return; } TPM_RESULT TPM_Pubkey_Load(TPM_PUBKEY *tpm_pubkey, /* result */ unsigned char **stream, /* pointer to next parameter */ uint32_t *stream_size) /* stream size left */ { TPM_RESULT rc = 0; printf(" TPM_Pubkey_Load:\n"); /* load algorithmParms */ if (rc == 0) { rc = TPM_KeyParms_Load(&(tpm_pubkey->algorithmParms), stream, stream_size); } /* load pubKey */ if (rc == 0) { rc = TPM_SizedBuffer_Load(&(tpm_pubkey->pubKey), stream, stream_size); } return rc; } /* TPM_Pubkey_Store serializes a TPM_PUBKEY structure, appending results to 'sbuffer' */ TPM_RESULT TPM_Pubkey_Store(TPM_STORE_BUFFER *sbuffer, TPM_PUBKEY *tpm_pubkey) { TPM_RESULT rc = 0; printf(" TPM_Pubkey_Store:\n"); if (rc == 0) { rc = TPM_KeyParms_Store(sbuffer, &(tpm_pubkey->algorithmParms)); } if (rc == 0) { rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_pubkey->pubKey)); } return rc; } void TPM_Pubkey_Delete(TPM_PUBKEY *tpm_pubkey) { printf(" TPM_Pubkey_Delete:\n"); if (tpm_pubkey != NULL) { TPM_KeyParms_Delete(&(tpm_pubkey->algorithmParms)); TPM_SizedBuffer_Delete(&(tpm_pubkey->pubKey)); TPM_Pubkey_Init(tpm_pubkey); } return; } TPM_RESULT TPM_Pubkey_Set(TPM_PUBKEY *tpm_pubkey, TPM_KEY *tpm_key) { TPM_RESULT rc = 0; printf(" TPM_Pubkey_Set:\n"); if (rc == 0) { /* add TPM_KEY_PARMS algorithmParms */ rc = TPM_KeyParms_Copy(&(tpm_pubkey->algorithmParms), &(tpm_key->algorithmParms)); } if (rc == 0) { /* add TPM_SIZED_BUFFER pubKey */ rc = TPM_SizedBuffer_Copy(&(tpm_pubkey->pubKey), &(tpm_key->pubKey)); } return rc; } TPM_RESULT TPM_Pubkey_Copy(TPM_PUBKEY *dest_tpm_pubkey, TPM_PUBKEY *src_tpm_pubkey) { TPM_RESULT rc = 0; printf(" TPM_Pubkey_Copy:\n"); /* copy TPM_KEY_PARMS algorithmParms */ if (rc == 0) { rc = TPM_KeyParms_Copy(&(dest_tpm_pubkey->algorithmParms), &(src_tpm_pubkey->algorithmParms)); } /* copy TPM_SIZED_BUFFER pubKey */ if (rc == 0) { rc = TPM_SizedBuffer_Copy(&(dest_tpm_pubkey->pubKey), &(src_tpm_pubkey->pubKey)); } return rc; } /* TPM_Pubkey_GetExponent() gets the exponent key from the TPM_RSA_KEY_PARMS contained in a TPM_PUBKEY */ TPM_RESULT TPM_Pubkey_GetExponent(uint32_t *ebytes, unsigned char **earr, TPM_PUBKEY *tpm_pubkey) { TPM_RESULT rc = 0; printf(" TPM_Pubkey_GetExponent:\n"); if (rc == 0) { rc = TPM_KeyParms_GetExponent(ebytes, earr, &(tpm_pubkey->algorithmParms)); } return rc; } /* TPM_Pubkey_GetPublicKey() gets the public key from the TPM_PUBKEY */ TPM_RESULT TPM_Pubkey_GetPublicKey(uint32_t *nbytes, unsigned char **narr, TPM_PUBKEY *tpm_pubkey) { TPM_RESULT rc = 0; printf(" TPM_Pubkey_GetPublicKey:\n"); if (rc == 0) { *nbytes = tpm_pubkey->pubKey.size; *narr = tpm_pubkey->pubKey.buffer; } return rc; } /* TPM_RSA_KEY_PARMS */ /* Allocates and loads a TPM_RSA_KEY_PARMS structure Must be delete'd and freed by the caller. */ void TPM_RSAKeyParms_Init(TPM_RSA_KEY_PARMS *tpm_rsa_key_parms) { printf(" TPM_RSAKeyParms_Init:\n"); tpm_rsa_key_parms->keyLength = 0; tpm_rsa_key_parms->numPrimes = 0; TPM_SizedBuffer_Init(&(tpm_rsa_key_parms->exponent)); return; } /* TPM_RSAKeyParms_Load() sets members from stream, and shifts the stream past the bytes consumed. Must call TPM_RSAKeyParms_Delete() to free */ TPM_RESULT TPM_RSAKeyParms_Load(TPM_RSA_KEY_PARMS *tpm_rsa_key_parms, /* result */ unsigned char **stream, /* pointer to next parameter */ uint32_t *stream_size) /* stream size left */ { TPM_RESULT rc = 0; printf(" TPM_RSAKeyParms_Load:\n"); /* load keyLength */ if (rc == 0) { rc = TPM_Load32(&(tpm_rsa_key_parms->keyLength), stream, stream_size); } /* load numPrimes */ if (rc == 0) { rc = TPM_Load32(&(tpm_rsa_key_parms->numPrimes), stream, stream_size); } /* load exponent */ if (rc == 0) { rc = TPM_SizedBuffer_Load(&(tpm_rsa_key_parms->exponent), stream, stream_size); } return rc; } /* TPM_RSAKeyParms_Store serializes a TPM_RSA_KEY_PARMS structure, appending results to 'sbuffer' */ TPM_RESULT TPM_RSAKeyParms_Store(TPM_STORE_BUFFER *sbuffer, const TPM_RSA_KEY_PARMS *tpm_rsa_key_parms) { TPM_RESULT rc = 0; printf(" TPM_RSAKeyParms_Store:\n"); /* store keyLength */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_rsa_key_parms->keyLength); } /* store numPrimes */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_rsa_key_parms->numPrimes); } /* store exponent */ if (rc == 0) { rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_rsa_key_parms->exponent)); } return rc; } /* TPM_RSAKeyParms_Delete frees any member allocated memory If 'tpm_rsa_key_parms' is NULL, this is a no-op. */ void TPM_RSAKeyParms_Delete(TPM_RSA_KEY_PARMS *tpm_rsa_key_parms) { printf(" TPM_RSAKeyParms_Delete:\n"); if (tpm_rsa_key_parms != NULL) { TPM_SizedBuffer_Delete(&(tpm_rsa_key_parms->exponent)); TPM_RSAKeyParms_Init(tpm_rsa_key_parms); } return; } /* TPM_RSAKeyParms_Copy() does a copy of the source to the destination. The destination must be initialized first. */ TPM_RESULT TPM_RSAKeyParms_Copy(TPM_RSA_KEY_PARMS *tpm_rsa_key_parms_dest, TPM_RSA_KEY_PARMS *tpm_rsa_key_parms_src) { TPM_RESULT rc = 0; printf(" TPM_RSAKeyParms_Copy:\n"); if (rc == 0) { tpm_rsa_key_parms_dest->keyLength = tpm_rsa_key_parms_src->keyLength; tpm_rsa_key_parms_dest->numPrimes = tpm_rsa_key_parms_src->numPrimes; rc = TPM_SizedBuffer_Copy(&(tpm_rsa_key_parms_dest->exponent), &(tpm_rsa_key_parms_src->exponent)); } return rc; } /* TPM_RSAKeyParms_New() allocates memory for a TPM_RSA_KEY_PARMS and initializes the structure */ TPM_RESULT TPM_RSAKeyParms_New(TPM_RSA_KEY_PARMS **tpm_rsa_key_parms) { TPM_RESULT rc = 0; printf(" TPM_RSAKeyParms_New:\n"); if (rc == 0) { rc = TPM_Malloc((unsigned char **)tpm_rsa_key_parms, sizeof(TPM_RSA_KEY_PARMS)); } if (rc == 0) { TPM_RSAKeyParms_Init(*tpm_rsa_key_parms); } return rc; } /* TPM_RSAKeyParms_GetExponent() gets the exponent array and size from tpm_rsa_key_parms. If the structure exponent.size is zero, the default RSA exponent is returned. */ TPM_RESULT TPM_RSAKeyParms_GetExponent(uint32_t *ebytes, unsigned char **earr, TPM_RSA_KEY_PARMS *tpm_rsa_key_parms) { TPM_RESULT rc = 0; printf(" TPM_RSAKeyParms_GetExponent:\n"); if (tpm_rsa_key_parms->exponent.size != 0) { *ebytes = tpm_rsa_key_parms->exponent.size; *earr = tpm_rsa_key_parms->exponent.buffer; } else { *ebytes = 3; *earr = tpm_default_rsa_exponent; } return rc; } /* A Key Handle Entry */ /* TPM_KeyHandleEntry_Init() removes an entry from the list. It DOES NOT delete the TPM_KEY object. */ void TPM_KeyHandleEntry_Init(TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry) { tpm_key_handle_entry->handle = 0; tpm_key_handle_entry->key = NULL; tpm_key_handle_entry->parentPCRStatus = TRUE; tpm_key_handle_entry->keyControl = 0; return; } /* TPM_KeyHandleEntry_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_KeyHandleEntry_Init() After use, call TPM_KeyHandleEntry_Delete() to free memory */ TPM_RESULT TPM_KeyHandleEntry_Load(TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_KeyHandleEntry_Load:\n"); /* load handle */ if (rc == 0) { rc = TPM_Load32(&(tpm_key_handle_entry->handle), stream, stream_size); } /* malloc space for the key member */ if (rc == 0) { rc = TPM_Malloc((unsigned char **)&(tpm_key_handle_entry->key), sizeof(TPM_KEY)); } /* load key */ if (rc == 0) { TPM_Key_Init(tpm_key_handle_entry->key); rc = TPM_Key_LoadClear(tpm_key_handle_entry->key, FALSE, /* not EK */ stream, stream_size); } /* load parentPCRStatus */ if (rc == 0) { rc = TPM_LoadBool(&(tpm_key_handle_entry->parentPCRStatus), stream, stream_size); } /* load keyControl */ if (rc == 0) { rc = TPM_Load32(&(tpm_key_handle_entry->keyControl), stream, stream_size); } return rc; } /* TPM_KeyHandleEntry_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_KeyHandleEntry_Store(TPM_STORE_BUFFER *sbuffer, const TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry) { TPM_RESULT rc = 0; printf(" TPM_KeyHandleEntry_Store:\n"); /* store handle */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_key_handle_entry->handle); } /* store key with private data appended in clear text */ if (rc == 0) { rc = TPM_Key_StoreClear(sbuffer, FALSE, /* not EK */ tpm_key_handle_entry->key); } /* store parentPCRStatus */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_key_handle_entry->parentPCRStatus), sizeof(TPM_BOOL)); } /* store keyControl */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_key_handle_entry->keyControl); } return rc; } /* TPM_KeyHandleEntry_Delete() deletes an entry from the list, deletes the TPM_KEY object, and free's the TPM_KEY. */ void TPM_KeyHandleEntry_Delete(TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry) { if (tpm_key_handle_entry != NULL) { if (tpm_key_handle_entry->handle != 0) { printf(" TPM_KeyHandleEntry_Delete: Deleting %08x\n", tpm_key_handle_entry->handle); TPM_Key_Delete(tpm_key_handle_entry->key); free(tpm_key_handle_entry->key); } TPM_KeyHandleEntry_Init(tpm_key_handle_entry); } return; } /* TPM_KeyHandleEntry_FlushSpecific() flushes a key handle according to the rules of TPM_FlushSpecific() */ TPM_RESULT TPM_KeyHandleEntry_FlushSpecific(tpm_state_t *tpm_state, TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry) { TPM_RESULT rc = 0; TPM_AUTHHANDLE authHandle = 0; /* dummy parameter */ TPM_BOOL continueAuthSession; /* dummy parameter */ printf(" TPM_KeyHandleEntry_FlushSpecific:\n"); if (rc == 0) { /* Internal error, should never happen */ if (tpm_key_handle_entry->key == NULL) { printf("TPM_KeyHandleEntry_FlushSpecific: Error (fatal), key is NULL\n"); rc = TPM_FAIL; } } /* terminate OSAP and DSAP sessions associated with the key */ if (rc == 0) { /* The dummy parameters are not used. The session, if any, associated with this function is handled elsewhere. */ TPM_AuthSessions_TerminateEntity(&continueAuthSession, authHandle, tpm_state->tpm_stclear_data.authSessions, TPM_ET_KEYHANDLE, /* TPM_ENTITY_TYPE */ &(tpm_key_handle_entry->key-> tpm_store_asymkey->pubDataDigest)); /* entityDigest */ printf(" TPM_KeyHandleEntry_FlushSpecific: Flushing key handle %08x\n", tpm_key_handle_entry->handle); /* free the TPM_KEY resources, free the key itself, and remove entry from the key handle entries list */ TPM_KeyHandleEntry_Delete(tpm_key_handle_entry); } return rc; } /* Key Handle Entries */ /* TPM_KeyHandleEntries_Init() initializes the fixed TPM_KEY_HANDLE_ENTRY array. All entries are emptied. The keys are not deleted. */ void TPM_KeyHandleEntries_Init(TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries) { size_t i; printf(" TPM_KeyHandleEntries_Init:\n"); for (i = 0 ; i < TPM_KEY_HANDLES ; i++) { TPM_KeyHandleEntry_Init(&(tpm_key_handle_entries[i])); } return; } /* TPM_KeyHandleEntries_Delete() deletes and freed all TPM_KEY's stored in entries, and the entry */ void TPM_KeyHandleEntries_Delete(TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries) { size_t i; printf(" TPM_KeyHandleEntries_Delete:\n"); for (i = 0 ; i < TPM_KEY_HANDLES ; i++) { TPM_KeyHandleEntry_Delete(&(tpm_key_handle_entries[i])); } return; } /* TPM_KeyHandleEntries_Load() loads the key handle entries from a stream created by TPM_KeyHandleEntries_Store() The two functions must be kept in sync. */ TPM_RESULT TPM_KeyHandleEntries_Load(tpm_state_t *tpm_state, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; uint32_t keyCount = 0; /* keys to be saved */ size_t i; TPM_KEY_HANDLE_ENTRY tpm_key_handle_entry; /* check format tag */ /* In the future, if multiple formats are supported, this check will be replaced by a 'switch' on the tag */ if (rc == 0) { rc = TPM_CheckTag(TPM_TAG_KEY_HANDLE_ENTRIES_V1, stream, stream_size); } /* get the count of keys in the stream */ if (rc == 0) { rc = TPM_Load32(&keyCount, stream, stream_size); printf(" TPM_KeyHandleEntries_Load: %u keys to be loaded\n", keyCount); } /* sanity check that keyCount not greater than key slots */ if (rc == 0) { if (keyCount > TPM_KEY_HANDLES) { printf("TPM_KeyHandleEntries_Load: Error (fatal)" " key handles in stream %u greater than %d\n", keyCount, TPM_KEY_HANDLES); rc = TPM_FAIL; } } /* for each key handle entry */ for (i = 0 ; (rc == 0) && (i < keyCount) ; i++) { /* deserialize the key handle entry and its key member */ if (rc == 0) { TPM_KeyHandleEntry_Init(&tpm_key_handle_entry); /* freed @2 on error */ rc = TPM_KeyHandleEntry_Load(&tpm_key_handle_entry, stream, stream_size); } if (rc == 0) { printf(" TPM_KeyHandleEntries_Load: Loading key handle %08x\n", tpm_key_handle_entry.handle); /* Add the entry to the list. Keep the handle. If the suggested value could not be accepted, this is a "should never happen" fatal error. It means that the save key handle was saved twice. */ rc = TPM_KeyHandleEntries_AddEntry(&(tpm_key_handle_entry.handle), /* suggested */ TRUE, /* keep handle */ tpm_state->tpm_key_handle_entries, &tpm_key_handle_entry); } /* if there was an error copying the entry to the array, the entry must be delete'd to prevent a memory leak, since a key has been loaded to the entry */ if (rc != 0) { TPM_KeyHandleEntry_Delete(&tpm_key_handle_entry); /* @2 on error */ } } return rc; } /* TPM_KeyHandleEntries_Store() stores the key handle entries to a stream that can be restored through TPM_KeyHandleEntries_Load(). The two functions must be kept in sync. */ TPM_RESULT TPM_KeyHandleEntries_Store(TPM_STORE_BUFFER *sbuffer, tpm_state_t *tpm_state) { TPM_RESULT rc = 0; size_t start; /* iterator though key handle entries */ size_t current; /* iterator though key handle entries */ uint32_t keyCount; /* keys to be saved */ TPM_BOOL save; /* should key be saved */ TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry; if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_KEY_HANDLE_ENTRIES_V1); } /* first count up the keys */ if (rc == 0) { start = 0; keyCount = 0; printf(" TPM_KeyHandleEntries_Store: Counting keys to be stored\n"); } while ((rc == 0) && /* returns TPM_RETRY when at the end of the table, terminates loop */ (TPM_KeyHandleEntries_GetNextEntry(&tpm_key_handle_entry, ¤t, tpm_state->tpm_key_handle_entries, start)) == 0) { TPM_SaveState_IsSaveKey(&save, tpm_key_handle_entry); if (save) { keyCount++; } start = current + 1; } /* store the number of entries to save */ if (rc == 0) { printf(" TPM_KeyHandleEntries_Store: %u keys to be stored\n", keyCount); rc = TPM_Sbuffer_Append32(sbuffer, keyCount); } /* for each key handle entry */ if (rc == 0) { printf(" TPM_KeyHandleEntries_Store: Storing keys\n"); start = 0; } while ((rc == 0) && /* returns TPM_RETRY when at the end of the table, terminates loop */ (TPM_KeyHandleEntries_GetNextEntry(&tpm_key_handle_entry, ¤t, tpm_state->tpm_key_handle_entries, start)) == 0) { TPM_SaveState_IsSaveKey(&save, tpm_key_handle_entry); if (save) { /* store the key handle entry and its associated key */ rc = TPM_KeyHandleEntry_Store(sbuffer, tpm_key_handle_entry); } start = current + 1; } return rc; } /* TPM_KeyHandleEntries_StoreHandles() stores only the two members which are part of the specification. - the number of loaded keys - a list of key handles A TPM_KEY_HANDLE_LIST structure that enumerates all key handles loaded on the TPM. The list only contains the number of handles that an external manager can operate with and does not include the EK or SRK. This is command is available for backwards compatibility. It is the same as TPM_CAP_HANDLE with a resource type of keys. */ TPM_RESULT TPM_KeyHandleEntries_StoreHandles(TPM_STORE_BUFFER *sbuffer, const TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries) { TPM_RESULT rc = 0; uint16_t i, loadedCount; printf(" TPM_KeyHandleEntries_StoreHandles:\n"); if (rc == 0) { loadedCount = 0; /* count the number of loaded handles */ for (i = 0 ; i < TPM_KEY_HANDLES ; i++) { if (tpm_key_handle_entries[i].key != NULL) { loadedCount++; } } /* store 'loaded' handle count */ rc = TPM_Sbuffer_Append16(sbuffer, loadedCount); } for (i = 0 ; (rc == 0) && (i < TPM_KEY_HANDLES) ; i++) { if (tpm_key_handle_entries[i].key != NULL) { /* if the index is loaded */ rc = TPM_Sbuffer_Append32(sbuffer, tpm_key_handle_entries[i].handle); /* store it */ } } return rc; } /* TPM_KeyHandleEntries_DeleteHandle() removes a handle from the list. The TPM_KEY object must be _Delete'd and possibly free'd separately, because it might not be in the table. */ TPM_RESULT TPM_KeyHandleEntries_DeleteHandle(TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries, TPM_KEY_HANDLE tpm_key_handle) { TPM_RESULT rc = 0; TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry; printf(" TPM_KeyHandleEntries_DeleteHandle: %08x\n", tpm_key_handle); /* search for the handle */ if (rc == 0) { rc = TPM_KeyHandleEntries_GetEntry(&tpm_key_handle_entry, tpm_key_handle_entries, tpm_key_handle); if (rc != 0) { printf("TPM_KeyHandleEntries_DeleteHandle: Error, key handle %08x not found\n", tpm_key_handle); } } /* delete the entry */ if (rc == 0) { TPM_KeyHandleEntry_Init(tpm_key_handle_entry); } return rc; } /* TPM_KeyHandleEntries_IsSpace() returns 'isSpace' TRUE if an entry is available, FALSE if not. If TRUE, 'index' holds the first free position. */ void TPM_KeyHandleEntries_IsSpace(TPM_BOOL *isSpace, uint32_t *index, const TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries) { printf(" TPM_KeyHandleEntries_IsSpace:\n"); for (*index = 0, *isSpace = FALSE ; *index < TPM_KEY_HANDLES ; (*index)++) { if (tpm_key_handle_entries[*index].key == NULL) { /* if the index is empty */ printf(" TPM_KeyHandleEntries_IsSpace: Found space at %u\n", *index); *isSpace = TRUE; break; } } return; } /* TPM_KeyHandleEntries_GetSpace() returns the number of unused key handle entries. */ void TPM_KeyHandleEntries_GetSpace(uint32_t *space, const TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries) { uint32_t i; printf(" TPM_KeyHandleEntries_GetSpace:\n"); for (*space = 0 , i = 0 ; i < TPM_KEY_HANDLES ; i++) { if (tpm_key_handle_entries[i].key == NULL) { /* if the index is empty */ (*space)++; } } return; } /* TPM_KeyHandleEntries_IsEvictSpace() returns 'isSpace' TRUE if there are at least 'minSpace' entries that do not have the ownerEvict bit set, FALSE if not. */ void TPM_KeyHandleEntries_IsEvictSpace(TPM_BOOL *isSpace, const TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries, uint32_t minSpace) { uint32_t evictSpace; uint32_t i; for (i = 0, evictSpace = 0 ; i < TPM_KEY_HANDLES ; i++) { if (tpm_key_handle_entries[i].key == NULL) { /* if the index is empty */ evictSpace++; } else { /* is index is used */ if (!(tpm_key_handle_entries[i].keyControl & TPM_KEY_CONTROL_OWNER_EVICT)) { evictSpace++; /* space that can be evicted */ } } } printf(" TPM_KeyHandleEntries_IsEvictSpace: evictable space, minimum %u free %u\n", minSpace, evictSpace); if (evictSpace >= minSpace) { *isSpace = TRUE; } else { *isSpace = FALSE; } return; } /* TPM_KeyHandleEntries_AddKeyEntry() adds a TPM_KEY object to the list. If *tpm_key_handle == 0, a value is assigned. If *tpm_key_handle != 0, that value is used if it it not currently in use. The handle is returned in tpm_key_handle. */ TPM_RESULT TPM_KeyHandleEntries_AddKeyEntry(TPM_KEY_HANDLE *tpm_key_handle, /* i/o */ TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries, /* in */ TPM_KEY *tpm_key, TPM_BOOL parentPCRStatus, TPM_KEY_CONTROL keyControl) { TPM_RESULT rc = 0; TPM_KEY_HANDLE_ENTRY tpm_key_handle_entry; printf(" TPM_KeyHandleEntries_AddKeyEntry:\n"); tpm_key_handle_entry.key = tpm_key; tpm_key_handle_entry.parentPCRStatus = parentPCRStatus; tpm_key_handle_entry.keyControl = keyControl; rc = TPM_KeyHandleEntries_AddEntry(tpm_key_handle, FALSE, /* don't have to keep handle */ tpm_key_handle_entries, &tpm_key_handle_entry); return rc; } /* TPM_KeyHandleEntries_AddEntry() adds (copies) the TPM_KEY_HANDLE_ENTRY object to the list. If *tpm_key_handle == 0: a value is assigned. If *tpm_key_handle != 0: If keepHandle is TRUE, the handle must be used. An error is returned if the handle is already in use. If keepHandle is FALSE, if the handle is already in use, a new value is assigned. The handle is returned in tpm_key_handle. */ TPM_RESULT TPM_KeyHandleEntries_AddEntry(TPM_KEY_HANDLE *tpm_key_handle, /* i/o */ TPM_BOOL keepHandle, /* input */ TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries, /* input */ TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry) /* input */ { TPM_RESULT rc = 0; uint32_t index; TPM_BOOL isSpace; printf(" TPM_KeyHandleEntries_AddEntry: handle %08x, keepHandle %u\n", *tpm_key_handle, keepHandle); /* check for valid TPM_KEY */ if (rc == 0) { if (tpm_key_handle_entry->key == NULL) { /* should never occur */ printf("TPM_KeyHandleEntries_AddEntry: Error (fatal), NULL TPM_KEY\n"); rc = TPM_FAIL; } } /* is there an empty entry, get the location index */ if (rc == 0) { TPM_KeyHandleEntries_IsSpace(&isSpace, &index, tpm_key_handle_entries); if (!isSpace) { printf("TPM_KeyHandleEntries_AddEntry: Error, key handle entries full\n"); rc = TPM_NOSPACE; } } if (rc == 0) { rc = TPM_Handle_GenerateHandle(tpm_key_handle, /* I/O */ tpm_key_handle_entries, /* handle array */ keepHandle, TRUE, /* isKeyHandle */ (TPM_GETENTRY_FUNCTION_T)TPM_KeyHandleEntries_GetEntry); } if (rc == 0) { tpm_key_handle_entries[index].handle = *tpm_key_handle; tpm_key_handle_entries[index].key = tpm_key_handle_entry->key; tpm_key_handle_entries[index].keyControl = tpm_key_handle_entry->keyControl; tpm_key_handle_entries[index].parentPCRStatus = tpm_key_handle_entry->parentPCRStatus; printf(" TPM_KeyHandleEntries_AddEntry: Index %u key handle %08x key pointer %p\n", index, tpm_key_handle_entries[index].handle, tpm_key_handle_entries[index].key); } return rc; } /* TPM_KeyHandleEntries_GetEntry() searches all entries for the entry matching the handle, and returns that entry */ TPM_RESULT TPM_KeyHandleEntries_GetEntry(TPM_KEY_HANDLE_ENTRY **tpm_key_handle_entry, TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries, TPM_KEY_HANDLE tpm_key_handle) { TPM_RESULT rc = 0; size_t i; TPM_BOOL found; printf(" TPM_KeyHandleEntries_GetEntry: Get entry for handle %08x\n", tpm_key_handle); for (i = 0, found = FALSE ; (i < TPM_KEY_HANDLES) && !found ; i++) { /* first test for matching handle. Then check for non-NULL to insure that entry is valid */ if ((tpm_key_handle_entries[i].handle == tpm_key_handle) && tpm_key_handle_entries[i].key != NULL) { /* found */ found = TRUE; *tpm_key_handle_entry = &(tpm_key_handle_entries[i]); } } if (!found) { printf(" TPM_KeyHandleEntries_GetEntry: key handle %08x not found\n", tpm_key_handle); rc = TPM_INVALID_KEYHANDLE; } else { printf(" TPM_KeyHandleEntries_GetEntry: key handle %08x found\n", tpm_key_handle); } return rc; } /* TPM_KeyHandleEntries_GetNextEntry() gets the next valid TPM_KEY_HANDLE_ENTRY at or after the 'start' index. The current position is returned in 'current'. For iteration, the next 'start' should be 'current' + 1. Returns 0 on success. Returns TPM_RETRY when no more valid entries are found. */ TPM_RESULT TPM_KeyHandleEntries_GetNextEntry(TPM_KEY_HANDLE_ENTRY **tpm_key_handle_entry, size_t *current, TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries, size_t start) { TPM_RESULT rc = TPM_RETRY; printf(" TPM_KeyHandleEntries_GetNextEntry: Start %lu\n", (unsigned long)start); for (*current = start ; *current < TPM_KEY_HANDLES ; (*current)++) { if (tpm_key_handle_entries[*current].key != NULL) { *tpm_key_handle_entry = &(tpm_key_handle_entries[*current]); rc = 0; /* found an entry */ break; } } return rc; } /* TPM_KeyHandleEntries_GetKey() gets the TPM_KEY associated with the handle. If the key has PCR usage (size is non-zero and one or more mask bits are set), PCR's have been specified. It computes a PCR digest based on the TPM PCR's and verifies it against the key digestAtRelease. Exceptions: readOnly is TRUE when the caller is indicating that only the public key is being read (e.g. TPM_GetPubKey). In this case, if keyFlags TPM_PCRIGNOREDONREAD is also TRUE, the PCR digest and locality must not be checked. If ignorePCRs is TRUE, the PCR digest is also ignored. A typical case is during OSAP and DSAP session setup. */ TPM_RESULT TPM_KeyHandleEntries_GetKey(TPM_KEY **tpm_key, TPM_BOOL *parentPCRStatus, tpm_state_t *tpm_state, TPM_KEY_HANDLE tpm_key_handle, TPM_BOOL readOnly, TPM_BOOL ignorePCRs, TPM_BOOL allowEK) { TPM_RESULT rc = 0; TPM_BOOL found = FALSE; /* found a special handle key */ TPM_BOOL validatePcrs = TRUE; TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry; printf(" TPM_KeyHandleEntries_GetKey: For handle %08x\n", tpm_key_handle); /* If it's one of the special handles, return the TPM_KEY */ if (rc == 0) { switch (tpm_key_handle) { case TPM_KH_SRK: /* The handle points to the SRK */ if (tpm_state->tpm_permanent_data.ownerInstalled) { *tpm_key = &(tpm_state->tpm_permanent_data.srk); *parentPCRStatus = FALSE; /* storage root key (SRK) has no parent */ found = TRUE; } else { printf(" TPM_KeyHandleEntries_GetKey: Error, SRK handle with no owner\n"); rc = TPM_KEYNOTFOUND; } break; case TPM_KH_EK: /* The handle points to the PUBEK, only usable with TPM_OwnerReadInternalPub */ if (rc == 0) { if (!allowEK) { printf(" TPM_KeyHandleEntries_GetKey: Error, EK handle not allowed\n"); rc = TPM_KEYNOTFOUND; } } if (rc == 0) { if (tpm_state->tpm_permanent_data.endorsementKey.keyUsage == TPM_KEY_UNINITIALIZED) { printf(" TPM_KeyHandleEntries_GetKey: Error, EK handle but no EK\n"); rc = TPM_KEYNOTFOUND; } } if (rc == 0) { *tpm_key = &(tpm_state->tpm_permanent_data.endorsementKey); *parentPCRStatus = FALSE; /* endorsement key (EK) has no parent */ found = TRUE; } break; case TPM_KH_OWNER: /* handle points to the TPM Owner */ case TPM_KH_REVOKE: /* handle points to the RevokeTrust value */ case TPM_KH_TRANSPORT: /* handle points to the EstablishTransport static authorization */ case TPM_KH_OPERATOR: /* handle points to the Operator auth */ case TPM_KH_ADMIN: /* handle points to the delegation administration auth */ printf("TPM_KeyHandleEntries_GetKey: Error, Unsupported key handle %08x\n", tpm_key_handle); rc = TPM_INVALID_RESOURCE; break; default: /* continue searching */ break; } } /* If not one of the special key handles, search for the handle in the list */ if ((rc == 0) && !found) { rc = TPM_KeyHandleEntries_GetEntry(&tpm_key_handle_entry, tpm_state->tpm_key_handle_entries, tpm_key_handle); if (rc != 0) { printf("TPM_KeyHandleEntries_GetKey: Error, key handle %08x not found\n", tpm_key_handle); } } /* Part 1 25.1 Validate Key for use 2. Set LK to the loaded key that is being used */ /* NOTE: For special handle keys, this was already done. Just do here for keys in table */ if ((rc == 0) && !found) { *tpm_key = tpm_key_handle_entry->key; *parentPCRStatus = tpm_key_handle_entry->parentPCRStatus; } /* 3. If LK -> pcrInfoSize is not 0 - if the key specifies PCR's */ /* NOTE Done by TPM_Key_CheckPCRDigest() */ /* a. If LK -> pcrInfo -> releasePCRSelection identifies the use of one or more PCR */ if (rc == 0) { #ifdef TPM_V12 validatePcrs = !ignorePCRs && !(readOnly && ((*tpm_key)->keyFlags & TPM_PCRIGNOREDONREAD)); #else validatePcrs = !ignorePCRs && !readOnly; #endif } if ((rc == 0) && validatePcrs) { if (rc == 0) { rc = TPM_Key_CheckPCRDigest(*tpm_key, tpm_state); } } return rc; } /* TPM_KeyHandleEntries_SetParentPCRStatus() updates the parentPCRStatus member of the TPM_KEY_HANDLE_ENTRY */ TPM_RESULT TPM_KeyHandleEntries_SetParentPCRStatus(TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries, TPM_KEY_HANDLE tpm_key_handle, TPM_BOOL parentPCRStatus) { TPM_RESULT rc = 0; TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry; printf(" TPM_KeyHandleEntries_SetParentPCRStatus: Handle %08x\n", tpm_key_handle); /* get the entry for the handle from the table */ if (rc == 0) { rc = TPM_KeyHandleEntries_GetEntry(&tpm_key_handle_entry, tpm_key_handle_entries, tpm_key_handle); if (rc != 0) { printf("TPM_KeyHandleEntries_SetParentPCRStatus: Error, key handle %08x not found\n", tpm_key_handle); } } if (rc == 0) { tpm_key_handle_entry->parentPCRStatus = parentPCRStatus; } return rc; } /* TPM_KeyHandleEntries_OwnerEvictLoad() loads all owner evict keys from the stream into the key handle entries table. */ TPM_RESULT TPM_KeyHandleEntries_OwnerEvictLoad(TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; uint16_t keyCount; uint16_t i; /* the uint16_t corresponds to the standard getcap */ TPM_KEY_HANDLE_ENTRY tpm_key_handle_entry; /* each entry as read from the stream */ TPM_TAG ownerEvictVersion; printf(" TPM_KeyHandleEntries_OwnerEvictLoad:\n"); /* get the owner evict version number */ if (rc == 0) { rc = TPM_Load16(&ownerEvictVersion, stream, stream_size); } if (rc == 0) { if (ownerEvictVersion != TPM_TAG_NVSTATE_OE_V1) { printf("TPM_KeyHandleEntries_OwnerEvictLoad: " "Error (fatal) unsupported version tag %04x\n", ownerEvictVersion); rc = TPM_FAIL; } } /* get the count of owner evict keys in the stream */ if (rc == 0) { rc = TPM_Load16(&keyCount, stream, stream_size); } /* sanity check that keyCount not greater than key slots */ if (rc == 0) { if (keyCount > TPM_OWNER_EVICT_KEY_HANDLES) { printf("TPM_KeyHandleEntries_OwnerEvictLoad: Error (fatal)" " key handles in stream %u greater than %d\n", keyCount, TPM_OWNER_EVICT_KEY_HANDLES); rc = TPM_FAIL; } } if (rc == 0) { printf(" TPM_KeyHandleEntries_OwnerEvictLoad: Count %hu\n", keyCount); } for (i = 0 ; (rc == 0) && (i < keyCount) ; i++) { /* Must init each time through. This just resets the structure members. It does not free the key that is in the structure after the first time through. That key has been added (copied) to the key handle entries array. */ printf(" TPM_KeyHandleEntries_OwnerEvictLoad: Loading key %hu\n", i); TPM_KeyHandleEntry_Init(&tpm_key_handle_entry); /* freed @2 on error */ if (rc == 0) { rc = TPM_KeyHandleEntry_Load(&tpm_key_handle_entry, stream, stream_size); } /* add the entry to the list */ if (rc == 0) { rc = TPM_KeyHandleEntries_AddEntry(&(tpm_key_handle_entry.handle), /* suggested */ TRUE, /* keep handle */ tpm_key_handle_entries, &tpm_key_handle_entry); } /* if there was an error copying the entry to the array, the entry must be delete'd to prevent a memory leak, since a key has been loaded to the entry */ if (rc != 0) { TPM_KeyHandleEntry_Delete(&tpm_key_handle_entry); /* @2 on error */ } } return rc; } /* TPM_KeyHandleEntries_OwnerEvictStore() stores all owner evict keys from the key handle entries table to the stream. It is used to serialize to NVRAM. */ TPM_RESULT TPM_KeyHandleEntries_OwnerEvictStore(TPM_STORE_BUFFER *sbuffer, const TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries) { TPM_RESULT rc = 0; uint16_t count; uint16_t i; /* the uint16_t corresponds to the standard getcap */ printf(" TPM_KeyHandleEntries_OwnerEvictStore:\n"); /* append the owner evict version number to the stream */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_NVSTATE_OE_V1); } /* count the number of owner evict keys */ if (rc == 0) { rc = TPM_KeyHandleEntries_OwnerEvictGetCount(&count, tpm_key_handle_entries); } /* append the count to the stream */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, count); } for (i = 0 ; (rc == 0) && (i < TPM_KEY_HANDLES) ; i++) { /* if the slot is occupied */ if (tpm_key_handle_entries[i].key != NULL) { /* if the key is owner evict */ if ((tpm_key_handle_entries[i].keyControl & TPM_KEY_CONTROL_OWNER_EVICT)) { /* store it */ rc = TPM_KeyHandleEntry_Store(sbuffer, &(tpm_key_handle_entries[i])); } } } return rc; } /* TPM_KeyHandleEntries_OwnerEvictGetCount returns the number of owner evict key entries */ TPM_RESULT TPM_KeyHandleEntries_OwnerEvictGetCount(uint16_t *count, const TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries) { TPM_RESULT rc = 0; uint16_t i; /* the uint16_t corresponds to the standard getcap */ printf(" TPM_KeyHandleEntries_OwnerEvictGetCount:\n"); /* count the number of loaded owner evict handles */ if (rc == 0) { for (i = 0 , *count = 0 ; i < TPM_KEY_HANDLES ; i++) { /* if the slot is occupied */ if (tpm_key_handle_entries[i].key != NULL) { /* if the key is owner evict */ if ((tpm_key_handle_entries[i].keyControl & TPM_KEY_CONTROL_OWNER_EVICT)) { (*count)++; /* count it */ } } } printf(" TPM_KeyHandleEntries_OwnerEvictGetCount: Count %hu\n", *count); } /* sanity check */ if (rc == 0) { if (*count > TPM_OWNER_EVICT_KEY_HANDLES) { printf("TPM_KeyHandleEntries_OwnerEvictGetCount: Error (fatal), " "count greater that max %u\n", TPM_OWNER_EVICT_KEY_HANDLES); rc = TPM_FAIL; /* should never occur */ } } return rc; } /* TPM_KeyHandleEntries_OwnerEvictDelete() flushes owner evict keys. It does NOT write to NV. */ void TPM_KeyHandleEntries_OwnerEvictDelete(TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries) { uint16_t i; /* the uint16_t corresponds to the standard getcap */ for (i = 0 ; i < TPM_KEY_HANDLES ; i++) { /* if the slot is occupied */ if (tpm_key_handle_entries[i].key != NULL) { /* if the key is owner evict */ if ((tpm_key_handle_entries[i].keyControl & TPM_KEY_CONTROL_OWNER_EVICT)) { TPM_KeyHandleEntry_Delete(&(tpm_key_handle_entries[i])); } } } return; } /* Processing Functions */ /* 14.4 TPM_ReadPubek rev 99 Return the endorsement key public portion. This value should have controls placed upon access as it is a privacy sensitive value The readPubek flag is set to FALSE by TPM_TakeOwnership and set to TRUE by TPM_OwnerClear, thus mirroring if a TPM Owner is present. */ TPM_RESULT TPM_Process_ReadPubek(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, /* of remaining parameters*/ TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_NONCE antiReplay; /* processing */ const unsigned char *pubEndorsementKeyStreamBuffer; uint32_t pubEndorsementKeyStreamLength; /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_STORE_BUFFER pubEndorsementKeyStream; TPM_DIGEST checksum; printf("TPM_Process_ReadPubek: Ordinal Entry\n"); TPM_Sbuffer_Init(&pubEndorsementKeyStream); /* freed @1 */ /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get antiReplay parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Nonce_Load(antiReplay, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { TPM_PrintFour(" TPM_Process_ReadPubek: antiReplay", antiReplay); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_ReadPubek: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ /* 1. If TPM_PERMANENT_FLAGS -> readPubek is FALSE return TPM_DISABLED_CMD. */ if (returnCode == TPM_SUCCESS) { printf(" TPM_Process_ReadPubek: readPubek %02x\n", tpm_state->tpm_permanent_flags.readPubek); if (!tpm_state->tpm_permanent_flags.readPubek) { printf("TPM_Process_ReadPubek: Error, readPubek is FALSE\n"); returnCode = TPM_DISABLED_CMD; } } /* 2. If no EK is present the TPM MUST return TPM_NO_ENDORSEMENT */ if (returnCode == TPM_SUCCESS) { if (tpm_state->tpm_permanent_data.endorsementKey.keyUsage == TPM_KEY_UNINITIALIZED) { printf("TPM_Process_ReadPubek: Error, no EK is present\n"); returnCode = TPM_NO_ENDORSEMENT; } } /* 3. Create checksum by performing SHA-1 on the concatenation of (pubEndorsementKey || antiReplay). */ if (returnCode == TPM_SUCCESS) { /* serialize the TPM_PUBKEY components of the EK */ returnCode = TPM_Key_StorePubkey(&pubEndorsementKeyStream, /* output */ &pubEndorsementKeyStreamBuffer, /* output */ &pubEndorsementKeyStreamLength, /* output */ &(tpm_state->tpm_permanent_data.endorsementKey)); /* input */ } if (returnCode == TPM_SUCCESS) { printf(" TPM_Process_ReadPubek: pubEndorsementKey length %u\n", pubEndorsementKeyStreamLength); /* create the checksum */ returnCode = TPM_SHA1(checksum, #if 0 /* The old Atmel chip and the LTC test code assume this, but it is incorrect */ tpm_state->tpm_permanent_data.endorsementKey.pubKey.keyLength, tpm_state->tpm_permanent_data.endorsementKey.pubKey.key, #else /* this meets the TPM 1.2 standard */ pubEndorsementKeyStreamLength, pubEndorsementKeyStreamBuffer, #endif sizeof(TPM_NONCE), antiReplay, 0, NULL); } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_ReadPubek: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { /* 4. Export the PUBEK and checksum. */ if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* append pubEndorsementKey */ returnCode = TPM_Sbuffer_Append(response, pubEndorsementKeyStreamBuffer, pubEndorsementKeyStreamLength); } /* append checksum */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Digest_Store(response, checksum); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* cleanup */ TPM_Sbuffer_Delete(&pubEndorsementKeyStream); /* @1 */ return rcf; } /* 14.2 TPM_CreateRevocableEK rev 98 This command creates the TPM endorsement key. It returns a failure code if an endorsement key already exists. The TPM vendor may have a separate mechanism to create the EK and "squirt" the value into the TPM. */ TPM_RESULT TPM_Process_CreateRevocableEK(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_NONCE antiReplay; /* Arbitrary data */ TPM_KEY_PARMS keyInfo; /* Information about key to be created, this includes all algorithm parameters */ TPM_BOOL generateReset = FALSE; /* If TRUE use TPM RNG to generate EKreset. If FALSE use the passed value inputEKreset */ TPM_NONCE inputEKreset; /* The authorization value to be used with TPM_RevokeTrust if generateReset==FALSE, else the parameter is present but unused */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus = FALSE; /* audit the ordinal */ TPM_BOOL transportEncrypt = FALSE; /* wrapped in encrypted transport session */ TPM_KEY *endorsementKey; /* EK object from permanent store */ TPM_BOOL writeAllNV1 = FALSE; /* flags to write back NV */ TPM_BOOL writeAllNV2 = FALSE; /* flags to write back NV */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_PUBKEY pubEndorsementKey; /* The public endorsement key */ TPM_DIGEST checksum; /* Hash of pubEndorsementKey and antiReplay */ printf("TPM_Process_CreateRevocableEK: Ordinal Entry\n"); /* get pointers */ endorsementKey = &(tpm_state->tpm_permanent_data.endorsementKey); /* so that Delete's are safe */ TPM_KeyParms_Init(&keyInfo); /* freed @1 */ TPM_Pubkey_Init(&pubEndorsementKey); /* freed @2 */ /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get antiReplay parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Nonce_Load(antiReplay, &command, ¶mSize); } /* get keyInfo parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyParms_Load(&keyInfo, &command, ¶mSize); /* freed @1 */ } /* get generateReset parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_LoadBool(&generateReset, &command, ¶mSize); } /* get inputEKreset parameter */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CreateRevocableEK: generateReset %02x\n", generateReset); /* an email clarification says that this parameter is still present (but ignored) if generateReset is TRUE */ returnCode = TPM_Nonce_Load(inputEKreset, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { TPM_PrintFour("TPM_Process_CreateRevocableEK: inputEKreset", inputEKreset); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_CreateRevocableEK: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ /* 1. If an EK already exists, return TPM_DISABLED_CMD */ /* 2. Perform the actions of TPM_CreateEndorsementKeyPair, if any errors return with error */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CreateEndorsementKeyPair_Common(endorsementKey, &pubEndorsementKey, checksum, &writeAllNV1, tpm_state, &keyInfo, antiReplay); } if (returnCode == TPM_SUCCESS) { /* 3. Set TPM_PERMANENT_FLAGS -> enableRevokeEK to TRUE */ TPM_SetCapability_Flag(&writeAllNV1, /* altered */ &(tpm_state->tpm_permanent_flags.enableRevokeEK), /* flag */ TRUE); /* value */ /* a. If generateReset is TRUE then */ if (generateReset) { /* i. Set TPM_PERMANENT_DATA -> EKreset to the next value from the TPM RNG */ returnCode = TPM_Nonce_Generate(tpm_state->tpm_permanent_data.EKReset); } /* b. Else */ else { /* i. Set TPM_PERMANENT_DATA -> EKreset to inputEkreset */ TPM_Nonce_Copy(tpm_state->tpm_permanent_data.EKReset, inputEKreset); } } /* save the permanent data and flags structure sto NVRAM */ returnCode = TPM_PermanentAll_NVStore(tpm_state, (TPM_BOOL)(writeAllNV1 || writeAllNV2), returnCode); /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_CreateRevocableEK: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* 4. Return PUBEK, checksum and Ekreset */ /* append pubEndorsementKey. */ returnCode = TPM_Pubkey_Store(response, &pubEndorsementKey); } /* append checksum */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Digest_Store(response, checksum); } /* append outputEKreset */ /* 5. The outputEKreset authorization is sent in the clear. There is no uniqueness on the TPM available to actually perform encryption or use an encrypted channel. The assumption is that this operation is occurring in a controlled environment and sending the value in the clear is acceptable. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Nonce_Store(response, tpm_state->tpm_permanent_data.EKReset); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* cleanup */ TPM_KeyParms_Delete(&keyInfo); /* @1 */ TPM_Pubkey_Delete(&pubEndorsementKey); /* @2 */ return rcf; } /* 14.1 TPM_CreateEndorsementKeyPair rev 104 This command creates the TPM endorsement key. It returns a failure code if an endorsement key already exists. */ TPM_RESULT TPM_Process_CreateEndorsementKeyPair(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, /* of remaining parameters*/ TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_NONCE antiReplay; /* Arbitrary data */ TPM_KEY_PARMS keyInfo; /* Information about key to be created, this includes all algorithm parameters */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus = FALSE; /* audit the ordinal */ TPM_BOOL transportEncrypt = FALSE; /* wrapped in encrypted transport session */ TPM_KEY *endorsementKey = FALSE; /* EK object from permanent store */ TPM_BOOL writeAllNV1 = FALSE; /* flags to write back data */ TPM_BOOL writeAllNV2 = FALSE; /* flags to write back flags */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_PUBKEY pubEndorsementKey; /* The public endorsement key */ TPM_DIGEST checksum; /* Hash of pubEndorsementKey and antiReplay */ printf("TPM_Process_CreateEndorsementKeyPair: Ordinal Entry\n"); /* get pointers */ endorsementKey = &(tpm_state->tpm_permanent_data.endorsementKey); /* so that Delete's are safe */ TPM_KeyParms_Init(&keyInfo); /* freed @1 */ TPM_Pubkey_Init(&pubEndorsementKey); /* freed @2 */ /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get antiReplay parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Nonce_Load(antiReplay, &command, ¶mSize); } /* get keyInfo parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyParms_Load(&keyInfo, &command, ¶mSize); /* freed @1 */ } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_CreateEndorsementKeyPair: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CreateEndorsementKeyPair_Common(endorsementKey, &pubEndorsementKey, checksum, &writeAllNV1, tpm_state, &keyInfo, antiReplay); } /* 10. Set TPM_PERMANENT_FLAGS -> enableRevokeEK to FALSE */ if (returnCode == TPM_SUCCESS) { TPM_SetCapability_Flag(&writeAllNV2, /* altered */ &(tpm_state->tpm_permanent_flags.enableRevokeEK), /* flag */ FALSE); /* value */ } /* save the permanent data and flags structures to NVRAM */ returnCode = TPM_PermanentAll_NVStore(tpm_state, (TPM_BOOL)(writeAllNV1 || writeAllNV2), returnCode); /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_CreateEndorsementKeyPair: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { /* append pubEndorsementKey. */ if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; returnCode = TPM_Pubkey_Store(response, &pubEndorsementKey); } /* append checksum */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Digest_Store(response, checksum); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* cleanup */ TPM_KeyParms_Delete(&keyInfo); /* @1 */ TPM_Pubkey_Delete(&pubEndorsementKey); /* @2 */ return rcf; } /* TPM_CreateEndorsementKeyPair_Common rev 104 Actions common to TPM_CreateEndorsementKeyPair and TPM_CreateRevocableEK 'endorsementKey' points to TPM_PERMANENT_DATA -> endorsementKey */ TPM_RESULT TPM_CreateEndorsementKeyPair_Common(TPM_KEY *endorsementKey, /* output */ TPM_PUBKEY *pubEndorsementKey, /* output */ TPM_DIGEST checksum, /* output */ TPM_BOOL *writePermanentData, /* output */ tpm_state_t *tpm_state, /* input */ TPM_KEY_PARMS *keyInfo, /* input */ TPM_NONCE antiReplay) /* input */ { TPM_RESULT returnCode = TPM_SUCCESS; TPM_RSA_KEY_PARMS *tpm_rsa_key_parms; /* from keyInfo */ TPM_STORE_BUFFER pubEndorsementKeySerial; /* serialization for checksum calculation */ const unsigned char *pubEndorsementKeyBuffer; uint32_t pubEndorsementKeyLength; printf("TPM_CreateEndorsementKeyPair_Common:\n"); TPM_Sbuffer_Init(&pubEndorsementKeySerial); /* freed @1 */ /* 1. If an EK already exists, return TPM_DISABLED_CMD */ if (returnCode == TPM_SUCCESS) { if (endorsementKey->keyUsage != TPM_KEY_UNINITIALIZED) { printf("TPM_CreateEndorsementKeyPair_Common: Error, key already initialized\n"); returnCode = TPM_DISABLED_CMD; } } /* 2. Validate the keyInfo parameters for the key description */ if (returnCode == TPM_SUCCESS) { /* RSA */ /* a. If the algorithm type is RSA the key length MUST be a minimum of 2048. For interoperability the key length SHOULD be 2048 */ if (keyInfo->algorithmID == TPM_ALG_RSA) { if (returnCode == TPM_SUCCESS) { /* get the keyInfo TPM_RSA_KEY_PARMS structure */ returnCode = TPM_KeyParms_GetRSAKeyParms(&tpm_rsa_key_parms, keyInfo); } if (returnCode == TPM_SUCCESS) { if (tpm_rsa_key_parms->keyLength != TPM_KEY_RSA_NUMBITS) { /* in bits */ printf("TPM_CreateEndorsementKeyPair_Common: Error, " "Bad keyLength should be %u, was %u\n", TPM_KEY_RSA_NUMBITS, tpm_rsa_key_parms->keyLength); returnCode = TPM_BAD_KEY_PROPERTY; } } /* kgold - Support only 2 primes */ if (returnCode == TPM_SUCCESS) { if (tpm_rsa_key_parms->numPrimes != 2) { printf("TPM_CreateEndorsementKeyPair_Common: Error, " "Bad numPrimes should be 2, was %u\n", tpm_rsa_key_parms->numPrimes); returnCode = TPM_BAD_KEY_PROPERTY; } } } /* not RSA */ /* b. If the algorithm type is other than RSA the strength provided by the key MUST be comparable to RSA 2048 */ else { if (returnCode == TPM_SUCCESS) { printf("TPM_CreateEndorsementKeyPair_Common: Error, " "algorithmID %08x not supported\n", keyInfo->algorithmID); returnCode = TPM_BAD_KEY_PROPERTY; } } } /* c. The other parameters of keyInfo (encScheme, sigScheme, etc.) are ignored. */ /* 3. Create a key pair called the "endorsement key pair" using a TPM-protected capability. The type and size of key are that indicated by keyInfo. Set encScheme to TPM_ES_RSAESOAEP_SHA1_MGF1. Save the endorsement key in permanent structure. Save the endorsement private key 'd' in the TPM_KEY structure as encData */ /* Certain HW TPMs do not ignore the encScheme parameter, and expect it to be TPM_ES_RSAESOAEP_SHA1_MGF1. Test the value here to detect an application program that will fail with that TPM. */ if (returnCode == TPM_SUCCESS) { if (keyInfo->encScheme != TPM_ES_RSAESOAEP_SHA1_MGF1) { returnCode = TPM_BAD_KEY_PROPERTY; printf("TPM_CreateEndorsementKeyPair_Common: Error, " "encScheme %08x must be TPM_ES_RSAESOAEP_SHA1_MGF1\n", keyInfo->encScheme); } } if (returnCode == TPM_SUCCESS) { keyInfo->sigScheme = TPM_ES_NONE; returnCode = TPM_Key_GenerateRSA(endorsementKey, tpm_state, NULL, /* parent key, indicate root key */ tpm_state->tpm_stclear_data.PCRS, /* PCR array */ 1, /* TPM_KEY */ TPM_KEY_STORAGE, /* keyUsage */ 0, /* keyFlags */ TPM_AUTH_ALWAYS, /* authDataUsage */ keyInfo, NULL, /* no PCR's */ NULL); /* no PCR's */ *writePermanentData = TRUE; } /* Assemble the TPM_PUBKEY pubEndorsementKey for the response */ if (returnCode == TPM_SUCCESS) { /* add TPM_KEY_PARMS algorithmParms */ returnCode = TPM_KeyParms_Copy(&(pubEndorsementKey->algorithmParms), keyInfo); } if (returnCode == TPM_SUCCESS) { /* add TPM_SIZED_BUFFER pubKey */ returnCode = TPM_SizedBuffer_Set(&(pubEndorsementKey->pubKey), endorsementKey->pubKey.size, endorsementKey->pubKey.buffer); } /* 4. Create checksum by performing SHA-1 on the concatenation of (PUBEK || antiReplay) */ if (returnCode == TPM_SUCCESS) { /* serialize the pubEndorsementKey */ returnCode = TPM_Pubkey_Store(&pubEndorsementKeySerial, pubEndorsementKey); } if (returnCode == TPM_SUCCESS) { TPM_Sbuffer_Get(&pubEndorsementKeySerial, &pubEndorsementKeyBuffer, &pubEndorsementKeyLength); /* create the checksum */ returnCode = TPM_SHA1(checksum, pubEndorsementKeyLength, pubEndorsementKeyBuffer, sizeof(TPM_NONCE), antiReplay, 0, NULL); } /* 5. Store the PRIVEK */ /* NOTE Created in TPM_PERMANENT_DATA, call should save to NVRAM */ /* 6. Create TPM_PERMANENT_DATA -> tpmDAASeed from the TPM RNG */ /* 7. Create TPM_PERMANENT_DATA -> daaProof from the TPM RNG */ /* 8. Create TPM_PERMANENT_DATA -> daaBlobKey from the TPM RNG */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_PermanentData_InitDaa(&(tpm_state->tpm_permanent_data)); } /* 9. Set TPM_PERMANENT_FLAGS -> CEKPUsed to TRUE */ if (returnCode == TPM_SUCCESS) { tpm_state->tpm_permanent_flags.CEKPUsed = TRUE; } /* cleanup */ TPM_Sbuffer_Delete(&pubEndorsementKeySerial); /* @1 */ return returnCode; } /* 14.3 TPM_RevokeTrust rev 98 This command clears the EK and sets the TPM back to a pure default state. The generation of the AuthData value occurs during the generation of the EK. It is the responsibility of the EK generator to properly protect and disseminate the RevokeTrust AuthData. */ TPM_RESULT TPM_Process_RevokeTrust(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, /* of remaining parameters*/ TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_NONCE EKReset; /* The value that will be matched to EK Reset */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus = FALSE; /* audit the ordinal */ TPM_BOOL transportEncrypt = FALSE; /* wrapped in encrypted transport session */ TPM_BOOL writeAllNV1 = FALSE; /* flags to write back data */ TPM_BOOL writeAllNV2 = FALSE; /* flags to write back flags */ TPM_BOOL writeAllNV3 = FALSE; /* flags to write back flags */ TPM_BOOL physicalPresence; /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_RevokeTrust: Ordinal Entry\n"); /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get EKReset parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Nonce_Load(EKReset, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { TPM_PrintFour(" TPM_Process_RevokeTrust: EKReset", EKReset); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_RevokeTrust: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ /* 1. The TPM MUST validate that TPM_PERMANENT_FLAGS -> enableRevokeEK is TRUE, return TPM_PERMANENTEK on error */ if (returnCode == TPM_SUCCESS) { if (!tpm_state->tpm_permanent_flags.enableRevokeEK) { printf("TPM_Process_RevokeTrust: Error, enableRevokeEK is FALSE\n"); returnCode = TPM_PERMANENTEK; } } /* 2. The TPM MUST validate that the EKReset matches TPM_PERMANENT_DATA -> EKReset, return TPM_AUTHFAIL on error. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Nonce_Compare(tpm_state->tpm_permanent_data.EKReset, EKReset); if (returnCode != 0) { printf("TPM_Process_RevokeTrust: Error, EKReset mismatch\n"); returnCode = TPM_AUTHFAIL; } } /* 3. Ensure that physical presence is being asserted */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Global_GetPhysicalPresence(&physicalPresence, tpm_state); } if (returnCode == TPM_SUCCESS) { if (!physicalPresence) { printf("TPM_Process_RevokeTrust: Error, physicalPresence is FALSE\n"); returnCode = TPM_BAD_PRESENCE; } } /* 4. Perform the actions of TPM_OwnerClear (excepting the command authentication) */ /* a. NV items with the pubInfo -> nvIndex D value set MUST be deleted. This changes the TPM_OwnerClear handling of the same NV areas */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_OwnerClearCommon(tpm_state, TRUE); /* delete all NVRAM */ writeAllNV1 = TRUE; } if (returnCode == TPM_SUCCESS) { /* b. Set TPM_PERMANENT_FLAGS -> nvLocked to FALSE */ TPM_SetCapability_Flag(&writeAllNV2, /* altered (dummy) */ &(tpm_state->tpm_permanent_flags.nvLocked), /* flag */ FALSE); /* value */ /* 5. Invalidate TPM_PERMANENT_DATA -> tpmDAASeed */ /* 6. Invalidate TPM_PERMANENT_DATA -> daaProof */ /* 7. Invalidate TPM_PERMANENT_DATA -> daaBlobKey */ returnCode = TPM_PermanentData_InitDaa(&(tpm_state->tpm_permanent_data)); } if (returnCode == TPM_SUCCESS) { /* 8. Invalidate the EK and any internal state associated with the EK */ printf("TPM_Process_RevokeTrust: Deleting endorsement key\n"); TPM_Key_Delete(&(tpm_state->tpm_permanent_data.endorsementKey)); TPM_SetCapability_Flag(&writeAllNV3, /* altered (dummy) */ &(tpm_state->tpm_permanent_flags.CEKPUsed), /* flag */ FALSE); /* value */ } /* Store the permanent data and flags back to NVRAM */ returnCode = TPM_PermanentAll_NVStore(tpm_state, writeAllNV1, returnCode); /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_RevokeTrust: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* cleanup */ return rcf; } /* 27.7 TPM_DisablePubekRead rev 94 The TPM Owner may wish to prevent any entity from reading the PUBEK. This command sets the non-volatile flag so that the TPM_ReadPubek command always returns TPM_DISABLED_CMD. This commands has in essence been deprecated as TPM_TakeOwnership now sets the value to false. The commands remains at this time for backward compatibility. */ TPM_RESULT TPM_Process_DisablePubekRead(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, /* of remaining parameters*/ TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_AUTHHANDLE authHandle; /* The authorization handle used for owner authorization. */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization handle */ TPM_AUTHDATA ownerAuth; /* The authorization digest for inputs and owner authorization. HMAC key: ownerAuth. */ /* processing */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_AUTH_SESSION_DATA *auth_session_data; /* session data for authHandle */ TPM_SECRET *hmacKey; TPM_BOOL writeAllNV = FALSE; /* flag to write back NV */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_DisablePubekRead: Ordinal Entry\n"); /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag1(tag); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, ownerAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_DisablePubekRead: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* Verify that the TPM Owner authorizes the command and all of the input, on error return TPM_AUTHFAIL. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_OWNER, ordinal, NULL, &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ } if (returnCode == TPM_SUCCESS) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* owner HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, ownerAuth); /* Authorization digest for input */ } /* 1. This capability sets the TPM_PERMANENT_FLAGS -> readPubek flag to FALSE. */ if (returnCode == TPM_SUCCESS) { TPM_SetCapability_Flag(&writeAllNV, /* altered */ &(tpm_state->tpm_permanent_flags.readPubek), /* flag */ FALSE); /* value */ printf("TPM_Process_DisablePubekRead: readPubek now %02x\n", tpm_state->tpm_permanent_flags.readPubek); /* save the permanent flags structure to NVRAM */ returnCode = TPM_PermanentAll_NVStore(tpm_state, writeAllNV, returnCode); } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_DisablePubekRead: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if (returnCode == TPM_SUCCESS) { /* no outParam's, set authorization response data */ returnCode = TPM_AuthParams_Set(response, *hmacKey, /* owner HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, terminate the session. */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } return rcf; } /* 27.6 TPM_OwnerReadPubek rev 94 Return the endorsement key public portion. This is authorized by the TPM Owner. */ TPM_RESULT TPM_Process_OwnerReadPubek(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, /* of remaining parameters*/ TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_AUTHHANDLE authHandle; /* The authorization handle used for owner authorization. */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization handle */ TPM_AUTHDATA ownerAuth; /* The authorization digest for inputs and owner authorization. HMAC key: ownerAuth. */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_AUTH_SESSION_DATA *auth_session_data; /* session data for authHandle */ TPM_SECRET *hmacKey; const unsigned char *pubEndorsementKeyStreamBuffer; uint32_t pubEndorsementKeyStreamLength; /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_STORE_BUFFER pubEndorsementKeyStream; /* The public endorsement key */ printf("TPM_Process_OwnerReadPubek: Ordinal Entry\n"); TPM_Sbuffer_Init(&pubEndorsementKeyStream); /* freed @1 */ /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag1(tag); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, ownerAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_OwnerReadPubek: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* 1. Validate the TPM Owner authorization to execute this command */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_OWNER, ordinal, NULL, &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ } if (returnCode == TPM_SUCCESS) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* owner HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, ownerAuth); /* Authorization digest for input */ } /* serialize the TPM_PUBKEY components of the EK */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Key_StorePubkey(&pubEndorsementKeyStream, /* output */ &pubEndorsementKeyStreamBuffer, /* output */ &pubEndorsementKeyStreamLength, /* output */ &(tpm_state->tpm_permanent_data.endorsementKey)); /* input */ } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_OwnerReadPubek: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* 2. Export the PUBEK */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Sbuffer_Append(response, pubEndorsementKeyStreamBuffer, pubEndorsementKeyStreamLength); } /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if (returnCode == TPM_SUCCESS) { /* no outParam's, set authorization response data */ returnCode = TPM_AuthParams_Set(response, *hmacKey, /* owner HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, terminate the session. */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ TPM_Sbuffer_Delete(&pubEndorsementKeyStream); /* @1 */ return rcf; } /* 27.1.1 TPM_EvictKey rev 87 The key commands are deprecated as the new way to handle keys is to use the standard context commands. So TPM_EvictKey is now handled by TPM_FlushSpecific, TPM_TerminateHandle by TPM_FlushSpecific. The TPM will invalidate the key stored in the specified handle and return the space to the available internal pool for subsequent query by TPM_GetCapability and usage by TPM_LoadKey. If the specified key handle does not correspond to a valid key, an error will be returned. */ TPM_RESULT TPM_Process_EvictKey(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, /* of remaining parameters*/ TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_KEY_HANDLE evictHandle; /* The handle of the key to be evicted. */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry; /* table entry for the evictHandle */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_EvictKey: Ordinal Entry\n"); /* get inputs */ /* get evictHandle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&evictHandle, &command, ¶mSize); } /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_EvictKey: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ /* New 1.2 functionality The command must check the status of the ownerEvict flag for the key and if the flag is TRUE return TPM_KEY_CONTROL_OWNER */ /* evict the key stored in the specified handle */ /* get the TPM_KEY_HANDLE_ENTRY */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_EvictKey: Evicting handle %08x\n", evictHandle); returnCode = TPM_KeyHandleEntries_GetEntry(&tpm_key_handle_entry, tpm_state->tpm_key_handle_entries, evictHandle); if (returnCode != TPM_SUCCESS) { printf("TPM_Process_EvictKey: Error, key handle %08x not found\n", evictHandle); } } /* If tpm_key_handle_entry -> ownerEvict is TRUE return TPM_KEY_OWNER_CONTROL */ if (returnCode == TPM_SUCCESS) { if (tpm_key_handle_entry->keyControl & TPM_KEY_CONTROL_OWNER_EVICT) { printf("TPM_Process_EvictKey: Error, keyHandle specifies owner evict\n"); returnCode = TPM_KEY_OWNER_CONTROL; } } /* delete the entry, delete the key structure, and free the key */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyHandleEntry_FlushSpecific(tpm_state, tpm_key_handle_entry); } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_EvictKey: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } return rcf; } /* 14.5 TPM_OwnerReadInternalPub rev 87 A TPM Owner authorized command that returns the public portion of the EK or SRK. The keyHandle parameter is included in the incoming session authorization to prevent alteration of the value, causing a different key to be read. Unlike most key handles, which can be mapped by higher layer software, this key handle has only two fixed values. */ TPM_RESULT TPM_Process_OwnerReadInternalPub(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, /* of remaining parameters */ TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_KEY_HANDLE keyHandle; /* Handle for either PUBEK or SRK */ TPM_AUTHHANDLE authHandle; /* The authorization session handle used for owner authentication. */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization session handle */ TPM_AUTHDATA ownerAuth; /* The authorization session digest for inputs and owner authentication. HMAC key: ownerAuth. */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_AUTH_SESSION_DATA *auth_session_data; /* session data for authHandle */ TPM_SECRET *hmacKey; TPM_KEY *readKey = NULL; /* key to be read back */ const unsigned char *stream; uint32_t stream_size; /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_OwnerReadInternalPub: Ordinal Entry\n"); /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ /* NOTE: This is a special case, where the keyHandle is part of the HMAC calculation to avoid a man-in-the-middle privacy attack that replaces the SRK handle with the EK handle. */ inParamStart = command; /* get keyHandle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&keyHandle, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_OwnerReadInternalPub: keyHandle %08x\n", keyHandle); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag1(tag); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, ownerAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_OwnerReadInternalPub: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* 1. Validate the parameters and TPM Owner AuthData for this command */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_OWNER, ordinal, NULL, &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ } if (returnCode == TPM_SUCCESS) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* owner HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, ownerAuth); /* Authorization digest for input */ } if (returnCode == TPM_SUCCESS) { /* 2. If keyHandle is TPM_KH_EK */ if (keyHandle == TPM_KH_EK) { /* a. Set publicPortion to PUBEK */ printf("TPM_Process_OwnerReadInternalPub: Reading EK\n"); readKey = &(tpm_state->tpm_permanent_data.endorsementKey); } /* 3. Else If keyHandle is TPM_KH_SRK */ else if (keyHandle == TPM_KH_SRK) { /* a. Set publicPortion to the TPM_PUBKEY of the SRK */ printf("TPM_Process_OwnerReadInternalPub: Reading SRK\n"); readKey = &(tpm_state->tpm_permanent_data.srk); } /* 4. Else return TPM_BAD_PARAMETER */ else { printf("TPM_Process_OwnerReadInternalPub: Error, invalid keyHandle %08x\n", keyHandle); returnCode = TPM_BAD_PARAMETER; } } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_OwnerReadInternalPub: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* 5. Export the public key of the referenced key */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Key_StorePubkey(response, &stream, &stream_size, readKey); } /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if (returnCode == TPM_SUCCESS) { /* no outParam's, set authorization response data */ returnCode = TPM_AuthParams_Set(response, *hmacKey, /* owner HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, terminate the session. */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ return rcf; } libtpms-0.9.3/src/tpm12/tpm_key.h000066400000000000000000000560461421143571500165660ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Key Handler */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_key.h 4526 2011-03-24 21:14:42Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_KEY_H #define TPM_KEY_H #include "tpm_global.h" #include "tpm_store.h" #include "tpm_structures.h" #define TPM_KEY_RSA_NUMBITS 2048 extern unsigned char tpm_default_rsa_exponent[]; /* TPM_KEY */ void TPM_Key_Init(TPM_KEY *tpm_key); void TPM_Key_InitTag12(TPM_KEY *tpm_key); TPM_RESULT TPM_Key_Load(TPM_KEY *tpm_key, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_Key_LoadPubData(TPM_KEY *tpm_key, TPM_BOOL isEK, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_Key_LoadClear(TPM_KEY *tpm_key, TPM_BOOL isEK, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_Key_Store(TPM_STORE_BUFFER *sbuffer, TPM_KEY *tpm_key); TPM_RESULT TPM_Key_StorePubData(TPM_STORE_BUFFER *sbuffer, TPM_BOOL isEK, TPM_KEY *tpm_key); TPM_RESULT TPM_Key_StoreClear(TPM_STORE_BUFFER *sbuffer, TPM_BOOL isEK, TPM_KEY *tpm_key); void TPM_Key_Delete(TPM_KEY *tpm_key); TPM_RESULT TPM_Key_CheckStruct(int *ver, TPM_KEY *tpm_key); TPM_RESULT TPM_Key_Set(TPM_KEY *tpm_key, tpm_state_t *tpm_state, TPM_KEY *parent_key, TPM_DIGEST *tpm_pcrs, int ver, TPM_KEY_USAGE keyUsage, TPM_KEY_FLAGS keyFlags, TPM_AUTH_DATA_USAGE authDataUsage, TPM_KEY_PARMS *tpm_key_parms, TPM_PCR_INFO *tpm_pcr_info, TPM_PCR_INFO_LONG *tpm_pcr_info_long, uint32_t keyLength, BYTE* publicKey, TPM_STORE_ASYMKEY *tpm_store_asymkey, TPM_MIGRATE_ASYMKEY *tpm_migrate_asymkey); TPM_RESULT TPM_Key_Copy(TPM_KEY *tpm_key_dest, TPM_KEY *tpm_key_src, TPM_BOOL copyEncData); TPM_RESULT TPM_Key_LoadStoreAsymKey(TPM_KEY *tpm_key, TPM_BOOL isEK, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_Key_StorePubkey(TPM_STORE_BUFFER *pubkeyStream, const unsigned char **pubkKeyStreamBuffer, uint32_t *pubkeyStreamLength, TPM_KEY *tpm_key); TPM_RESULT TPM_Key_GenerateRSA(TPM_KEY *tpm_key, tpm_state_t *tpm_state, TPM_KEY *parent_key, TPM_DIGEST *tpm_pcrs, int ver, TPM_KEY_USAGE keyUsage, TPM_KEY_FLAGS keyFlags, TPM_AUTH_DATA_USAGE authDataUsage, TPM_KEY_PARMS *tpm_key_parms, TPM_PCR_INFO *tpm_pcr_info, TPM_PCR_INFO_LONG *tpm_pcr_info_long); TPM_RESULT TPM_Key_GeneratePubDataDigest(TPM_KEY *tpm_key); TPM_RESULT TPM_Key_GeneratePubkeyDigest(TPM_DIGEST tpm_digest, TPM_KEY *tpm_key); TPM_RESULT TPM_Key_ComparePubkey(TPM_KEY *tpm_key, TPM_PUBKEY *tpm_pubkey); TPM_RESULT TPM_Key_CheckPubDataDigest(TPM_KEY *tpm_key); TPM_RESULT TPM_Key_GenerateEncData(TPM_KEY *tpm_key, TPM_KEY *parent_key); TPM_RESULT TPM_Key_DecryptEncData(TPM_KEY *tpm_key, TPM_KEY *parent_key); TPM_RESULT TPM_Key_GetStoreAsymkey(TPM_STORE_ASYMKEY **tpm_store_asymkey, TPM_KEY *tpm_key); TPM_RESULT TPM_Key_GetMigrateAsymkey(TPM_MIGRATE_ASYMKEY **tpm_migrate_asymkey, TPM_KEY *tpm_key); TPM_RESULT TPM_Key_GetUsageAuth(TPM_SECRET **usageAuth, TPM_KEY *tpm_key); TPM_RESULT TPM_Key_GetPublicKey(uint32_t *nbytes, unsigned char **narr, TPM_KEY *tpm_key); TPM_RESULT TPM_Key_GetPrimeFactorP(uint32_t *pbytes, unsigned char **parr, TPM_KEY *tpm_key); TPM_RESULT TPM_Key_GetPrivateKey(uint32_t *dbytes, unsigned char **darr, TPM_KEY *tpm_key); TPM_RESULT TPM_Key_GetExponent(uint32_t *ebytes, unsigned char **earr, TPM_KEY *tpm_key); TPM_RESULT TPM_Key_CheckProperties(int *ver, TPM_KEY *tpm_key, uint32_t keyLength, TPM_BOOL FIPS); TPM_RESULT TPM_Key_GetPCRUsage(TPM_BOOL *pcrUsage, TPM_KEY *tpm_key, size_t start_index); TPM_RESULT TPM_Key_GetLocalityAtRelease(TPM_LOCALITY_SELECTION *localityAtRelease, TPM_KEY *tpm_key); TPM_RESULT TPM_Key_CheckPCRDigest(TPM_KEY *tpm_key, tpm_state_t *tpm_state); TPM_RESULT TPM_Key_CheckRestrictDelegate(TPM_KEY *tpm_key, TPM_CMK_DELEGATE restrictDelegate); /* TPM_KEY_FLAGS */ TPM_RESULT TPM_KeyFlags_Load(TPM_KEY_FLAGS *tpm_key_flags, unsigned char **stream, uint32_t *stream_size); /* TPM_KEY_PARMS */ void TPM_KeyParms_Init(TPM_KEY_PARMS *tpm_key_parms); TPM_RESULT TPM_KeyParms_Set(TPM_KEY_PARMS *tpm_key_parms, TPM_ALGORITHM_ID algorithmID, TPM_ENC_SCHEME encScheme, TPM_SIG_SCHEME sigScheme, uint32_t parmSize, BYTE* parms); #if 0 TPM_RESULT TPM_KeyParms_SetRSA(TPM_KEY_PARMS *tpm_key_parms, TPM_ALGORITHM_ID algorithmID, TPM_ENC_SCHEME encScheme, TPM_SIG_SCHEME sigScheme, uint32_t keyLength, TPM_SIZED_BUFFER *exponent); #endif TPM_RESULT TPM_KeyParms_Copy(TPM_KEY_PARMS *tpm_key_parms_dest, TPM_KEY_PARMS *tpm_key_parms_src); TPM_RESULT TPM_KeyParms_Load(TPM_KEY_PARMS *tpm_key_parms, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_KeyParms_Store(TPM_STORE_BUFFER *sbuffer, TPM_KEY_PARMS *tpm_key_parms); void TPM_KeyParms_Delete(TPM_KEY_PARMS *tpm_key_parms); TPM_RESULT TPM_KeyParms_GetRSAKeyParms(TPM_RSA_KEY_PARMS **tpm_rsa_key_parms, TPM_KEY_PARMS *tpm_key_parms); TPM_RESULT TPM_KeyParms_GetExponent(uint32_t *ebytes, unsigned char **earr, TPM_KEY_PARMS *tpm_key_parms); TPM_RESULT TPM_KeyParms_CheckProperties(TPM_KEY_PARMS *tpm_key_parms, TPM_KEY_USAGE tpm_key_usage, uint32_t keyLength, TPM_BOOL FIPS); TPM_RESULT TPM_KeyParams_CheckDefaultExponent(TPM_SIZED_BUFFER *exponent); /* TPM_PUBKEY */ void TPM_Pubkey_Init(TPM_PUBKEY *tpm_pubkey); TPM_RESULT TPM_Pubkey_Load(TPM_PUBKEY *tpm_pubkey, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_Pubkey_Store(TPM_STORE_BUFFER *sbuffer, TPM_PUBKEY *tpm_pubkey); void TPM_Pubkey_Delete(TPM_PUBKEY *tpm_pubkey); TPM_RESULT TPM_Pubkey_Set(TPM_PUBKEY *tpm_pubkey, TPM_KEY *tpm_key); TPM_RESULT TPM_Pubkey_Copy(TPM_PUBKEY *dest_tpm_pubkey, TPM_PUBKEY *src_tpm_pubkey); TPM_RESULT TPM_Pubkey_GetExponent(uint32_t *ebytes, unsigned char **earr, TPM_PUBKEY *tpm_pubkey); TPM_RESULT TPM_Pubkey_GetPublicKey(uint32_t *nbytes, unsigned char **narr, TPM_PUBKEY *tpm_pubkey); /* TPM_KEY_HANDLE_ENTRY */ void TPM_KeyHandleEntry_Init(TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry); TPM_RESULT TPM_KeyHandleEntry_Load(TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_KeyHandleEntry_Store(TPM_STORE_BUFFER *sbuffer, const TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry); void TPM_KeyHandleEntry_Delete(TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry); TPM_RESULT TPM_KeyHandleEntry_FlushSpecific(tpm_state_t *tpm_state, TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry); /* TPM_KEY_HANDLE_ENTRY entries list */ void TPM_KeyHandleEntries_Init(TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries); void TPM_KeyHandleEntries_Delete(TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries); TPM_RESULT TPM_KeyHandleEntries_Load(tpm_state_t *tpm_state, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_KeyHandleEntries_Store(TPM_STORE_BUFFER *sbuffer, tpm_state_t *tpm_state); TPM_RESULT TPM_KeyHandleEntries_StoreHandles(TPM_STORE_BUFFER *sbuffer, const TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries); TPM_RESULT TPM_KeyHandleEntries_DeleteHandle(TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries, TPM_KEY_HANDLE tpm_key_handle); void TPM_KeyHandleEntries_IsSpace(TPM_BOOL *isSpace, uint32_t *index, const TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries); void TPM_KeyHandleEntries_GetSpace(uint32_t *space, const TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries); void TPM_KeyHandleEntries_IsEvictSpace(TPM_BOOL *isSpace, const TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries, uint32_t minSpace); TPM_RESULT TPM_KeyHandleEntries_AddKeyEntry(TPM_KEY_HANDLE *tpm_key_handle, TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries, TPM_KEY *tpm_key, TPM_BOOL parentPCRStatus, TPM_KEY_CONTROL keyControl); TPM_RESULT TPM_KeyHandleEntries_AddEntry(TPM_KEY_HANDLE *tpm_key_handle, TPM_BOOL keepHandle, TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries, TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry); TPM_RESULT TPM_KeyHandleEntries_GetEntry(TPM_KEY_HANDLE_ENTRY **tpm_key_handle_entry, TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries, TPM_KEY_HANDLE tpm_key_handle); TPM_RESULT TPM_KeyHandleEntries_GetKey(TPM_KEY **tpm_key, TPM_BOOL *parentPCRStatus, tpm_state_t *tpm_state, TPM_KEY_HANDLE tpm_key_handle, TPM_BOOL readOnly, TPM_BOOL ignorePCRs, TPM_BOOL allowEK); TPM_RESULT TPM_KeyHandleEntries_SetParentPCRStatus(TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries, TPM_KEY_HANDLE tpm_key_handle, TPM_BOOL parentPCRStatus); TPM_RESULT TPM_KeyHandleEntries_GetNextEntry(TPM_KEY_HANDLE_ENTRY **tpm_key_handle_entry, size_t *current, TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries, size_t start); TPM_RESULT TPM_KeyHandleEntries_OwnerEvictLoad(TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_KeyHandleEntries_OwnerEvictStore(TPM_STORE_BUFFER *sbuffer, const TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries); TPM_RESULT TPM_KeyHandleEntries_OwnerEvictGetCount(uint16_t *count, const TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries); void TPM_KeyHandleEntries_OwnerEvictDelete(TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries); /* TPM_RSA_KEY_PARMS */ void TPM_RSAKeyParms_Init(TPM_RSA_KEY_PARMS *tpm_rsa_key_parms); TPM_RESULT TPM_RSAKeyParms_Load(TPM_RSA_KEY_PARMS *tpm_rsa_key_parms, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_RSAKeyParms_Store(TPM_STORE_BUFFER *sbuffer, const TPM_RSA_KEY_PARMS *tpm_rsa_key_parms); void TPM_RSAKeyParms_Delete(TPM_RSA_KEY_PARMS *tpm_rsa_key_parms); TPM_RESULT TPM_RSAKeyParms_Copy(TPM_RSA_KEY_PARMS *tpm_rsa_key_parms_dest, TPM_RSA_KEY_PARMS *tpm_rsa_key_parms_src); TPM_RESULT TPM_RSAKeyParms_New(TPM_RSA_KEY_PARMS **tpm_rsa_key_parms); TPM_RESULT TPM_RSAKeyParms_GetExponent(uint32_t *ebytes, unsigned char **earr, TPM_RSA_KEY_PARMS *tpm_rsa_key_parms); /* TPM_STORE_ASYMKEY */ void TPM_StoreAsymkey_Init(TPM_STORE_ASYMKEY *tpm_store_asymkey); TPM_RESULT TPM_StoreAsymkey_Load(TPM_STORE_ASYMKEY *tpm_store_asymkey, TPM_BOOL isEK, unsigned char **stream, uint32_t *stream_size, TPM_KEY_PARMS *tpm_key_parms, TPM_SIZED_BUFFER *tpm_store_pubkey); TPM_RESULT TPM_StoreAsymkey_Store(TPM_STORE_BUFFER *sbuffer, TPM_BOOL isEK, const TPM_STORE_ASYMKEY *tpm_store_asymkey); void TPM_StoreAsymkey_Delete(TPM_STORE_ASYMKEY *tpm_store_asymkey); TPM_RESULT TPM_StoreAsymkey_GenerateEncData(TPM_SIZED_BUFFER *encData, TPM_STORE_ASYMKEY *tpm_store_asymkey, TPM_KEY *parent_key); TPM_RESULT TPM_StoreAsymkey_GetPrimeFactorP(uint32_t *pbytes, unsigned char **parr, TPM_STORE_ASYMKEY *tpm_store_asymkey); void TPM_StoreAsymkey_GetO1Size(uint32_t *o1_size, TPM_STORE_ASYMKEY *tpm_store_asymkey); TPM_RESULT TPM_StoreAsymkey_CheckO1Size(uint32_t o1_size, uint32_t k1k2_length); TPM_RESULT TPM_StoreAsymkey_StoreO1(BYTE *o1, uint32_t o1_size, TPM_STORE_ASYMKEY *tpm_store_asymkey, TPM_DIGEST pHash, TPM_PAYLOAD_TYPE payload_type, TPM_SECRET usageAuth); TPM_RESULT TPM_StoreAsymkey_LoadO1(TPM_STORE_ASYMKEY *tpm_store_asymkey, BYTE *o1, uint32_t o1_size); /* TPM_MIGRATE_ASYMKEY */ void TPM_MigrateAsymkey_Init(TPM_MIGRATE_ASYMKEY *tpm_migrate_asymkey); TPM_RESULT TPM_MigrateAsymkey_Load(TPM_MIGRATE_ASYMKEY *tpm_migrate_asymkey, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_MigrateAsymkey_Store(TPM_STORE_BUFFER *sbuffer, const TPM_MIGRATE_ASYMKEY *tpm_migrate_asymkey); void TPM_MigrateAsymkey_Delete(TPM_MIGRATE_ASYMKEY *tpm_migrate_asymkey); /* TPM_STORE_PRIVKEY */ void TPM_StorePrivkey_Init(TPM_STORE_PRIVKEY *tpm_store_privkey); TPM_RESULT TPM_StorePrivkey_Store(TPM_STORE_BUFFER *sbuffer, const TPM_STORE_PRIVKEY *tpm_store_privkey); void TPM_StorePrivkey_Delete(TPM_STORE_PRIVKEY *tpm_store_privkey); TPM_RESULT TPM_StorePrivkey_Convert(TPM_STORE_ASYMKEY *tpm_store_asymkey, TPM_KEY_PARMS *tpm_key_parms, TPM_SIZED_BUFFER *pubKey); /* Command Processing Functions */ TPM_RESULT TPM_Process_ReadPubek(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_CreateRevocableEK(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_CreateEndorsementKeyPair(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_CreateEndorsementKeyPair_Common(TPM_KEY *endorsementKey, TPM_PUBKEY *pubEndorsementKey, TPM_DIGEST checksum, TPM_BOOL *writePermanentData, tpm_state_t *tpm_state, TPM_KEY_PARMS *keyInfo, TPM_NONCE antiReplay); TPM_RESULT TPM_Process_RevokeTrust(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_DisablePubekRead(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_OwnerReadPubek(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_EvictKey(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_OwnerReadInternalPub(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); #endif libtpms-0.9.3/src/tpm12/tpm_libtpms_io.c000066400000000000000000000061621421143571500201240ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Libtpms IO Init */ /* Written by Ken Goldman, Stefan Berger */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_io.c 4564 2011-04-13 19:33:38Z stefanb $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include "tpm_debug.h" #include "tpm_error.h" #include "tpm_platform.h" #include "tpm_types.h" #include "tpm_library_intern.h" /* header for this file */ #include "tpm_io.h" /* TPM_IO_Init initializes the TPM to host interface. This is the Unix platform dependent socket version. */ TPM_RESULT TPM_IO_Init(void) { TPM_RESULT rc = 0; struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks(); /* call user-provided function if available */ if (cbs->tpm_io_init) { rc = cbs->tpm_io_init(); return rc; } else { /* Below code would start a TCP server socket; we don't want this but rather expect all commands via TPMLIB_Process() to be sent to the TPM. */ return TPM_SUCCESS; } } libtpms-0.9.3/src/tpm12/tpm_load.c000066400000000000000000000230431421143571500166770ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Load from Stream Utilities */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_load.c 4668 2012-01-25 21:16:48Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ /* Generally useful utilities to deserialize structures from a stream */ #include #include #include #include "tpm_debug.h" #include "tpm_error.h" #include "tpm_sizedbuffer.h" #include "tpm_types.h" #include "tpm_load.h" /* The LOADn() functions convert a big endian stream to integer types */ uint32_t LOAD32(const unsigned char *buffer, unsigned int offset) { unsigned int i; uint32_t result = 0; for (i = 0 ; i < 4 ; i++) { result <<= 8; result |= buffer[offset + i]; } return result; } uint16_t LOAD16(const unsigned char *buffer, unsigned int offset) { unsigned int i; uint16_t result = 0; for (i = 0 ; i < 2 ; i++) { result <<= 8; result |= buffer[offset + i]; } return result; } uint8_t LOAD8(const unsigned char *buffer, unsigned int offset) { uint8_t result = 0; result |= buffer[offset]; return result; } /* TPM_Load32() loads 'tpm_uint32' from the stream. It checks that the stream has sufficient data, and adjusts 'stream' and 'stream_size' past the data. */ TPM_RESULT TPM_Load32(uint32_t *tpm_uint32, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; /* check stream_size */ if (rc == 0) { if (*stream_size < sizeof(uint32_t)) { printf("TPM_Load32: Error, stream_size %u less than %lu\n", *stream_size, (unsigned long)sizeof(uint32_t)); rc = TPM_BAD_PARAM_SIZE; } } /* load the parameter */ if (rc == 0) { *tpm_uint32 = LOAD32(*stream, 0); *stream += sizeof (uint32_t); *stream_size -= sizeof (uint32_t); } return rc; } /* TPM_Load16() loads 'tpm_uint16' from the stream. It checks that the stream has sufficient data, and adjusts 'stream' and 'stream_size' past the data. */ TPM_RESULT TPM_Load16(uint16_t *tpm_uint16, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; /* check stream_size */ if (rc == 0) { if (*stream_size < sizeof(uint16_t)) { printf("TPM_Load16: Error, stream_size %u less than %lu\n", *stream_size, (unsigned long)sizeof(uint16_t)); rc = TPM_BAD_PARAM_SIZE; } } /* load the parameter */ if (rc == 0) { *tpm_uint16 = LOAD16(*stream, 0); *stream += sizeof (uint16_t); *stream_size -= sizeof (uint16_t); } return rc; } TPM_RESULT TPM_Load8(uint8_t *tpm_uint8, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; /* check stream_size */ if (rc == 0) { if (*stream_size < sizeof(uint8_t)) { printf("TPM_Load8: Error, stream_size %u less than %lu\n", *stream_size, (unsigned long)sizeof(uint8_t)); rc = TPM_BAD_PARAM_SIZE; } } /* load the parameter */ if (rc == 0) { *tpm_uint8 = LOAD8(*stream, 0); *stream += sizeof (uint8_t); *stream_size -= sizeof (uint8_t); } return rc; } /* Boolean incoming parameter values other than 0x00 and 0x01 have an implementation specific interpretation. The TPM SHOULD return TPM_BAD_PARAMETER. */ TPM_RESULT TPM_LoadBool(TPM_BOOL *tpm_bool, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; /* check stream_size */ if (rc == 0) { if (*stream_size < sizeof(TPM_BOOL)) { printf("TPM_LoadBool: Error, stream_size %u less than %lu\n", *stream_size, (unsigned long)sizeof(TPM_BOOL)); rc = TPM_BAD_PARAM_SIZE; } } /* load the parameter */ if (rc == 0) { *tpm_bool = LOAD8(*stream, 0); *stream += sizeof (uint8_t); *stream_size -= sizeof (uint8_t); } if (rc == 0) { if ((*tpm_bool != TRUE) && (*tpm_bool != FALSE)) { printf("TPM_LoadBool: Error, illegal value %02x\n", *tpm_bool); rc = TPM_BAD_PARAMETER; } } return rc; } /* TPM_Loadn() copies 'data_length' bytes from 'stream' to 'data' with no endian adjustments. */ TPM_RESULT TPM_Loadn(BYTE *data, size_t data_length, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; /* check stream_size */ if (rc == 0) { if (*stream_size < data_length) { printf("TPM_Loadn: Error, stream_size %u less than %lu\n", *stream_size, (unsigned long)data_length); rc = TPM_BAD_PARAM_SIZE; } } /* load the parameter */ if (rc == 0) { memcpy(data, *stream, data_length); *stream += data_length; *stream_size -= data_length; } return rc; } /* TPM_LoadLong() creates a long from a stream in network byte order. The stream is not advanced. */ TPM_RESULT TPM_LoadLong(unsigned long *result, const unsigned char *stream, uint32_t stream_size) { TPM_RESULT rc = 0; size_t i; /* byte iterator */ printf(" TPM_LoadLong:\n"); if (rc == 0) { if (stream_size > sizeof(unsigned long)) { printf(" TPM_LoadLong: Error, stream size %u too large\n", stream_size); rc = TPM_BAD_PARAM_SIZE; } } if (rc == 0) { *result = 0; /* initialize all bytes to 0 in case buffer is less than sizeof(unsigned long) bytes */ for (i = 0 ; i < stream_size ; i++) { /* copy big endian stream, put lowest address in an upper byte, highest address in byte 0 */ *result |= (unsigned long)(((unsigned long)stream[i]) << ((stream_size - 1 - i) * 8)); } printf(" TPM_LoadLong: Result %08lx\n", *result); } return rc; } #if 0 /* TPM_LoadString() returns a pointer to a C string. It does not copy the string. */ TPM_RESULT TPM_LoadString(const char **name, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; char *ptr; *name = NULL; /* search for the first nul character */ if (rc == 0) { ptr = memchr(*stream, (int)'\0', *stream_size); if (ptr == NULL) { rc = TPM_BAD_PARAM_SIZE; } } if (rc == 0) { *name = (char *)*stream; /* cast because converting binary to string */ *stream_size -= (ptr - *name) + 1; *stream = (unsigned char *)ptr + 1; } return rc; } #endif /* TPM_CheckTag() loads a TPM_STRUCTURE_TAG from 'stream'. It check that the value is 'expectedTag' and returns TPM_INVALID_STRUCTURE on error. */ TPM_RESULT TPM_CheckTag(TPM_STRUCTURE_TAG expectedTag, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; TPM_STRUCTURE_TAG tag; if (rc == 0) { rc = TPM_Load16(&tag, stream, stream_size); } if (rc == 0) { if (tag != expectedTag) { printf("TPM_CheckTag: Error, tag expected %04x found %04hx\n", expectedTag, tag); rc = TPM_INVALID_STRUCTURE; } } return rc; } libtpms-0.9.3/src/tpm12/tpm_load.h000066400000000000000000000074241421143571500167110ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Load from Stream Utilities */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_load.h 4668 2012-01-25 21:16:48Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_LOAD_H #define TPM_LOAD_H #include "tpm_types.h" TPM_RESULT TPM_Load32(uint32_t *tpm_uint32, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_Load16(uint16_t *tpm_uint16, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_Load8(uint8_t *tpm_uint8, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_Loadn(BYTE *data, size_t data_length, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_LoadBool(TPM_BOOL *tpm_bool, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_LoadLong(unsigned long *result, const unsigned char *stream, uint32_t stream_size); #if 0 TPM_RESULT TPM_LoadString(const char **name, unsigned char **stream, uint32_t *stream_size); #endif TPM_RESULT TPM_CheckTag(TPM_STRUCTURE_TAG expectedTag, unsigned char **stream, uint32_t *stream_size); /* byte stream to type */ uint32_t LOAD32(const unsigned char *buffer, unsigned int offset); uint16_t LOAD16(const unsigned char *buffer, unsigned int offset); uint8_t LOAD8(const unsigned char *buffer, unsigned int offset); #endif libtpms-0.9.3/src/tpm12/tpm_maint.c000066400000000000000000001446721421143571500171040ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Maintenance Handler */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_maint.c 4442 2011-02-14 20:20:01Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #if !defined(TPM_NOMAINTENANCE) && !defined(TPM_NOMAINTENANCE_COMMANDS) #include #include #include "tpm_auth.h" #include "tpm_crypto.h" #include "tpm_cryptoh.h" #include "tpm_debug.h" #include "tpm_digest.h" #include "tpm_error.h" #include "tpm_io.h" #include "tpm_key.h" #include "tpm_memory.h" #include "tpm_nonce.h" #include "tpm_owner.h" #include "tpm_permanent.h" #include "tpm_process.h" #include "tpm_maint.h" /* Processing Functions */ /* 12. Maintenance Functions (optional) The maintenance mechanisms in the TPM MUST not require the TPM to hold a global secret. The definition of global secret is a secret value shared by more than one TPM. The TPME is not allowed to pre-store or use unique identifiers in the TPM for the purpose of maintenance. The TPM MUST NOT use the endorsement key for identification or encryption in the maintenance process. The maintenance process MAY use a TPM Identity to deliver maintenance information to specific TPM's. The maintenance process can only change the SRK, tpmProof and TPM Owner AuthData fields. The maintenance process can only access data in shielded locations where this data is necessary to validate the TPM Owner, validate the TPME and manipulate the blob The TPM MUST be conformant to the TPM specification, protection profiles and security targets after maintenance. The maintenance MAY NOT decrease the security values from the original security target. The security target used to evaluate this TPM MUST include this command in the TOE. */ /* When a maintenance archive is created with generateRandom FALSE, the maintenance blob is XOR encrypted with the owner authorization before encryption with the maintenance public key. This prevents the manufacturer from obtaining plaintext data. The receiving TPM must have the same owner authorization as the sending TPM in order to XOR decrypt the archive. When generateRandom is TRUE, the maintenance blob is XOR encrypted with random data, which is also returned. This permits someone trusted by the Owner to load the maintenance archive into the replacement platform in the absence of the Owner and manufacturer, without the Owner having to reveal information about his auth value. The receiving and sending TPM's may have different owner authorizations. The random data is transferred from the sending TPM owner to the receiving TPM owner out of band, so the maintenance blob remains hidden from the manufacturer. This is a typical maintenance sequence: 1. Manufacturer: - generates maintenance key pair - gives public key to TPM1 owner 2. TPM1: TPM_LoadManuMaintPub - load maintenance public key 3. TPM1: TPM_CreateMaintenanceArchive - XOR encrypt with owner auth or random - encrypt with maintenance public key 4. Manufacturer: - decrypt with maintenance private key - (still XOR encrypted with owner auth or random) - encrypt with TPM2 SRK public key 5. TPM2: TPM_LoadMaintenanceArchive - decrypt with SRK private key - XOR decrypt with owner auth or random */ /* 12.1 TPM_CreateMaintenanceArchive rev 101 This command creates the MaintenanceArchive. It can only be executed by the owner, and may be shut off with the TPM_KillMaintenanceFeature command. */ TPM_RESULT TPM_Process_CreateMaintenanceArchive(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_BOOL generateRandom; /* Use RNG or Owner auth to generate 'random'. */ TPM_AUTHHANDLE authHandle; /* The authorization session handle used for owner authentication. */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization session handle */ TPM_AUTHDATA ownerAuth; /* The authorization session digest for inputs and owner authentication. HMAC key: ownerAuth. */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus = FALSE; /* audit the ordinal */ TPM_BOOL transportEncrypt = FALSE; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_SECRET *hmacKey = NULL; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ uint32_t o1Oaep_size; BYTE *o1Oaep; BYTE *r1InnerWrapKey; BYTE *x1InnerWrap; TPM_KEY a1; /* SRK archive result */ TPM_BOOL writeAllNV = FALSE; /* flag to write back flags */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_SIZED_BUFFER random; /* Random data to XOR with result. */ TPM_STORE_BUFFER archive; /* Encrypted key archive. */ printf("TPM_Process_CreateMaintenanceArchive: Ordinal Entry\n"); TPM_SizedBuffer_Init(&random); /* freed @1 */ TPM_Key_Init(&a1); /* freed @2 */ TPM_Sbuffer_Init(&archive); /* freed @3 */ o1Oaep = NULL; /* freed @4 */ r1InnerWrapKey = NULL; /* freed @5 */ x1InnerWrap = NULL; /* freed @6 */ /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get generateRandom parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_LoadBool(&generateRandom, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag1(tag); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, ownerAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_CreateMaintenanceArchive: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* Upon authorization being confirmed this command does the following: */ /* 1. Validates that the TPM_PERMANENT_FLAGS -> AllowMaintenance is TRUE. If it is FALSE, the TPM SHALL return TPM_DISABLED_CMD and exit this capability. */ if (returnCode == TPM_SUCCESS) { if (!tpm_state->tpm_permanent_flags.allowMaintenance) { printf("TPM_Process_CreateMaintenanceArchive: Error allowMaintenance FALSE\n"); returnCode = TPM_DISABLED_CMD; } } /* 2. Validates the TPM Owner AuthData. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_OWNER, ordinal, NULL, &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ } if (returnCode == TPM_SUCCESS) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* owner HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, ownerAuth); /* Authorization digest for input */ } /* 3. If the value of TPM_PERMANENT_DATA -> ManuMaintPub is zero, the TPM MUST return the error code TPM_KEYNOTFOUND */ if (returnCode == TPM_SUCCESS) { /* since there is no keyUsage, algorithmID seems like a way to check for an empty key */ if (tpm_state->tpm_permanent_data.manuMaintPub.algorithmParms.algorithmID != TPM_ALG_RSA) { printf("TPM_Process_CreateMaintenanceArchive: manuMaintPub key not found\n"); returnCode = TPM_KEYNOTFOUND; } } /* 4. Build a1 a TPM_KEY structure using the SRK. The encData field is not a normal TPM_STORE_ASYMKEY structure but rather a TPM_MIGRATE_ASYMKEY structure built using the following actions. */ if (returnCode == TPM_SUCCESS) { TPM_Key_Copy(&a1, &(tpm_state->tpm_permanent_data.srk), FALSE); /* don't copy encData */ } /* 5. Build a TPM_STORE_PRIVKEY structure from the SRK. This privKey element should be 132 bytes long for a 2K RSA key. */ /* 6. Create k1 and k2 by splitting the privKey element created in step 4 into 2 parts. k1 is the first 20 bytes of privKey, k2 contains the remainder of privKey. */ /* 7. Build m1 by creating and filling in a TPM_MIGRATE_ASYMKEY structure */ /* a. m1 -> usageAuth is set to TPM_PERMANENT_DATA -> tpmProof */ /* b. m1 -> pubDataDigest is set to the digest value of the SRK fields from step 4 */ /* c. m1 -> payload is set to TPM_PT_MAINT */ /* d. m1 -> partPrivKey is set to k2 */ /* 8. Create o1 (which SHALL be 198 bytes for a 2048 bit RSA key) by performing the OAEP encoding of m using OAEP parameters of */ /* a. m = TPM_MIGRATE_ASYMKEY structure (step 7) */ /* b. pHash = TPM_PERMANENT_DATA -> ownerAuth */ /* c. seed = s1 = k1 (step 6) */ if (returnCode == TPM_SUCCESS) { TPM_StoreAsymkey_GetO1Size(&o1Oaep_size, tpm_state->tpm_permanent_data.srk.tpm_store_asymkey); } if (returnCode == TPM_SUCCESS) { returnCode = TPM_Malloc(&o1Oaep, o1Oaep_size); } if (returnCode == TPM_SUCCESS) { returnCode = TPM_Malloc(&r1InnerWrapKey, o1Oaep_size); } if (returnCode == TPM_SUCCESS) { returnCode = TPM_Malloc(&x1InnerWrap, o1Oaep_size); } if (returnCode == TPM_SUCCESS) { returnCode = TPM_StoreAsymkey_StoreO1 (o1Oaep, o1Oaep_size, tpm_state->tpm_permanent_data.srk.tpm_store_asymkey, tpm_state->tpm_permanent_data.ownerAuth, /* pHash */ TPM_PT_MAINT, /* TPM_PAYLOAD_TYPE */ tpm_state->tpm_permanent_data.tpmProof); /* usageAuth */ } if (returnCode == TPM_SUCCESS) { TPM_PrintFour("TPM_Process_CreateMaintenanceArchive: o1 -", o1Oaep); /* 9. If generateRandom = TRUE */ if (generateRandom) { /* a. Create r1 by obtaining values from the TPM RNG. The size of r1 MUST be the same size as o1. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Random(r1InnerWrapKey, o1Oaep_size); } /* Set random parameter to r1 */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_Set(&random, o1Oaep_size, r1InnerWrapKey); } } /* 10. If generateRandom = FALSE */ else { /* a. Create r1 by applying MGF1 to the TPM Owner AuthData. The size of r1 MUST be the same size as o1. */ returnCode = TPM_MGF1(r1InnerWrapKey, /* unsigned char *mask */ o1Oaep_size, /* long len */ tpm_state->tpm_permanent_data.ownerAuth, /* const unsigned char *seed */ TPM_SECRET_SIZE); /* long seedlen */ /* Set randomSize to 0. */ /* NOTE Done by TPM_SizedBuffer_Init() */ } } if (returnCode == TPM_SUCCESS) { TPM_PrintFour("TPM_Process_CreateMaintenanceArchive: r1 -", r1InnerWrapKey); /* 11. Create x1 by XOR of o1 with r1 */ TPM_XOR(x1InnerWrap, o1Oaep, r1InnerWrapKey, o1Oaep_size); TPM_PrintFour("TPM_Process_CreateMaintenanceArchive: x1", x1InnerWrap); /* 12. Encrypt x1 with the manuMaintPub key using the TPM_ES_RSAESOAEP_SHA1_MGF1 encryption scheme. NOTE The check for OAEP is done by TPM_LoadManuMaintPub */ /* 13. Set a1 -> encData to the encryption of x1 */ returnCode = TPM_RSAPublicEncrypt_Pubkey(&(a1.encData), x1InnerWrap, o1Oaep_size, &(tpm_state->tpm_permanent_data.manuMaintPub)); TPM_PrintFour("TPM_Process_CreateMaintenanceArchive: encData", a1.encData.buffer); } /* 14. Set TPM_PERMANENT_FLAGS -> maintenanceDone to TRUE */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CreateMaintenanceArchive: Set maintenanceDone\n"); TPM_SetCapability_Flag(&writeAllNV, /* altered */ &(tpm_state->tpm_permanent_flags.maintenanceDone), /* flag */ TRUE); /* value */ } /* Store the permanent flags back to NVRAM */ returnCode = TPM_PermanentAll_NVStore(tpm_state, writeAllNV, returnCode); /* 15. Return a1 in the archive parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Key_Store(&archive, &a1); } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_CreateMaintenanceArchive: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* return randomSize and random */ returnCode = TPM_SizedBuffer_Store(response, &random); } if (returnCode == TPM_SUCCESS) { /* return archiveSize and archive */ returnCode = TPM_Sbuffer_AppendAsSizedBuffer(response, &archive); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* owner HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ TPM_SizedBuffer_Delete(&random); /* @1 */ TPM_Key_Delete(&a1); /* @2 */ TPM_Sbuffer_Delete(&archive); /* @3 */ free(o1Oaep); /* @4 */ free(r1InnerWrapKey); /* @5 */ free(x1InnerWrap); /* @6 */ return rcf; } /* 12.2 TPM_LoadMaintenanceArchive rev 98 This command loads in a Maintenance archive that has been massaged by the manufacturer to load into another TPM If the maintenance archive was created using the owner authorization for XOR encryption, the current owner authorization must be used for decryption. The owner authorization does not change. If the maintenance archive was created using random data for the XOR encryption, the vendor specific arguments must include the random data. The owner authorization may change. */ TPM_RESULT TPM_Process_LoadMaintenanceArchive(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_SIZED_BUFFER archive; /* Vendor specific arguments, from TPM_CreateMaintenanceArchive */ TPM_AUTHHANDLE authHandle; /* The authorization session handle used for owner authentication. */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization session handle */ TPM_AUTHDATA ownerAuth; /* The authorization session digest for inputs and owner authentication. HMAC key: ownerAuth.*/ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus = FALSE; /* audit the ordinal */ TPM_BOOL transportEncrypt = FALSE; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_SECRET *hmacKey; TPM_SECRET saveKey; /* copy of HMAC key, since key changes */ TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ unsigned char *stream; /* the input archive stream */ uint32_t stream_size; BYTE *x1InnerWrap; uint32_t x1InnerWrap_size; BYTE *r1InnerWrapKey; /* for XOR decryption */ BYTE *o1Oaep; TPM_KEY newSrk; TPM_STORE_ASYMKEY srk_store_asymkey; TPM_STORE_BUFFER asym_sbuffer; TPM_BOOL writeAllNV1 = FALSE; /* flags to write back data */ TPM_BOOL writeAllNV2 = FALSE; /* flags to write back NV */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; /* Vendor specific arguments */ printf("TPM_Process_LoadMaintenanceArchive: Ordinal Entry\n"); TPM_SizedBuffer_Init(&archive); /* freed @1 */ TPM_Key_Init(&newSrk); /* freed @2 */ x1InnerWrap = NULL; /* freed @3 */ r1InnerWrapKey = NULL; /* freed @4 */ o1Oaep = NULL; /* freed @5 */ TPM_StoreAsymkey_Init(&srk_store_asymkey); /* freed @6 */ TPM_Sbuffer_Init(&asym_sbuffer); /* freed @7 */ /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get Vendor specific arguments */ if (returnCode == TPM_SUCCESS) { /* NOTE TPM_CreateMaintenanceArchive sends a TPM_SIZED_BUFFER archive. */ returnCode = TPM_SizedBuffer_Load(&archive, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag1(tag); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, ownerAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_LoadMaintenanceArchive: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* 1. Validate the TPM Owner's AuthData */ /* Upon authorization being confirmed this command does the following: */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_OWNER, ordinal, NULL, &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ } if (returnCode == TPM_SUCCESS) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* owner HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, ownerAuth); /* Authorization digest for input */ } /* 2. Validate that the maintenance information was sent by the TPME. The validation mechanism MUST use a strength of function that is at least the same strength of function as a digital signature performed using a 2048 bit RSA key. */ /* NOTE SRK is 2048 bits minimum */ /* 3. The packet MUST contain m2 as defined in Section 12.1 */ /* The TPM_SIZED_BUFFER archive contains a TPM_KEY with a TPM_MIGRATE_ASYMKEY that will become the new SRK */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_LoadMaintenanceArchive: Deserializing TPM_KEY parameter\n"); stream = archive.buffer; stream_size = archive.size; returnCode = TPM_Key_Load(&newSrk, &stream, &stream_size); } /* decrypt the TPM_KEY -> encData to x1 using the current SRK */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_LoadMaintenanceArchive: Decrypting TPM_KEY -> encData with SRK\n"); returnCode = TPM_RSAPrivateDecryptMalloc(&x1InnerWrap, &x1InnerWrap_size, newSrk.encData.buffer, newSrk.encData.size, &(tpm_state->tpm_permanent_data.srk)); } /* allocate memory for r1 based on x1 XOR encrypted data */ if (returnCode == TPM_SUCCESS) { TPM_PrintFour("TPM_Process_LoadMaintenanceArchive: x1", x1InnerWrap); printf("TPM_Process_LoadMaintenanceArchive: x1 size %u\n", x1InnerWrap_size); returnCode = TPM_Malloc(&r1InnerWrapKey, x1InnerWrap_size); } /* allocate memory for o1 based on x1 XOR encrypted data */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Malloc(&o1Oaep, x1InnerWrap_size); } /* generate the XOR encryption secret from the ownerAuth */ /* NOTE: This does not yet support a supplied random number as the inner wrapper key */ if (returnCode == TPM_SUCCESS) { TPM_MGF1(r1InnerWrapKey, /* unsigned char *mask */ x1InnerWrap_size, /* long len */ tpm_state->tpm_permanent_data.ownerAuth, /* const unsigned char *seed */ TPM_SECRET_SIZE); /* long seedlen */ TPM_PrintFour("TPM_Process_LoadMaintenanceArchive: r1 -", r1InnerWrapKey); /* decrypt x1 to o1 using XOR encryption secret */ printf("TPM_Process_LoadMaintenanceArchive: XOR Decrypting TPM_KEY SRK parameter\n"); TPM_XOR(o1Oaep, x1InnerWrap, r1InnerWrapKey, x1InnerWrap_size); TPM_PrintFour("TPM_Process_LoadMaintenanceArchive: o1 -", o1Oaep); } /* convert o1 to TPM_STORE_ASYMKEY */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_StoreAsymkey_LoadO1(&srk_store_asymkey, o1Oaep, x1InnerWrap_size); } /* TPM1 tpmProof comes in as TPM_STORE_ASYMKEY -> usageAuth */ /* TPM1 ownerAuth comes in as TPM_STORE_ASYMKEY -> migrationAuth (from pHash) */ /* 4. Ensure that only the target TPM can interpret the maintenance packet. The protection mechanism MUST use a strength of function that is at least the same strength of function as a digital signature performed using a 2048 bit RSA key. */ /* 5. Execute the actions of TPM_OwnerClear. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_OwnerClearCommon(tpm_state, FALSE); /* don't erase NVRAM with D bit set */ writeAllNV1 = TRUE; } if (returnCode == TPM_SUCCESS) { /* 6. Process the maintenance information */ /* a. Update the SRK */ /* i. Set the SRK usageAuth to be the same as the TPM source owner's AuthData */ /* NOTE The source srk.usageAuth was lost, as usageAuth is used to transfer the tpmProof */ TPM_Secret_Copy(srk_store_asymkey.usageAuth, srk_store_asymkey.migrationAuth); /* b. Update TPM_PERMANENT_DATA -> tpmProof */ TPM_Secret_Copy(tpm_state->tpm_permanent_data.tpmProof, srk_store_asymkey.usageAuth); /* save a copy of the HMAC key for the response before invalidating */ TPM_Secret_Copy(saveKey, *hmacKey); /* c. Update TPM_PERMANENT_DATA -> ownerAuth */ TPM_Secret_Copy(tpm_state->tpm_permanent_data.ownerAuth, srk_store_asymkey.migrationAuth); /* serialize the TPM_STORE_ASYMKEY object */ returnCode = TPM_StoreAsymkey_Store(&asym_sbuffer, FALSE, &srk_store_asymkey); } /* copy back to the new srk encData (clear text for SRK) */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_SetFromStore(&(newSrk.encData), &asym_sbuffer); } if (returnCode == TPM_SUCCESS) { /* free old SRK resources */ TPM_Key_Delete(&(tpm_state->tpm_permanent_data.srk)); /* Copy new SRK to TPM_PERMANENT_DATA -> srk */ /* This copies the basic TPM_KEY, but not the TPM_STORE_ASYMKEY cache */ returnCode = TPM_Key_Copy(&(tpm_state->tpm_permanent_data.srk), &newSrk, TRUE); /* copy encData */ } /* Recreate the TPM_STORE_ASYMKEY cache */ if (returnCode == TPM_SUCCESS) { stream = newSrk.encData.buffer; stream_size = newSrk.encData.size; returnCode = TPM_Key_LoadStoreAsymKey(&(tpm_state->tpm_permanent_data.srk), FALSE, &stream, &stream_size); } /* 7. Set TPM_PERMANENT_FLAGS -> maintenanceDone to TRUE */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_LoadMaintenanceArchive: Set maintenanceDone\n"); TPM_SetCapability_Flag(&writeAllNV2, /* altered */ &(tpm_state->tpm_permanent_flags.maintenanceDone), /* flag */ TRUE); /* value */ } /* Store the permanent data and flags back to NVRAM */ returnCode = TPM_PermanentAll_NVStore(tpm_state, (TPM_BOOL)(writeAllNV1 || writeAllNV2), returnCode); /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_LoadMaintenanceArchive: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Set(response, saveKey, /* the original owner HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ TPM_SizedBuffer_Delete(&archive); /* @1 */ TPM_Key_Delete(&newSrk); /* @2 */ free(x1InnerWrap); /* @3 */ free(r1InnerWrapKey); /* @4 */ free(o1Oaep); /* @5 */ TPM_StoreAsymkey_Delete(&srk_store_asymkey); /* @6 */ TPM_Sbuffer_Delete(&asym_sbuffer); /* @7 */ return rcf; } /* 12.3 TPM_KillMaintenanceFeature rev 87 The KillMaintencanceFeature is a permanent action that prevents ANYONE from creating a maintenance archive. This action, once taken, is permanent until a new TPM Owner is set. This action is to allow those customers who do not want the maintenance feature to not allow the use of the maintenance feature. At the discretion of the Owner, it should be possible to kill the maintenance feature in such a way that the only way to recover maintainability of the platform would be to wipe out the root keys. This feature is mandatory in any TPM that implements the maintenance feature. */ TPM_RESULT TPM_Process_KillMaintenanceFeature(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_AUTHHANDLE authHandle; /* The authorization session handle used for owner authentication. */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization session handle */ TPM_AUTHDATA ownerAuth; /* The authorization session digest for inputs and owner authentication. HMAC key: ownerAuth.*/ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_SECRET *hmacKey; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ TPM_BOOL writeAllNV = FALSE; /* flag to write back flags */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_KillMaintenanceFeature: Ordinal Entry\n"); /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag1(tag); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, ownerAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_KillMaintenanceFeature: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* 1. Validate the TPM Owner AuthData */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_OWNER, ordinal, NULL, &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ } if (returnCode == TPM_SUCCESS) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* owner HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, ownerAuth); /* Authorization digest for input */ } /* 2. Set the TPM_PERMANENT_FLAGS.allowMaintenance flag to FALSE. */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_KillMaintenanceFeature: Clear allowMaintenance\n"); TPM_SetCapability_Flag(&writeAllNV, /* altered */ &(tpm_state->tpm_permanent_flags.allowMaintenance), /* flag */ FALSE); /* value */ /* Store the permanent flags back to NVRAM */ returnCode = TPM_PermanentAll_NVStore(tpm_state, writeAllNV, returnCode); } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_KillMaintenanceFeature: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* owner HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ return rcf; } /* 12.4 TPM_LoadManuMaintPub rev 96 The LoadManuMaintPub command loads the manufacturer's public key for use in the maintenance process. The command installs ManuMaintPub in PERMANENT data storage inside a TPM. Maintenance enables duplication of non-migratory data in protected storage. There is therefore a security hole if a platform is shipped before the maintenance public key has been installed in a TPM. The command is expected to be used before installation of a TPM Owner or any key in TPM protected storage. It therefore does not use authorization. The pubKey MUST specify an algorithm whose strength is not less than the RSA algorithm with 2048 bit keys. pubKey SHOULD unambiguously identify the entity that will perform the maintenance process with the TPM Owner. TPM_PERMANENT_DATA -> manuMaintPub SHALL exist in a TPM-shielded location, only. If an entity (Platform Entity) does not support the maintenance process but issues a platform credential for a platform containing a TPM that supports the maintenance process, the value of TPM_PERMANENT_DATA -> manuMaintPub MUST be set to zero before the platform leaves the entity's control. */ TPM_RESULT TPM_Process_LoadManuMaintPub(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_NONCE antiReplay; /* AntiReplay and validation nonce */ TPM_PUBKEY pubKey; /* The public key of the manufacturer to be in use for maintenance */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus = FALSE; /* audit the ordinal */ TPM_BOOL transportEncrypt = FALSE; /* wrapped in encrypted transport session */ TPM_STORE_BUFFER pubKeySerial; /* serialization for checksum calculation */ const unsigned char *pubKeyBuffer; uint32_t pubKeyLength; TPM_BOOL writeAllNV = FALSE; /* flag to write back NV */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_DIGEST checksum; /* Digest of pubKey and antiReplay */ printf("TPM_Process_LoadManuMaintPub: Ordinal Entry\n"); TPM_Pubkey_Init(&pubKey); /* freed @1 */ TPM_Sbuffer_Init(&pubKeySerial); /* freed @2 */ /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get antiReplay parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Nonce_Load(antiReplay, &command, ¶mSize); } /* get pubKey parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Pubkey_Load(&pubKey, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_LoadManuMaintPub: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ /* The first valid TPM_LoadManuMaintPub command received by a TPM SHALL */ if (returnCode == TPM_SUCCESS) { if (!tpm_state->tpm_permanent_data.allowLoadMaintPub) { printf("TPM_Process_LoadManuMaintPub: Error, command already run\n"); returnCode = TPM_DISABLED_CMD; } } /* The pubKey MUST specify an algorithm whose strength is not less than the RSA algorithm with 2048 bit keys. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyParms_CheckProperties(&(pubKey.algorithmParms), /* TPM_KEY_PARMS */ TPM_KEY_STORAGE, /* TPM_KEY_USAGE */ 2048, /* required, in bits */ TRUE); /* FIPS */ } /* 1. Store the parameter pubKey as TPM_PERMANENT_DATA -> manuMaintPub. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Pubkey_Copy(&(tpm_state->tpm_permanent_data.manuMaintPub), &pubKey); writeAllNV = TRUE; } /* 2. Set checksum to SHA-1 of (pubkey || antiReplay) */ if (returnCode == TPM_SUCCESS) { /* serialize pubkey */ returnCode = TPM_Pubkey_Store(&pubKeySerial, &pubKey); } if (returnCode == TPM_SUCCESS) { TPM_Sbuffer_Get(&pubKeySerial, &pubKeyBuffer, &pubKeyLength); /* create the checksum */ returnCode = TPM_SHA1(checksum, pubKeyLength, pubKeyBuffer, sizeof(TPM_NONCE), antiReplay, 0, NULL); } /* 4. Subsequent calls to TPM_LoadManuMaintPub SHALL return code TPM_DISABLED_CMD. */ if (returnCode == TPM_SUCCESS) { tpm_state->tpm_permanent_data.allowLoadMaintPub = FALSE; } returnCode = TPM_PermanentAll_NVStore(tpm_state, writeAllNV, returnCode); /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_LoadManuMaintPub: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* 3. Export the checksum */ returnCode = TPM_Digest_Store(response, checksum); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* cleanup */ TPM_Pubkey_Delete(&pubKey); /* @1 */ TPM_Sbuffer_Delete(&pubKeySerial); /* @2 */ return rcf; } /* 12.5 TPM_ReadManuMaintPub rev 99 The ReadManuMaintPub command is used to check whether the manufacturer's public maintenance key in a TPM has the expected value. This may be useful during the manufacture process. The command returns a digest of the installed key, rather than the key itself. This hinders discovery of the maintenance key, which may (or may not) be useful for manufacturer privacy. The command is expected to be used before installation of a TPM Owner or any key in TPM protected storage. It therefore does not use authorization. This command returns the hash of the antiReplay nonce and the previously loaded manufacturer's maintenance public key. */ TPM_RESULT TPM_Process_ReadManuMaintPub(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_NONCE antiReplay; /* AntiReplay and validation nonce */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_STORE_BUFFER pubKeySerial; /* serialization for checksum calculation */ const unsigned char *pubKeyBuffer; uint32_t pubKeyLength; /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_DIGEST checksum; /* Digest of pubKey and antiReplay */ printf("TPM_Process_ReadManuMaintPub: Ordinal Entry\n"); TPM_Sbuffer_Init(&pubKeySerial); /* freed @1 */ /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get antiReplay parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Nonce_Load(antiReplay, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_ReadManuMaintPub: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ /* 1. Create "checksum" by concatenating data to form (TPM_PERMANENT_DATA -> manuMaintPub || antiReplay) and passing the concatenated data through SHA-1. */ if (returnCode == TPM_SUCCESS) { /* serialize pubkey */ returnCode = TPM_Pubkey_Store(&pubKeySerial, &(tpm_state->tpm_permanent_data.manuMaintPub)); } if (returnCode == TPM_SUCCESS) { TPM_Sbuffer_Get(&pubKeySerial, &pubKeyBuffer, &pubKeyLength); /* create the checksum */ returnCode = TPM_SHA1(checksum, pubKeyLength, pubKeyBuffer, sizeof(TPM_NONCE), antiReplay, 0, NULL); } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_ReadManuMaintPub: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* 2. Export the checksum */ returnCode = TPM_Digest_Store(response, checksum); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* cleanup */ TPM_Sbuffer_Delete(&pubKeySerial); /* @1 */ return rcf; } #endif libtpms-0.9.3/src/tpm12/tpm_maint.h000066400000000000000000000115671421143571500171050ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Maintenance Handler */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_maint.h 4071 2010-04-29 19:26:45Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_MAINT_H #define TPM_MAINT_H #include "tpm_types.h" #include "tpm_global.h" /* Processing Functions */ TPM_RESULT TPM_Process_CreateMaintenanceArchive(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_LoadMaintenanceArchive(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_KillMaintenanceFeature(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_LoadManuMaintPub(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_ReadManuMaintPub(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); #endif libtpms-0.9.3/src/tpm12/tpm_migration.c000066400000000000000000004774601421143571500177710ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM Migration */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_migration.c 4526 2011-03-24 21:14:42Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include #include #include #include "tpm_auth.h" #include "tpm_crypto.h" #include "tpm_cryptoh.h" #include "tpm_debug.h" #include "tpm_digest.h" #include "tpm_error.h" #include "tpm_io.h" #include "tpm_key.h" #include "tpm_memory.h" #include "tpm_nonce.h" #include "tpm_permanent.h" #include "tpm_process.h" #include "tpm_secret.h" #include "tpm_migration.h" /* TPM_MIGRATIONKEYAUTH */ /* TPM_Migrationkeyauth_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_Migrationkeyauth_Init(TPM_MIGRATIONKEYAUTH *tpm_migrationkeyauth) { printf(" TPM_Migrationkeyauth_Init:\n"); TPM_Pubkey_Init(&(tpm_migrationkeyauth->migrationKey)); tpm_migrationkeyauth->migrationScheme = 0; TPM_Digest_Init(tpm_migrationkeyauth->digest); return; } /* TPM_Migrationkeyauth_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_Migrationkeyauth_Init() After use, call TPM_Migrationkeyauth_Delete() to free memory */ TPM_RESULT TPM_Migrationkeyauth_Load(TPM_MIGRATIONKEYAUTH *tpm_migrationkeyauth, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_Migrationkeyauth_Load:\n"); /* load migrationKey */ if (rc == 0) { rc = TPM_Pubkey_Load(&(tpm_migrationkeyauth->migrationKey), stream, stream_size); } /* load migrationScheme */ if (rc == 0) { rc = TPM_Load16(&(tpm_migrationkeyauth->migrationScheme), stream, stream_size); } /* load digest */ if (rc == 0) { rc = TPM_Digest_Load(tpm_migrationkeyauth->digest, stream, stream_size); } return rc; } /* TPM_Migrationkeyauth_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_Migrationkeyauth_Store(TPM_STORE_BUFFER *sbuffer, TPM_MIGRATIONKEYAUTH *tpm_migrationkeyauth) { TPM_RESULT rc = 0; printf(" TPM_Migrationkeyauth_Store:\n"); /* store migrationKey */ if (rc == 0) { rc = TPM_Pubkey_Store(sbuffer, &(tpm_migrationkeyauth->migrationKey)); } /* store migrationScheme */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, tpm_migrationkeyauth->migrationScheme); } /* store digest */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_migrationkeyauth->digest); } return rc; } /* TPM_Migrationkeyauth_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_Migrationkeyauth_Init to set members back to default values The object itself is not freed */ void TPM_Migrationkeyauth_Delete(TPM_MIGRATIONKEYAUTH *tpm_migrationkeyauth) { printf(" TPM_Migrationkeyauth_Delete:\n"); if (tpm_migrationkeyauth != NULL) { TPM_Pubkey_Delete(&(tpm_migrationkeyauth->migrationKey)); TPM_Migrationkeyauth_Init(tpm_migrationkeyauth); } return; } /* TPM_MSA_COMPOSITE */ /* TPM_MsaComposite_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_MsaComposite_Init(TPM_MSA_COMPOSITE *tpm_msa_composite) { printf(" TPM_MsaComposite_Init:\n"); tpm_msa_composite->MSAlist = 0; tpm_msa_composite->migAuthDigest = NULL; return; } /* TPM_MsaComposite_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_MsaComposite_Init() After use, call TPM_MsaComposite_Delete() to free memory */ TPM_RESULT TPM_MsaComposite_Load(TPM_MSA_COMPOSITE *tpm_msa_composite, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; uint32_t i; printf(" TPM_MsaComposite_Load:\n"); /* load MSAlist */ if (rc == 0) { rc = TPM_Load32(&(tpm_msa_composite->MSAlist), stream, stream_size); } /* MSAlist MUST be one (1) or greater. */ if (rc == 0) { if (tpm_msa_composite->MSAlist == 0) { printf("TPM_MsaComposite_Load: Error, MSAlist is zero\n"); rc = TPM_INVALID_STRUCTURE; } } /* FIXME add MSAlist limit */ /* allocate memory for the migAuthDigest array */ if (rc == 0) { rc = TPM_Malloc((unsigned char **)&(tpm_msa_composite->migAuthDigest), (tpm_msa_composite->MSAlist) * TPM_DIGEST_SIZE); } /* load migAuthDigest array */ for (i = 0 ; (rc == 0) && (i < tpm_msa_composite->MSAlist) ; i++) { rc = TPM_Digest_Load(tpm_msa_composite->migAuthDigest[i], stream, stream_size); } return rc; } /* TPM_MsaComposite_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_MsaComposite_Store(TPM_STORE_BUFFER *sbuffer, const TPM_MSA_COMPOSITE *tpm_msa_composite) { TPM_RESULT rc = 0; uint32_t i; printf(" TPM_MsaComposite_Store:\n"); /* store MSAlist */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_msa_composite->MSAlist); } /* store migAuthDigest array */ for (i = 0 ; (rc == 0) && (i < tpm_msa_composite->MSAlist) ; i++) { rc = TPM_Digest_Store(sbuffer, tpm_msa_composite->migAuthDigest[i]); } return rc; } /* TPM_MsaComposite_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_MsaComposite_Init to set members back to default values The object itself is not freed */ void TPM_MsaComposite_Delete(TPM_MSA_COMPOSITE *tpm_msa_composite) { printf(" TPM_MsaComposite_Delete:\n"); if (tpm_msa_composite != NULL) { free(tpm_msa_composite->migAuthDigest); TPM_MsaComposite_Init(tpm_msa_composite); } return; } TPM_RESULT TPM_MsaComposite_CheckMigAuthDigest(TPM_DIGEST tpm_digest, /* value to check vs list */ TPM_MSA_COMPOSITE *tpm_msa_composite) { TPM_RESULT rc = 0; uint32_t n; /* count through msaList */ TPM_BOOL match; printf(" TPM_MsaComposite_CheckMigAuthDigest:\n"); for (n = 0 , match = FALSE ; (n < tpm_msa_composite->MSAlist) && !match ; n++) { rc = TPM_Digest_Compare(tpm_digest, tpm_msa_composite->migAuthDigest[n]); if (rc == 0) { match = TRUE; } } if (match) { rc = TPM_SUCCESS; } else { printf("TPM_MsaComposite_CheckMigAuthDigest: Error, no match to msaList\n"); rc = TPM_MA_TICKET_SIGNATURE; } return rc; } /* TPM_MsaComposite_CheckSigTicket() i. Verify that for one of the n=1 to n=(msaList -> MSAlist) values of msaList -> migAuthDigest[n], sigTicket == HMAC (V1) using tpmProof as the secret where V1 is a TPM_CMK_SIGTICKET structure such that: (1) V1 -> verKeyDigest = msaList -> migAuthDigest[n] (2) V1 -> signedData = SHA1[restrictTicket] */ TPM_RESULT TPM_MsaComposite_CheckSigTicket(TPM_DIGEST sigTicket, /* expected HMAC */ TPM_SECRET tpmProof, /* HMAC key */ TPM_MSA_COMPOSITE *tpm_msa_composite, TPM_CMK_SIGTICKET *tpm_cmk_sigticket) { TPM_RESULT rc = 0; uint32_t n; /* count through msaList */ TPM_BOOL match; TPM_STORE_BUFFER sbuffer; const unsigned char *buffer; uint32_t length; printf(" TPM_MsaComposite_CheckSigTicket: TPM_MSA_COMPOSITE length %u\n", tpm_msa_composite->MSAlist); TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ for (n = 0 , match = FALSE ; (rc == 0) && (n < tpm_msa_composite->MSAlist) && !match ; n++) { if (rc == 0) { /* verKeyDigest = msaList -> migAuthDigest[n]. The rest of the structure is initialized by the caller */ TPM_PrintFour(" TPM_MsaComposite_CheckSigTicket: Checking migAuthDigest: ", tpm_msa_composite->migAuthDigest[n]); TPM_Digest_Copy(tpm_cmk_sigticket->verKeyDigest, tpm_msa_composite->migAuthDigest[n]); /* serialize the TPM_CMK_SIGTICKET structure */ TPM_Sbuffer_Clear(&sbuffer); /* reset pointers without free */ rc = TPM_CmkSigticket_Store(&sbuffer, tpm_cmk_sigticket); TPM_Sbuffer_Get(&sbuffer, &buffer, &length); } if (rc == 0) { rc = TPM_HMAC_Check(&match, sigTicket, /* expected */ tpmProof, /* HMAC key*/ length, buffer, /* TPM_CMK_SIGTICKET */ 0, NULL); } } if (rc == 0) { if (!match) { printf("TPM_MsaComposite_CheckSigTicket: Error, no match to msaList\n"); rc = TPM_MA_TICKET_SIGNATURE; } } TPM_Sbuffer_Delete(&sbuffer); /* @1 */ return rc; } /* TPM_CMK_AUTH */ /* TPM_CmkAuth_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_CmkAuth_Init(TPM_CMK_AUTH *tpm_cmk_auth) { printf(" TPM_CmkAuth_Init:\n"); TPM_Digest_Init(tpm_cmk_auth->migrationAuthorityDigest); TPM_Digest_Init(tpm_cmk_auth->destinationKeyDigest); TPM_Digest_Init(tpm_cmk_auth->sourceKeyDigest); return; } /* TPM_CmkAuth_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_CmkAuth_Init() After use, call TPM_CmkAuth_Delete() to free memory */ TPM_RESULT TPM_CmkAuth_Load(TPM_CMK_AUTH *tpm_cmk_auth, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_CmkAuth_Load:\n"); /* load migrationAuthorityDigest */ if (rc == 0) { rc = TPM_Digest_Load(tpm_cmk_auth->migrationAuthorityDigest, stream, stream_size); } /* load destinationKeyDigest */ if (rc == 0) { rc = TPM_Digest_Load(tpm_cmk_auth->destinationKeyDigest, stream, stream_size); } /* load sourceKeyDigest */ if (rc == 0) { rc = TPM_Digest_Load(tpm_cmk_auth->sourceKeyDigest, stream, stream_size); } return rc; } /* TPM_CmkAuth_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_CmkAuth_Store(TPM_STORE_BUFFER *sbuffer, const TPM_CMK_AUTH *tpm_cmk_auth) { TPM_RESULT rc = 0; printf(" TPM_CmkAuth_Store:\n"); /* store migrationAuthorityDigest */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_cmk_auth->migrationAuthorityDigest); } /* store destinationKeyDigest */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_cmk_auth->destinationKeyDigest); } /* store sourceKeyDigest */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_cmk_auth->sourceKeyDigest); } return rc; } /* TPM_CmkAuth_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_CmkAuth_Init to set members back to default values The object itself is not freed */ void TPM_CmkAuth_Delete(TPM_CMK_AUTH *tpm_cmk_auth) { printf(" TPM_CmkAuth_Delete:\n"); if (tpm_cmk_auth != NULL) { TPM_CmkAuth_Init(tpm_cmk_auth); } return; } /* TPM_CMK_MIGAUTH */ /* TPM_CmkMigauth_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_CmkMigauth_Init(TPM_CMK_MIGAUTH *tpm_cmk_migauth) { printf(" TPM_CmkMigauth_Init:\n"); TPM_Digest_Init(tpm_cmk_migauth->msaDigest); TPM_Digest_Init(tpm_cmk_migauth->pubKeyDigest); return; } /* TPM_CmkMigauth_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_CmkMigauth_Init() After use, call TPM_CmkMigauth_Delete() to free memory */ TPM_RESULT TPM_CmkMigauth_Load(TPM_CMK_MIGAUTH *tpm_cmk_migauth, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_CmkMigauth_Load:\n"); /* check tag */ if (rc == 0) { rc = TPM_CheckTag(TPM_TAG_CMK_MIGAUTH, stream, stream_size); } /* load msaDigest */ if (rc == 0) { rc = TPM_Digest_Load(tpm_cmk_migauth->msaDigest , stream, stream_size); } /* load pubKeyDigest */ if (rc == 0) { rc = TPM_Digest_Load(tpm_cmk_migauth->pubKeyDigest , stream, stream_size); } return rc; } /* TPM_CmkMigauth_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_CmkMigauth_Store(TPM_STORE_BUFFER *sbuffer, const TPM_CMK_MIGAUTH *tpm_cmk_migauth) { TPM_RESULT rc = 0; printf(" TPM_CmkMigauth_Store:\n"); /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_CMK_MIGAUTH); } /* store msaDigest */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_cmk_migauth->msaDigest); } /* store pubKeyDigest */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_cmk_migauth->pubKeyDigest); } return rc; } /* TPM_CmkMigauth_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_CmkMigauth_Init to set members back to default values The object itself is not freed */ void TPM_CmkMigauth_Delete(TPM_CMK_MIGAUTH *tpm_cmk_migauth) { printf(" TPM_CmkMigauth_Delete:\n"); if (tpm_cmk_migauth != NULL) { TPM_CmkMigauth_Init(tpm_cmk_migauth); } return; } /* TPM_CmkMigauth_CheckHMAC() checks an HMAC of a TPM_CMK_MIGAUTH object. It serializes the structure and HMAC's the result. The common function cannot be used because 'tpm_hmac' is not part of the structure and cannot be NULL'ed. */ TPM_RESULT TPM_CmkMigauth_CheckHMAC(TPM_BOOL *valid, /* result */ TPM_HMAC tpm_hmac, /* expected */ TPM_SECRET tpm_hmac_key, /* key */ TPM_CMK_MIGAUTH *tpm_cmk_migauth) /* data */ { TPM_RESULT rc = 0; TPM_STORE_BUFFER sbuffer; /* serialized TPM_CMK_MIGAUTH */ printf(" TPM_CmkMigauth_CheckHMAC:\n"); TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ /* Serialize the TPM_CMK_MIGAUTH structure */ if (rc == 0) { rc = TPM_CmkMigauth_Store(&sbuffer, tpm_cmk_migauth); } /* verify the HMAC of the serialized structure */ if (rc == 0) { rc = TPM_HMAC_CheckSbuffer(valid, /* result */ tpm_hmac, /* expected */ tpm_hmac_key, /* key */ &sbuffer); /* data stream */ } TPM_Sbuffer_Delete(&sbuffer); /* @1 */ return rc; } /* TPM_CMK_SIGTICKET */ /* TPM_CmkSigticket_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_CmkSigticket_Init(TPM_CMK_SIGTICKET *tpm_cmk_sigticket) { printf(" TPM_CmkSigticket_Init:\n"); TPM_Digest_Init(tpm_cmk_sigticket->verKeyDigest); TPM_Digest_Init(tpm_cmk_sigticket->signedData); return; } /* TPM_CmkSigticket_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_CmkSigticket_Init() After use, call TPM_CmkSigticket_Delete() to free memory */ TPM_RESULT TPM_CmkSigticket_Load(TPM_CMK_SIGTICKET *tpm_cmk_sigticket, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_CmkSigticket_Load:\n"); /* check tag */ if (rc == 0) { rc = TPM_CheckTag(TPM_TAG_CMK_SIGTICKET, stream, stream_size); } /* load verKeyDigest */ if (rc == 0) { rc = TPM_Digest_Load(tpm_cmk_sigticket->verKeyDigest , stream, stream_size); } /* load signedData */ if (rc == 0) { rc = TPM_Digest_Load(tpm_cmk_sigticket->signedData , stream, stream_size); } return rc; } /* TPM_CmkSigticket_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_CmkSigticket_Store(TPM_STORE_BUFFER *sbuffer, const TPM_CMK_SIGTICKET *tpm_cmk_sigticket) { TPM_RESULT rc = 0; printf(" TPM_CmkSigticket_Store:\n"); /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_CMK_SIGTICKET); } /* store verKeyDigest */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_cmk_sigticket->verKeyDigest); } /* store signedData */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_cmk_sigticket->signedData); } return rc; } /* TPM_CmkSigticket_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_CmkSigticket_Init to set members back to default values The object itself is not freed */ void TPM_CmkSigticket_Delete(TPM_CMK_SIGTICKET *tpm_cmk_sigticket) { printf(" TPM_CmkSigticket_Delete:\n"); if (tpm_cmk_sigticket != NULL) { TPM_CmkSigticket_Init(tpm_cmk_sigticket); } return; } /* TPM_CMK_MA_APPROVAL */ /* TPM_CmkMaApproval_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_CmkMaApproval_Init(TPM_CMK_MA_APPROVAL *tpm_cmk_ma_approval) { printf(" TPM_CmkMaApproval_Init:\n"); TPM_Digest_Init(tpm_cmk_ma_approval->migrationAuthorityDigest); return; } /* TPM_CmkMaApproval_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_CmkMaApproval_Init() After use, call TPM_CmkMaApproval_Delete() to free memory */ TPM_RESULT TPM_CmkMaApproval_Load(TPM_CMK_MA_APPROVAL *tpm_cmk_ma_approval, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_CmkMaApproval_Load:\n"); /* check tag */ if (rc == 0) { rc = TPM_CheckTag(TPM_TAG_CMK_MA_APPROVAL, stream, stream_size); } /* load migrationAuthorityDigest */ if (rc == 0) { rc = TPM_Digest_Load(tpm_cmk_ma_approval->migrationAuthorityDigest, stream, stream_size); } return rc; } /* TPM_CmkMaApproval_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_CmkMaApproval_Store(TPM_STORE_BUFFER *sbuffer, const TPM_CMK_MA_APPROVAL *tpm_cmk_ma_approval) { TPM_RESULT rc = 0; printf(" TPM_CmkMaApproval_Store:\n"); /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_CMK_MA_APPROVAL); } /* store migrationAuthorityDigest */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_cmk_ma_approval->migrationAuthorityDigest); } return rc; } /* TPM_CmkMaApproval_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_CmkMaApproval_Init to set members back to default values The object itself is not freed */ void TPM_CmkMaApproval_Delete(TPM_CMK_MA_APPROVAL *tpm_cmk_ma_approval) { printf(" TPM_CmkMaApproval_Delete:\n"); if (tpm_cmk_ma_approval != NULL) { TPM_CmkMaApproval_Init(tpm_cmk_ma_approval); } return; } /* TPM_CmkMaApproval_CheckHMAC() generates an HMAC of a TPM_CMK_MIGAUTH object It serializes the structure and HMAC's the result.The common function cannot be used because 'tpm_hmac' is not part of the structure and cannot be NULL'ed. */ TPM_RESULT TPM_CmkMaApproval_CheckHMAC(TPM_BOOL *valid, /* result */ TPM_HMAC tpm_hmac, /* expected */ TPM_SECRET tpm_hmac_key, /* key */ TPM_CMK_MA_APPROVAL *tpm_cmk_ma_approval) /* data */ { TPM_RESULT rc = 0; TPM_STORE_BUFFER sbuffer; /* serialized TPM_CMK_MA_APPROVAL */ printf(" TPM_CmkMaApproval_CheckHMAC:\n"); TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ /* Serialize the TPM_CMK_MA_APPROVAL structure */ if (rc == 0) { rc = TPM_CmkMaApproval_Store(&sbuffer, tpm_cmk_ma_approval); } /* verify the HMAC of the serialized structure */ if (rc == 0) { rc = TPM_HMAC_CheckSbuffer(valid, /* result */ tpm_hmac, /* expected */ tpm_hmac_key, /* key */ &sbuffer); /* data stream */ } TPM_Sbuffer_Delete(&sbuffer); /* @1 */ return rc; } /* Processing functions */ /* TPM_CreateBlobCommon() does the steps common to TPM_CreateMigrationBlob and TPM_CMK_CreateBlob It takes a TPM_STORE_ASYMKEY, and - splits the TPM_STORE_PRIVKEY into k1 (20) and k2 (112) - builds a TPM_MIGRATE_ASYMKEY using 'payload_type' TPM_STORE_ASYMKEY usageAuth, pubDataDigest k2 as partPrivKey - serializes the TPM_MIGRATE_ASYMKEY - OAEP encode using 'phash' k1 as seed */ TPM_RESULT TPM_CreateBlobCommon(TPM_SIZED_BUFFER *outData, /* The modified, encrypted entity. */ TPM_STORE_ASYMKEY *d1AsymKey, TPM_DIGEST pHash, /* for OAEP padding */ TPM_PAYLOAD_TYPE payload_type, TPM_SIZED_BUFFER *random, /* String used for xor encryption */ TPM_PUBKEY *migrationKey) /* public key of the migration facility */ { TPM_RESULT rc = 0; uint32_t o1_size; BYTE *o1; BYTE *r1; BYTE *x1; printf("TPM_CreateBlobCommon:\n"); o1 = NULL; /* freed @1 */ r1 = NULL; /* freed @2 */ x1 = NULL; /* freed @3 */ if (rc == 0) { TPM_StoreAsymkey_GetO1Size(&o1_size, d1AsymKey); } if (rc == 0) { rc = TPM_Malloc(&o1, o1_size); } if (rc == 0) { rc = TPM_Malloc(&r1, o1_size); } if (rc == 0) { rc = TPM_Malloc(&x1, o1_size); } if (rc == 0) { rc = TPM_StoreAsymkey_StoreO1(o1, o1_size, d1AsymKey, pHash, payload_type, d1AsymKey->usageAuth); } /* NOTE Comments from TPM_CreateMigrationBlob rev 81 */ /* d. Create r1 a random value from the TPM RNG. The size of r1 MUST be the size of o1. Return r1 in the Random parameter. */ if (rc == 0) { rc = TPM_Random(r1, o1_size); } /* e. Create x1 by XOR of o1 with r1 */ if (rc == 0) { TPM_PrintFourLimit("TPM_CreateBlobCommon: r1 -", r1, o1_size); TPM_XOR(x1, o1, r1, o1_size); TPM_PrintFourLimit("TPM_CreateBlobCommon: x1 -", x1, o1_size); /* f. Copy r1 into the output field "random".*/ rc = TPM_SizedBuffer_Set(random, o1_size, r1); } /* g. Encrypt x1 with the migration public key included in migrationKeyAuth. */ if (rc == 0) { rc = TPM_RSAPublicEncrypt_Pubkey(outData, x1, o1_size, migrationKey); TPM_PrintFour("TPM_CreateBlobCommon: outData", outData->buffer); } free(o1); /* @1 */ free(r1); /* @2 */ free(x1); /* @3 */ return rc; } /* 11.1 TPM_CreateMigrationBlob rev 109 The TPM_CreateMigrationBlob command implements the first step in the process of moving a migratable key to a new parent or platform. Execution of this command requires knowledge of the migrationAuth field of the key to be migrated. Migrate mode is generally used to migrate keys from one TPM to another for backup, upgrade or to clone a key on another platform. To do this, the TPM needs to create a data blob that another TPM can deal with. This is done by loading in a backup public key that will be used by the TPM to create a new data blob for a migratable key. The TPM Owner does the selection and authorization of migration public keys at any time prior to the execution of TPM_CreateMigrationBlob by performing the TPM_AuthorizeMigrationKey command. IReWrap mode is used to directly move the key to a new parent (either on this platform or another). The TPM simply re-encrypts the key using a new parent, and outputs a normal encrypted element that can be subsequently used by a TPM_LoadKey command. TPM_CreateMigrationBlob implicitly cannot be used to migrate a non-migratory key. No explicit check is required. Only the TPM knows tpmProof. Therefore it is impossible for the caller to submit an authorization value equal to tpmProof and migrate a non-migratory key. */ TPM_RESULT TPM_Process_CreateMigrationBlob(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_KEY_HANDLE parentHandle; /* Handle of the parent key that can decrypt encData. */ TPM_MIGRATE_SCHEME migrationType; /* The migration type, either MIGRATE or REWRAP */ TPM_MIGRATIONKEYAUTH migrationKeyAuth; /* Migration public key and its authorization digest. */ TPM_SIZED_BUFFER encData; /* The encrypted entity that is to be modified. */ TPM_AUTHHANDLE parentAuthHandle; /* The authorization handle used for the parent key. */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with parentAuthHandle */ TPM_BOOL continueAuthSession; /* Continue use flag for parent session */ TPM_AUTHDATA parentAuth; /* Authorization HMAC key: parentKey.usageAuth. */ TPM_AUTHHANDLE entityAuthHandle; /* The authorization handle used for the encrypted entity. */ TPM_NONCE entitynonceOdd; /* Nonce generated by system associated with entityAuthHandle */ TPM_BOOL continueEntitySession = TRUE; /* Continue use flag for entity session */ TPM_AUTHDATA entityAuth; /* Authorization HMAC key: entity.migrationAuth. */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL parentAuthHandleValid = FALSE; TPM_BOOL entityAuthHandleValid = FALSE; TPM_AUTH_SESSION_DATA *parent_auth_session_data = NULL; /* session data for parentAuthHandle */ TPM_AUTH_SESSION_DATA *entity_auth_session_data = NULL; /* session data for entityAuthHandle */ TPM_SECRET *hmacKey; TPM_SECRET *entityHmacKey; TPM_KEY *parentKey; TPM_BOOL parentPCRStatus; TPM_SECRET *parentUsageAuth; unsigned char *d1Decrypt; /* decryption of encData */ uint32_t d1DecryptLength = 0; /* actual valid data */ unsigned char *stream; /* for deserializing decrypted encData */ uint32_t stream_size; TPM_STORE_ASYMKEY d1AsymKey; /* structure from decrypted encData */ TPM_STORE_BUFFER mka_sbuffer; /* serialized migrationKeyAuth */ const unsigned char *mka_buffer; uint32_t mka_length; /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_SIZED_BUFFER random; /* String used for xor encryption */ TPM_SIZED_BUFFER outData; /* The modified, encrypted entity. */ printf("TPM_Process_CreateMigrationBlob: Ordinal Entry\n"); TPM_Migrationkeyauth_Init(&migrationKeyAuth); /* freed @1 */ TPM_SizedBuffer_Init(&encData); /* freed @2 */ TPM_SizedBuffer_Init(&random); /* freed @3 */ TPM_SizedBuffer_Init(&outData); /* freed @4 */ d1Decrypt = NULL; /* freed @5 */ TPM_StoreAsymkey_Init(&d1AsymKey); /* freed @6 */ TPM_Sbuffer_Init(&mka_sbuffer); /* freed @7 */ /* get inputs */ /* get parentHandle */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&parentHandle, &command, ¶mSize); } /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get migrationType */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CreateMigrationBlob: parentHandle %08x\n", parentHandle); returnCode = TPM_Load16(&migrationType, &command, ¶mSize); } /* get migrationKeyAuth */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Migrationkeyauth_Load(&migrationKeyAuth, &command, ¶mSize); } /* get encData */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_Load(&encData, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag21(tag); } /* get the optional 'below the line' authorization parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { returnCode = TPM_AuthParams_Get(&parentAuthHandle, &parentAuthHandleValid, nonceOdd, &continueAuthSession, parentAuth, &command, ¶mSize); } if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { printf("TPM_Process_CreateMigrationBlob: parentAuthHandle %08x\n", parentAuthHandle); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Get(&entityAuthHandle, &entityAuthHandleValid, entitynonceOdd, &continueEntitySession, entityAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CreateMigrationBlob: entityAuthHandle %08x\n", entityAuthHandle); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_CreateMigrationBlob: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { parentAuthHandleValid = FALSE; entityAuthHandleValid = FALSE; } /* Processing */ /* The TPM does not check the PCR values when migrating values locked to a PCR. */ /* get the key associated with parentHandle */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyHandleEntries_GetKey(&parentKey, &parentPCRStatus, tpm_state, parentHandle, FALSE, /* read-only, do not check PCR's */ FALSE, /* do not ignore PCRs */ FALSE); /* cannot use EK */ } /* get parentHandle -> usageAuth */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { returnCode = TPM_Key_GetUsageAuth(&parentUsageAuth, parentKey); } /* get the session data */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { returnCode = TPM_AuthSessions_GetData(&parent_auth_session_data, &hmacKey, tpm_state, parentAuthHandle, TPM_PID_NONE, TPM_ET_KEYHANDLE, ordinal, parentKey, parentUsageAuth, /* OIAP */ parentKey->tpm_store_asymkey->pubDataDigest); /*OSAP*/ } /* 1. Validate that parentAuth authorizes the use of the key pointed to by parentHandle. */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* HMAC key */ inParamDigest, parent_auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, parentAuth); /* Authorization digest for input */ } /* if there is no parent authorization, check that the parent authDataUsage is TPM_AUTH_NEVER */ if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_AUTH2_COMMAND)) { if (parentKey->authDataUsage != TPM_AUTH_NEVER) { printf("TPM_Process_CreateMigrationBlob: Error, parent key authorization required\n"); returnCode = TPM_AUTHFAIL; } } /* 2. Validate that parentHandle -> keyUsage is TPM_KEY_STORAGE, if not return TPM_INVALID_KEYUSAGE */ if (returnCode == TPM_SUCCESS) { if (parentKey->keyUsage != TPM_KEY_STORAGE) { printf("TPM_Process_CreateMigrationBlob: Error, keyUsage %04hx is invalid\n", parentKey->keyUsage); returnCode = TPM_INVALID_KEYUSAGE; } } /* 3. Create d1 a TPM_STORE_ASYMKEY structure by decrypting encData using the key pointed to by parentHandle. */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CreateMigrationBlob: Decrypting encData\n"); /* decrypt with the parent key to a stream */ returnCode = TPM_RSAPrivateDecryptMalloc(&d1Decrypt, /* decrypted data */ &d1DecryptLength, /* actual size of d1 data */ encData.buffer,/* encrypted data */ encData.size, /* encrypted data size */ parentKey); } /* deserialize the stream to a TPM_STORE_ASYMKEY d1AsymKey */ if (returnCode == TPM_SUCCESS) { stream = d1Decrypt; stream_size = d1DecryptLength; returnCode = TPM_StoreAsymkey_Load(&d1AsymKey, FALSE, &stream, &stream_size, NULL, /* TPM_KEY_PARMS */ NULL); /* TPM_SIZED_BUFFER pubKey */ } /* a. Verify that d1 -> payload is TPM_PT_ASYM. */ if (returnCode == TPM_SUCCESS) { if (d1AsymKey.payload != TPM_PT_ASYM) { printf("TPM_Process_CreateMigrationBlob: Error, bad payload %02x\n", d1AsymKey.payload); returnCode = TPM_BAD_MIGRATION; } } /* 4. Validate that entityAuth authorizes the migration of d1. The validation MUST use d1 -> migrationAuth as the secret. */ /* get the second session data */ /* The second authorisation session (using entityAuth) MUST be OIAP because OSAP does not have a suitable entityType */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetData(&entity_auth_session_data, &entityHmacKey, tpm_state, entityAuthHandle, TPM_PID_OIAP, TPM_ET_KEYHANDLE, ordinal, NULL, &(d1AsymKey.migrationAuth), NULL); } if (returnCode == TPM_SUCCESS) { returnCode = TPM_Auth2data_Check(tpm_state, *entityHmacKey, /* HMAC key */ inParamDigest, entity_auth_session_data, /* authorization session */ entitynonceOdd, /* Nonce generated by system associated with authHandle */ continueEntitySession, entityAuth); /* Authorization digest for input */ } /* 5. Validate that migrationKeyAuth -> digest is the SHA-1 hash of (migrationKeyAuth -> migrationKey || migrationKeyAuth -> migrationScheme || TPM_PERMANENT_DATA -> tpmProof). */ /* first serialize the TPM_PUBKEY migrationKeyAuth -> migrationKey */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CreateMigrationBlob: Verifying migrationKeyAuth\n"); returnCode = TPM_Pubkey_Store(&mka_sbuffer, &(migrationKeyAuth.migrationKey)); } if (returnCode == TPM_SUCCESS) { /* get the serialization result */ TPM_Sbuffer_Get(&mka_sbuffer, &mka_buffer, &mka_length); /* compare to migrationKeyAuth -> digest */ returnCode = TPM_SHA1_Check(migrationKeyAuth.digest, mka_length, mka_buffer, /* serialized migrationKey */ sizeof(TPM_MIGRATE_SCHEME), &(migrationKeyAuth.migrationScheme), TPM_SECRET_SIZE, tpm_state->tpm_permanent_data.tpmProof, 0, NULL); } /* 6. If migrationType == TPM_MS_MIGRATE the TPM SHALL perform the following actions: */ if ((returnCode == TPM_SUCCESS) && (migrationType == TPM_MS_MIGRATE)) { printf("TPM_Process_CreateMigrationBlob: migrationType TPM_MS_MIGRATE\n"); /* a. Build two byte arrays, K1 and K2: */ /* i. K1 = d1.privKey[0..19] (d1.privKey.keyLength + 16 bytes of d1.privKey.key), sizeof(K1) = 20 */ /* ii. K2 = d1.privKey[20..131] (position 16-127 of TPM_STORE_ASYMKEY. privKey.key) (position 16-127 of d1 . privKey.key), sizeof(K2) = 112 */ /* b. Build M1 a TPM_MIGRATE_ASYMKEY structure */ /* i. TPM_MIGRATE_ASYMKEY.payload = TPM_PT_MIGRATE */ /* ii. TPM_MIGRATE_ASYMKEY.usageAuth = d1.usageAuth */ /* iii. TPM_MIGRATE_ASYMKEY.pubDataDigest = d1.pubDataDigest */ /* iv. TPM_MIGRATE_ASYMKEY.partPrivKeyLen = 112 - 127. */ /* v. TPM_MIGRATE_ASYMKEY.partPrivKey = K2 */ /* c. Create o1 (which SHALL be 198 bytes for a 2048 bit RSA key) by performing the OAEP encoding of m using OAEP parameters of */ /* i. m = M1 the TPM_MIGRATE_ASYMKEY structure */ /* ii. pHash = d1->migrationAuth */ /* iii. seed = s1 = K1 */ /* d. Create r1 a random value from the TPM RNG. The size of r1 MUST be the size of o1. Return r1 in the Random parameter. */ /* e. Create x1 by XOR of o1 with r1*/ /* f. Copy r1 into the output field "random".*/ /* g. Encrypt x1 with the migration public key included in migrationKeyAuth.*/ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CreateBlobCommon(&outData, /* output */ &d1AsymKey, /* TPM_STORE_ASYMKEY */ d1AsymKey.migrationAuth, /* pHash */ TPM_PT_MIGRATE, /* payload type */ &random, /* string for XOR encryption */ &(migrationKeyAuth.migrationKey)); /* TPM_PUBKEY */ } } /* 7. If migrationType == TPM_MS_REWRAP the TPM SHALL perform the following actions: */ else if ((returnCode == TPM_SUCCESS) && (migrationType == TPM_MS_REWRAP)) { printf("TPM_Process_CreateMigrationBlob: migrationType TPM_MS_REWRAP\n"); /* a. Rewrap the key using the public key in migrationKeyAuth, keeping the existing contents of that key. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_RSAPublicEncrypt_Pubkey(&outData, d1Decrypt, /* decrypted encData parameter */ d1DecryptLength, &(migrationKeyAuth.migrationKey)); } /* b. Set randomSize to 0 in the output parameter array */ /* NOTE Done by TPM_SizedBuffer_Init() */ } /* 8. Else */ /* a. Return TPM_BAD_PARAMETER */ else if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CreateMigrationBlob: Error, illegal migrationType %04hx\n", migrationType); returnCode = TPM_BAD_PARAMETER; } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_CreateMigrationBlob: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* return random */ returnCode = TPM_SizedBuffer_Store(response, &random); } if (returnCode == TPM_SUCCESS) { /* return outData */ returnCode = TPM_SizedBuffer_Store(response, &outData); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* HMAC key */ parent_auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* calculate and set the below the line parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Set(response, *entityHmacKey, /* HMAC key */ entity_auth_session_data, outParamDigest, entitynonceOdd, continueEntitySession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && parentAuthHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, parentAuthHandle); } if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueEntitySession) && entityAuthHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, entityAuthHandle); } /* cleanup */ TPM_Migrationkeyauth_Delete(&migrationKeyAuth); /* @1 */ TPM_SizedBuffer_Delete(&encData); /* @2 */ TPM_SizedBuffer_Delete(&random); /* @3 */ TPM_SizedBuffer_Delete(&outData); /* @4 */ free(d1Decrypt); /* @5 */ TPM_StoreAsymkey_Delete(&d1AsymKey); /* @6 */ TPM_Sbuffer_Delete(&mka_sbuffer); /* @7 */ return rcf; } /* 11.2 TPM_ConvertMigrationBlob rev 87 This command takes a migration blob and creates a normal wrapped blob. The migrated blob must be loaded into the TPM using the normal TPM_LoadKey function. Note that the command migrates private keys, only. The migration of the associated public keys is not specified by TPM because they are not security sensitive. Migration of the associated public keys may be specified in a platform specific specification. A TPM_KEY structure must be recreated before the migrated key can be used by the target TPM in a LoadKey command. */ /* The relationship between Create and Convert parameters are: Create: k1 || k2 = privKey m = TPM_MIGRATE_ASYMKEY, partPrivKey = k2 o1 = OAEP (m), seed = k1 x1 = o1 ^ r1 out = pub (x1) Convert: d1 = priv (in) o1 = d1 ^ r1 m1, seed = OAEP (o1) k1 = seed || partPrivKey */ TPM_RESULT TPM_Process_ConvertMigrationBlob(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_KEY_HANDLE parentHandle; /* Handle of a loaded key that can decrypt keys. */ TPM_SIZED_BUFFER inData; /* The XOR'd and encrypted key */ TPM_SIZED_BUFFER random; /* Random value used to hide key data. */ TPM_AUTHHANDLE authHandle; /* The authorization handle used for keyHandle. */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization handle */ TPM_AUTHDATA parentAuth; /* The authorization digest that authorizes the inputs and the migration of the key in parentHandle. HMAC key: parentKey.usageAuth */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_SECRET *hmacKey; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ TPM_KEY *parentKey = NULL; /* the key specified by parentHandle */ TPM_BOOL parentPCRStatus; TPM_SECRET *parentUsageAuth; unsigned char *d1Decrypt; uint32_t d1DecryptLength = 0; /* actual valid data */ BYTE *o1Oaep; TPM_STORE_ASYMKEY d2AsymKey; TPM_STORE_BUFFER d2_sbuffer; /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_SIZED_BUFFER outData; /* The encrypted private key that can be loaded with TPM_LoadKey */ printf("TPM_Process_ConvertMigrationBlob: Ordinal Entry\n"); TPM_SizedBuffer_Init(&inData); /* freed @1 */ TPM_SizedBuffer_Init(&random); /* freed @2 */ TPM_SizedBuffer_Init(&outData); /* freed @3 */ d1Decrypt = NULL; /* freed @4 */ o1Oaep = NULL; /* freed @5 */ TPM_StoreAsymkey_Init(&d2AsymKey); /* freed @6 */ TPM_Sbuffer_Init(&d2_sbuffer); /* freed @7 */ /* get inputs */ /* get parentHandle */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&parentHandle, &command, ¶mSize); } /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get inData */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_ConvertMigrationBlob: parentHandle %08x\n", parentHandle); returnCode = TPM_SizedBuffer_Load(&inData, &command, ¶mSize); } /* get random */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_Load(&random, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag10(tag); } /* get the optional 'below the line' authorization parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, parentAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_ConvertMigrationBlob: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* Verify that parentHandle points to a valid key. Get the TPM_KEY associated with parentHandle */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyHandleEntries_GetKey(&parentKey, &parentPCRStatus, tpm_state, parentHandle, FALSE, /* not r/o, using to decrypt */ FALSE, /* do not ignore PCRs */ FALSE); /* cannot use EK */ } /* check TPM_AUTH_DATA_USAGE authDataUsage */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)) { if (parentKey->authDataUsage != TPM_AUTH_NEVER) { printf("TPM_Process_ConvertMigrationBlob: Error, parent key authorization required\n"); returnCode = TPM_AUTHFAIL; } } /* get parentHandle -> usageAuth */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_Key_GetUsageAuth(&parentUsageAuth, parentKey); } /* get the session data */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_KEYHANDLE, ordinal, parentKey, parentUsageAuth, /* OIAP */ parentKey->tpm_store_asymkey->pubDataDigest); /*OSAP*/ } /* 1. Validate the authorization to use the key in parentHandle */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, parentAuth); /* Authorization digest for input */ } /* 2. If the keyUsage field of the key referenced by parentHandle does not have the value TPM_KEY_STORAGE, the TPM must return the error code TPM_INVALID_KEYUSAGE */ if (returnCode == TPM_SUCCESS) { if (parentKey->keyUsage != TPM_KEY_STORAGE) { printf("TPM_Process_ConvertMigrationBlob: Error, " "parentHandle -> keyUsage should be TPM_KEY_STORAGE, is %04x\n", parentKey->keyUsage); returnCode = TPM_INVALID_KEYUSAGE; } } /* 3. Create d1 by decrypting the inData area using the key in parentHandle */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_ConvertMigrationBlob: Decrypting inData\n"); TPM_PrintFourLimit("TPM_Process_ConvertMigrationBlob: inData", inData.buffer, inData.size); returnCode = TPM_RSAPrivateDecryptMalloc(&d1Decrypt, /* decrypted data */ &d1DecryptLength, /* actual size of d1 data */ inData.buffer, /* encrypted data */ inData.size, parentKey); } /* the random input parameter must be the same length as the decrypted data */ if (returnCode == TPM_SUCCESS) { if (d1DecryptLength != random.size) { printf("TPM_Process_ConvertMigrationBlob: Error " "decrypt data length %u random size %u\n", d1DecryptLength, random.size); returnCode = TPM_BAD_PARAMETER; } } /* allocate memory for o1 */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Malloc(&o1Oaep, d1DecryptLength); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_ConvertMigrationBlob: d1 length %u\n", d1DecryptLength); TPM_PrintFourLimit("TPM_Process_ConvertMigrationBlob: d1 -", d1Decrypt, d1DecryptLength); /* 4. Create o1 by XOR d1 and random parameter */ TPM_XOR(o1Oaep, d1Decrypt, random.buffer, d1DecryptLength); /* 5. Create m1 a TPM_MIGRATE_ASYMKEY structure, seed and pHash by OAEP decoding o1 */ /* NOTE TPM_StoreAsymkey_LoadO1() extracts TPM_STORE_ASYMKEY from the OAEP encoded TPM_MIGRATE_ASYMKEY. */ returnCode = TPM_StoreAsymkey_LoadO1(&d2AsymKey, o1Oaep, d1DecryptLength); } /* 6. Create k1 by combining seed and the TPM_MIGRATE_ASYMKEY -> partPrivKey field */ /* NOTE Done by TPM_StoreAsymkey_LoadO1 () */ /* 7. Create d2 a TPM_STORE_ASYMKEY structure */ if (returnCode == TPM_SUCCESS) { /* a. Verify that m1 -> payload == TPM_PT_MIGRATE */ /* NOTE TPM_StoreAsymkey_LoadO1() copied TPM_MIGRATE_ASYMKEY -> payload to TPM_STORE_ASYMKEY -> payload */ if (d2AsymKey.payload != TPM_PT_MIGRATE) { printf("TPM_Process_ConvertMigrationBlob: Error, invalid payload %02x\n", d2AsymKey.payload); returnCode = TPM_BAD_MIGRATION; } } if (returnCode == TPM_SUCCESS) { /* b. Set d2 -> payload = TPM_PT_ASYM */ d2AsymKey.payload = TPM_PT_ASYM; /* c. Set d2 -> usageAuth to m1 -> usageAuth */ /* d. Set d2 -> migrationAuth to pHash */ /* e. Set d2 -> pubDataDigest to m1 -> pubDataDigest */ /* f. Set d2 -> privKey field to k1 */ /* NOTE Done by TPM_StoreAsymkey_LoadO1() */ /* 9. Create outData using the key in parentHandle to perform the encryption */ /* serialize d2key to d2 */ returnCode = TPM_StoreAsymkey_Store(&d2_sbuffer, FALSE, &d2AsymKey); } /* encrypt d2 with parentKey */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_RSAPublicEncryptSbuffer_Key(&outData, &d2_sbuffer, parentKey); } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_ConvertMigrationBlob: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* return the outData */ returnCode = TPM_SizedBuffer_Store(response, &outData); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ TPM_SizedBuffer_Delete(&inData); /* @1 */ TPM_SizedBuffer_Delete(&random); /* @2 */ TPM_SizedBuffer_Delete(&outData); /* @3 */ free(d1Decrypt); /* @4 */ free(o1Oaep); /* @5 */ TPM_StoreAsymkey_Delete(&d2AsymKey); /* @6 */ TPM_Sbuffer_Delete(&d2_sbuffer); /* @7 */ return rcf; } /* 11.3 TPM_AuthorizeMigrationKey rev 114 This command creates an authorization blob, to allow the TPM owner to specify which migration facility they will use and allow users to migrate information without further involvement with the TPM owner. It is the responsibility of the TPM Owner to determine whether migrationKey is appropriate for migration. The TPM checks just the cryptographic strength of migrationKey. */ TPM_RESULT TPM_Process_AuthorizeMigrationKey(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_MIGRATE_SCHEME migrationScheme; /* Type of migration operation that is to be permitted for this key. */ TPM_PUBKEY migrationKey; /* The public key to be authorized. */ TPM_AUTHHANDLE authHandle; /* The authorization handle used for owner authorization. */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization handle */ TPM_AUTHDATA ownerAuth; /* The authorization digest for inputs and owner authorization. HMAC key: ownerAuth. */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_SECRET *hmacKey; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ TPM_RSA_KEY_PARMS *rsa_key_parms; /* for migrationKey */ TPM_STORE_BUFFER sbuffer; const unsigned char *buffer; uint32_t length; /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_MIGRATIONKEYAUTH outData; /* (f1) Returned public key and authorization digest. */ printf("TPM_Process_AuthorizeMigrationKey: Ordinal Entry\n"); TPM_Pubkey_Init(&migrationKey); /* freed @1 */ TPM_Migrationkeyauth_Init(&outData); /* freed @2 */ TPM_Sbuffer_Init(&sbuffer); /* freed @3 */ /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get migrationScheme */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load16(&migrationScheme, &command, ¶mSize); } /* get migrationKey */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Pubkey_Load(&migrationKey, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag1(tag); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, ownerAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_AuthorizeMigrationKey: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* 1. Check that the cryptographic strength of migrationKey is at least that of a 2048 bit RSA key. If migrationKey is an RSA key, this means that migrationKey MUST be 2048 bits or greater and MUST use the default exponent. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyParms_GetRSAKeyParms(&rsa_key_parms, &(migrationKey.algorithmParms)); } if (returnCode == TPM_SUCCESS) { if (rsa_key_parms->keyLength < 2048) { printf("TPM_Process_AuthorizeMigrationKey: Error, " "migrationKey length %u less than 2048\n", rsa_key_parms->keyLength); returnCode = TPM_BAD_KEY_PROPERTY; } } if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyParams_CheckDefaultExponent(&(rsa_key_parms->exponent)); } /* 2. Validate the AuthData to use the TPM by the TPM Owner */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_OWNER, ordinal, NULL, &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ } if (returnCode == TPM_SUCCESS) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* owner HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, ownerAuth); /* Authorization digest for input */ } /* 3. Create a f1 a TPM_MIGRATIONKEYAUTH structure */ /* NOTE: This is outData */ /* 4. Verify that migrationKey-> algorithmParms -> encScheme is TPM_ES_RSAESOAEP_SHA1_MGF1, and return the error code TPM_INAPPROPRIATE_ENC if it is not */ if (returnCode == TPM_SUCCESS) { if (migrationKey.algorithmParms.encScheme != TPM_ES_RSAESOAEP_SHA1_MGF1) { printf("TPM_Process_AuthorizeMigrationKey: Error, " "migrationKey encScheme %04hx must be TPM_ES_RSAESOAEP_SHA1_MGF1\n", migrationKey.algorithmParms.encScheme); returnCode = TPM_INAPPROPRIATE_ENC; } } /* 5. Set f1 -> migrationKey to the input migrationKey */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Pubkey_Copy(&(outData.migrationKey), &(migrationKey)); } if (returnCode == TPM_SUCCESS) { /* 6. Set f1 -> migrationScheme to the input migrationScheme */ outData.migrationScheme = migrationScheme; /* 7. Create v1 by concatenating (migrationKey || migrationScheme || TPM_PERMANENT_DATA -> tpmProof) */ /* 8. Create h1 by performing a SHA-1 hash of v1 */ /* first serialize the TPM_PUBKEY migrationKey */ returnCode = TPM_Pubkey_Store(&sbuffer, &migrationKey); } if (returnCode == TPM_SUCCESS) { TPM_Sbuffer_Get(&sbuffer, &buffer, &length); /* 9. Set f1 -> digest to h1 */ returnCode = TPM_SHA1(outData.digest, length, buffer, /* serialized migrationKey */ sizeof(TPM_MIGRATE_SCHEME), &(migrationScheme), TPM_SECRET_SIZE, tpm_state->tpm_permanent_data.tpmProof, 0, NULL); } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_AuthorizeMigrationKey: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* 10. Return f1 as outData */ returnCode = TPM_Migrationkeyauth_Store(response, &outData); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* owner HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ TPM_Pubkey_Delete(&migrationKey); /* @1 */ TPM_Migrationkeyauth_Delete(&outData); /* @2 */ TPM_Sbuffer_Delete(&sbuffer); /* @3 */ return rcf; } /* 11.4 TPM_MigrateKey rev 87 The TPM_MigrateKey command performs the function of a migration authority. The command is relatively simple; it just decrypts the input packet (coming from TPM_CreateMigrationBlob or TPM_CMK_CreateBlob) and then re-encrypts it with the input public key. The output of this command would then be sent to TPM_ConvertMigrationBlob or TPM_CMK_ConvertMigration on the target TPM. TPM_MigrateKey does not make ANY assumptions about the contents of the encrypted blob. Since it does not have the XOR string, it cannot actually determine much about the key that is being migrated. This command exists to permit the TPM to be a migration authority. If used in this way, it is expected that the physical security of the system containing the TPM and the AuthData value for the MA key would be tightly controlled. To prevent the execution of this command using any other key as a parent key, this command works only if keyUsage for maKeyHandle is TPM_KEY_MIGRATE. */ TPM_RESULT TPM_Process_MigrateKey(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_KEY_HANDLE maKeyHandle; /* Handle of the key to be used to migrate the key. */ TPM_PUBKEY pubKey; /* Public key to which the blob is to be migrated */ TPM_SIZED_BUFFER inData; /* The input blob */ TPM_AUTHHANDLE maAuthHandle; /* The authorization session handle used for maKeyHandle. */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with certAuthHandle */ TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization session handle */ TPM_AUTHDATA keyAuth; /* The authorization session digest for the inputs and key to be signed. HMAC key: maKeyHandle.usageAuth. */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL maAuthHandleValid = FALSE; TPM_SECRET *hmacKey; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ TPM_KEY *maKey = NULL; /* the key specified by maKeyHandle */ TPM_RSA_KEY_PARMS *tpm_rsa_key_parms; /* for maKey */ TPM_SECRET *maKeyUsageAuth; TPM_BOOL maPCRStatus; uint32_t decrypt_data_size; /* resulting decrypted data size */ BYTE *decrypt_data = NULL; /* The resulting decrypted data. */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_SIZED_BUFFER outData; /* The re-encrypted blob */ printf("TPM_Process_MigrateKey: Ordinal Entry\n"); TPM_SizedBuffer_Init(&inData); /* freed @1 */ TPM_SizedBuffer_Init(&outData); /* freed @2 */ TPM_Pubkey_Init(&pubKey); /* freed @4 */ /* get inputs */ /* get maKeyHandle */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&maKeyHandle, &command, ¶mSize); } /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get pubKey */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_MigrateKey: maKeyHandle %08x\n", maKeyHandle); returnCode = TPM_Pubkey_Load(&pubKey, &command, ¶mSize); } /* get encData */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_Load(&inData, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag10(tag); } /* get the optional 'below the line' authorization parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Get(&maAuthHandle, &maAuthHandleValid, nonceOdd, &continueAuthSession, keyAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_MigrateKey: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { maAuthHandleValid = FALSE; } /* Processing */ /* 1. Validate that keyAuth authorizes the use of the key pointed to by maKeyHandle */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyHandleEntries_GetKey(&maKey, &maPCRStatus, tpm_state, maKeyHandle, FALSE, /* not read-only */ FALSE, /* do not ignore PCRs */ FALSE); /* cannot use EK */ } /* get maKeyHandle -> usageAuth */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_Key_GetUsageAuth(&maKeyUsageAuth, maKey); } /* get the session data */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { printf("TPM_Process_MigrateKey: maAuthHandle %08x\n", maAuthHandle); returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, maAuthHandle, TPM_PID_NONE, TPM_ET_KEYHANDLE, ordinal, maKey, maKeyUsageAuth, /* OIAP */ maKey->tpm_store_asymkey->pubDataDigest); /* OSAP */ } if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, keyAuth); /* Authorization digest for input */ } /* check TPM_AUTH_DATA_USAGE authDataUsage */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)) { if (maKey->authDataUsage != TPM_AUTH_NEVER) { printf("TPM_Process_MigrateKey: Error, authorization required\n"); returnCode = TPM_AUTHFAIL; } } /* 2. The TPM validates that the key pointed to by maKeyHandle has a key usage value of TPM_KEY_MIGRATE, and that the allowed encryption scheme is TPM_ES_RSAESOAEP_SHA1_MGF1. */ if (returnCode == TPM_SUCCESS) { if (maKey->keyUsage != TPM_KEY_MIGRATE) { printf("TPM_Process_MigrateKey: Error, keyUsage %04hx not TPM_KEY_MIGRATE\n", maKey->keyUsage); returnCode = TPM_INVALID_KEYUSAGE; } else if (maKey->algorithmParms.encScheme != TPM_ES_RSAESOAEP_SHA1_MGF1) { printf("TPM_Process_MigrateKey: Error, encScheme %04hx not TPM_ES_RSAESOAEP_SHA_MGF1\n", maKey->algorithmParms.encScheme); returnCode = TPM_BAD_KEY_PROPERTY; } } /* 3. The TPM validates that pubKey is of a size supported by the TPM and that its size is consistent with the input blob and maKeyHandle. */ /* NOTE: Let the encryption step do this step */ /* 4. The TPM decrypts inData and re-encrypts it using pubKey. */ /* get the TPM_RSA_KEY_PARMS associated with maKey */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyParms_GetRSAKeyParms(&tpm_rsa_key_parms, &(maKey->algorithmParms)); } /* decrypt using maKey */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_MigrateKey: Decrypt using maKey\n"); returnCode = TPM_RSAPrivateDecryptMalloc(&decrypt_data, /* decrypted data, freed @3 */ &decrypt_data_size, /* actual size of decrypt data */ inData.buffer, inData.size, maKey); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_MigrateKey: Encrypt using pubKey\n"); returnCode = TPM_RSAPublicEncrypt_Pubkey(&outData, /* encrypted data */ decrypt_data, decrypt_data_size, &pubKey); } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_MigrateKey: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* return outData */ returnCode = TPM_SizedBuffer_Store(response, &outData); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && maAuthHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, maAuthHandle); } /* cleanup */ TPM_SizedBuffer_Delete(&inData); /* @1 */ TPM_SizedBuffer_Delete(&outData); /* @2 */ free(decrypt_data); /* @3 */ TPM_Pubkey_Delete(&pubKey); /* @4 */ return rcf; } /* 11.7 TPM_CMK_CreateKey rev 114 The TPM_CMK_CreateKey command both generates and creates a secure storage bundle for asymmetric keys whose migration is controlled by a migration authority. TPM_CMK_CreateKey is very similar to TPM_CreateWrapKey, but: (1) the resultant key must be a migratable key and can be migrated only by TPM_CMK_CreateBlob; (2) the command is Owner authorized via a ticket. TPM_CMK_CreateKey creates an otherwise normal migratable key except that (1) migrationAuth is an HMAC of the migration authority and the new key's public key, signed by tpmProof (instead of being tpmProof); (2) the migrationAuthority bit is set TRUE; (3) the payload type is TPM_PT_MIGRATE_RESTRICTED. The migration-selection/migration authority is specified by passing in a public key (actually the digests of one or more public keys, so more than one migration authority can be specified). */ TPM_RESULT TPM_Process_CMK_CreateKey(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_KEY_HANDLE parentHandle; /* Handle of a loaded key that can perform key wrapping. */ TPM_ENCAUTH dataUsageAuth; /* Encrypted usage authorization data for the key. */ TPM_KEY keyInfo; /* Information about key to be created, pubkey.keyLength and keyInfo.encData elements are 0. MUST be TPM_KEY12 */ TPM_HMAC migrationAuthorityApproval;/* A ticket, created by the TPM Owner using TPM_CMK_ApproveMA, approving a TPM_MSA_COMPOSITE structure */ TPM_DIGEST migrationAuthorityDigest;/* The digest of a TPM_MSA_COMPOSITE structure */ TPM_AUTHHANDLE authHandle; /* The authorization handle used for parent key authorization. Must be an OSAP session. */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* Ignored */ TPM_AUTHDATA pubAuth; /* The authorization session digest that authorizes the use of the public key in parentHandle. HMAC key: parentKey.usageAuth.*/ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for entityAuthHandle */ TPM_SECRET *hmacKey; TPM_KEY *parentKey = NULL; /* the key specified by parentHandle */ TPM_BOOL parentPCRStatus; TPM_BOOL hmacValid; /* for migrationAuthorityApproval */ TPM_SECRET du1DecryptAuth; TPM_STORE_ASYMKEY *wrappedStoreAsymkey; /* substructure of wrappedKey */ TPM_CMK_MA_APPROVAL m1CmkMaApproval; TPM_CMK_MIGAUTH m2CmkMigauth; int ver; /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_KEY wrappedKey; /* The TPM_KEY structure which includes the public and encrypted private key. MUST be TPM_KEY12 */ printf("TPM_Process_CMK_CreateKey: Ordinal Entry\n"); TPM_Key_Init(&keyInfo); /* freed @1 */ TPM_Key_Init(&wrappedKey); /* freed @2 */ TPM_CmkMaApproval_Init(&m1CmkMaApproval); /* freed @3 */ TPM_CmkMigauth_Init(&m2CmkMigauth); /* freed @4 */ /* get inputs */ /* get parentHandle */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&parentHandle, &command, ¶mSize); } /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get dataUsageAuth */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CMK_CreateKey: parentHandle %08x\n", parentHandle); returnCode = TPM_Authdata_Load(dataUsageAuth, &command, ¶mSize); } /* get keyInfo */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Key_Load(&keyInfo, &command, ¶mSize); } /* get migrationAuthorityApproval */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Digest_Load(migrationAuthorityApproval, &command, ¶mSize); } /* get migrationAuthorityDigest */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Digest_Load(migrationAuthorityDigest, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag1(tag); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, pubAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CMK_CreateKey: authHandle %08x\n", authHandle); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_CMK_CreateKey: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* 1. Validate the authorization to use the key pointed to by parentHandle. Return TPM_AUTHFAIL on any error. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyHandleEntries_GetKey(&parentKey, &parentPCRStatus, tpm_state, parentHandle, FALSE, /* not r/o, using to encrypt */ FALSE, /* do not ignore PCRs */ FALSE); /* cannot use EK */ } /* get the session data */ /* 2. Validate the session type for parentHandle is OSAP. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_OSAP, TPM_ET_KEYHANDLE, ordinal, parentKey, NULL, /* OIAP */ parentKey->tpm_store_asymkey->pubDataDigest); /*OSAP*/ } if (returnCode == TPM_SUCCESS) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, pubAuth); /* Authorization digest for input */ } /* 3. If the TPM is not designed to create a key of the type requested in keyInfo, return the error code TPM_BAD_KEY_PROPERTY */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Key_CheckProperties(&ver, &keyInfo, 0, tpm_state->tpm_permanent_flags.FIPS); printf("TPM_Process_CMK_CreateKey: key parameters v = %d\n", ver); } /* 4. Verify that parentHandle->keyUsage equals TPM_KEY_STORAGE */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CMK_CreateKey: Checking parent key\n"); if (parentKey->keyUsage != TPM_KEY_STORAGE) { printf("TPM_Process_CMK_CreateKey: Error, parent keyUsage not TPM_KEY_STORAGE\n"); returnCode = TPM_INVALID_KEYUSAGE; } } /* 5. Verify that parentHandle-> keyFlags-> migratable == FALSE */ if (returnCode == TPM_SUCCESS) { if (parentKey->keyFlags & TPM_MIGRATABLE) { printf("TPM_Process_CMK_CreateKey: Error, parent migratable\n"); returnCode = TPM_INVALID_KEYUSAGE; } } /* 6. If keyInfo -> keyFlags -> migratable is FALSE then return TPM_INVALID_KEYUSAGE */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CMK_CreateKey: Checking key flags\n"); if (!(keyInfo.keyFlags & TPM_MIGRATABLE)) { printf("TPM_Process_CMK_CreateKey: Error, keyInfo migratable is FALSE\n"); returnCode = TPM_INVALID_KEYUSAGE; } } /* 7. If keyInfo -> keyFlags -> migrateAuthority is FALSE , return TPM_INVALID_KEYUSAGE */ if (returnCode == TPM_SUCCESS) { if (!(keyInfo.keyFlags & TPM_MIGRATEAUTHORITY)) { printf("TPM_Process_CMK_CreateKey: Error, keyInfo migrateauthority is FALSE\n"); returnCode = TPM_INVALID_KEYUSAGE; } } /* 8. Verify that the migration authority is authorized */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CMK_CreateKey: Checking migration authority authorization\n"); /* a. Create M1 a TPM_CMK_MA_APPROVAL structure */ /* NOTE Done by TPM_CmkMaApproval_Init() */ /* i. Set M1 ->migrationAuthorityDigest to migrationAuthorityDigest */ TPM_Digest_Copy(m1CmkMaApproval.migrationAuthorityDigest, migrationAuthorityDigest); /* b. Verify that migrationAuthorityApproval == HMAC(M1) using tpmProof as the secret and return error TPM_MA_AUTHORITY on mismatch */ returnCode = TPM_CmkMaApproval_CheckHMAC(&hmacValid, migrationAuthorityApproval, /* expect */ tpm_state->tpm_permanent_data.tpmProof, /* HMAC key */ &m1CmkMaApproval); if (!hmacValid) { printf("TPM_Process_CMK_CreateKey: Error, Invalid migrationAuthorityApproval\n"); returnCode = TPM_MA_AUTHORITY; } } /* 9. Validate key parameters */ /* a. keyInfo -> keyUsage MUST NOT be TPM_KEY_IDENTITY or TPM_KEY_AUTHCHANGE. If it is, return TPM_INVALID_KEYUSAGE */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CMK_CreateKey: Checking key usage\n"); if ((keyInfo.keyUsage == TPM_KEY_IDENTITY) || (keyInfo.keyUsage == TPM_KEY_AUTHCHANGE)) { printf("TPM_Process_CMK_CreateKey: Error, invalid keyInfo -> keyUsage %04hx\n", keyInfo.keyUsage); returnCode = TPM_INVALID_KEYUSAGE; } } /* 10. If TPM_PERMANENT_FLAGS -> FIPS is TRUE then */ /* a. If keyInfo -> keySize is less than 1024 return TPM_NOTFIPS */ /* b. If keyInfo -> authDataUsage specifies TPM_AUTH_NEVER return TPM_NOTFIPS */ /* c. If keyInfo -> keyUsage specifies TPM_KEY_LEGACY return TPM_NOTFIPS */ /* NOTE Done by TPM_Key_CheckProperties() */ /* 11. If keyInfo -> keyUsage equals TPM_KEY_STORAGE or TPM_KEY_MIGRATE */ /* a. algorithmID MUST be TPM_ALG_RSA */ /* b. encScheme MUST be TPM_ES_RSAESOAEP_SHA1_MGF1 */ /* c. sigScheme MUST be TPM_SS_NONE */ /* d. key size MUST be 2048 */ /* e. exponentSize MUST be 0 */ /* NOTE Done by TPM_Key_CheckProperties() */ /* 12. If keyInfo -> tag is NOT TPM_TAG_KEY12 return TPM_INVALID_STRUCTURE */ if (returnCode == TPM_SUCCESS) { if (ver != 2) { printf("TPM_Process_CMK_CreateKey: Error, keyInfo must be TPM_TAG_KEY12\n"); returnCode = TPM_INVALID_STRUCTURE; } } /* 13. Map wrappedKey to a TPM_KEY12 structure */ /* NOTE: Not required. TPM_KEY functions handle TPM_KEY12 subclass */ /* 14. Create DU1 by decrypting dataUsageAuth according to the ADIP indicated by authHandle. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessionData_Decrypt(du1DecryptAuth, NULL, dataUsageAuth, auth_session_data, NULL, NULL, FALSE); /* even and odd */ } if (returnCode == TPM_SUCCESS) { /* 15. Set continueAuthSession to FALSE */ continueAuthSession = FALSE; /* 16. Generate asymmetric key according to algorithm information in keyInfo */ /* 17. Fill in the wrappedKey structure with information from the newly generated key. */ printf("TPM_Process_CMK_CreateKey: Generating key\n"); returnCode = TPM_Key_GenerateRSA(&wrappedKey, tpm_state, parentKey, tpm_state->tpm_stclear_data.PCRS, /* PCR array */ ver, /* TPM_KEY12 */ keyInfo.keyUsage, keyInfo.keyFlags, keyInfo.authDataUsage, /* TPM_AUTH_DATA_USAGE */ &(keyInfo.algorithmParms), /* TPM_KEY_PARMS */ keyInfo.tpm_pcr_info, /* TPM_PCR_INFO */ keyInfo.tpm_pcr_info_long); /* TPM_PCR_INFO_LONG */ } if (returnCode == TPM_SUCCESS) { returnCode = TPM_Key_GetStoreAsymkey(&wrappedStoreAsymkey, &wrappedKey); } if (returnCode == TPM_SUCCESS) { /* a. Set wrappedKey -> encData -> usageAuth to DU1 */ TPM_Secret_Copy(wrappedStoreAsymkey->usageAuth, du1DecryptAuth); /* b. Set wrappedKey -> encData -> payload to TPM_PT_MIGRATE_RESTRICTED */ wrappedStoreAsymkey->payload = TPM_PT_MIGRATE_RESTRICTED; /* c. Create thisPubKey, a TPM_PUBKEY structure containing wrappedKey's public key. */ /* NOTE All that is really needed is its digest, which is calculated directly */ } if (returnCode == TPM_SUCCESS) { /* d. Create M2 a TPM_CMK_MIGAUTH structure */ /* NOTE Done by TPM_CmkMigauth_Init() */ /* i. Set M2 -> msaDigest to migrationAuthorityDigest */ TPM_Digest_Copy(m2CmkMigauth.msaDigest, migrationAuthorityDigest); /* ii. Set M2 -> pubKeyDigest to SHA-1 (thisPubKey) */ returnCode = TPM_Key_GeneratePubkeyDigest(m2CmkMigauth.pubKeyDigest, &wrappedKey); /* e. Set wrappedKey -> encData -> migrationAuth equal to HMAC(M2), using tpmProof as the shared secret */ returnCode = TPM_HMAC_GenerateStructure (wrappedStoreAsymkey->migrationAuth, /* HMAC */ tpm_state->tpm_permanent_data.tpmProof, /* HMAC key */ &m2CmkMigauth, /* structure */ (TPM_STORE_FUNCTION_T)TPM_CmkMigauth_Store); /* store function */ } /* 18. If keyInfo->PCRInfoSize is non-zero */ /* a. Set wrappedKey -> pcrInfo to a TPM_PCR_INFO_LONG structure */ /* b. Set wrappedKey -> pcrInfo to keyInfo -> pcrInfo */ /* b. Set wrappedKey -> digestAtCreation to the TPM_COMPOSITE_HASH indicated by creationPCRSelection */ /* c. Set wrappedKey -> localityAtCreation to TPM_STANY_FLAGS -> localityModifier */ /* NOTE This is done during TPM_Key_GenerateRSA() */ /* 19. Encrypt the private portions of the wrappedKey structure using the key in parentHandle */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Key_GenerateEncData(&wrappedKey, parentKey); } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_CMK_CreateKey: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* 20. Return the newly generated key in the wrappedKey parameter */ returnCode = TPM_Key_Store(response, &wrappedKey); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ TPM_Key_Delete(&keyInfo); /* @1 */ TPM_Key_Delete(&wrappedKey); /* @2 */ TPM_CmkMaApproval_Delete(&m1CmkMaApproval); /* @3 */ TPM_CmkMigauth_Delete(&m2CmkMigauth); /* @4 */ return rcf; } /* 11.5 TPM_CMK_CreateTicket rev 101 The TPM_verifySignature command uses a public key to verify the signature over a digest. TPM_verifySignature returns a ticket that can be used to prove to the same TPM that signature verification with a particular public key was successful. */ TPM_RESULT TPM_Process_CMK_CreateTicket(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_PUBKEY verificationKey; /* The public key to be used to check signatureValue */ TPM_DIGEST signedData; /* The data to be verified */ TPM_SIZED_BUFFER signatureValue; /* The signatureValue to be verified */ TPM_AUTHHANDLE authHandle; /* The authorization handle used for owner authorization. */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* Ignored */ TPM_AUTHDATA pubAuth; /* The authorization digest for inputs and owner. HMAC key: ownerAuth. */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_SECRET *hmacKey; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ TPM_CMK_SIGTICKET m2CmkSigticket; /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_HMAC sigTicket; /* Ticket that proves digest created on this TPM */ printf("TPM_Process_CMK_CreateTicket: Ordinal Entry\n"); TPM_Pubkey_Init(&verificationKey); /* freed @1 */ TPM_SizedBuffer_Init(&signatureValue); /* freed @2 */ TPM_CmkSigticket_Init(&m2CmkSigticket); /* freed @3 */ /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get verificationKey */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Pubkey_Load(&verificationKey, &command, ¶mSize); } /* get signedData */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Digest_Load(signedData, &command, ¶mSize); } /* get signatureValue */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_Load(&signatureValue, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag1(tag); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, pubAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_CMK_CreateTicket: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* 1. Validate the TPM Owner authorization to use the command */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_OWNER, ordinal, NULL, &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ } if (returnCode == TPM_SUCCESS) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* owner HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, pubAuth); /* Authorization digest for input */ } /* 2. Validate that the key type and algorithm are correct */ /* a. Validate that verificationKey -> algorithmParms -> algorithmID == TPM_ALG_RSA */ if (returnCode == TPM_SUCCESS) { if (verificationKey.algorithmParms.algorithmID != TPM_ALG_RSA) { printf("TPM_Process_CMK_CreateTicket: Error, incorrect algorithmID %08x\n", verificationKey.algorithmParms.algorithmID); returnCode = TPM_BAD_KEY_PROPERTY; } } /* b. Validate that verificationKey -> algorithmParms ->encScheme == TPM_ES_NONE */ if (returnCode == TPM_SUCCESS) { if (verificationKey.algorithmParms.encScheme != TPM_ES_NONE) { printf("TPM_Process_CMK_CreateTicket: Error, incorrect encScheme %04hx\n", verificationKey.algorithmParms.encScheme); returnCode = TPM_INAPPROPRIATE_ENC; } } /* c. Validate that verificationKey ->algorithmParms ->sigScheme is TPM_SS_RSASSAPKCS1v15_SHA1 or TPM_SS_RSASSAPKCS1v15_INFO */ if (returnCode == TPM_SUCCESS) { if ((verificationKey.algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1) && (verificationKey.algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_INFO)) { printf("TPM_Process_CMK_CreateTicket: Error, incorrect sigScheme %04hx\n", verificationKey.algorithmParms.sigScheme); returnCode = TPM_INVALID_KEYUSAGE; } } /* 3. Use verificationKey to verify that signatureValue is a valid signature on signedData, and return error TPM_BAD_SIGNATURE on mismatch */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CMK_CreateTicket: Verifying signature\n"); returnCode = TPM_RSAVerifyH(&signatureValue, /* signature */ signedData, /* data that was signed */ TPM_DIGEST_SIZE, /* size of signed data */ &verificationKey); /* TPM_PUBKEY public key */ if (returnCode != TPM_SUCCESS) { printf("TPM_Process_CMK_CreateTicket: Error verifying signature\n"); } } /* 4. Create M2 a TPM_CMK_SIGTICKET */ /* NOTE Done by TPM_CmkSigticket_Init() */ /* a. Set M2 -> verKeyDigest to the SHA-1 (verificationKey) */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SHA1_GenerateStructure(m2CmkSigticket.verKeyDigest, &verificationKey, (TPM_STORE_FUNCTION_T)TPM_Pubkey_Store); } if (returnCode == TPM_SUCCESS) { /* b. Set M2 -> signedData to signedData */ TPM_Digest_Copy(m2CmkSigticket.signedData, signedData); /* 5. Set sigTicket = HMAC(M2) signed by using tpmProof as the secret */ returnCode = TPM_HMAC_GenerateStructure (sigTicket, /* HMAC */ tpm_state->tpm_permanent_data.tpmProof, /* HMAC key */ &m2CmkSigticket, /* structure */ (TPM_STORE_FUNCTION_T)TPM_CmkSigticket_Store); /* store function */ } /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_CMK_CreateTicket: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* return sigTicket */ returnCode = TPM_Digest_Store(response, sigTicket); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* owner HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ TPM_Pubkey_Delete(&verificationKey); /* @1 */ TPM_SizedBuffer_Delete(&signatureValue); /* @2 */ TPM_CmkSigticket_Delete(&m2CmkSigticket); /* @3 */ return rcf; } /* 11.9 TPM_CMK_CreateBlob rev 114 TPM_CMK_CreateBlob command is very similar to TPM_CreateMigrationBlob, except that it: (1) uses an extra ticket (restrictedKeyAuth) instead of a migrationAuth authorization session; (2) uses the migration options TPM_MS_RESTRICT_MIGRATE or TPM_MS_RESTRICT_APPROVE; (3) produces a wrapped key blob whose migrationAuth is independent of tpmProof. If the destination (parent) public key is the MA, migration is implicitly permitted. Further checks are required if the MA is not the destination (parent) public key, and merely selects a migration destination: (1) sigTicket must prove that restrictTicket was signed by the MA; (2) restrictTicket must vouch that the target public key is approved for migration to the destination (parent) public key. (Obviously, this more complex method may also be used by an MA to approve migration to that MA.) In both cases, the MA must be one of the MAs implicitly listed in the migrationAuth of the target key-to-be-migrated. When the migrationType is TPM_MS_RESTRICT_MIGRATE, restrictTicket and sigTicket are unused. The TPM may test that the corresponding sizes are zero, so the caller should set them to zero for interoperability. */ TPM_RESULT TPM_Process_CMK_CreateBlob(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_KEY_HANDLE parentHandle; /* Handle of the parent key that can decrypt encData. */ TPM_MIGRATE_SCHEME migrationType; /* The migration type, either TPM_MS_RESTRICT_MIGRATE or TPM_MS_RESTRICT_APPROVE NOTE Never used */ TPM_MIGRATIONKEYAUTH migrationKeyAuth; /* Migration public key and its authorization session digest. */ TPM_DIGEST pubSourceKeyDigest; /* The digest of the TPM_PUBKEY of the entity to be migrated */ TPM_SIZED_BUFFER msaListBuffer; /* One or more digests of public keys belonging to migration authorities */ TPM_SIZED_BUFFER restrictTicketBuffer; /* If migrationType is TPM_MS_RESTRICT_APPROVE, a TPM_CMK_AUTH structure, containing the digests of the public keys belonging to the Migration Authority, the destination parent key and the key-to-be-migrated. */ TPM_SIZED_BUFFER sigTicketBuffer; /* If migrationType is TPM_MS_RESTRICT_APPROVE, a TPM_HMAC structure, generated by the TPM, signaling a valid signature over restrictTicket */ TPM_SIZED_BUFFER encData; /* The encrypted entity that is to be modified. */ TPM_AUTHHANDLE parentAuthHandle; /* The authorization handle used for the parent key. */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with parentAuthHandle */ TPM_BOOL continueAuthSession; /* Continue use flag for parent session */ TPM_AUTHDATA parentAuth; /* The authorization digest for inputs and parentHandle. HMAC key: parentKey.usageAuth. */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_SECRET *hmacKey; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ TPM_KEY *parentKey; TPM_BOOL parentPCRStatus; TPM_SECRET *parentUsageAuth; unsigned char *d1Decrypt; /* decryption of encData */ uint32_t d1DecryptLength = 0; /* actual valid data */ TPM_STORE_ASYMKEY d1AsymKey; /* structure from decrypted encData */ unsigned char *stream; /* for deserializing structures */ uint32_t stream_size; TPM_STORE_BUFFER mka_sbuffer; /* serialized migrationKeyAuth.migrationKey */ const unsigned char *mka_buffer; uint32_t mka_length; TPM_DIGEST migrationKeyDigest; /* digest of migrationKeyAuth.migrationKey */ TPM_DIGEST pHash; TPM_CMK_MIGAUTH m2CmkMigauth; TPM_BOOL valid; TPM_MSA_COMPOSITE msaList; TPM_DIGEST sigTicket; TPM_CMK_AUTH restrictTicket; TPM_CMK_SIGTICKET v1CmkSigticket; /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_SIZED_BUFFER random; /* String used for xor encryption */ TPM_SIZED_BUFFER outData; /* The modified, encrypted entity. */ printf("TPM_Process_CMK_CreateBlob: Ordinal Entry\n"); d1Decrypt = NULL; /* freed @1 */ TPM_Migrationkeyauth_Init(&migrationKeyAuth); /* freed @2 */ TPM_SizedBuffer_Init(&msaListBuffer); /* freed @3 */ TPM_SizedBuffer_Init(&restrictTicketBuffer); /* freed @4 */ TPM_SizedBuffer_Init(&sigTicketBuffer); /* freed @5 */ TPM_SizedBuffer_Init(&encData); /* freed @6 */ TPM_SizedBuffer_Init(&random); /* freed @7 */ TPM_SizedBuffer_Init(&outData); /* freed @8 */ TPM_Sbuffer_Init(&mka_sbuffer); /* freed @9 */ TPM_StoreAsymkey_Init(&d1AsymKey); /* freed @10 */ TPM_MsaComposite_Init(&msaList); /* freed @11 */ TPM_CmkAuth_Init(&restrictTicket); /* freed @12 */ TPM_CmkMigauth_Init(&m2CmkMigauth); /* freed @13 */ TPM_CmkSigticket_Init(&v1CmkSigticket); /* freed @14 */ /* get inputs */ /* get parentHandle */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&parentHandle, &command, ¶mSize); } /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get migrationType */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load16(&migrationType, &command, ¶mSize); } /* get migrationKeyAuth */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Migrationkeyauth_Load(&migrationKeyAuth, &command, ¶mSize); } /* get pubSourceKeyDigest */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Digest_Load(pubSourceKeyDigest, &command, ¶mSize); } /* get msaListBuffer */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_Load(&msaListBuffer, &command, ¶mSize); } /* deserialize to msaList */ if (returnCode == TPM_SUCCESS) { stream = msaListBuffer.buffer; stream_size = msaListBuffer.size; returnCode = TPM_MsaComposite_Load(&msaList, &stream, &stream_size); } /* get restrictTicket */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_Load(&restrictTicketBuffer, &command, ¶mSize); } /* get sigTicket */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_Load(&sigTicketBuffer, &command, ¶mSize); } /* get encData */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_Load(&encData, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag1(tag); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Get(&parentAuthHandle, &authHandleValid, nonceOdd, &continueAuthSession, parentAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_CMK_CreateBlob: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* The TPM does not check the PCR values when migrating values locked to a PCR. */ /* get the key associated with parentHandle */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyHandleEntries_GetKey(&parentKey, &parentPCRStatus, tpm_state, parentHandle, FALSE, /* do not check PCR's */ FALSE, /* do not ignore PCRs */ FALSE); /* cannot use EK */ } /* get parentHandle -> usageAuth */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Key_GetUsageAuth(&parentUsageAuth, parentKey); } /* get the session data */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, parentAuthHandle, TPM_PID_NONE, TPM_ET_KEYHANDLE, ordinal, parentKey, parentUsageAuth, /* OIAP */ parentKey->tpm_store_asymkey->pubDataDigest); /*OSAP*/ } /* 1. Validate that parentAuth authorizes the use of the key pointed to by parentHandle. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, parentAuth); /* Authorization digest for input */ } /* 2.The TPM MAY verify that migrationType == migrationKeyAuth -> migrationScheme and return TPM_BAD_MODE on error. a.The TPM MAY ignore migrationType. */ /* 3. Verify that parentHandle-> keyFlags-> migratable == FALSE */ if (returnCode == TPM_SUCCESS) { if (parentKey->keyFlags & TPM_MIGRATABLE) { printf("TPM_Process_CMK_CreateBlob: Error, parent migratable\n"); returnCode = TPM_INVALID_KEYUSAGE; } } /* Validate that parentHandle -> keyUsage is TPM_KEY_STORAGE, if not return the error code TPM_INVALID_KEYUSAGE */ if (returnCode == TPM_SUCCESS) { if (parentKey->keyUsage != TPM_KEY_STORAGE) { printf("TPM_Process_CMK_CreateBlob: Error, keyUsage %04hx is invalid\n", parentKey->keyUsage); returnCode = TPM_INVALID_KEYUSAGE; } } /* 4. Create d1 by decrypting encData using the key pointed to by parentHandle. */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CMK_CreateBlob: Decrypting encData\n"); /* decrypt with the parent key to a stream */ returnCode = TPM_RSAPrivateDecryptMalloc(&d1Decrypt, /* decrypted data, freed @1 */ &d1DecryptLength, /* actual size of d1 data */ encData.buffer,/* encrypted data */ encData.size, /* encrypted data size */ parentKey); } /* deserialize the stream to a TPM_STORE_ASYMKEY d1AsymKey */ if (returnCode == TPM_SUCCESS) { stream = d1Decrypt; stream_size = d1DecryptLength; returnCode = TPM_StoreAsymkey_Load(&d1AsymKey, FALSE, &stream, &stream_size, NULL, /* TPM_KEY_PARMS */ NULL); /* TPM_SIZED_BUFFER pubKey */ } /* 5. Verify that the digest within migrationKeyAuth is legal for this TPM and public key */ /* NOTE Presumably, this reverses the steps from TPM_AuthorizeMigrationKey */ /* create h1 by concatenating (migrationKey || migrationScheme || TPM_PERMANENT_DATA -> tpmProof) */ /* first serialize the TPM_PUBKEY migrationKeyAuth -> migrationKey */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CMK_CreateBlob: Verifying migrationKeyAuth\n"); returnCode = TPM_Pubkey_Store(&mka_sbuffer, &(migrationKeyAuth.migrationKey)); } if (returnCode == TPM_SUCCESS) { /* get the serialization result */ TPM_Sbuffer_Get(&mka_sbuffer, &mka_buffer, &mka_length); /* then create the hash. tpmProof indicates that the input knew ownerAuth in TPM_AuthorizeMigrationKey */ /* compare to migrationKeyAuth -> digest */ returnCode = TPM_SHA1_Check(migrationKeyAuth.digest, mka_length, mka_buffer, /* serialized migrationKey */ sizeof(TPM_MIGRATE_SCHEME), &(migrationKeyAuth.migrationScheme), TPM_SECRET_SIZE, tpm_state->tpm_permanent_data.tpmProof, 0, NULL); } /* 6. Verify that d1 -> payload == TPM_PT_MIGRATE_RESTRICTED or TPM_PT_MIGRATE_EXTERNAL */ if (returnCode == TPM_SUCCESS) { if ((d1AsymKey.payload != TPM_PT_MIGRATE_RESTRICTED) && (d1AsymKey.payload != TPM_PT_MIGRATE_EXTERNAL)) { printf("TPM_Process_CMK_CreateBlob: Error, invalid payload %02x\n", d1AsymKey.payload); returnCode = TPM_INVALID_STRUCTURE; } } /* 7. Verify that the migration authorities in msaList are authorized to migrate this key */ /* a. Create M2 a TPM_CMK_MIGAUTH structure */ /* NOTE Done by TPM_CmkMigauth_Init() */ /* i. Set M2 -> msaDigest to SHA-1[msaList] */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SHA1_GenerateStructure(m2CmkMigauth.msaDigest, &msaList, (TPM_STORE_FUNCTION_T)TPM_MsaComposite_Store); } if (returnCode == TPM_SUCCESS) { /* ii. Set M2 -> pubKeyDigest to pubSourceKeyDigest */ TPM_Digest_Copy(m2CmkMigauth.pubKeyDigest, pubSourceKeyDigest); /* b. Verify that d1 -> migrationAuth == HMAC(M2) using tpmProof as the secret and return error TPM_MA_AUTHORITY on mismatch */ returnCode = TPM_CmkMigauth_CheckHMAC(&valid, d1AsymKey.migrationAuth, /* expected */ tpm_state->tpm_permanent_data.tpmProof, /* HMAC key*/ &m2CmkMigauth); if (!valid) { printf("TPM_Process_CMK_CreateBlob: Error validating migrationAuth\n"); returnCode = TPM_MA_AUTHORITY; } } /* SHA-1[migrationKeyAuth -> migrationKey] is required below */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SHA1(migrationKeyDigest, mka_length, mka_buffer, /* serialized migrationKey */ 0, NULL); } /* 8. If migrationKeyAuth -> migrationScheme == TPM_MS_RESTRICT_MIGRATE */ if ((returnCode == TPM_SUCCESS) && (migrationKeyAuth.migrationScheme == TPM_MS_RESTRICT_MIGRATE)) { /* a. Verify that intended migration destination is an MA: */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CMK_CreateBlob: migrationScheme is TPM_MS_RESTRICT_MIGRATE\n"); /* i. For one of n=1 to n=(msaList -> MSAlist), verify that SHA-1[migrationKeyAuth -> migrationKey] == msaList -> migAuthDigest[n] */ returnCode = TPM_MsaComposite_CheckMigAuthDigest(migrationKeyDigest, &msaList); } /* b. Validate that the MA key is the correct type */ /* i. Validate that migrationKeyAuth -> migrationKey -> algorithmParms -> algorithmID == TPM_ALG_RSA */ if (returnCode == TPM_SUCCESS) { if (migrationKeyAuth.migrationKey.algorithmParms.algorithmID != TPM_ALG_RSA) { printf("TPM_Process_CMK_CreateBlob: Error, algorithmID %08x not TPM_ALG_RSA\n", migrationKeyAuth.migrationKey.algorithmParms.algorithmID); returnCode = TPM_BAD_KEY_PROPERTY; } } /* ii. Validate that migrationKeyAuth -> migrationKey -> algorithmParms -> encScheme is an encryption scheme supported by the TPM */ if (returnCode == TPM_SUCCESS) { if (migrationKeyAuth.migrationKey.algorithmParms.encScheme != TPM_ES_RSAESOAEP_SHA1_MGF1) { printf("TPM_Process_CMK_CreateBlob: Error, " "encScheme %04hx not TPM_ES_RSAESOAEP_SHA1_MGF1\n", migrationKeyAuth.migrationKey.algorithmParms.encScheme ); returnCode = TPM_INAPPROPRIATE_ENC; } } /* iii. Validate that migrationKeyAuth -> migrationKey ->algorithmParms -> sigScheme is TPM_SS_NONE */ if (returnCode == TPM_SUCCESS) { if (migrationKeyAuth.migrationKey.algorithmParms.sigScheme != TPM_SS_NONE) { printf("TPM_Process_CMK_CreateBlob: Error, sigScheme %04hx not TPM_SS_NONE\n", migrationKeyAuth.migrationKey.algorithmParms.sigScheme); returnCode = TPM_INVALID_KEYUSAGE; } } /* c. The TPM MAY validate that restrictTicketSize is zero. */ if (returnCode == TPM_SUCCESS) { if (restrictTicketBuffer.size != 0) { printf("TPM_Process_CMK_CreateBlob: Error, " "TPM_MS_RESTRICT_MIGRATE and restrictTicketSize %u not zero\n", restrictTicketBuffer.size); returnCode = TPM_BAD_PARAMETER; } } /* d. The TPM MAY validate that sigTicketSize is zero. */ if (returnCode == TPM_SUCCESS) { if (sigTicketBuffer.size != 0) { printf("TPM_Process_CMK_CreateBlob: Error, " "TPM_MS_RESTRICT_MIGRATE and sigTicketSize %u not zero\n", sigTicketBuffer.size); returnCode = TPM_BAD_PARAMETER; } } } /* 9. If migrationKeyAuth -> migrationScheme == TPM_MS_RESTRICT_APPROVE */ else if ((returnCode == TPM_SUCCESS) && (migrationKeyAuth.migrationScheme == TPM_MS_RESTRICT_APPROVE)) { /* a. Verify that the intended migration destination has been approved by the MSA: */ /* i. Verify that for one of the n=1 to n=(msaList -> MSAlist) values of msaList -> migAuthDigest[n], sigTicket == HMAC (V1) using tpmProof as the secret where V1 is a TPM_CMK_SIGTICKET structure such that: */ /* (1) V1 -> verKeyDigest = msaList -> migAuthDigest[n] */ /* (2) V1 -> signedData = SHA-1[restrictTicket] */ printf("TPM_Process_CMK_CreateBlob: migrationScheme is TPM_MS_RESTRICT_APPROVE_DOUBLE\n"); /* deserialize the sigTicket TPM_HMAC */ if (returnCode == TPM_SUCCESS) { stream = sigTicketBuffer.buffer; stream_size = sigTicketBuffer.size; returnCode = TPM_Digest_Load(sigTicket, &stream, &stream_size); } if (returnCode == TPM_SUCCESS) { returnCode = TPM_SHA1(v1CmkSigticket.signedData, restrictTicketBuffer.size, restrictTicketBuffer.buffer, 0, NULL); } if (returnCode == TPM_SUCCESS) { returnCode = TPM_MsaComposite_CheckSigTicket(sigTicket, tpm_state->tpm_permanent_data.tpmProof, &msaList, &v1CmkSigticket); } /* ii. If [restrictTicket -> destinationKeyDigest] != SHA-1[migrationKeyAuth -> migrationKey], return error TPM_MA_DESTINATION */ /* deserialize the restrictTicket structure */ if (returnCode == TPM_SUCCESS) { stream = restrictTicketBuffer.buffer; stream_size = restrictTicketBuffer.size; returnCode = TPM_CmkAuth_Load(&restrictTicket, &stream, &stream_size); } if (returnCode == TPM_SUCCESS) { returnCode = TPM_Digest_Compare(migrationKeyDigest, restrictTicket.destinationKeyDigest); if (returnCode != TPM_SUCCESS) { printf("TPM_Process_CMK_CreateBlob: Error, no match to destinationKeyDigest\n"); returnCode = TPM_MA_DESTINATION; } } /* iii. If [restrictTicket -> sourceKeyDigest] != pubSourceKeyDigest, return error TPM_MA_SOURCE */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Digest_Compare(pubSourceKeyDigest, restrictTicket.sourceKeyDigest); if (returnCode != TPM_SUCCESS) { printf("TPM_Process_CMK_CreateBlob: Error, no match to sourceKeyDigest\n"); returnCode = TPM_MA_SOURCE; } } } /* 10. Else return with error TPM_BAD_PARAMETER. */ else if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CMK_CreateBlob: Error, Illegal migrationScheme %04hx\n", migrationKeyAuth.migrationScheme); returnCode = TPM_BAD_PARAMETER; } /* 11. Build two bytes array, K1 and K2, using d1: */ /* a. K1 = TPM_STORE_ASYMKEY.privKey[0..19] (TPM_STORE_ASYMKEY.privKey.keyLength + 16 bytes of TPM_STORE_ASYMKEY.privKey.key), sizeof(K1) = 20 */ /* b. K2 = TPM_STORE_ASYMKEY.privKey[20..131] (position 16-127 of TPM_STORE_ASYMKEY.privKey.key), sizeof(K2) = 112 */ /* 12. Build M1 a TPM_MIGRATE_ASYMKEY structure */ /* a. TPM_MIGRATE_ASYMKEY.payload = TPM_PT_CMK_MIGRATE */ /* b. TPM_MIGRATE_ASYMKEY.usageAuth = TPM_STORE_ASYMKEY.usageAuth */ /* c. TPM_MIGRATE_ASYMKEY.pubDataDigest = TPM_STORE_ASYMKEY.pubDataDigest */ /* d. TPM_MIGRATE_ASYMKEY.partPrivKeyLen = 112 - 127. */ /* e. TPM_MIGRATE_ASYMKEY.partPrivKey = K2 */ /* 13. Create o1 (which SHALL be 198 bytes for a 2048 bit RSA key) by performing the OAEP encoding of m using OAEP parameters m, pHash, and seed */ /* a. m is the previously created M1 */ /* b. pHash = SHA-1( SHA-1[msaList] || pubSourceKeyDigest) */ /* c. seed = s1 = the previously created K1 */ /* 14. Create r1 a random value from the TPM RNG. The size of r1 MUST be the size of o1. Return r1 in the */ /* random parameter */ /* 15. Create x1 by XOR of o1 with r1 */ /* 16. Copy r1 into the output field "random" */ /* 17. Encrypt x1 with the migrationKeyAuth-> migrationKey */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SHA1(pHash, TPM_DIGEST_SIZE, m2CmkMigauth.msaDigest, TPM_DIGEST_SIZE, pubSourceKeyDigest, 0, NULL); } if (returnCode == TPM_SUCCESS) { returnCode = TPM_CreateBlobCommon(&outData, &d1AsymKey, pHash, TPM_PT_CMK_MIGRATE, &random, &(migrationKeyAuth.migrationKey)); } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_CMK_CreateBlob: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* return random */ returnCode = TPM_SizedBuffer_Store(response, &random); } if (returnCode == TPM_SUCCESS) { /* return outData */ returnCode = TPM_SizedBuffer_Store(response, &outData); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* owner HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, parentAuthHandle); } /* cleanup */ free(d1Decrypt); /* @1 */ TPM_Migrationkeyauth_Delete(&migrationKeyAuth); /* @2 */ TPM_SizedBuffer_Delete(&msaListBuffer); /* @3 */ TPM_SizedBuffer_Delete(&restrictTicketBuffer); /* @4 */ TPM_SizedBuffer_Delete(&sigTicketBuffer); /* @5 */ TPM_SizedBuffer_Delete(&encData); /* @6 */ TPM_SizedBuffer_Delete(&random); /* @7 */ TPM_SizedBuffer_Delete(&outData); /* @8 */ TPM_Sbuffer_Delete(&mka_sbuffer); /* @9 */ TPM_StoreAsymkey_Delete(&d1AsymKey); /* @10 */ TPM_MsaComposite_Delete(&msaList); /* @11 */ TPM_CmkAuth_Delete(&restrictTicket); /* @12 */ TPM_CmkMigauth_Delete(&m2CmkMigauth); /* @13 */ TPM_CmkSigticket_Delete(&v1CmkSigticket); /* @14 */ return rcf; } /* 11.7 TPM_CMK_SetRestrictions rev 96 This command is used by the Owner to dictate the usage of a certified-migration key with delegated authorisation (authorisation other than actual Owner authorisation). This command is provided for privacy reasons and must not itself be delegated, because a certified-migration-key may involve a contractual relationship between the Owner and an external entity. Since restrictions are validated at DSAP session use, there is no need to invalidate DSAP sessions when the restriction value changes. */ TPM_RESULT TPM_Process_CMK_SetRestrictions(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_CMK_DELEGATE restriction; /* The bit mask of how to set the restrictions on CMK keys */ TPM_AUTHHANDLE authHandle; /* The authorization handle TPM Owner authorization */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization handle */ TPM_AUTHDATA ownerAuth; /* The authorization digest. HMAC key: TPM Owner Auth */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_SECRET *hmacKey; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_CMK_SetRestrictions: Ordinal Entry\n"); /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get restriction */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&restriction, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CMK_SetRestrictions: restriction %08x\n", restriction); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag1(tag); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, ownerAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_CMK_SetRestrictions: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* 1. Validate the ordinal and parameters using TPM Owner authorization, return TPM_AUTHFAIL on error */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_OWNER, ordinal, NULL, &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ } if (returnCode == TPM_SUCCESS) { TPM_PrintFour("TPM_Process_CMK_SetRestrictions: ownerAuth secret", *hmacKey); returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* owner HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, ownerAuth); /* Authorization digest for input */ } /* 2. Set TPM_PERMANENT_DATA -> TPM_CMK_DELEGATE -> restrictDelegate = restriction */ if (returnCode == TPM_SUCCESS) { /* only update NVRAM if the value is changing */ if (tpm_state->tpm_permanent_data.restrictDelegate != restriction) { tpm_state->tpm_permanent_data.restrictDelegate = restriction; /* Store the permanent data back to NVRAM */ printf("TPM_Process_CMK_SetRestrictions: Storing permanent data\n"); returnCode = TPM_PermanentAll_NVStore(tpm_state, TRUE, /* write NV */ 0); /* no roll back */ } else { printf("TPM_Process_CMK_SetRestrictions: No change to value\n"); } } /* 3. Return TPM_SUCCESS */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_CMK_SetRestrictions: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* owner HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ return rcf; } /* 11.6 TPM_CMK_ApproveMA 87 This command creates an authorization ticket, to allow the TPM owner to specify which Migration Authorities they approve and allow users to create certified-migration-keys without further involvement with the TPM owner. It is the responsibility of the TPM Owner to determine whether a particular Migration Authority is suitable to control migration. */ TPM_RESULT TPM_Process_CMK_ApproveMA(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_DIGEST migrationAuthorityDigest; /* A digest of a TPM_MSA_COMPOSITE structure (itself one or more digests of public keys belonging to migration authorities) */ TPM_AUTHHANDLE authHandle; /* The authorization session handle used for owner authentication. */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization session handle */ TPM_AUTHDATA ownerAuth; /* Authorization HMAC, key: ownerAuth. */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_SECRET *hmacKey; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ TPM_CMK_MA_APPROVAL m2CmkMaApproval; /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_HMAC outData; /* HMAC of migrationAuthorityDigest */ printf("TPM_Process_CMK_ApproveMA: Ordinal Entry\n"); TPM_CmkMaApproval_Init(&m2CmkMaApproval); /* freed @1 */ /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get migrationAuthorityDigest */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Digest_Load(migrationAuthorityDigest, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag1(tag); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, ownerAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_CMK_ApproveMA: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* 1. Validate the AuthData to use the TPM by the TPM Owner */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_OWNER, ordinal, NULL, &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ } if (returnCode == TPM_SUCCESS) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* owner HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, ownerAuth); /* Authorization digest for input */ } if (returnCode == TPM_SUCCESS) { /* 2. Create M2 a TPM_CMK_MA_APPROVAL structure */ /* NOTE Done by TPM_CmkMaApproval_Init() */ /* a. Set M2 ->migrationAuthorityDigest to migrationAuthorityDigest */ TPM_Digest_Copy(m2CmkMaApproval.migrationAuthorityDigest, migrationAuthorityDigest); /* 3. Set outData = HMAC(M2) using tpmProof as the secret */ returnCode = TPM_HMAC_GenerateStructure (outData, /* HMAC */ tpm_state->tpm_permanent_data.tpmProof, /* HMAC key */ &m2CmkMaApproval, /* structure */ (TPM_STORE_FUNCTION_T)TPM_CmkMaApproval_Store); /* store function */ } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_CMK_ApproveMA: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* return the outData */ returnCode = TPM_Digest_Store(response, outData); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ TPM_CmkMaApproval_Delete(&m2CmkMaApproval); /* @1 */ return rcf; } /* 11.10 TPM_CMK_ConvertMigration rev 106 TPM_CMK_ConvertMigration completes the migration of certified migration blobs. This command takes a certified migration blob and creates a normal wrapped blob with payload type TPM_PT_MIGRATE_EXTERNAL. The migrated blob must be loaded into the TPM using the normal TPM_LoadKey function. Note that the command migrates private keys, only. The migration of the associated public keys is not specified by TPM because they are not security sensitive. Migration of the associated public keys may be specified in a platform specific specification. A TPM_KEY structure must be recreated before the migrated key can be used by the target TPM in a LoadKey command. TPM_CMK_ConvertMigration checks that one of the MAs implicitly listed in the migrationAuth of the target key has approved migration of the target key to the destination (parent) key, and that the settings (flags etc.) in the target key are those of a CMK. */ TPM_RESULT TPM_Process_CMK_ConvertMigration(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_KEY_HANDLE parentHandle; /* Handle of a loaded key that can decrypt keys. */ TPM_CMK_AUTH restrictTicket; /* The digests of public keys belonging to the Migration Authority, the destination parent key and the key-to-be-migrated. */ TPM_HMAC sigTicket; /* A signature ticket, generated by the TPM, signaling a valid signature over restrictTicket */ TPM_KEY migratedKey; /* The public key of the key-to-be-migrated. The private portion MUST be TPM_MIGRATE_ASYMKEY properly XOR'd */ TPM_SIZED_BUFFER msaListBuffer; /* One or more digests of public keys belonging to migration authorities */ TPM_SIZED_BUFFER random; /* Random value used to hide key data. */ TPM_AUTHHANDLE authHandle; /* The authorization session handle used for keyHandle. */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession; /* The continue use flag for the authorization session handle */ TPM_AUTHDATA parentAuth; /* Authorization HMAC: parentKey.usageAuth */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_SECRET *hmacKey; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ TPM_KEY *parentKey; TPM_BOOL parentPCRStatus; TPM_SECRET *parentUsageAuth; unsigned char *d1Decrypt; uint32_t d1DecryptLength = 0; /* actual valid data */ BYTE *o1Oaep; unsigned char *stream; /* for deserializing structures */ uint32_t stream_size; TPM_MSA_COMPOSITE msaList; TPM_DIGEST msaListDigest; TPM_DIGEST migratedPubKeyDigest; TPM_STORE_ASYMKEY d2AsymKey; TPM_STORE_BUFFER d2_sbuffer; TPM_DIGEST parentPubKeyDigest; TPM_CMK_SIGTICKET v1CmkSigticket; TPM_CMK_MIGAUTH m2CmkMigauth; /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_SIZED_BUFFER outData; /* The encrypted private key that can be loaded with TPM_LoadKey */ printf("TPM_Process_CMK_ConvertMigration: Ordinal Entry\n"); TPM_CmkAuth_Init(&restrictTicket); /* freed @1 */ TPM_Key_Init(&migratedKey); /* freed @2 */ TPM_SizedBuffer_Init(&msaListBuffer); /* freed @3 */ TPM_SizedBuffer_Init(&random); /* freed @4 */ TPM_SizedBuffer_Init(&outData); /* freed @5 */ d1Decrypt = NULL; /* freed @6 */ TPM_MsaComposite_Init(&msaList); /* freed @7 */ TPM_StoreAsymkey_Init(&d2AsymKey); /* freed @8 */ TPM_Sbuffer_Init(&d2_sbuffer); /* freed @9 */ TPM_CmkSigticket_Init(&v1CmkSigticket); /* freed @10 */ o1Oaep = NULL; /* freed @11 */ TPM_CmkMigauth_Init(&m2CmkMigauth); /* freed @12 */ /* get inputs */ /* get parentHandle */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&parentHandle, &command, ¶mSize); } /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get restrictTicket */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CMK_ConvertMigration: parentHandle %08x\n", parentHandle); returnCode = TPM_CmkAuth_Load(&restrictTicket, &command, ¶mSize); } /* get sigTicket */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Digest_Load(sigTicket, &command, ¶mSize); } /* get migratedKey */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Key_Load(&migratedKey, &command, ¶mSize); } /* get msaListBuffer */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_Load(&msaListBuffer, &command, ¶mSize); } /* get random */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_Load(&random, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag1(tag); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, parentAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_CMK_ConvertMigration: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* 1. Validate the AuthData to use the key in parentHandle */ /* get the key associated with parentHandle */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyHandleEntries_GetKey(&parentKey, &parentPCRStatus, tpm_state, parentHandle, FALSE, /* not r/o, using private key */ FALSE, /* do not ignore PCRs */ FALSE); /* cannot use EK */ } /* get parentHandle -> usageAuth */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Key_GetUsageAuth(&parentUsageAuth, parentKey); } /* get the session data */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_KEYHANDLE, ordinal, parentKey, parentUsageAuth, /* OIAP */ parentKey->tpm_store_asymkey->pubDataDigest); /*OSAP*/ } /* 1. Validate the authorization to use the key in parentHandle */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, parentAuth); /* Authorization digest for input */ } /* 2. If the keyUsage field of the key referenced by parentHandle does not have the value TPM_KEY_STORAGE, the TPM must return the error code TPM_INVALID_KEYUSAGE */ if (returnCode == TPM_SUCCESS) { if (parentKey->keyUsage != TPM_KEY_STORAGE) { printf("TPM_Process_CMK_ConvertMigration: Error, " "parentHandle -> keyUsage should be TPM_KEY_STORAGE, is %04x\n", parentKey->keyUsage); returnCode = TPM_INVALID_KEYUSAGE; } } /* 3. Create d1 by decrypting the migratedKey -> encData area using the key in parentHandle */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CMK_ConvertMigration: Decrypting encData\n"); TPM_PrintFour("TPM_Process_CMK_ConvertMigration: encData", migratedKey.encData.buffer); returnCode = TPM_RSAPrivateDecryptMalloc(&d1Decrypt, /* decrypted data */ &d1DecryptLength, /* actual size of d1 data */ migratedKey.encData.buffer, /* encrypted data */ migratedKey.encData.size, parentKey); } /* the random input parameter must be the same length as the decrypted data */ if (returnCode == TPM_SUCCESS) { if (d1DecryptLength != random.size) { printf("TPM_Process_CMK_ConvertMigration: Error " "decrypt data length %u random size %u\n", d1DecryptLength, random.size); returnCode = TPM_BAD_PARAMETER; } } /* allocate memory for o1 */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Malloc(&o1Oaep, d1DecryptLength); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CMK_ConvertMigration: d1 length %u\n", d1DecryptLength); TPM_PrintFour("TPM_Process_CMK_ConvertMigration: d1 -", d1Decrypt); /* 4. Create o1 by XOR d1 and random parameter */ TPM_XOR(o1Oaep, d1Decrypt, random.buffer, d1DecryptLength); /* 5. Create m1 a TPM_MIGRATE_ASYMKEY, seed and pHash by OAEP decoding o1 */ /* 7. Create k1 by combining seed and the TPM_MIGRATE_ASYMKEY -> partPrivKey */ /* 8. Create d2 a TPM_STORE_ASYMKEY structure */ /* a. Set the TPM_STORE_ASYMKEY -> privKey field to k1 */ /* b. Set d2 -> usageAuth to m1 -> usageAuth */ /* c. Set d2 -> pubDataDigest to m1 -> pubDataDigest */ returnCode = TPM_StoreAsymkey_LoadO1(&d2AsymKey, o1Oaep, d1DecryptLength); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CMK_ConvertMigration: Checking pHash\n"); /* 6. Create migratedPubKey a TPM_PUBKEY structure corresponding to migratedKey */ /* NOTE this function goes directly to the SHA1 digest */ returnCode = TPM_Key_GeneratePubkeyDigest(migratedPubKeyDigest, &migratedKey); } /* 6.a. Verify that pHash == SHA-1( SHA-1[msaList] || SHA-1(migratedPubKey ) */ /* deserialize to msaListBuffer to msaList */ if (returnCode == TPM_SUCCESS) { stream = msaListBuffer.buffer; stream_size = msaListBuffer.size; returnCode = TPM_MsaComposite_Load(&msaList, &stream, &stream_size); } if (returnCode == TPM_SUCCESS) { returnCode = TPM_SHA1_GenerateStructure(msaListDigest, &msaList, (TPM_STORE_FUNCTION_T)TPM_MsaComposite_Store); } /* pHash is returned in TPM_STORE_ASYMKEY -> migrationAuth */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SHA1_Check(d2AsymKey.migrationAuth, TPM_DIGEST_SIZE, msaListDigest, TPM_DIGEST_SIZE, migratedPubKeyDigest, 0, NULL); } /* 9. Verify that parentHandle-> keyFlags -> migratable == FALSE and parentHandle-> encData -> migrationAuth == tpmProof */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CMK_ConvertMigration: Checking parent key\n"); if (parentKey->keyFlags & TPM_MIGRATABLE) { printf("TPM_Process_CMK_ConvertMigration: Error, parent migratable\n"); returnCode = TPM_INVALID_KEYUSAGE; } } /* 10. Verify that m1 -> payload == TPM_PT_CMK_MIGRATE, then set d2-> payload = TPM_PT_MIGRATE_EXTERNAL */ /* NOTE TPM_StoreAsymkey_LoadO1() copied TPM_MIGRATE_ASYMKEY -> payload to TPM_STORE_ASYMKEY -> payload */ if (returnCode == TPM_SUCCESS) { if (d2AsymKey.payload != TPM_PT_CMK_MIGRATE) { printf("TPM_Process_CMK_ConvertMigration: Error, invalid payload %02x\n", d2AsymKey.payload); returnCode = TPM_BAD_MIGRATION; } else { d2AsymKey.payload = TPM_PT_MIGRATE_EXTERNAL; } } /* 11. Verify that for one of the n=1 to n=(msaList -> MSAlist) values of msaList -> migAuthDigest[n], sigTicket == HMAC (V1) using tpmProof as the secret where V1 is a TPM_CMK_SIGTICKET structure such that: */ /* a. V1 -> verKeyDigest = msaList -> migAuthDigest[n] */ /* b. V1 -> signedData = SHA-1[restrictTicket] */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CMK_ConvertMigration: Checking sigTicket\n"); /* generate SHA1[restrictTicket] */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SHA1_GenerateStructure(v1CmkSigticket.signedData, &restrictTicket, (TPM_STORE_FUNCTION_T)TPM_CmkAuth_Store); } if (returnCode == TPM_SUCCESS) { TPM_PrintFour(" TPM_Process_CMK_ConvertMigration: TPM_CMK_SIGTICKET -> sigTicket", v1CmkSigticket.signedData); returnCode = TPM_MsaComposite_CheckSigTicket(sigTicket, tpm_state->tpm_permanent_data.tpmProof, &msaList, &v1CmkSigticket); } } /* 12. Create parentPubKey, a TPM_PUBKEY structure corresponding to parenthandle */ if (returnCode == TPM_SUCCESS) { /* NOTE this function goes directly to the SHA1 digest */ returnCode = TPM_Key_GeneratePubkeyDigest(parentPubKeyDigest, parentKey); } /* 13. If [restrictTicket -> destinationKeyDigest] != SHA-1(parentPubKey), return error TPM_MA_DESTINATION */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Digest_Compare(restrictTicket.destinationKeyDigest, parentPubKeyDigest); if (returnCode != TPM_SUCCESS) { printf("TPM_Process_CMK_ConvertMigration: Error checking destinationKeyDigest\n"); returnCode = TPM_MA_DESTINATION; } } /* 14. Verify that migratedKey is corresponding to d2 */ /* NOTE check the private key against the public key */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_StorePrivkey_Convert(&d2AsymKey, &(migratedKey.algorithmParms), &(migratedKey.pubKey)); } /* 15. If migratedKey -> keyFlags -> migratable is FALSE, and return error TPM_INVALID_KEYUSAGE */ if (returnCode == TPM_SUCCESS) { if (!(migratedKey.keyFlags & TPM_MIGRATABLE)) { printf("TPM_Process_CMK_ConvertMigration: Error, migratedKey migratable is FALSE\n"); returnCode = TPM_INVALID_KEYUSAGE; } } /* 16. If migratedKey -> keyFlags -> migrateAuthority is FALSE, return error TPM_INVALID_KEYUSAGE */ if (returnCode == TPM_SUCCESS) { if (!(migratedKey.keyFlags & TPM_MIGRATEAUTHORITY)) { printf("TPM_Process_CMK_ConvertMigration: Error, " "migratedKey migrateauthority is FALSE\n"); returnCode = TPM_INVALID_KEYUSAGE; } } /* 17. If [restrictTicket -> sourceKeyDigest] != SHA-1(migratedPubKey), return error TPM_MA_SOURCE */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Digest_Compare(restrictTicket.sourceKeyDigest, migratedPubKeyDigest); if (returnCode != TPM_SUCCESS) { printf("TPM_Process_CMK_ConvertMigration: Error checking sourceKeyDigest\n"); returnCode = TPM_MA_SOURCE; } } /* 18. Create M2 a TPM_CMK_MIGAUTH structure */ /* NOTE Done by TPM_CmkMigauth_Init() */ /* a. Set M2 -> msaDigest to SHA-1[msaList] */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SHA1_GenerateStructure(m2CmkMigauth.msaDigest, &msaList, (TPM_STORE_FUNCTION_T)TPM_MsaComposite_Store); } if (returnCode == TPM_SUCCESS) { /* b. Set M2 -> pubKeyDigest to SHA-1[migratedPubKey] */ TPM_Digest_Copy(m2CmkMigauth.pubKeyDigest, migratedPubKeyDigest); /* 19. Set d2 -> migrationAuth = HMAC(M2) using tpmProof as the secret */ returnCode = TPM_HMAC_GenerateStructure (d2AsymKey.migrationAuth, /* HMAC */ tpm_state->tpm_permanent_data.tpmProof, /* HMAC key */ &m2CmkMigauth, /* structure */ (TPM_STORE_FUNCTION_T)TPM_CmkMigauth_Store); /* store function */ } /* 21. Create outData using the key in parentHandle to perform the encryption */ if (returnCode == TPM_SUCCESS) { /* serialize d2Asymkey to d2_sbuffer */ returnCode = TPM_StoreAsymkey_Store(&d2_sbuffer, FALSE, &d2AsymKey); } if (returnCode == TPM_SUCCESS) { returnCode = TPM_RSAPublicEncryptSbuffer_Key(&outData, &d2_sbuffer, parentKey); } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_CMK_ConvertMigration: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* return the outData */ returnCode = TPM_SizedBuffer_Store(response, &outData); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ TPM_CmkAuth_Delete(&restrictTicket); /* @1 */ TPM_Key_Delete(&migratedKey); /* @2 */ TPM_SizedBuffer_Delete(&msaListBuffer); /* @3 */ TPM_SizedBuffer_Delete(&random); /* @4 */ TPM_SizedBuffer_Delete(&outData); /* @5 */ free(d1Decrypt); /* @6 */ TPM_MsaComposite_Delete(&msaList); /* @7 */ TPM_StoreAsymkey_Delete(&d2AsymKey); /* @8 */ TPM_Sbuffer_Delete(&d2_sbuffer); /* @9 */ TPM_CmkSigticket_Delete(&v1CmkSigticket); /* @10 */ free(o1Oaep); /* @11 */ TPM_CmkMigauth_Delete(&m2CmkMigauth); /* @12 */ return rcf; } libtpms-0.9.3/src/tpm12/tpm_migration.h000066400000000000000000000262261421143571500177640ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Migration */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_migration.h 4071 2010-04-29 19:26:45Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_MIGRATION_H #define TPM_MIGRATION_H #include "tpm_global.h" /* TPM_MIGRATIONKEYAUTH */ void TPM_Migrationkeyauth_Init(TPM_MIGRATIONKEYAUTH *tpm_migrationkeyauth); TPM_RESULT TPM_Migrationkeyauth_Load(TPM_MIGRATIONKEYAUTH *tpm_migrationkeyauth, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_Migrationkeyauth_Store(TPM_STORE_BUFFER *sbuffer, TPM_MIGRATIONKEYAUTH *tpm_migrationkeyauth); void TPM_Migrationkeyauth_Delete(TPM_MIGRATIONKEYAUTH *tpm_migrationkeyauth); /* TPM_MSA_COMPOSITE */ void TPM_MsaComposite_Init(TPM_MSA_COMPOSITE *tpm_msa_composite); TPM_RESULT TPM_MsaComposite_Load(TPM_MSA_COMPOSITE *tpm_msa_composite, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_MsaComposite_Store(TPM_STORE_BUFFER *sbuffer, const TPM_MSA_COMPOSITE *tpm_msa_composite); void TPM_MsaComposite_Delete(TPM_MSA_COMPOSITE *tpm_msa_composite); TPM_RESULT TPM_MsaComposite_CheckMigAuthDigest(TPM_DIGEST tpm_digest, TPM_MSA_COMPOSITE *tpm_msa_composite); TPM_RESULT TPM_MsaComposite_CheckSigTicket(TPM_DIGEST sigTicket, TPM_SECRET tpmProof, TPM_MSA_COMPOSITE *tpm_msa_composite, TPM_CMK_SIGTICKET *tpm_cmk_sigticket); /* TPM_CMK_AUTH */ void TPM_CmkAuth_Init(TPM_CMK_AUTH *tpm_cmk_auth); TPM_RESULT TPM_CmkAuth_Load(TPM_CMK_AUTH *tpm_cmk_auth, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_CmkAuth_Store(TPM_STORE_BUFFER *sbuffer, const TPM_CMK_AUTH *tpm_cmk_auth); void TPM_CmkAuth_Delete(TPM_CMK_AUTH *tpm_cmk_auth); /* TPM_CMK_MIGAUTH */ void TPM_CmkMigauth_Init(TPM_CMK_MIGAUTH *tpm_cmk_migauth); TPM_RESULT TPM_CmkMigauth_Load(TPM_CMK_MIGAUTH *tpm_cmk_migauth, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_CmkMigauth_Store(TPM_STORE_BUFFER *sbuffer, const TPM_CMK_MIGAUTH *tpm_cmk_migauth); void TPM_CmkMigauth_Delete(TPM_CMK_MIGAUTH *tpm_cmk_migauth); TPM_RESULT TPM_CmkMigauth_CheckHMAC(TPM_BOOL *valid, TPM_HMAC tpm_hmac, TPM_SECRET tpm_hmac_key, TPM_CMK_MIGAUTH *tpm_cmk_migauth); /* TPM_CMK_SIGTICKET */ void TPM_CmkSigticket_Init(TPM_CMK_SIGTICKET *tpm_cmk_sigticket); TPM_RESULT TPM_CmkSigticket_Load(TPM_CMK_SIGTICKET *tpm_cmk_sigticket, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_CmkSigticket_Store(TPM_STORE_BUFFER *sbuffer, const TPM_CMK_SIGTICKET *tpm_cmk_sigticket); void TPM_CmkSigticket_Delete(TPM_CMK_SIGTICKET *tpm_cmk_sigticket); /* TPM_CMK_MA_APPROVAL */ void TPM_CmkMaApproval_Init(TPM_CMK_MA_APPROVAL *tpm_cmk_ma_approval); TPM_RESULT TPM_CmkMaApproval_Load(TPM_CMK_MA_APPROVAL *tpm_cmk_ma_approval, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_CmkMaApproval_Store(TPM_STORE_BUFFER *sbuffer, const TPM_CMK_MA_APPROVAL *tpm_cmk_ma_approval); void TPM_CmkMaApproval_Delete(TPM_CMK_MA_APPROVAL *tpm_cmk_ma_approval); TPM_RESULT TPM_CmkMaApproval_CheckHMAC(TPM_BOOL *valid, TPM_HMAC tpm_hmac, TPM_SECRET tpm_hmac_key, TPM_CMK_MA_APPROVAL *tpm_cmk_ma_approval); /* Processing Functions */ TPM_RESULT TPM_CreateBlobCommon(TPM_SIZED_BUFFER *outData, TPM_STORE_ASYMKEY *d1Key, TPM_DIGEST pHash, TPM_PAYLOAD_TYPE payload_type, TPM_SIZED_BUFFER *random, TPM_PUBKEY *migrationKey); TPM_RESULT TPM_Process_CreateMigrationBlob(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_ConvertMigrationBlob(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_AuthorizeMigrationKey(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_MigrateKey(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_CMK_CreateKey(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_CMK_CreateTicket(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_CMK_CreateBlob(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_CMK_SetRestrictions(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_CMK_ApproveMA(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_CMK_ConvertMigration(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); #endif libtpms-0.9.3/src/tpm12/tpm_nonce.c000066400000000000000000000120051421143571500170560ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Nonce Handler */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_nonce.c 4071 2010-04-29 19:26:45Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include #include #include "tpm_crypto.h" #include "tpm_debug.h" #include "tpm_error.h" #include "tpm_structures.h" #include "tpm_nonce.h" /* TPM_Nonce_Init resets a nonce structure to zeros */ void TPM_Nonce_Init(TPM_NONCE tpm_nonce) { size_t i; printf(" TPM_Nonce_Init:\n"); for (i = 0 ; i < TPM_NONCE_SIZE ; i++) { tpm_nonce[i] = 0; } return; } /* TPM_Nonce_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes */ TPM_RESULT TPM_Nonce_Load(TPM_NONCE tpm_nonce, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_Nonce_Load:\n"); rc = TPM_Loadn(tpm_nonce, TPM_NONCE_SIZE, stream, stream_size); return rc; } /* TPM_Nonce_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes After use, call TPM_Sbuffer_Delete() to free memory */ TPM_RESULT TPM_Nonce_Store(TPM_STORE_BUFFER *sbuffer, const TPM_NONCE tpm_nonce) { TPM_RESULT rc = 0; printf(" TPM_Nonce_Store:\n"); rc = TPM_Sbuffer_Append(sbuffer, tpm_nonce, TPM_NONCE_SIZE); return rc; } /* TPM_Nonce_Copy() copies the source to the destination */ void TPM_Nonce_Copy(TPM_NONCE destination, const TPM_NONCE source) { printf(" TPM_Nonce_Copy:\n"); memcpy(destination, source, TPM_NONCE_SIZE); return; } /* TPM_Nonce_Compare() compares the source to the destination. Returns TPM_AUTHFAIL if the nonces are not equal */ TPM_RESULT TPM_Nonce_Compare(TPM_NONCE expect, const TPM_NONCE actual) { TPM_RESULT rc = 0; printf(" TPM_Nonce_Compare:\n"); rc = memcmp(expect, actual, TPM_NONCE_SIZE); if (rc != 0) { printf("TPM_Nonce_Compare: Error comparing nonce\n"); TPM_PrintFour(" TPM_Nonce_Compare: Expect", expect); TPM_PrintFour(" TPM_Nonce_Compare: Actual", actual); rc = TPM_AUTHFAIL; } return rc; } /* TPM_Nonce_Generate() generates a new nonce from the random number generator */ TPM_RESULT TPM_Nonce_Generate(TPM_NONCE tpm_nonce) { TPM_RESULT rc = 0; printf(" TPM_Nonce_Generate:\n"); rc = TPM_Random(tpm_nonce, TPM_NONCE_SIZE); return rc; } /* TPM_Nonce_IsZero() returns 'isZero' TRUE is all bytes 'tpm_nonce' are 0x00 */ void TPM_Nonce_IsZero(TPM_BOOL *isZero, TPM_NONCE tpm_nonce) { size_t i; printf(" TPM_Nonce_IsZero:\n"); for (i = 0, *isZero = TRUE ; (i < TPM_NONCE_SIZE) && *isZero ; i++) { if (tpm_nonce[i] != 0) { *isZero = FALSE; } } return; } libtpms-0.9.3/src/tpm12/tpm_nonce.h000066400000000000000000000060551421143571500170730ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Nonce Handler */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_nonce.h 4071 2010-04-29 19:26:45Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_NONCE_H #define TPM_NONCE_H #include "tpm_store.h" #include "tpm_structures.h" void TPM_Nonce_Init(TPM_NONCE tpm_nonce); TPM_RESULT TPM_Nonce_Generate(TPM_NONCE tpm_nonce); void TPM_Nonce_Copy(TPM_NONCE destination, const TPM_NONCE source); TPM_RESULT TPM_Nonce_Load(TPM_NONCE tpm_nonce, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_Nonce_Store(TPM_STORE_BUFFER *sbuffer, const TPM_NONCE tpm_nonce); TPM_RESULT TPM_Nonce_Compare(TPM_NONCE expect, const TPM_NONCE actual); void TPM_Nonce_IsZero(TPM_BOOL *isZero, TPM_NONCE tpm_nonce); #endif libtpms-0.9.3/src/tpm12/tpm_nvram.c000066400000000000000000004240011421143571500171020ustar00rootroot00000000000000/********************************************************************************/ /* */ /* NVRAM Utilities */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_nvram.c 4724 2014-08-11 20:33:23Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include #include #include #include #include "tpm_auth.h" #include "tpm_crypto.h" #include "tpm_cryptoh.h" #include "tpm_debug.h" #include "tpm_digest.h" #include "tpm_error.h" #include "tpm_io.h" #include "tpm_memory.h" #include "tpm_nvfile.h" #include "tpm_pcr.h" #include "tpm_permanent.h" #include "tpm_platform.h" #include "tpm_process.h" #include "tpm_secret.h" #include "tpm_storage.h" #include "tpm_structures.h" #include "tpm_nvram.h" /* NV Defined Space Utilities */ /* TPM_NV_ATTRIBUTES */ /* TPM_NVAttributes_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_NVAttributes_Init(TPM_NV_ATTRIBUTES *tpm_nv_attributes) { printf(" TPM_NVAttributes_Init:\n"); tpm_nv_attributes->attributes = 0; return; } /* TPM_NVAttributes_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_NVAttributes_Init() After use, call TPM_NVAttributes_Delete() to free memory */ TPM_RESULT TPM_NVAttributes_Load(TPM_NV_ATTRIBUTES *tpm_nv_attributes, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_NVAttributes_Load:\n"); /* check tag */ if (rc == 0) { rc = TPM_CheckTag(TPM_TAG_NV_ATTRIBUTES, stream, stream_size); } /* load attributes */ if (rc == 0) { rc = TPM_Load32(&(tpm_nv_attributes->attributes), stream, stream_size); } return rc; } /* TPM_NVAttributes_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_NVAttributes_Store(TPM_STORE_BUFFER *sbuffer, const TPM_NV_ATTRIBUTES *tpm_nv_attributes) { TPM_RESULT rc = 0; printf(" TPM_NVAttributes_Store:\n"); /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_NV_ATTRIBUTES); } if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_nv_attributes->attributes); } return rc; } /* TPM_NVAttributes_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the nv_attributes sets pointers to NULL calls TPM_NVAttributes_Init to set members back to default values The object itself is not freed */ void TPM_NVAttributes_Delete(TPM_NV_ATTRIBUTES *tpm_nv_attributes) { printf(" TPM_NVAttributes_Delete:\n"); if (tpm_nv_attributes != NULL) { TPM_NVAttributes_Init(tpm_nv_attributes); } return; } void TPM_NVAttributes_Copy(TPM_NV_ATTRIBUTES *tpm_nv_attributes_dest, TPM_NV_ATTRIBUTES *tpm_nv_attributes_src) { tpm_nv_attributes_dest->attributes = tpm_nv_attributes_src->attributes; return; } /* TPM_NV_DATA_PUBLIC */ /* TPM_NVDataPublic_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_NVDataPublic_Init(TPM_NV_DATA_PUBLIC *tpm_nv_data_public) { printf(" TPM_NVDataPublic_Init:\n"); tpm_nv_data_public->nvIndex = TPM_NV_INDEX_LOCK; /* mark unused */ TPM_PCRInfoShort_Init(&(tpm_nv_data_public->pcrInfoRead)); TPM_PCRInfoShort_Init(&(tpm_nv_data_public->pcrInfoWrite)); TPM_NVAttributes_Init(&(tpm_nv_data_public->permission)); tpm_nv_data_public->bReadSTClear = FALSE; tpm_nv_data_public->bWriteSTClear = FALSE; tpm_nv_data_public->bWriteDefine = FALSE; tpm_nv_data_public->dataSize = 0; return; } /* TPM_NVDataPublic_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_NVDataPublic_Init() After use, call TPM_NVDataPublic_Delete() to free memory */ TPM_RESULT TPM_NVDataPublic_Load(TPM_NV_DATA_PUBLIC *tpm_nv_data_public, unsigned char **stream, uint32_t *stream_size, TPM_BOOL optimize) { TPM_RESULT rc = 0; printf(" TPM_NVDataPublic_Load:\n"); /* check tag */ if (rc == 0) { rc = TPM_CheckTag(TPM_TAG_NV_DATA_PUBLIC, stream, stream_size); } /* load nvIndex */ if (rc == 0) { rc = TPM_Load32(&(tpm_nv_data_public->nvIndex), stream, stream_size); } /* load pcrInfoRead */ if (rc == 0) { rc = TPM_PCRInfoShort_Load(&(tpm_nv_data_public->pcrInfoRead), stream, stream_size, optimize); } /* load pcrInfoWrite */ if (rc == 0) { rc = TPM_PCRInfoShort_Load(&(tpm_nv_data_public->pcrInfoWrite), stream, stream_size, optimize); } /* load permission */ if (rc == 0) { rc = TPM_NVAttributes_Load(&(tpm_nv_data_public->permission), stream, stream_size); } /* load bReadSTClear */ if (rc == 0) { rc = TPM_LoadBool(&(tpm_nv_data_public->bReadSTClear), stream, stream_size); } /* load bWriteSTClear */ if (rc == 0) { rc = TPM_LoadBool(&(tpm_nv_data_public->bWriteSTClear), stream, stream_size); } /* load bWriteDefine */ if (rc == 0) { rc = TPM_LoadBool(&(tpm_nv_data_public->bWriteDefine), stream, stream_size); } /* load dataSize */ if (rc == 0) { rc = TPM_Load32(&(tpm_nv_data_public->dataSize), stream, stream_size); } return rc; } /* TPM_NVDataPublic_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_NVDataPublic_Store(TPM_STORE_BUFFER *sbuffer, const TPM_NV_DATA_PUBLIC *tpm_nv_data_public, TPM_BOOL optimize) { TPM_RESULT rc = 0; printf(" TPM_NVDataPublic_Store:\n"); /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_NV_DATA_PUBLIC); } /* store nvIndex */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_nv_data_public->nvIndex); } /* store pcrInfoRead */ if (rc == 0) { rc = TPM_PCRInfoShort_Store(sbuffer, &(tpm_nv_data_public->pcrInfoRead), optimize); } /* store pcrInfoWrite */ if (rc == 0) { rc = TPM_PCRInfoShort_Store(sbuffer, &(tpm_nv_data_public->pcrInfoWrite), optimize); } /* store permission */ if (rc == 0) { rc = TPM_NVAttributes_Store(sbuffer, &(tpm_nv_data_public->permission)); } /* store bReadSTClear */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_nv_data_public->bReadSTClear), sizeof(TPM_BOOL)); } /* store bWriteSTClear */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_nv_data_public->bWriteSTClear), sizeof(TPM_BOOL)); } /* store bWriteDefine */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_nv_data_public->bWriteDefine), sizeof(TPM_BOOL)); } /* store dataSize */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_nv_data_public->dataSize); } return rc; } /* TPM_NVDataPublic_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_NVDataPublic_Init to set members back to default values The object itself is not freed */ void TPM_NVDataPublic_Delete(TPM_NV_DATA_PUBLIC *tpm_nv_data_public) { printf(" TPM_NVDataPublic_Delete:\n"); if (tpm_nv_data_public != NULL) { TPM_PCRInfoShort_Delete(&(tpm_nv_data_public->pcrInfoRead)); TPM_PCRInfoShort_Delete(&(tpm_nv_data_public->pcrInfoWrite)); TPM_NVAttributes_Delete(&(tpm_nv_data_public->permission)); TPM_NVDataPublic_Init(tpm_nv_data_public); } return; } /* TPM_NV_DATA_SENSITIVE */ /* TPM_NVDataSensitive_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_NVDataSensitive_Init(TPM_NV_DATA_SENSITIVE *tpm_nv_data_sensitive) { printf(" TPM_NVDataSensitive_Init:\n"); TPM_NVDataPublic_Init(&(tpm_nv_data_sensitive->pubInfo)); TPM_Secret_Init(tpm_nv_data_sensitive->authValue); tpm_nv_data_sensitive->data = NULL; TPM_Digest_Init(tpm_nv_data_sensitive->digest); return; } /* TPM_NVDataSensitive_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_NVDataSensitive_Init() After use, call TPM_NVDataSensitive_Delete() to free memory */ TPM_RESULT TPM_NVDataSensitive_Load(TPM_NV_DATA_SENSITIVE *tpm_nv_data_sensitive, TPM_TAG nvEntriesVersion, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; TPM_BOOL optimize; TPM_BOOL isGPIO; printf(" TPM_NVDataSensitive_Load: nvEntriesVersion %04hx\n", nvEntriesVersion); /* check tag */ if (rc == 0) { rc = TPM_CheckTag(TPM_TAG_NV_DATA_SENSITIVE, stream, stream_size); } /* load pubInfo */ if (rc == 0) { /* versions after V1 optimise the serialization */ optimize = (nvEntriesVersion != TPM_TAG_NVSTATE_NV_V1); rc = TPM_NVDataPublic_Load(&(tpm_nv_data_sensitive->pubInfo), stream, stream_size, optimize); /* optimize digestAtRelease */ } /* load authValue */ if (rc == 0) { rc = TPM_Secret_Load(tpm_nv_data_sensitive->authValue, stream, stream_size); } /* is the nvIndex GPIO space */ if (rc == 0) { rc = TPM_NVDataSensitive_IsGPIO(&isGPIO, tpm_nv_data_sensitive->pubInfo.nvIndex); } /* allocate memory for data */ if ((rc == 0) && !isGPIO) { rc = TPM_Malloc(&(tpm_nv_data_sensitive->data), tpm_nv_data_sensitive->pubInfo.dataSize); } /* load data */ if ((rc == 0) && !isGPIO) { rc = TPM_Loadn(tpm_nv_data_sensitive->data, tpm_nv_data_sensitive->pubInfo.dataSize, stream, stream_size); } /* create digest. The digest is not stored to save NVRAM space */ if (rc == 0) { rc = TPM_SHA1(tpm_nv_data_sensitive->digest, sizeof(TPM_NV_INDEX), (unsigned char *)&tpm_nv_data_sensitive->pubInfo.nvIndex, TPM_AUTHDATA_SIZE, tpm_nv_data_sensitive->authValue, 0, NULL); } return rc; } /* TPM_NVDataSensitive_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes nvWrite TRUE indicates a write command, not a command to define the space. */ TPM_RESULT TPM_NVDataSensitive_Store(TPM_STORE_BUFFER *sbuffer, const TPM_NV_DATA_SENSITIVE *tpm_nv_data_sensitive) { TPM_RESULT rc = 0; TPM_BOOL isGPIO; printf(" TPM_NVDataSensitive_Store:\n"); /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_NV_DATA_SENSITIVE); } /* store pubInfo */ if (rc == 0) { rc = TPM_NVDataPublic_Store(sbuffer, &(tpm_nv_data_sensitive->pubInfo), TRUE); /* optimize digestAtRelease */ } /* store authValue */ if (rc == 0) { rc = TPM_Secret_Store(sbuffer, tpm_nv_data_sensitive->authValue); } /* is the nvIndex GPIO space */ if (rc == 0) { rc = TPM_NVDataSensitive_IsGPIO(&isGPIO, tpm_nv_data_sensitive->pubInfo.nvIndex); } /* store data */ if ((rc == 0) && !isGPIO) { rc = TPM_Sbuffer_Append(sbuffer, tpm_nv_data_sensitive->data, tpm_nv_data_sensitive->pubInfo.dataSize); } return rc; } /* TPM_NVDataSensitive_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_NVDataSensitive_Init to set members back to default values The object itself is not freed */ void TPM_NVDataSensitive_Delete(TPM_NV_DATA_SENSITIVE *tpm_nv_data_sensitive) { printf(" TPM_NVDataSensitive_Delete:\n"); if (tpm_nv_data_sensitive != NULL) { /* zero any secrets in NV index data */ if (tpm_nv_data_sensitive->data != NULL) { memset(tpm_nv_data_sensitive->data, 0xff, tpm_nv_data_sensitive->pubInfo.dataSize); } TPM_NVDataPublic_Delete(&(tpm_nv_data_sensitive->pubInfo)); TPM_Secret_Delete(tpm_nv_data_sensitive->authValue); free(tpm_nv_data_sensitive->data); TPM_NVDataSensitive_Init(tpm_nv_data_sensitive); } return; } /* TPM_NVDataSensitive_IsValidIndex() determines if 'nvIndex' is permissible for an NV defined space TPM_NV_DATA_SENSITIVE structure. Some values have special meaning, so they are allowed for the TPM_NV_DefineSpace command but will not actually define a space. */ TPM_RESULT TPM_NVDataSensitive_IsValidIndex(TPM_NV_INDEX nvIndex) { TPM_RESULT rc = 0; TPM_BOOL isGPIO; printf(" TPM_NVDataSensitive_IsValidIndex: nvIndex %08x\n", nvIndex); if (rc == 0) { if ((nvIndex == TPM_NV_INDEX_LOCK) || (nvIndex == TPM_NV_INDEX0) || (nvIndex == TPM_NV_INDEX_DIR)) { printf("TPM_NVDataSensitive_IsValidIndex: Error, illegal special index\n"); rc = TPM_BADINDEX; } } if (rc == 0) { if ((nvIndex & TPM_NV_INDEX_RESVD) != 0) { printf("TPM_NVDataSensitive_IsValidIndex: Error, illegal reserved index\n"); rc = TPM_BADINDEX; } } if (rc == 0) { rc = TPM_NVDataSensitive_IsValidPlatformIndex(nvIndex); } /* The GPIO range validity is platform dependent */ if (rc == 0) { rc = TPM_NVDataSensitive_IsGPIO(&isGPIO, nvIndex); } return rc; } /* TPM_NVDataSensitive_IsGPIO() determines if 'nvIndex' is in the GPIO range and is valid. Returns: TPM_SUCCESS , FALSE if 'nvIndex' is not in the GPIO range TPM_SUCCESS , TRUE if 'nvIndex' is in the GPIO range and the platform allows GPIO defined space TPM_BADINDEX, FALSE if 'nvIndex' is in the GPIO range and the platform does not allow GPIO defined space */ TPM_RESULT TPM_NVDataSensitive_IsGPIO(TPM_BOOL *isGPIO, TPM_NV_INDEX nvIndex) { TPM_RESULT rc = 0; printf(" TPM_NVDataSensitive_IsGPIO: nvIndex %08x\n", nvIndex); *isGPIO = FALSE; #if defined TPM_PCCLIENT if (rc == 0) { /* GPIO space allowed for PC Client */ if ((nvIndex >= TPM_NV_INDEX_GPIO_START) && (nvIndex <= TPM_NV_INDEX_GPIO_END)) { printf(" TPM_NVDataSensitive_IsGPIO: nvIndex is GPIO space\n"); *isGPIO = TRUE; } } /* #elif */ #else if (rc == 0) { /* GPIO space cannot be defined in platforms with no GPIO */ if ((nvIndex >= TPM_NV_INDEX_GPIO_START) && (nvIndex <= TPM_NV_INDEX_GPIO_END)) { printf("TPM_NVDataSensitive_IsGPIO: Error, illegal index\n"); rc = TPM_BADINDEX; } } #endif return rc; } TPM_RESULT TPM_NVDataSensitive_IsValidPlatformIndex(TPM_NV_INDEX nvIndex) { TPM_RESULT rc = 0; printf(" TPM_NVDataSensitive_IsValidPlatformIndex: nvIndex %08x\n", nvIndex); #ifndef TPM_PCCLIENT if (rc == 0) { if (((nvIndex & TPM_NV_INDEX_PURVIEW_MASK) >> TPM_NV_INDEX_PURVIEW_BIT) == TPM_PC) { printf(" TPM_NVDataSensitive_IsValidPlatformIndex: Error, PC Client index\n"); rc = TPM_BADINDEX; } } #endif return rc; } /* NV Index Entries This handles the in-memory copy of NV defined space */ /* TPM_NVIndexEntries_Init() initializes the TPM_NV_INDEX_ENTRIES array */ void TPM_NVIndexEntries_Init(TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries) { printf(" TPM_NVIndexEntries_Init:\n"); tpm_nv_index_entries->nvIndexCount = 0; tpm_nv_index_entries->tpm_nvindex_entry = NULL; return; } /* TPM_NVIndexEntries_Delete() iterates through the entire TPM_NV_INDEX_ENTRIES array, deleting any used entries. It then frees and reinitializes the array. */ void TPM_NVIndexEntries_Delete(TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries) { size_t i; printf(" TPM_NVIndexEntries_Delete: Deleting from %u slots\n", tpm_nv_index_entries->nvIndexCount); /* free the entries */ for (i = 0 ; i < tpm_nv_index_entries->nvIndexCount ; i++) { TPM_NVDataSensitive_Delete(&(tpm_nv_index_entries->tpm_nvindex_entry[i])); } /* free the array */ free(tpm_nv_index_entries->tpm_nvindex_entry); TPM_NVIndexEntries_Init(tpm_nv_index_entries); return; } /* TPM_NVIndexEntries_Trace() traces the TPM_NV_INDEX_ENTRIES array. Edit and call as required for debugging. */ void TPM_NVIndexEntries_Trace(TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries) { uint32_t i; TPM_NV_DATA_SENSITIVE *tpm_nv_data_sensitive; printf("\tTPM_NVIndexEntries_Trace: %u slots\n", tpm_nv_index_entries->nvIndexCount); for (i = 0 ; i < tpm_nv_index_entries->nvIndexCount ; i++) { tpm_nv_data_sensitive = &(tpm_nv_index_entries->tpm_nvindex_entry[i]); printf("\tTPM_NVIndexEntries_Trace: TPM_NV_DATA_SENSITIVE.data %p\n", tpm_nv_data_sensitive->data); } return; } /* TPM_NVIndexEntries_Load() loads the TPM_NV_INDEX_ENTRIES array from a stream. The first data in the stream must be a uint32_t count of the number of entries to follow. */ TPM_RESULT TPM_NVIndexEntries_Load(TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; uint32_t i; TPM_TAG nvEntriesVersion; printf(" TPM_NVIndexEntries_Load:\n"); /* get the NV entries version number */ if (rc == 0) { rc = TPM_Load16(&nvEntriesVersion, stream, stream_size); } /* check tag */ if (rc == 0) { switch (nvEntriesVersion) { case TPM_TAG_NVSTATE_NV_V1: case TPM_TAG_NVSTATE_NV_V2: break; default: printf("TPM_NVIndexEntries_Load: Error (fatal), version %04x unsupported\n", nvEntriesVersion); rc = TPM_FAIL; break; } } /* nvIndexCount */ if (rc == 0) { rc = TPM_Load32(&(tpm_nv_index_entries->nvIndexCount), stream, stream_size); } /* allocate memory for the array, nvIndexCount TPM_NV_DATA_SENSITIVE structures */ if ((rc == 0) && (tpm_nv_index_entries->nvIndexCount > 0)) { printf(" TPM_NVIndexEntries_Load: Loading %u slots\n", tpm_nv_index_entries->nvIndexCount); rc = TPM_Malloc((unsigned char **)&(tpm_nv_index_entries->tpm_nvindex_entry), sizeof(TPM_NV_DATA_SENSITIVE) * tpm_nv_index_entries->nvIndexCount); } /* immediately after allocating, initialize so that _Delete is safe even on a _Load error */ for (i = 0 ; (rc == 0) && (i < tpm_nv_index_entries->nvIndexCount) ; i++) { TPM_NVDataSensitive_Init(&(tpm_nv_index_entries->tpm_nvindex_entry[i])); } /* tpm_nvindex_entry array */ for (i = 0 ; (rc == 0) && (i < tpm_nv_index_entries->nvIndexCount) ; i++) { printf(" TPM_NVIndexEntries_Load: Loading slot %u\n", i); if (rc == 0) { rc = TPM_NVDataSensitive_Load(&(tpm_nv_index_entries->tpm_nvindex_entry[i]), nvEntriesVersion, stream, stream_size); } /* should never load an unused entry */ if (rc == 0) { printf(" TPM_NVIndexEntries_Load: Loaded NV index %08x\n", tpm_nv_index_entries->tpm_nvindex_entry[i].pubInfo.nvIndex); if (tpm_nv_index_entries->tpm_nvindex_entry[i].pubInfo.nvIndex == TPM_NV_INDEX_LOCK) { printf("TPM_NVIndexEntries_Load: Error (fatal) Entry %u bad NV index %08x\n", i, tpm_nv_index_entries->tpm_nvindex_entry[i].pubInfo.nvIndex); rc = TPM_FAIL; } } } return rc; } /* TPM_NVIndexEntries_Store() serializes the TPM_NV_INDEX_ENTRIES array into a stream. Only used entries are serialized. The first data in the stream is the used count, obtained by iterating through the array. */ TPM_RESULT TPM_NVIndexEntries_Store(TPM_STORE_BUFFER *sbuffer, TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries) { TPM_RESULT rc = 0; uint32_t count; /* number of used entries to store */ size_t i; printf(" TPM_NVIndexEntries_Store: Storing from %u slots\n", tpm_nv_index_entries->nvIndexCount); /* append the NV entries version number to the stream */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_NVSTATE_NV_V2); } /* count the number of used entries */ if (rc == 0) { rc = TPM_NVIndexEntries_GetUsedCount(&count, tpm_nv_index_entries); } /* store the actual used count, not the number of array entries */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, count); } /* tpm_nvindex_entry array */ for (i = 0 ; (rc == 0) && (i < tpm_nv_index_entries->nvIndexCount) ; i++) { /* if the entry is used */ if (tpm_nv_index_entries->tpm_nvindex_entry[i].pubInfo.nvIndex != TPM_NV_INDEX_LOCK) { printf(" TPM_NVIndexEntries_Store: Storing slot %lu NV index %08x\n", (unsigned long)i, tpm_nv_index_entries->tpm_nvindex_entry[i].pubInfo.nvIndex); rc = TPM_NVDataSensitive_Store(sbuffer, &(tpm_nv_index_entries->tpm_nvindex_entry[i])); } else { printf(" TPM_NVIndexEntries_Store: Skipping unused slot %lu\n", (unsigned long)i); } } return rc; } /* TPM_NVIndexEntries_StClear() steps through each entry in the NV TPM_NV_INDEX_ENTRIES array, setting the volatile flags to FALSE. */ void TPM_NVIndexEntries_StClear(TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries) { size_t i; printf(" TPM_NVIndexEntries_StClear: Clearing %u slots\n", tpm_nv_index_entries->nvIndexCount); /* bReadSTClear and bWriteSTClear are volatile, in that they are set FALSE at TPM_Startup(ST_Clear) */ for (i = 0 ; i < tpm_nv_index_entries->nvIndexCount ; i++) { tpm_nv_index_entries->tpm_nvindex_entry[i].pubInfo.bReadSTClear = FALSE; tpm_nv_index_entries->tpm_nvindex_entry[i].pubInfo.bWriteSTClear = FALSE; } return; } /* TPM_NVIndexEntries_LoadVolatile() deserializes the stream into the volatile members of the TPM_NV_INDEX_ENTRIES array. */ TPM_RESULT TPM_NVIndexEntries_LoadVolatile(TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; uint32_t usedCount; uint32_t entryIndex; TPM_NV_DATA_PUBLIC *tpm_nv_data_public; printf(" TPM_NVIndexEntries_LoadVolatile:\n"); /* check tag */ if (rc == 0) { rc = TPM_CheckTag(TPM_TAG_NV_INDEX_ENTRIES_VOLATILE_V1, stream, stream_size); } /* Get the number of used slots. This should be equal to the total number of slots. */ if (rc == 0) { rc = TPM_Load32(&usedCount, stream, stream_size); } if (rc == 0) { printf(" TPM_NVIndexEntries_LoadVolatile: usedCount %u\n", usedCount); if (usedCount != tpm_nv_index_entries->nvIndexCount) { printf("TPM_NVIndexEntries_LoadVolatile: Error (fatal), " "usedCount %u does not equal slot count %u\n", usedCount, tpm_nv_index_entries->nvIndexCount); rc = TPM_FAIL; } } /* deserialize the stream into the TPM_NV_INDEX_ENTRIES array */ for (entryIndex = 0 ; (rc == 0) && (entryIndex < tpm_nv_index_entries->nvIndexCount) ; entryIndex++) { tpm_nv_data_public = &(tpm_nv_index_entries->tpm_nvindex_entry[entryIndex].pubInfo); printf(" TPM_NVIndexEntries_LoadVolatile: Loading index %08x\n", tpm_nv_data_public->nvIndex); /* load bReadSTClear */ if (rc == 0) { rc = TPM_LoadBool(&(tpm_nv_data_public->bReadSTClear), stream, stream_size); } /* load bWriteSTClear */ if (rc == 0) { rc = TPM_LoadBool(&(tpm_nv_data_public->bWriteSTClear), stream, stream_size); } } return rc; } /* TPM_NVIndexEntries_StoreVolatile() serializes the volatile members of the TPM_NV_INDEX_ENTRIES array into the TPM_STORE_BUFFER. */ TPM_RESULT TPM_NVIndexEntries_StoreVolatile(TPM_STORE_BUFFER *sbuffer, TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries) { TPM_RESULT rc = 0; uint32_t usedCount; uint32_t entryIndex; TPM_NV_DATA_PUBLIC *tpm_nv_data_public; printf(" TPM_NVIndexEntries_StoreVolatile: %u slots\n", tpm_nv_index_entries->nvIndexCount); /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_NV_INDEX_ENTRIES_VOLATILE_V1); } /* Get the number of used slots. If indexes were deleted since the last TPM_Init, there can be some unused slots. */ if (rc == 0) { rc = TPM_NVIndexEntries_GetUsedCount(&usedCount, tpm_nv_index_entries); } /* store usedCount */ if (rc == 0) { printf(" TPM_NVIndexEntries_StoreVolatile: usedCount %u\n", usedCount); rc = TPM_Sbuffer_Append32(sbuffer, usedCount); } /* save entries into the array */ for (entryIndex = 0 ; (rc == 0) && (entryIndex < tpm_nv_index_entries->nvIndexCount) ; entryIndex++) { /* Only save used slots. During a rollback, slots are deleted and recreated. At that time, unused slots will be reclaimed. */ if (tpm_nv_index_entries->tpm_nvindex_entry[entryIndex].pubInfo.nvIndex != TPM_NV_INDEX_LOCK) { tpm_nv_data_public = &(tpm_nv_index_entries->tpm_nvindex_entry[entryIndex].pubInfo); printf(" TPM_NVIndexEntries_StoreVolatile: Storing index %08x\n", tpm_nv_data_public->nvIndex); /* store bReadSTClear */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_nv_data_public->bReadSTClear), sizeof(TPM_BOOL)); } /* store bWriteSTClear */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_nv_data_public->bWriteSTClear), sizeof(TPM_BOOL)); } } } return rc; } /* TPM_NVIndexEntries_GetVolatile() saves an array of the NV defined space volatile flags. The array is used during a rollback, since the volatile flags are not stored in NVRAM */ TPM_RESULT TPM_NVIndexEntries_GetVolatile(TPM_NV_DATA_ST **tpm_nv_data_st, /* freed by caller */ TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries) { TPM_RESULT rc = 0; uint32_t usedCount; uint32_t entryIndex; uint32_t usedIndex; printf(" TPM_NVIndexEntries_GetVolatile: %u slots\n", tpm_nv_index_entries->nvIndexCount); /* Get the number of used slots. If indexes were deleted since the last TPM_Init, there can be some unused slots. */ if (rc == 0) { rc = TPM_NVIndexEntries_GetUsedCount(&usedCount, tpm_nv_index_entries); } /* allocate memory for the array, nvIndexCount TPM_NV_DATA_SENSITIVE structures */ if ((rc == 0) && (usedCount > 0)) { printf(" TPM_NVIndexEntries_GetVolatile: Aloocating for %u used slots\n", usedCount); rc = TPM_Malloc((unsigned char **)tpm_nv_data_st, sizeof(TPM_NV_DATA_ST) * usedCount); } /* save entries into the array */ for (entryIndex = 0 , usedIndex = 0 ; (rc == 0) && (entryIndex < tpm_nv_index_entries->nvIndexCount) && (usedCount > 0) ; entryIndex++) { /* Only save used slots. During a rollback, slots are deleted and recreated. At that time, unused slots will be reclaimed. */ if (tpm_nv_index_entries->tpm_nvindex_entry[entryIndex].pubInfo.nvIndex != TPM_NV_INDEX_LOCK) { printf(" TPM_NVIndexEntries_GetVolatile: Saving slot %u at used %u NV index %08x\n", entryIndex, usedIndex, tpm_nv_index_entries->tpm_nvindex_entry[entryIndex].pubInfo.nvIndex); printf(" TPM_NVIndexEntries_GetVolatile: bReadSTClear %u bWriteSTClear %u\n", tpm_nv_index_entries->tpm_nvindex_entry[entryIndex].pubInfo.bReadSTClear, tpm_nv_index_entries->tpm_nvindex_entry[entryIndex].pubInfo.bWriteSTClear); (*tpm_nv_data_st)[usedIndex].nvIndex = tpm_nv_index_entries->tpm_nvindex_entry[entryIndex].pubInfo.nvIndex; (*tpm_nv_data_st)[usedIndex].bReadSTClear = tpm_nv_index_entries->tpm_nvindex_entry[entryIndex].pubInfo.bReadSTClear; (*tpm_nv_data_st)[usedIndex].bWriteSTClear = tpm_nv_index_entries->tpm_nvindex_entry[entryIndex].pubInfo.bWriteSTClear; usedIndex++; } } return rc; } /* TPM_NVIndexEntries_SetVolatile() restores an array of the NV defined space volatile flags. The array is used during a rollback, since the volatile flags are not stored in NVRAM */ TPM_RESULT TPM_NVIndexEntries_SetVolatile(TPM_NV_DATA_ST *tpm_nv_data_st, TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries) { TPM_RESULT rc = 0; uint32_t usedCount; uint32_t i; printf(" TPM_NVIndexEntries_SetVolatile: %u slots\n", tpm_nv_index_entries->nvIndexCount); /* Get the number of used slots. This should be equal to the total number of slots. */ if (rc == 0) { rc = TPM_NVIndexEntries_GetUsedCount(&usedCount, tpm_nv_index_entries); } if (rc == 0) { if (usedCount != tpm_nv_index_entries->nvIndexCount) { printf("TPM_NVIndexEntries_SetVolatile: Error (fatal), " "usedCount %u does not equal slot count %u\n", usedCount, tpm_nv_index_entries->nvIndexCount); rc = TPM_FAIL; } } /* if the used count is non-zero, the volatile array should not be NULL */ if (rc == 0) { if ((usedCount > 0) && (tpm_nv_data_st == NULL)) { printf("TPM_NVIndexEntries_SetVolatile: Error (fatal), " "usedCount %u unconsistant with volatile array NULL\n", usedCount); rc = TPM_FAIL; } } /* copy entries into the array */ for (i = 0 ; (rc == 0) && (i < tpm_nv_index_entries->nvIndexCount) ; i++) { printf(" TPM_NVIndexEntries_SetVolatile: slot %u index %08x\n", i, tpm_nv_index_entries->tpm_nvindex_entry[i].pubInfo.nvIndex); /* sanity check on a mismatch of entries between the save and restore */ if (tpm_nv_index_entries->tpm_nvindex_entry[i].pubInfo.nvIndex != tpm_nv_data_st[i].nvIndex) { printf("TPM_NVIndexEntries_SetVolatile: Error (fatal), " "mismatch NV entry %08x, saved %08x\n", tpm_nv_index_entries->tpm_nvindex_entry[i].pubInfo.nvIndex, tpm_nv_data_st[i].nvIndex); rc = TPM_FAIL; } /* restore entries from the array */ else { printf(" TPM_NVIndexEntries_SetVolatile: bReadSTClear %u bWriteSTClear %u\n", tpm_nv_data_st[i].bReadSTClear, tpm_nv_data_st[i].bWriteSTClear); tpm_nv_index_entries->tpm_nvindex_entry[i].pubInfo.bReadSTClear = tpm_nv_data_st[i].bReadSTClear; tpm_nv_index_entries->tpm_nvindex_entry[i].pubInfo.bWriteSTClear = tpm_nv_data_st[i].bWriteSTClear; } } return rc; } /* TPM_NVIndexEntries_GetFreeEntry() gets a free entry in the TPM_NV_INDEX_ENTRIES array. If a free entry exists, it it returned. It should already be initialized. If a free entry does not exist, it it created and initialized. If a slot cannot be created, tpm_nv_data_sensitive returns NULL, so a subsequent free is safe. */ TPM_RESULT TPM_NVIndexEntries_GetFreeEntry(TPM_NV_DATA_SENSITIVE **tpm_nv_data_sensitive, TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries) { TPM_RESULT rc = 0; TPM_BOOL done = FALSE; size_t i; printf(" TPM_NVIndexEntries_GetFreeEntry: Searching %u slots\n", tpm_nv_index_entries->nvIndexCount); /* for debug - trace the entire TPM_NV_INDEX_ENTRIES array */ for (i = 0 ; i < tpm_nv_index_entries->nvIndexCount ; i++) { *tpm_nv_data_sensitive = &(tpm_nv_index_entries->tpm_nvindex_entry[i]); printf(" TPM_NVIndexEntries_GetFreeEntry: slot %lu entry %08x\n", (unsigned long)i, (*tpm_nv_data_sensitive)->pubInfo.nvIndex); } /* search the existing array for a free entry */ for (i = 0 ; (rc == 0) && (i < tpm_nv_index_entries->nvIndexCount) && !done ; i++) { *tpm_nv_data_sensitive = &(tpm_nv_index_entries->tpm_nvindex_entry[i]); /* if the entry is not used */ if ((*tpm_nv_data_sensitive)->pubInfo.nvIndex == TPM_NV_INDEX_LOCK) { printf(" TPM_NVIndexEntries_GetFreeEntry: Found free slot %lu\n", (unsigned long)i); done = TRUE; } } /* need to expand the array */ if ((rc == 0) && !done) { *tpm_nv_data_sensitive = NULL; rc = TPM_Realloc((unsigned char **)&(tpm_nv_index_entries->tpm_nvindex_entry), sizeof(TPM_NV_DATA_SENSITIVE) * (i + 1)); } /* initialize the new entry in the array */ if ((rc == 0) && !done) { printf(" TPM_NVIndexEntries_GetFreeEntry: Created new slot at index %lu\n", (unsigned long)i); *tpm_nv_data_sensitive = &(tpm_nv_index_entries->tpm_nvindex_entry[i]); TPM_NVDataSensitive_Init(*tpm_nv_data_sensitive); tpm_nv_index_entries->nvIndexCount++; } return rc; } /* TPM_NVIndexEntries_GetEntry() gets the TPM_NV_DATA_SENSITIVE entry corresponding to nvIndex. Returns TPM_BADINDEX on non-existent nvIndex */ TPM_RESULT TPM_NVIndexEntries_GetEntry(TPM_NV_DATA_SENSITIVE **tpm_nv_data_sensitive, TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries, TPM_NV_INDEX nvIndex) { TPM_RESULT rc = 0; size_t i; TPM_BOOL found; printf(" TPM_NVIndexEntries_GetEntry: Getting NV index %08x in %u slots\n", nvIndex, tpm_nv_index_entries->nvIndexCount); /* for debug tracing */ for (i = 0 ; i < tpm_nv_index_entries->nvIndexCount ; i++) { *tpm_nv_data_sensitive = &(tpm_nv_index_entries->tpm_nvindex_entry[i]); printf(" TPM_NVIndexEntries_GetEntry: slot %lu entry %08x\n", (unsigned long)i, (*tpm_nv_data_sensitive)->pubInfo.nvIndex); } /* check for the special index that indicates an empty entry */ if (rc == 0) { if (nvIndex == TPM_NV_INDEX_LOCK) { rc = TPM_BADINDEX; } } for (i = 0 , found = FALSE ; (rc == 0) && (i < tpm_nv_index_entries->nvIndexCount) && !found ; i++) { *tpm_nv_data_sensitive = &(tpm_nv_index_entries->tpm_nvindex_entry[i]); if ((*tpm_nv_data_sensitive)->pubInfo.nvIndex == nvIndex) { printf(" TPM_NVIndexEntries_GetEntry: Found NV index at slot %lu\n", (unsigned long)i); printf(" TPM_NVIndexEntries_GetEntry: permission %08x dataSize %u\n", (*tpm_nv_data_sensitive)->pubInfo.permission.attributes, (*tpm_nv_data_sensitive)->pubInfo.dataSize); printf(" TPM_NVIndexEntries_GetEntry: " "bReadSTClear %02x bWriteSTClear %02x bWriteDefine %02x\n", (*tpm_nv_data_sensitive)->pubInfo.bReadSTClear, (*tpm_nv_data_sensitive)->pubInfo.bWriteSTClear, (*tpm_nv_data_sensitive)->pubInfo.bWriteDefine); found = TRUE; } } if (rc == 0) { if (!found) { printf(" TPM_NVIndexEntries_GetEntry: NV index not found\n"); rc = TPM_BADINDEX; } } return rc; } /* TPM_NVIndexEntries_GetUsedCount() returns the number of used entries in the TPM_NV_INDEX_ENTRIES array. At startup, all entries will be used. If an NV index is deleted, the entryis marked unused, but the TPM_NV_INDEX_ENTRIES space is not reclaimed until the next startup. */ TPM_RESULT TPM_NVIndexEntries_GetUsedCount(uint32_t *count, TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries) { TPM_RESULT rc = 0; size_t i; *count = 0; for (i = 0 ; (rc == 0) && (i < tpm_nv_index_entries->nvIndexCount) ; i++) { /* if the entry is used */ if (tpm_nv_index_entries->tpm_nvindex_entry[i].pubInfo.nvIndex != TPM_NV_INDEX_LOCK) { (*count)++; } } printf(" TPM_NVIndexEntries_GetUsedCount: Used count %d in %u slots\n", *count, tpm_nv_index_entries->nvIndexCount); return rc; } /* TPM_NVIndexEntries_GetNVList() serializes a list of the used NV indexes into the TPM_STORE_BUFFER */ TPM_RESULT TPM_NVIndexEntries_GetNVList(TPM_STORE_BUFFER *sbuffer, TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries) { TPM_RESULT rc = 0; size_t i; printf(" TPM_NVIndexEntries_GetNVList: Creating list from %u slots\n", tpm_nv_index_entries->nvIndexCount); for (i = 0 ; (rc == 0) && (i < tpm_nv_index_entries->nvIndexCount) ; i++) { /* if the entry is used */ if (tpm_nv_index_entries->tpm_nvindex_entry[i].pubInfo.nvIndex != TPM_NV_INDEX_LOCK) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_nv_index_entries->tpm_nvindex_entry[i].pubInfo.nvIndex); } } return rc; } /* TPM_NVIndexEntries_GetUsedSpace() gets the NV space consumed by NV defined space indexes. It does it inefficiently but reliably by serializing the structure with the same function used when writing to NV storage. */ TPM_RESULT TPM_NVIndexEntries_GetUsedSpace(uint32_t *usedSpace, TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries) { TPM_RESULT rc = 0; TPM_STORE_BUFFER sbuffer; const unsigned char *buffer; printf(" TPM_NVIndexEntries_GetUsedSpace:\n"); TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ /* serialize NV defined space */ if (rc == 0) { rc = TPM_NVIndexEntries_Store(&sbuffer, tpm_nv_index_entries); } /* get the serialized buffer and its length */ if (rc == 0) { TPM_Sbuffer_Get(&sbuffer, &buffer, usedSpace); printf(" TPM_NVIndexEntries_GetUsedSpace: Used space %u\n", *usedSpace); } TPM_Sbuffer_Delete(&sbuffer); /* @1 */ return rc; } /* TPM_NVIndexEntries_GetFreeSpace() gets the total free NV defined space. When defining an index, not all can be used for data, as some is consumed by metadata such as authorization and the index number. */ TPM_RESULT TPM_NVIndexEntries_GetFreeSpace(uint32_t *freeSpace, TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries) { TPM_RESULT rc = 0; uint32_t usedSpace; printf(" TPM_NVIndexEntries_GetFreeSpace:\n"); /* get the used space */ if (rc == 0) { rc = TPM_NVIndexEntries_GetUsedSpace(&usedSpace, tpm_nv_index_entries); } /* sanity check */ if (rc == 0) { if (usedSpace > TPM_MAX_NV_DEFINED_SIZE) { printf("TPM_NVIndexEntries_GetFreeSpace: used %u greater than max %u\n", usedSpace, TPM_MAX_NV_DEFINED_SIZE); rc = TPM_NOSPACE; } } /* calculate the free space */ if (rc == 0) { *freeSpace = TPM_MAX_NV_DEFINED_SIZE - usedSpace; printf(" TPM_NVIndexEntries_GetFreeSpace: Free space %u\n", *freeSpace); } return rc; } /* TPM_OwnerClear: rev 99 12. The TPM MUST deallocate all defined NV storage areas where a. TPM_NV_PER_OWNERWRITE is TRUE if nvIndex does not have the "D" bit set b. TPM_NV_PER_OWNERREAD is TRUE if nvIndex does not have the "D" bit set c. The TPM MUST NOT deallocate any other currently defined NV storage areas. TPM_RevokeTrust: a. NV items with the pubInfo -> nvIndex D value set MUST be deleted. This changes the TPM_OwnerClear handling of the same NV areas If deleteAllNvram is TRUE, all NVRAM is deleted. If it is FALSE, indexes with the D bit set are not cleared. The write to NV space is done bu the caller. */ TPM_RESULT TPM_NVIndexEntries_DeleteOwnerAuthorized(TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries, TPM_BOOL deleteAllNvram) { TPM_RESULT rc = 0; size_t i; TPM_NV_DATA_SENSITIVE *tpm_nv_data_sensitive; /* an entry in the array */ printf(" TPM_NVIndexEntries_DeleteOwnerAuthorized: Deleting from %u slots\n", tpm_nv_index_entries->nvIndexCount); for (i = 0 ; i < tpm_nv_index_entries->nvIndexCount ; i++) { /* get an entry in the array */ tpm_nv_data_sensitive = &(tpm_nv_index_entries->tpm_nvindex_entry[i]); /* if the index is in use */ if (tpm_nv_data_sensitive->pubInfo.nvIndex != TPM_NV_INDEX_LOCK) { /* if TPM_NV_PER_OWNERWRITE or TPM_NV_PER_OWNERREAD and nvIndex does not have the "D" bit set */ if ((tpm_nv_data_sensitive->pubInfo.permission.attributes & TPM_NV_PER_OWNERWRITE) || (tpm_nv_data_sensitive->pubInfo.permission.attributes & TPM_NV_PER_OWNERREAD)) { if (!(tpm_nv_data_sensitive->pubInfo.nvIndex & TPM_NV_INDEX_D_BIT) || deleteAllNvram) { /* delete the index */ printf(" TPM_NVIndexEntries_DeleteOwnerAuthorized: Deleting NV index %08x\n", tpm_nv_data_sensitive->pubInfo.nvIndex); TPM_NVDataSensitive_Delete(tpm_nv_data_sensitive); } } } } return rc; } /* TPM_NVIndexEntries_GetDataPublic() returns the TPM_NV_DATA_PUBLIC corresponding to the nvIndex */ TPM_RESULT TPM_NVIndexEntries_GetDataPublic(TPM_NV_DATA_PUBLIC **tpm_nv_data_public, TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries, TPM_NV_INDEX nvIndex) { TPM_RESULT rc = 0; TPM_NV_DATA_SENSITIVE *tpm_nv_data_sensitive; printf(" TPM_NVIndexEntries_GetDataPublic: Getting data at NV index %08x\n", nvIndex); if (rc == 0) { rc = TPM_NVIndexEntries_GetEntry(&tpm_nv_data_sensitive, tpm_nv_index_entries, nvIndex); } if (rc == 0) { *tpm_nv_data_public = &(tpm_nv_data_sensitive->pubInfo); } return rc; } /* Command Processing Functions */ /* 20.4 TPM_NV_ReadValue rev 114 Read a value from the NV store. This command uses optional owner authorization. Action 1 indicates that if the NV area is not locked then reading of the NV area continues without ANY authorization. This is intentional, and allows a platform manufacturer to set the NV areas, read them back, and then lock them all without having to install a TPM owner. */ TPM_RESULT TPM_Process_NVReadValue(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_NV_INDEX nvIndex; /* The index of the area to set */ uint32_t offset = 0; /* The offset into the area */ uint32_t dataSize = 0; /* The size of the data area */ TPM_AUTHHANDLE authHandle; /* The authorization handle used for TPM Owner authorization */ TPM_NONCE nonceOdd; /* Nonce generated by caller */ TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization handle */ TPM_AUTHDATA ownerAuth; /* HMAC key: TPM Owner authorization */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_SECRET *hmacKey; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ TPM_BOOL ignore_auth = FALSE; TPM_BOOL dir = FALSE; TPM_BOOL physicalPresence; TPM_BOOL isGPIO = FALSE; BYTE *gpioData = NULL; TPM_NV_DATA_SENSITIVE *d1NvdataSensitive; uint32_t s1Last; /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_SIZED_BUFFER data; /* The data to set the area to */ printf("TPM_Process_NVReadValue: Ordinal Entry\n"); TPM_SizedBuffer_Init(&data); /* freed @1 */ /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get nvIndex parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&nvIndex, &command, ¶mSize); } /* get offset parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&offset, &command, ¶mSize); } /* get dataSize parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&dataSize, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | TPM_CHECK_NO_LOCKOUT | TPM_CHECK_NV_NOAUTH)); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag10(tag); } /* get the optional 'below the line' authorization parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, ownerAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_NVReadValue: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* 1. If TPM_PERMANENT_FLAGS -> nvLocked is FALSE then all authorization checks are ignored */ /* a. Ignored checks include physical presence, owner authorization, PCR, bReadSTClear, locality, TPM_NV_PER_OWNERREAD, disabled and deactivated */ /* b. TPM_NV_PER_AUTHREAD is not ignored. */ /* c. If ownerAuth is present, the TPM MAY check the authorization HMAC. */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_NVReadValue: index %08x offset %u dataSize %u\n", nvIndex, offset, dataSize); if (!(tpm_state->tpm_permanent_flags.nvLocked)) { printf("TPM_Process_NVReadValue: nvLocked FALSE, ignoring authorization\n"); ignore_auth = TRUE; } /* determine whether the nvIndex is legal GPIO space */ if (returnCode == 0) { returnCode = TPM_NVDataSensitive_IsGPIO(&isGPIO, nvIndex); } } /* 2. Set D1 a TPM_NV_DATA_AREA structure to the area pointed to by nvIndex, if not found return TPM_BADINDEX */ if (returnCode == TPM_SUCCESS) { /* a. If nvIndex = TPM_NV_INDEX_DIR, set D1 to TPM_PERMANENT_DATA -> authDir[0] */ if (nvIndex == TPM_NV_INDEX_DIR) { printf("TPM_Process_NVReadValue: Reading DIR\n"); dir = TRUE; } else { printf("TPM_Process_NVReadValue: Loading data from NVRAM\n"); returnCode = TPM_NVIndexEntries_GetEntry(&d1NvdataSensitive, &(tpm_state->tpm_nv_index_entries), nvIndex); if (returnCode != 0) { printf("TPM_Process_NVReadValue: Error, NV index %08x not found\n", nvIndex); } } } /* Do not check permission for DIR, DIR is no-auth */ if ((returnCode == TPM_SUCCESS) && !dir) { /* 3. If TPM_PERMANENT_FLAGS -> nvLocked is TRUE */ if (tpm_state->tpm_permanent_flags.nvLocked) { /* a. If D1 -> permission -> TPM_NV_PER_OWNERREAD is TRUE */ if (d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_OWNERREAD) { /* i. If TPM_PERMANENT_FLAGS -> disable is TRUE, return TPM_DISABLED */ if (tpm_state->tpm_permanent_flags.disable) { printf("TPM_Process_NVReadValue: Error, disabled\n"); return TPM_DISABLED; } /* ii. If TPM_STCLEAR_FLAGS -> deactivated is TRUE, return TPM_DEACTIVATED */ else if (tpm_state->tpm_stclear_flags.deactivated) { printf("TPM_Process_NVReadValue: Error, deactivated\n"); return TPM_DEACTIVATED;; } } /* NOTE: Intel software requires NV access disabled and deactivated */ /* b. If D1 -> permission -> TPM_NV_PER_OWNERREAD is FALSE */ /* i. If TPM_PERMANENT_FLAGS -> disable is TRUE, the TPM MAY return TPM_DISABLED */ /* ii. If TPM_STCLEAR_FLAGS -> deactivated is TRUE, the TPM MAY return TPM_DEACTIVATED */ } } /* 4. If tag = TPM_TAG_RQU_AUTH1_COMMAND then */ /* NOTE: This is optional if ignore_auth is TRUE */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND) && !dir) { /* a. If D1 -> TPM_NV_PER_OWNERREAD is FALSE return TPM_AUTH_CONFLICT */ if (!(d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_OWNERREAD)) { printf("TPM_Process_NVReadValue: Error, " "owner authorization conflict, attributes %08x\n", d1NvdataSensitive->pubInfo.permission.attributes); returnCode = TPM_AUTH_CONFLICT; } } /* b. Validate command and parameters using TPM Owners authorization on error return TPM_AUTHFAIL */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_OWNER, ordinal, NULL, &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ } if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND) && !ignore_auth) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, ownerAuth); /* Authorization digest for input */ } /* 5. Else */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND) && !dir) { /* a. If D1 -> TPM_NV_PER_AUTHREAD is TRUE return TPM_AUTH_CONFLICT */ if (d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_AUTHREAD) { printf("TPM_Process_NVReadValue: Error, authorization conflict TPM_NV_PER_AUTHREAD\n"); returnCode = TPM_AUTH_CONFLICT; } } /* b. If D1 -> TPM_NV_PER_OWNERREAD is TRUE return TPM_AUTH_CONFLICT */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND) && !ignore_auth && !dir) { if (d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_OWNERREAD) { printf("TPM_Process_NVReadValue: Error, authorization conflict TPM_NV_PER_OWNERREAD\n"); returnCode = TPM_AUTH_CONFLICT; } } /* 6. Check that D1 -> pcrInfoRead -> localityAtRelease for TPM_STANY_DATA -> localityModifier is TRUE */ /* a. For example if TPM_STANY_DATA -> localityModifier was 2 then D1 -> pcrInfo -> localityAtRelease -> TPM_LOC_TWO would have to be TRUE */ /* b. On error return TPM_BAD_LOCALITY */ /* NOTE Done by TPM_PCRInfoShort_CheckDigest() */ /* 7. If D1 -> attributes specifies TPM_NV_PER_PPREAD then validate physical presence is asserted if not return TPM_BAD_PRESENCE */ if ((returnCode == TPM_SUCCESS) && !ignore_auth && !dir) { if (d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_PPREAD) { if (returnCode == TPM_SUCCESS) { returnCode = TPM_Global_GetPhysicalPresence(&physicalPresence, tpm_state); } if (returnCode == TPM_SUCCESS) { if (!physicalPresence) { printf("TPM_Process_NVReadValue: Error, physicalPresence is FALSE\n"); returnCode = TPM_BAD_PRESENCE; } } } } if ((returnCode == TPM_SUCCESS) && !ignore_auth && !dir) { /* 8. If D1 -> TPM_NV_PER_READ_STCLEAR then */ if ((d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_READ_STCLEAR) && /* a. If D1 -> bReadSTClear is TRUE return TPM_DISABLED_CMD */ (d1NvdataSensitive->pubInfo.bReadSTClear)) { printf("TPM_Process_NVReadValue: Error, area locked by bReadSTClear\n"); returnCode = TPM_DISABLED_CMD; } } /* 9. If D1 -> pcrInfoRead -> pcrSelection specifies a selection of PCR */ /* a. Create P1 a composite hash of the PCR specified by D1 -> pcrInfoRead */ /* b. Compare P1 to D1 -> pcrInfoRead -> digestAtRelease return TPM_WRONGPCRVAL on mismatch */ if ((returnCode == TPM_SUCCESS) && !ignore_auth && !dir) { returnCode = TPM_PCRInfoShort_CheckDigest(&(d1NvdataSensitive->pubInfo.pcrInfoRead), tpm_state->tpm_stclear_data.PCRS, tpm_state->tpm_stany_flags.localityModifier); } if (returnCode == TPM_SUCCESS && !dir) { /* 10. If dataSize is 0 then */ if (dataSize == 0) { printf("TPM_Process_NVReadValue: dataSize 0, setting bReadSTClear\n"); /* a. Set D1 -> bReadSTClear to TRUE */ d1NvdataSensitive->pubInfo.bReadSTClear = TRUE; /* b. Set data to NULL (output parameter dataSize to 0) */ /* NOTE Done by TPM_SizedBuffer_Init */ } /* 11. Else (if dataSize is not 0) */ else { if (returnCode == TPM_SUCCESS) { /* a. Set S1 to offset + dataSize */ s1Last = offset + dataSize; /* set to last data point */ /* b. If S1 > D1 -> dataSize return TPM_NOSPACE */ if (s1Last > d1NvdataSensitive->pubInfo.dataSize) { printf("TPM_Process_NVReadValue: Error, NVRAM dataSize %u\n", d1NvdataSensitive->pubInfo.dataSize); returnCode = TPM_NOSPACE; } } /* c. Set data to area pointed to by offset */ if ((returnCode == TPM_SUCCESS) && !isGPIO) { TPM_PrintFourLimit("TPM_Process_NVReadValue: read data", d1NvdataSensitive->data + offset, dataSize); returnCode = TPM_SizedBuffer_Set(&data, dataSize, d1NvdataSensitive->data + offset); } /* GPIO */ if ((returnCode == TPM_SUCCESS) && isGPIO) { returnCode = TPM_Malloc(&gpioData, dataSize); /* freed @2 */ } if ((returnCode == TPM_SUCCESS) && isGPIO) { printf("TPM_Process_NVReadValue: Reading GPIO\n"); returnCode = TPM_IO_GPIO_Read(nvIndex, dataSize, gpioData, tpm_state->tpm_number); } if ((returnCode == TPM_SUCCESS) && isGPIO) { returnCode = TPM_SizedBuffer_Set(&data, dataSize, gpioData); } } } /* DIR read */ if (returnCode == TPM_SUCCESS && dir) { /* DIR is hard coded as a TPM_DIRVALUE array */ if (returnCode == TPM_SUCCESS) { s1Last = offset + dataSize; /* set to last data point */ if (s1Last > TPM_DIGEST_SIZE) { printf("TPM_Process_NVReadValue: Error, NVRAM dataSize %u too small\n", TPM_DIGEST_SIZE); returnCode = TPM_NOSPACE; } } /* i.This includes partial reads of TPM_NV_INDEX_DIR. */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_NVReadValue: Copying data\n"); returnCode = TPM_SizedBuffer_Set(&data, dataSize, tpm_state->tpm_permanent_data.authDIR + offset); } } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_NVReadValue: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* return data */ returnCode = TPM_SizedBuffer_Store(response, &data); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* owner HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ TPM_SizedBuffer_Delete(&data); /* @1 */ free(gpioData); /* @2 */ return rcf; } /* 20.5 TPM_NV_ReadValueAuth rev 87 This command requires that the read be authorized by a value set with the blob. */ TPM_RESULT TPM_Process_NVReadValueAuth(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_NV_INDEX nvIndex; /* The index of the area to set */ uint32_t offset = 0; /* The offset from the data area */ uint32_t dataSize = 0; /* The size of the data area */ TPM_AUTHHANDLE authHandle; /* The auth handle for the NV element authorization */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization handle */ TPM_AUTHDATA authHmac; /* HMAC key: nv element authorization */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ TPM_SECRET *hmacKey; TPM_NV_DATA_SENSITIVE *d1NvdataSensitive; uint32_t s1Last; TPM_BOOL physicalPresence; TPM_BOOL isGPIO; BYTE *gpioData = NULL; /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_SIZED_BUFFER data; /* The data */ printf("TPM_Process_NVReadValueAuth: Ordinal Entry\n"); TPM_SizedBuffer_Init(&data); /* freed @1 */ /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get nvIndex parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&nvIndex, &command, ¶mSize); } /* get offset parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&offset, &command, ¶mSize); } /* get dataSize parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&dataSize, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag1(tag); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, authHmac, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_NVReadValueAuth: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* determine whether the nvIndex is legal GPIO space */ if (returnCode == 0) { returnCode = TPM_NVDataSensitive_IsGPIO(&isGPIO, nvIndex); } /* 1. Locate and set D1 to the TPM_NV_DATA_AREA that corresponds to nvIndex, on error return TPM_BAD_INDEX */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_NVReadValueAuth: index %08x offset %u dataSize %u\n", nvIndex, offset, dataSize); printf("TPM_Process_NVReadValueAuth: Loading data from NVRAM\n"); returnCode = TPM_NVIndexEntries_GetEntry(&d1NvdataSensitive, &(tpm_state->tpm_nv_index_entries), nvIndex); if (returnCode != 0) { printf("TPM_Process_NVReadValueAuth: Error, NV index %08x not found\n", nvIndex); } } /* 2. If D1 -> TPM_NV_PER_AUTHREAD is FALSE return TPM_AUTH_CONFLICT */ if (returnCode == TPM_SUCCESS) { if (!(d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_AUTHREAD)) { printf("TPM_Process_NVReadValueAuth: Error, authorization conflict\n"); returnCode = TPM_AUTH_CONFLICT; } } /* 3. Validate authHmac using D1 -> authValue on error return TPM_AUTHFAIL */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_NV, ordinal, NULL, &(d1NvdataSensitive->authValue), /* OIAP */ d1NvdataSensitive->digest); /* OSAP */ } if (returnCode == TPM_SUCCESS) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, authHmac); /* Authorization digest for input */ } /* 4. If D1 -> attributes specifies TPM_NV_PER_PPREAD then validate physical presence is asserted if not return TPM_BAD_PRESENCE */ if (returnCode == TPM_SUCCESS) { if (d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_PPREAD) { if (returnCode == TPM_SUCCESS) { returnCode = TPM_Global_GetPhysicalPresence(&physicalPresence, tpm_state); } if (returnCode == TPM_SUCCESS) { if (!physicalPresence) { printf("TPM_Process_NVReadValueAuth: Error, physicalPresence is FALSE\n"); returnCode = TPM_BAD_PRESENCE; } } } } /* 5. Check that D1 -> pcrInfoRead -> localityAtRelease for TPM_STANY_DATA -> localityModifier is TRUE */ /* a. For example if TPM_STANY_DATA -> localityModifier was 2 then D1 -> pcrInfo -> localityAtRelease -> TPM_LOC_TWO would have to be TRUE */ /* b. On error return TPM_BAD_LOCALITY */ /* 6. If D1 -> pcrInfoRead -> pcrSelection specifies a selection of PCR */ /* a. Create P1 a composite hash of the PCR specified by D1 -> pcrInfoRead */ /* b. Compare P1 to D1 -> pcrInfoRead -> digestAtRelease return TPM_WRONGPCRVAL on mismatch */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_PCRInfoShort_CheckDigest(&(d1NvdataSensitive->pubInfo.pcrInfoRead), tpm_state->tpm_stclear_data.PCRS, tpm_state->tpm_stany_flags.localityModifier); } if (returnCode == TPM_SUCCESS) { /* 7. If D1 specifies TPM_NV_PER_READ_STCLEAR then */ if ((d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_READ_STCLEAR) && /* a. If D1 -> bReadSTClear is TRUE return TPM_DISABLED_CMD */ (d1NvdataSensitive->pubInfo.bReadSTClear)) { printf("TPM_Process_NVReadValueAuth: Error, area locked by bReadSTClear\n"); returnCode = TPM_DISABLED_CMD; } } if (returnCode == TPM_SUCCESS) { /* 8. If dataSize is 0 then */ if (dataSize == 0) { printf("TPM_Process_NVReadValueAuth: dataSize 0, setting bReadSTClear\n"); /* a. Set D1 -> bReadSTClear to TRUE */ d1NvdataSensitive->pubInfo.bReadSTClear = TRUE; /* b. Set data to NULL */ /* NOTE Done by TPM_SizedBuffer_Init */ } /* 9. Else (if dataSize is not 0) */ else { if (returnCode == TPM_SUCCESS) { /* a. Set S1 to offset + dataSize */ s1Last = offset + dataSize; /* set to last data point */ /* b. If S1 > D1 -> dataSize return TPM_NOSPACE */ if (s1Last > d1NvdataSensitive->pubInfo.dataSize) { printf("TPM_Process_NVReadValueAuth: Error, NVRAM dataSize %u too small\n", d1NvdataSensitive->pubInfo.dataSize); returnCode = TPM_NOSPACE; } } /* c. Set data to area pointed to by offset */ if ((returnCode == TPM_SUCCESS) && !isGPIO) { TPM_PrintFourLimit("TPM_Process_NVReadValueAuth: read data", d1NvdataSensitive->data + offset, dataSize); returnCode = TPM_SizedBuffer_Set(&data, dataSize, d1NvdataSensitive->data + offset); } /* GPIO */ if ((returnCode == TPM_SUCCESS) && isGPIO) { returnCode = TPM_Malloc(&gpioData, dataSize); /* freed @2 */ } if ((returnCode == TPM_SUCCESS) && isGPIO) { printf("TPM_Process_NVReadValueAuth: Reading GPIO\n"); returnCode = TPM_IO_GPIO_Read(nvIndex, dataSize, gpioData, tpm_state->tpm_number); } if ((returnCode == TPM_SUCCESS) && isGPIO) { returnCode = TPM_SizedBuffer_Set(&data, dataSize, gpioData); } } } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_NVReadValueAuth: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* return data */ returnCode = TPM_SizedBuffer_Store(response, &data); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ TPM_SizedBuffer_Delete(&data); /* @1 */ return rcf; } /* 20.2 TPM_NV_WriteValue rev 117 This command writes the value to a defined area. The write can be TPM Owner authorized or unauthorized and protected by other attributes and will work when no TPM Owner is present. The action setting bGlobalLock to TRUE is intentionally before the action checking the owner authorization. This allows code (e.g., a BIOS) to lock NVRAM without knowing the owner authorization. The DIR (TPM_NV_INDEX_DIR) has the attributes TPM_NV_PER_OWNERWRITE and TPM_NV_WRITEALL. FIXME: A simpler way to do DIR might be to create the DIR as NV defined space at first initialization and remove the special casing here. */ TPM_RESULT TPM_Process_NVWriteValue(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ int irc; /* input parameters */ TPM_NV_INDEX nvIndex; /* The index of the area to set */ uint32_t offset = 0; /* The offset into the NV Area */ TPM_SIZED_BUFFER data; /* The data to set the area to */ TPM_AUTHHANDLE authHandle; /* The authorization handle used for TPM Owner */ TPM_NONCE nonceOdd; /* Nonce generated by caller */ TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization handle */ TPM_AUTHDATA ownerAuth; /* The authorization digest HMAC key: TPM Owner auth */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ TPM_SECRET *hmacKey = NULL; TPM_BOOL ignore_auth = FALSE; TPM_BOOL index0 = FALSE; TPM_BOOL done = FALSE; TPM_BOOL dir = FALSE; TPM_BOOL writeAllNV = FALSE; /* flag to write back NV */ TPM_NV_DATA_SENSITIVE *d1NvdataSensitive = NULL; uint32_t s1Last; TPM_BOOL physicalPresence; TPM_BOOL isGPIO = FALSE; uint32_t nv1 = tpm_state->tpm_permanent_data.noOwnerNVWrite; /* temp for noOwnerNVWrite, initialize to silence compiler */ TPM_BOOL nv1Incremented = FALSE; /* flag that nv1 was incremented */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_NVWriteValue: Ordinal Entry\n"); TPM_SizedBuffer_Init(&data); /* freed @1 */ /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get nvIndex parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&nvIndex, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&offset, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_Load(&data, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | TPM_CHECK_NO_LOCKOUT | TPM_CHECK_NV_NOAUTH)); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag10(tag); } /* get the optional 'below the line' authorization parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, ownerAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_NVWriteValue: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_NVWriteValue: index %08x offset %u dataSize %u\n", nvIndex, offset, data.size); TPM_PrintFourLimit("TPM_Process_NVWriteValue: data", data.buffer, data.size); /* 1. If TPM_PERMANENT_FLAGS -> nvLocked is FALSE then all authorization checks except for the max NV writes are ignored */ /* a. Ignored checks include physical presence, owner authorization, TPM_NV_PER_OWNERWRITE, PCR, bWriteDefine, bGlobalLock, bWriteSTClear, locality, disabled and deactivated */ /* b. TPM_NV_PER_AUTHWRITE is not ignored. */ /* a.If ownerAuth is present, the TPM MAY check the authorization HMAC. */ if (!(tpm_state->tpm_permanent_flags.nvLocked)) { printf("TPM_Process_NVWriteValue: nvLocked FALSE, ignoring authorization\n"); ignore_auth = TRUE; } if (nvIndex == TPM_NV_INDEX0) { index0 = TRUE; } /* determine whether the nvIndex is legal GPIO space */ if (returnCode == 0) { returnCode = TPM_NVDataSensitive_IsGPIO(&isGPIO, nvIndex); } } /* 2. Locate and set D1 to the TPM_NV_DATA_AREA that corresponds to nvIndex, return TPM_BADINDEX on error */ if ((returnCode == TPM_SUCCESS) && !index0) { /* a. If nvIndex = TPM_NV_INDEX_DIR, set D1 to TPM_PERMANENT_DATA -> authDir[0] */ if (nvIndex == TPM_NV_INDEX_DIR) { printf("TPM_Process_NVWriteValue: Writing DIR\n"); dir = TRUE; } else { printf("TPM_Process_NVWriteValue: Loading data space from NVRAM\n"); returnCode = TPM_NVIndexEntries_GetEntry(&d1NvdataSensitive, &(tpm_state->tpm_nv_index_entries), nvIndex); if (returnCode != 0) { printf("TPM_Process_NVWriteValue: Error, NV index %08x not found\n", nvIndex); } } } if ((returnCode == TPM_SUCCESS) && !index0) { /* 3. If TPM_PERMANENT_FLAGS -> nvLocked is TRUE */ if (tpm_state->tpm_permanent_flags.nvLocked) { /* a. If D1 -> permission -> TPM_NV_PER_OWNERWRITE is TRUE */ if (dir || /* DIR always has TPM_NV_PER_OWNERWRITE */ (d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_OWNERWRITE)) { /* i. If TPM_PERMANENT_FLAGS -> disable is TRUE, return TPM_DISABLED */ if (tpm_state->tpm_permanent_flags.disable) { printf("TPM_Process_NVWriteValue: Error, disabled\n"); return TPM_DISABLED; } /* ii.If TPM_STCLEAR_FLAGS -> deactivated is TRUE, return TPM_DEACTIVATED */ else if (tpm_state->tpm_stclear_flags.deactivated) { printf("TPM_Process_NVWriteValue: Error, deactivated\n"); return TPM_DEACTIVATED;; } } /* NOTE: Intel software requires NV access disabled and deactivated */ /* b. If D1 -> permission -> TPM_NV_PER_OWNERWRITE is FALSE */ /* i. If TPM_PERMANENT_FLAGS -> disable is TRUE, the TPM MAY return TPM_DISABLED */ /* ii. If TPM_STCLEAR_FLAGS -> deactivated is TRUE, the TPM MAY return TPM_DEACTIVATED */ } } /* 4. If tag = TPM_TAG_RQU_AUTH1_COMMAND then */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND) && !dir && !index0) { /* a. If D1 -> permission -> TPM_NV_PER_OWNERWRITE is FALSE return TPM_AUTH_CONFLICT */ /* i. This check is ignored if nvIndex is TPM_NV_INDEX0. */ if (!(d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_OWNERWRITE)) { printf("TPM_Process_NVWriteValue: Error, owner authorization conflict\n"); returnCode = TPM_AUTH_CONFLICT; } } /* b. Validate command and parameters using ownerAuth HMAC with TPM Owner authentication as the secret, return TPM_AUTHFAIL on error */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_OWNER, ordinal, NULL, &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ } /* NOTE: This is optional if ignore_auth is TRUE */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, ownerAuth); /* Authorization digest for input */ } /* 5. Else */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND) && !ignore_auth && !index0) { /* a. If D1 -> permission -> TPM_NV_PER_OWNERWRITE is TRUE return TPM_AUTH_CONFLICT */ if (dir || /* DIR always has TPM_NV_PER_OWNERWRITE */ (d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_OWNERWRITE)) { printf("TPM_Process_NVWriteValue: Error, no owner authorization conflict\n"); returnCode = TPM_AUTH_CONFLICT; } } if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND) && !index0) { /* b. If no TPM Owner validate max NV writes without an owner */ /* i. Set NV1 to TPM_PERMANENT_DATA -> noOwnerNVWrite */ nv1 = tpm_state->tpm_permanent_data.noOwnerNVWrite; /* ii. Increment NV1 by 1 */ nv1++; /* iii. If NV1 > TPM_MAX_NV_WRITE_NOOWNER return TPM_MAXNVWRITES */ if (nv1 > TPM_MAX_NV_WRITE_NOOWNER) { printf("TPM_Process_NVWriteValue: Error, max NV writes %d w/o owner reached\n", tpm_state->tpm_permanent_data.noOwnerNVWrite); returnCode = TPM_MAXNVWRITES; } /* iv. Set NV1_INCREMENTED to TRUE */ else { nv1Incremented = TRUE; } } if (returnCode == TPM_SUCCESS) { /* 6. If nvIndex = 0 then */ if (nvIndex == 0) { /* a. If dataSize is not 0, the TPM MAY return TPM_BADINDEX. */ if (data.size != 0) { printf("TPM_Process_NVWriteValue: Error, index 0 size %u\n", data.size); returnCode = TPM_BADINDEX; } else { /* b. Set TPM_STCLEAR_FLAGS -> bGlobalLock to TRUE */ printf("TPM_Process_NVWriteValue: nvIndex 0, setting bGlobalLock\n"); tpm_state->tpm_stclear_flags.bGlobalLock = TRUE; /* c. Return TPM_SUCCESS */ done = TRUE; } } } /* 7. If D1 -> permission -> TPM_NV_PER_AUTHWRITE is TRUE return TPM_AUTH_CONFLICT */ if ((returnCode == TPM_SUCCESS) && !done && !dir) { if (d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_AUTHWRITE) { printf("TPM_Process_NVWriteValue: Error, authorization conflict, attributes %08x \n", d1NvdataSensitive->pubInfo.permission.attributes); returnCode = TPM_AUTH_CONFLICT; } } /* 8. Check that D1 -> pcrInfoWrite -> localityAtRelease for TPM_STANY_DATA -> localityModifier is TRUE */ /* a. For example if TPM_STANY_DATA -> localityModifier was 2 then D1 -> pcrInfo -> localityAtRelease -> TPM_LOC_TWO would have to be TRUE */ /* b. On error return TPM_BAD_LOCALITY */ /* NOTE Done by TPM_PCRInfoShort_CheckDigest() */ /* 9. If D1 -> attributes specifies TPM_NV_PER_PPWRITE then validate physical presence is asserted if not return TPM_BAD_PRESENCE */ if ((returnCode == TPM_SUCCESS) && !done && !ignore_auth && !dir) { if (d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_PPWRITE) { if (returnCode == TPM_SUCCESS) { returnCode = TPM_Global_GetPhysicalPresence(&physicalPresence, tpm_state); } if (returnCode == TPM_SUCCESS) { if (!physicalPresence) { printf("TPM_Process_NVWriteValue: Error, physicalPresence is FALSE\n"); returnCode = TPM_BAD_PRESENCE; } } } } if ((returnCode == TPM_SUCCESS) && !done && !ignore_auth && !dir) { /* 10. If D1 -> attributes specifies TPM_NV_PER_WRITEDEFINE */ if ((d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_WRITEDEFINE) && /* a. If D1 -> bWriteDefine is TRUE return TPM_AREA_LOCKED */ (d1NvdataSensitive->pubInfo.bWriteDefine)) { printf("TPM_Process_NVWriteValue: Error, area locked by bWriteDefine\n"); returnCode = TPM_AREA_LOCKED; } } if ((returnCode == TPM_SUCCESS) && !done && !ignore_auth && !dir) { /* 11. If D1 -> attributes specifies TPM_NV_PER_GLOBALLOCK */ if ((d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_GLOBALLOCK) && /* a. If TPM_STCLEAR_FLAGS -> bGlobalLock is TRUE return TPM_AREA_LOCKED */ (tpm_state->tpm_stclear_flags.bGlobalLock)) { printf("TPM_Process_NVWriteValue: Error, area locked by bGlobalLock\n"); returnCode = TPM_AREA_LOCKED; } } if ((returnCode == TPM_SUCCESS) && !done && !ignore_auth && !dir) { /* 12. If D1 -> attributes specifies TPM_NV_PER_WRITE_STCLEAR */ if ((d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_WRITE_STCLEAR) && /* a. If D1 ->bWriteSTClear is TRUE return TPM_AREA_LOCKED */ (d1NvdataSensitive->pubInfo.bWriteSTClear)) { printf("TPM_Process_NVWriteValue: Error, area locked by bWriteSTClear\n"); returnCode = TPM_AREA_LOCKED; } } /* 13. If D1 -> pcrInfoWrite -> pcrSelection specifies a selection of PCR */ /* a. Create P1 a composite hash of the PCR specified by D1 -> pcrInfoWrite */ /* b. Compare P1 to D1 -> pcrInfoWrite -> digestAtRelease return TPM_WRONGPCRVAL on mismatch */ if ((returnCode == TPM_SUCCESS) && !done && !ignore_auth && !dir) { returnCode = TPM_PCRInfoShort_CheckDigest(&(d1NvdataSensitive->pubInfo.pcrInfoWrite), tpm_state->tpm_stclear_data.PCRS, tpm_state->tpm_stany_flags.localityModifier); } if ((returnCode == TPM_SUCCESS) && !done && !dir) { /* 14. If dataSize = 0 then */ if (data.size == 0) { printf("TPM_Process_NVWriteValue: dataSize 0, setting bWriteSTClear, bWriteDefine\n"); /* a. Set D1 -> bWriteSTClear to TRUE */ d1NvdataSensitive->pubInfo.bWriteSTClear = TRUE; /* b. Set D1 -> bWriteDefine */ if (!d1NvdataSensitive->pubInfo.bWriteDefine) { /* save wearout, only write if FALSE */ d1NvdataSensitive->pubInfo.bWriteDefine = TRUE; /* must write TPM_PERMANENT_DATA back to NVRAM, set this flag after structure is written */ writeAllNV = TRUE; } } /* 15. Else (if dataSize is not 0) */ else { if (returnCode == TPM_SUCCESS) { /* a. Set S1 to offset + dataSize */ s1Last = offset + data.size; /* set to last data point */ /* b. If S1 > D1 -> dataSize return TPM_NOSPACE */ if (s1Last > d1NvdataSensitive->pubInfo.dataSize) { printf("TPM_Process_NVWriteValue: Error, NVRAM dataSize %u too small\n", d1NvdataSensitive->pubInfo.dataSize); returnCode = TPM_NOSPACE; } } if (returnCode == TPM_SUCCESS) { /* c. If D1 -> attributes specifies TPM_NV_PER_WRITEALL */ if ((d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_WRITEALL) && /* i. If dataSize != D1 -> dataSize return TPM_NOT_FULLWRITE */ (data.size != d1NvdataSensitive->pubInfo.dataSize)) { printf("TPM_Process_NVWriteValue: Error, Must write full %u\n", d1NvdataSensitive->pubInfo.dataSize); returnCode = TPM_NOT_FULLWRITE; } } if (returnCode == TPM_SUCCESS) { /* not GPIO */ if (!isGPIO) { /* wearout optimization, don't write if the data is the same */ irc = memcmp((d1NvdataSensitive->data) + offset, data.buffer, data.size); if (irc != 0) { printf("TPM_Process_NVWriteValue: Copying data\n"); /* d. Write the new value into the NV storage area */ memcpy((d1NvdataSensitive->data) + offset, data.buffer, data.size); /* must write TPM_PERMANENT_DATA back to NVRAM, set this flag after structure is written */ writeAllNV = TRUE; } else { printf("TPM_Process_NVWriteValue: Same data, no copy\n"); } } /* GPIO */ else { printf("TPM_Process_NVWriteValue: Writing GPIO\n"); returnCode = TPM_IO_GPIO_Write(nvIndex, data.size, data.buffer, tpm_state->tpm_number); } } } } /* DIR write */ if ((returnCode == TPM_SUCCESS) && !done && dir) { /* For TPM_NV_INDEX_DIR, the ordinal MUST NOT set an error code for the "if dataSize = 0" action. However, the flags set in this case are not applicable to the DIR. */ if (data.size != 0) { /* DIR is hard coded as a TPM_DIRVALUE array, TPM_NV_WRITEALL is implied */ if (returnCode == TPM_SUCCESS) { if ((offset != 0) || (data.size != TPM_DIGEST_SIZE)) { printf("TPM_Process_NVWriteValue: Error, Must write full DIR %u\n", TPM_DIGEST_SIZE); returnCode = TPM_NOT_FULLWRITE; } } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_NVWriteValue: Copying data\n"); memcpy(tpm_state->tpm_permanent_data.authDIR, data.buffer, TPM_DIGEST_SIZE); writeAllNV = TRUE; } } } if ((returnCode == TPM_SUCCESS) && !done && !dir) { /* 16. Set D1 -> bReadSTClear to FALSE (unlocked by a successful write) */ d1NvdataSensitive->pubInfo.bReadSTClear = FALSE; } /* 15.d Write the new value into the NV storage area */ if (writeAllNV) { printf("TPM_Process_NVWriteValue: Writing data to NVRAM\n"); /* NOTE Don't do this step until just before the serialization */ /* e. If NV1_INCREMENTED is TRUE */ if (nv1Incremented) { /* i. Set TPM_PERMANENT_DATA -> noOwnerNVWrite to NV1 */ tpm_state->tpm_permanent_data.noOwnerNVWrite = nv1; } } returnCode = TPM_PermanentAll_NVStore(tpm_state, writeAllNV, returnCode); /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_NVWriteValue: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* owner HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ TPM_SizedBuffer_Delete(&data); /* @1 */ return rcf; } /* 20.3 TPM_NV_WriteValueAuth rev 87 This command writes to a previously defined area. The area must require authorization to write. This command is for using when authorization other than the owner authorization is to be used. Otherwise, you should use TPM_NV_WriteValue */ TPM_RESULT TPM_Process_NVWriteValueAuth(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ int irc; /* input parameters */ TPM_NV_INDEX nvIndex; /* The index of the area to set */ uint32_t offset = 0; /* The offset into the chunk */ TPM_SIZED_BUFFER data; /* The data to set the area to */ TPM_AUTHHANDLE authHandle; /* The authorization handle used for NV element authorization */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization handle */ TPM_AUTHDATA authValue; /* HMAC key: NV element auth value */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus = FALSE; /* audit the ordinal */ TPM_BOOL transportEncrypt = FALSE; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ TPM_SECRET *hmacKey = NULL; TPM_NV_DATA_SENSITIVE *d1NvdataSensitive; uint32_t s1Last; TPM_BOOL writeAllNV = FALSE; /* flag to write back NV */ TPM_BOOL physicalPresence; TPM_BOOL isGPIO; /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_NVWriteValueAuth: Ordinal Entry\n"); TPM_SizedBuffer_Init(&data); /* freed @1 */ /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get nvIndex parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&nvIndex, &command, ¶mSize); } /* get offset parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&offset, &command, ¶mSize); } /* get data parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_Load(&data, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag1(tag); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, authValue, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_NVWriteValueAuth: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* determine whether the nvIndex is legal GPIO space */ if (returnCode == 0) { returnCode = TPM_NVDataSensitive_IsGPIO(&isGPIO, nvIndex); } /* 1. Locate and set D1 to the TPM_NV_DATA_AREA that corresponds to nvIndex, return TPM_BADINDEX on error */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_NVWriteValueAuth: index %08x offset %u dataSize %u\n", nvIndex, offset, data.size); TPM_PrintFourLimit("TPM_Process_NVWriteValueAuth: data", data.buffer, data.size); printf("TPM_Process_NVWriteValueAuth: Loading data from NVRAM\n"); returnCode = TPM_NVIndexEntries_GetEntry(&d1NvdataSensitive, &(tpm_state->tpm_nv_index_entries), nvIndex); if (returnCode != 0) { printf("TPM_Process_NVWriteValueAuth: Error, NV index %08x not found\n", nvIndex); } } /* 2. If D1 -> attributes does not specify TPM_NV_PER_AUTHWRITE then return TPM_AUTH_CONFLICT */ if (returnCode == TPM_SUCCESS) { if (!(d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_AUTHWRITE)) { printf("TPM_Process_NVWriteValueAuth: Error, authorization conflict\n"); returnCode = TPM_AUTH_CONFLICT; } } /* 3. Validate authValue using D1 -> authValue, return TPM_AUTHFAIL on error */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_NV, ordinal, NULL, &(d1NvdataSensitive->authValue), /* OIAP */ d1NvdataSensitive->digest); /* OSAP */ } if (returnCode == TPM_SUCCESS) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, authValue); /* Authorization digest for input */ } /* 4. Check that D1 -> pcrInfoWrite -> localityAtRelease for TPM_STANY_DATA -> localityModifier is TRUE */ /* a. For example if TPM_STANY_DATA -> localityModifier was 2 then D1 -> pcrInfo -> localityAtRelease -> TPM_LOC_TWO would have to be TRUE */ /* b. On error return TPM_BAD_LOCALITY */ /* NOTE Done by TPM_PCRInfoShort_CheckDigest() */ /* 5. If D1 -> attributes specifies TPM_NV_PER_PPWRITE then validate physical presence is asserted if not return TPM_BAD_PRESENCE */ if (returnCode == TPM_SUCCESS) { if (d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_PPWRITE) { if (returnCode == TPM_SUCCESS) { returnCode = TPM_Global_GetPhysicalPresence(&physicalPresence, tpm_state); } if (returnCode == TPM_SUCCESS) { if (!physicalPresence) { printf("TPM_Process_NVWriteValueAuth: Error, physicalPresence is FALSE\n"); returnCode = TPM_BAD_PRESENCE; } } } } /* 6. If D1 -> pcrInfoWrite -> pcrSelection specifies a selection of PCR */ /* a. Create P1 a composite hash of the PCR specified by D1 -> pcrInfoWrite */ /* b. Compare P1 to digestAtRelease return TPM_WRONGPCRVAL on mismatch */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_PCRInfoShort_CheckDigest(&(d1NvdataSensitive->pubInfo.pcrInfoWrite), tpm_state->tpm_stclear_data.PCRS, tpm_state->tpm_stany_flags.localityModifier); } if (returnCode == TPM_SUCCESS) { /* 7. If D1 -> attributes specifies TPM_NV_PER_WRITEDEFINE */ if ((d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_WRITEDEFINE) && /* a. If D1 -> bWriteDefine is TRUE return TPM_AREA_LOCKED */ (d1NvdataSensitive->pubInfo.bWriteDefine)) { printf("TPM_Process_NVWriteValueAuth: Error, area locked by bWriteDefine\n"); returnCode = TPM_AREA_LOCKED; } } if (returnCode == TPM_SUCCESS) { /* 8. If D1 -> attributes specifies TPM_NV_PER_GLOBALLOCK */ if ((d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_GLOBALLOCK) && /* a. If TPM_STCLEAR_FLAGS -> bGlobalLock is TRUE return TPM_AREA_LOCKED */ (tpm_state->tpm_stclear_flags.bGlobalLock)) { printf("TPM_Process_NVWriteValueAuth: Error, area locked by bGlobalLock\n"); returnCode = TPM_AREA_LOCKED; } } if (returnCode == TPM_SUCCESS) { /* 9. If D1 -> attributes specifies TPM_NV_PER_WRITE_STCLEAR */ if ((d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_WRITE_STCLEAR) && /* a. If D1 -> bWriteSTClear is TRUE return TPM_AREA_LOCKED */ (d1NvdataSensitive->pubInfo.bWriteSTClear)) { printf("TPM_Process_NVWriteValueAuth: Error, area locked by bWriteSTClear\n"); returnCode = TPM_AREA_LOCKED; } } if (returnCode == TPM_SUCCESS) { /* 10. If dataSize = 0 then */ if (data.size == 0) { printf("TPM_Process_NVWriteValueAuth: " "dataSize 0, setting bWriteSTClear, bWriteDefine\n"); /* a. Set D1 -> bWriteSTClear to TRUE */ d1NvdataSensitive->pubInfo.bWriteSTClear = TRUE; /* b. Set D1 -> bWriteDefine to TRUE */ if (!d1NvdataSensitive->pubInfo.bWriteDefine) { /* save wearout, only write if FALSE */ d1NvdataSensitive->pubInfo.bWriteDefine = TRUE; /* must write TPM_PERMANENT_DATA back to NVRAM, set this flag after structure is written */ writeAllNV = TRUE; } } /* 11. Else (if dataSize is not 0) */ else { if (returnCode == TPM_SUCCESS) { /* a. Set S1 to offset + dataSize */ s1Last = offset + data.size; /* set to last data point */ /* b. If S1 > D1 -> dataSize return TPM_NOSPACE */ if (s1Last > d1NvdataSensitive->pubInfo.dataSize) { printf("TPM_Process_NVWriteValueAuth: Error, NVRAM dataSize %u\n", d1NvdataSensitive->pubInfo.dataSize); returnCode = TPM_NOSPACE; } } if (returnCode == TPM_SUCCESS) { /* c. If D1 -> attributes specifies TPM_PER_WRITEALL */ if ((d1NvdataSensitive->pubInfo.permission.attributes & TPM_NV_PER_WRITEALL) && /* i. If dataSize != D1 -> dataSize return TPM_NOT_FULLWRITE */ (data.size != d1NvdataSensitive->pubInfo.dataSize)) { printf("TPM_Process_NVWriteValueAuth: Error, Must write all %u\n", d1NvdataSensitive->pubInfo.dataSize); returnCode = TPM_NOT_FULLWRITE; } } if (returnCode == TPM_SUCCESS) { /* not GPIO */ if (!isGPIO) { /* wearout optimization, don't write if the data is the same */ irc = memcmp((d1NvdataSensitive->data) + offset, data.buffer, data.size); if (irc != 0) { /* d. Write the new value into the NV storage area */ printf("TPM_Process_NVWriteValueAuth: Copying data\n"); memcpy((d1NvdataSensitive->data) + offset, data.buffer, data.size); /* must write TPM_PERMANENT_DATA back to NVRAM, set this flag after structure is written */ writeAllNV = TRUE; } else { printf("TPM_Process_NVWriteValueAuth: Same data, no copy\n"); } } /* GPIO */ else { printf("TPM_Process_NVWriteValueAuth: Writing GPIO\n"); returnCode = TPM_IO_GPIO_Write(nvIndex, data.size, data.buffer, tpm_state->tpm_number); } } } } /* 12. Set D1 -> bReadSTClear to FALSE */ if (returnCode == TPM_SUCCESS) { d1NvdataSensitive->pubInfo.bReadSTClear = FALSE; printf("TPM_Process_NVWriteValueAuth: Writing data to NVRAM\n"); } /* write back TPM_PERMANENT_DATA if required */ returnCode = TPM_PermanentAll_NVStore(tpm_state, writeAllNV, returnCode); /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_NVWriteValueAuth: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ TPM_SizedBuffer_Delete(&data); /* @1 */ return rcf; } /* 20.1 TPM_NV_DefineSpace rev 109 This establishes the space necessary for the indicated index. The definition will include the access requirements for writing and reading the area. Previously defined space at the index and new size is non-zero (and space is available, etc.) -> redefine the index No previous space at the index and new size is non-zero (and space is available, etc.)-> define the index Previously defined space at the index and new size is 0 -> delete the index No previous space at the index and new size is 0 -> error The space definition size does not include the area needed to manage the space. Setting TPM_PERMANENT_FLAGS -> nvLocked TRUE when it is already TRUE is not an error. For the case where pubInfo -> dataSize is 0, pubInfo -> pcrInfoRead and pubInfo -> pcrInfoWrite are not used. However, since the general principle is to validate parameters before changing state, the TPM SHOULD parse pubInfo completely before invalidating the data area. */ TPM_RESULT TPM_Process_NVDefineSpace(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_NV_INDEX newNVIndex = TPM_NV_INDEX_LOCK; /* from input TPM_NV_DATA_PUBLIC, initialize to silence compiler */ TPM_ENCAUTH encAuth; /* The encrypted AuthData, only valid if the attributes require subsequent authorization */ TPM_AUTHHANDLE authHandle; /* The authorization session handle used for ownerAuth */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization session handle */ TPM_AUTHDATA ownerAuth; /* The authorization session digest HMAC key: ownerAuth */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ TPM_SECRET *hmacKey = NULL; TPM_BOOL ignore_auth = FALSE; TPM_BOOL writeAllNV = FALSE; /* flag to write back NV */ TPM_BOOL done = FALSE; /* processing is done */ TPM_DIGEST a1Auth; TPM_NV_DATA_SENSITIVE *d1_old; /* possibly old data */ TPM_NV_DATA_SENSITIVE *d1_new = NULL; /* new data */ TPM_NV_DATA_PUBLIC *pubInfo = NULL; /* new, initialize to silence compiler */ uint32_t freeSpace; /* free space after allocating new index */ TPM_BOOL writeLocalities = FALSE; TPM_BOOL physicalPresence; TPM_BOOL foundOld = TRUE; /* index already exists, initialize to silence compiler */ uint32_t nv1 = tpm_state->tpm_permanent_data.noOwnerNVWrite; /* temp for noOwnerNVWrite, initialize to silence compiler */ TPM_BOOL nv1Incremented = FALSE; /* flag that nv1 was incremented */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_NVDefineSpace: Ordinal Entry\n"); /* This design gets a slot in the TPM_NV_INDEX_ENTRIES array, either an existing empty one or a newly re'allocated one. The incoming parameters are deserialized directly into the slot. On success, the slot remains. On failure, the slot is deleted. There is no need to remove the slot from the array. It can remain for the next call. */ /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get or create a free index in the TPM_NV_INDEX_ENTRIES array */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_NVIndexEntries_GetFreeEntry(&d1_new, &(tpm_state->tpm_nv_index_entries)); } /* get pubInfo parameter */ if (returnCode == TPM_SUCCESS) { pubInfo = &(d1_new->pubInfo); /* pubInfo is an input parameter */ returnCode = TPM_NVDataPublic_Load(pubInfo, &command, ¶mSize, FALSE); /* not optimized for digestAtRelease */ /* The NV index cannot be immediately deserialized in the slot, or the function will think that the index already exists. Therefore, the nvIndex parameter is saved and temporarily set to empty until the old slot is deleted. */ newNVIndex = pubInfo->nvIndex; /* save the possibly new index */ pubInfo->nvIndex = TPM_NV_INDEX_LOCK; /* temporarily mark unused */ } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_NVDefineSpace: index %08x permission %08x dataSize %08x\n", newNVIndex, pubInfo->permission.attributes, pubInfo->dataSize); TPM_PCRInfo_Trace("TPM_Process_NVDefineSpace: pcrInfoRead", pubInfo->pcrInfoRead.pcrSelection, pubInfo->pcrInfoRead.digestAtRelease); TPM_PCRInfo_Trace("TPM_Process_NVDefineSpace: pcrInfoWrite", pubInfo->pcrInfoWrite.pcrSelection, pubInfo->pcrInfoWrite.digestAtRelease); /* get encAuth parameter */ returnCode = TPM_Secret_Load(encAuth, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER | TPM_CHECK_NV_NOAUTH); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag10(tag); } /* get the optional 'below the line' authorization parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, ownerAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_NVDefineSpace: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* 1. If pubInfo -> nvIndex == TPM_NV_INDEX_LOCK and tag = TPM_TAG_RQU_COMMAND */ if ((returnCode == TPM_SUCCESS) && (newNVIndex == TPM_NV_INDEX_LOCK) && (tag == TPM_TAG_RQU_COMMAND)) { /* a. If pubInfo -> dataSize is not 0, the command MAY return TPM_BADINDEX. */ if (pubInfo->dataSize != 0) { printf("TPM_Process_NVDefineSpace: Error, TPM_NV_INDEX_LOCK dataSize %u\n", pubInfo->dataSize); returnCode = TPM_BADINDEX; } else { /* b. Set TPM_PERMANENT_FLAGS -> nvLocked to TRUE */ /* writeAllNV set to TRUE if nvLocked is being set, not if already set */ printf("TPM_Process_NVDefineSpace: Setting nvLocked\n"); TPM_SetCapability_Flag(&writeAllNV, /* altered */ &(tpm_state->tpm_permanent_flags.nvLocked ), /* flag */ TRUE); /* value */ } /* c. Return TPM_SUCCESS */ done = TRUE; } /* 2. If TPM_PERMANENT_FLAGS -> nvLocked is FALSE then all authorization checks except for the Max NV writes are ignored */ /* a. Ignored checks include physical presence, owner authorization, 'D' bit check, bGlobalLock, no authorization with a TPM owner present, bWriteSTClear, the check that pubInfo -> dataSize is 0 in Action 5.c. (the no-authorization case), disabled and deactivated. */ /* NOTE: The disabled and deactivated flags are conditionally checked by TPM_CheckState() using the TPM_CHECK_NV_NOAUTH flag */ /* ii. The check that pubInfo -> dataSize is 0 is still enforced in Action 6.f. (returning after deleting a previously defined storage area) and Action 9.f. (not allowing a space of size 0 to be defined). */ /* i.If ownerAuth is present, the TPM MAY check the authorization HMAC. */ if (returnCode == TPM_SUCCESS) { if (!(tpm_state->tpm_permanent_flags.nvLocked)) { printf("TPM_Process_NVDefineSpace: nvLocked FALSE, ignoring authorization\n"); ignore_auth = TRUE; } } /* b.The check for pubInfo -> nvIndex == 0 in Action 3. is not ignored. */ if ((returnCode == TPM_SUCCESS) && !done) { if (newNVIndex == TPM_NV_INDEX0) { printf("TPM_Process_NVDefineSpace: Error, bad index %08x\n", newNVIndex); returnCode = TPM_BADINDEX; } } /* 3. If pubInfo -> nvIndex has the D bit (bit 28) set to a 1 or pubInfo -> nvIndex == 0 then */ if ((returnCode == TPM_SUCCESS) && !done && !ignore_auth) { /* b. The D bit specifies an index value that is set in manufacturing and can never be deleted or added to the TPM */ if (newNVIndex & TPM_NV_INDEX_D_BIT) { /* c. Index value of 0 is reserved and cannot be defined */ /* a. Return TPM_BADINDEX */ printf("TPM_Process_NVDefineSpace: Error, bad index %08x\n", newNVIndex); returnCode = TPM_BADINDEX; } } /* 4. If tag = TPM_TAG_RQU_AUTH1_COMMAND then */ /* b. authHandle session type MUST be OSAP */ /* must get the HMAC key for the response even if ignore_auth is TRUE */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_OSAP, TPM_ET_OWNER, ordinal, NULL, NULL, tpm_state->tpm_permanent_data.ownerAuth); } /* a. The TPM MUST validate the command and parameters using the TPM Owner authentication and ownerAuth, on error return TPM_AUTHFAIL */ /* NOTE: This is optional if ignore_auth is TRUE */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND) && !done) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, ownerAuth); /* Authorization digest for input */ } /* c. Create A1 by decrypting encAuth according to the ADIP indicated by authHandle. */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND) && !done) { returnCode = TPM_AuthSessionData_Decrypt(a1Auth, NULL, encAuth, auth_session_data, NULL, NULL, FALSE); /* even and odd */ } /* 5. else (not auth1) */ /* a. Validate the assertion of physical presence. Return TPM_BAD_PRESENCE on error. */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND) && !done && !ignore_auth) { if (returnCode == TPM_SUCCESS) { returnCode = TPM_Global_GetPhysicalPresence(&physicalPresence, tpm_state); } if (returnCode == TPM_SUCCESS) { if (!physicalPresence) { printf("TPM_Process_NVDefineSpace: Error, physicalPresence is FALSE\n"); returnCode = TPM_BAD_PRESENCE; } } } /* b. If TPM Owner is present then return TPM_OWNER_SET. */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND) && !done && !ignore_auth) { if (tpm_state->tpm_permanent_data.ownerInstalled) { printf("TPM_Process_NVDefineSpace: Error, no authorization, but owner installed\n"); returnCode = TPM_OWNER_SET; } } /* c. If pubInfo -> dataSize is 0 then return TPM_BAD_DATASIZE. Setting the size to 0 represents an attempt to delete the value without TPM Owner authentication. */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND) && !done && !ignore_auth) { if (pubInfo->dataSize == 0) { printf("TPM_Process_NVDefineSpace: Error, no owner authorization and dataSize 0\n"); returnCode = TPM_BAD_DATASIZE; } } /* d. Validate max NV writes without an owner */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND) && !done) { /* i. Set NV1 to TPM_PERMANENT_DATA -> noOwnerNVWrite */ nv1 = tpm_state->tpm_permanent_data.noOwnerNVWrite; /* ii. Increment NV1 by 1 */ nv1++; /* iii. If NV1 > TPM_MAX_NV_WRITE_NOOWNER return TPM_MAXNVWRITES */ if (nv1 > TPM_MAX_NV_WRITE_NOOWNER) { printf("TPM_Process_NVDefineSpace: Error, max NV writes %d w/o owner reached\n", tpm_state->tpm_permanent_data.noOwnerNVWrite); returnCode = TPM_MAXNVWRITES; } else { /* iv. Set NV1_INCREMENTED to TRUE */ nv1Incremented = TRUE; } } /* e. Set A1 to encAuth. There is no nonce or authorization to create the encryption string, hence the AuthData value is passed in the clear */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND) && !done) { TPM_Digest_Copy(a1Auth, encAuth); } /* 6. If pubInfo -> nvIndex points to a valid previously defined storage area then */ /* 6.a. Map D1 a TPM_NV_DATA_SENSITIVE to the storage area */ if ((returnCode == TPM_SUCCESS) && !done) { printf("TPM_Process_NVDefineSpace: Loading existing NV index %08x\n", newNVIndex); returnCode = TPM_NVIndexEntries_GetEntry(&d1_old, &(tpm_state->tpm_nv_index_entries), newNVIndex); if (returnCode == TPM_SUCCESS) { printf("TPM_Process_NVDefineSpace: NV index %08x exists\n", newNVIndex); foundOld = TRUE; } else if (returnCode == TPM_BADINDEX) { returnCode = TPM_SUCCESS; /* non-existent index is not an error */ foundOld = FALSE; printf("TPM_Process_NVDefineSpace: Index %08x is new\n", newNVIndex); } } if ((returnCode == TPM_SUCCESS) && !done && !ignore_auth && foundOld) { /* 6.b. If D1 -> attributes specifies TPM_NV_PER_GLOBALLOCK then */ if (d1_old->pubInfo.permission.attributes & TPM_NV_PER_GLOBALLOCK) { /* i. If TPM_STCLEAR_FLAGS -> bGlobalLock is TRUE then return TPM_AREA_LOCKED */ if (tpm_state->tpm_stclear_flags.bGlobalLock) { printf("TPM_Process_NVDefineSpace: Error, index %08x (bGlobalLock) locked\n", newNVIndex); returnCode = TPM_AREA_LOCKED; } } } if ((returnCode == TPM_SUCCESS) && !done && !ignore_auth && foundOld) { /* 6.c. If D1 -> attributes specifies TPM_NV_PER_WRITE_STCLEAR */ if (d1_old->pubInfo.permission.attributes & TPM_NV_PER_WRITE_STCLEAR) { /* i. If D1 -> pubInfo -> bWriteSTClear is TRUE then return TPM_AREA_LOCKED */ if (d1_old->pubInfo.bWriteSTClear) { printf("TPM_Process_NVDefineSpace: Error, area locked by bWriteSTClear\n"); returnCode = TPM_AREA_LOCKED; } } } /* NOTE Changed the Action order. Must terminate auth sessions while the old index digest still exists. */ /* 6.f. The TPM invalidates authorization sessions */ /* i. MUST invalidate all authorization sessions associated with D1 */ /* ii. MAY invalidate any other authorization session */ if ((returnCode == TPM_SUCCESS) && !done && foundOld) { TPM_AuthSessions_TerminateEntity(&continueAuthSession, authHandle, tpm_state->tpm_stclear_data.authSessions, TPM_ET_NV, &(d1_old->digest)); } if ((returnCode == TPM_SUCCESS) && !done && foundOld) { /* 6.d. Invalidate the data area currently pointed to by D1 and ensure that if the area is reallocated no residual information is left */ printf("TPM_Process_NVDefineSpace: Deleting index %08x\n", newNVIndex); TPM_NVDataSensitive_Delete(d1_old); /* must write deleted space back to NVRAM */ writeAllNV = TRUE; /* 6.e. If NV1_INCREMENTED is TRUE */ /* i. Set TPM_PERMANENT_DATA -> noOwnerNVWrite to NV1 */ /* NOTE Don't do this step until just before the serialization */ } /* g. If pubInfo -> dataSize is 0 then return TPM_SUCCESS */ if ((returnCode == TPM_SUCCESS) && !done && foundOld) { if (pubInfo->dataSize == 0) { printf("TPM_Process_NVDefineSpace: Size 0, done\n"); done = TRUE; } } /* 7. Parse pubInfo -> pcrInfoRead */ /* a. Validate pcrInfoRead structure on error return TPM_INVALID_STRUCTURE */ /* i. Validation includes proper PCR selections and locality selections */ /* NOTE: Done by TPM_NVDataPublic_Load() */ /* 8. Parse pubInfo -> pcrInfoWrite */ /* a. Validate pcrInfoWrite structure on error return TPM_INVALID_STRUCTURE */ /* i. Validation includes proper PCR selections and locality selections */ /* NOTE: Done by TPM_NVDataPublic_Load() */ if ((returnCode == TPM_SUCCESS) && !done) { /* b. If pcrInfoWrite -> localityAtRelease disallows some localities */ if (pubInfo->pcrInfoRead.localityAtRelease != TPM_LOC_ALL) { /* i. Set writeLocalities to TRUE */ writeLocalities = TRUE; } /* c. Else */ else { /* i. Set writeLocalities to FALSE */ writeLocalities = FALSE; } } /* 9. Validate that the attributes are consistent */ /* a. The TPM SHALL ignore the bReadSTClear, bWriteSTClear and bWriteDefine attributes during the execution of this command */ /* b. If TPM_NV_PER_OWNERWRITE is TRUE and TPM_NV_PER_AUTHWRITE is TRUE return TPM_AUTH_CONFLICT */ if ((returnCode == TPM_SUCCESS) && !done) { if ((pubInfo->permission.attributes & TPM_NV_PER_OWNERWRITE) && (pubInfo->permission.attributes & TPM_NV_PER_AUTHWRITE)) { printf("TPM_Process_NVDefineSpace: Error, write authorization conflict\n"); returnCode = TPM_AUTH_CONFLICT; } } /* c. If TPM_NV_PER_OWNERREAD is TRUE and TPM_NV_PER_AUTHREAD is TRUE return TPM_AUTH_CONFLICT */ if ((returnCode == TPM_SUCCESS) && !done) { if ((pubInfo->permission.attributes & TPM_NV_PER_OWNERREAD) && (pubInfo->permission.attributes & TPM_NV_PER_AUTHREAD)) { printf("TPM_Process_NVDefineSpace: Error, read authorization conflict\n"); returnCode = TPM_AUTH_CONFLICT; } } /* d. If TPM_NV_PER_OWNERWRITE and TPM_NV_PER_AUTHWRITE and TPM_NV_PER_WRITEDEFINE and TPM_NV_PER_PPWRITE and writeLocalities are all FALSE */ if ((returnCode == TPM_SUCCESS) && !done) { if (!(pubInfo->permission.attributes & TPM_NV_PER_OWNERWRITE) && !(pubInfo->permission.attributes & TPM_NV_PER_AUTHWRITE) && !(pubInfo->permission.attributes & TPM_NV_PER_WRITEDEFINE) && !(pubInfo->permission.attributes & TPM_NV_PER_PPWRITE) && !writeLocalities) { /* i. Return TPM_PER_NOWRITE */ printf("TPM_Process_NVDefineSpace: Error, no write\n"); returnCode = TPM_PER_NOWRITE; } } /* e. Validate pubInfo -> nvIndex */ /* i. Make sure that the index is applicable for this TPM return TPM_BADINDEX on error */ if ((returnCode == TPM_SUCCESS) && !done) { returnCode = TPM_NVDataSensitive_IsValidIndex(newNVIndex); } /* f. If dataSize is 0 return TPM_BAD_PARAM_SIZE */ if ((returnCode == TPM_SUCCESS) && !done) { if (pubInfo->dataSize == 0) { printf("TPM_Process_NVDefineSpace: Error, New index data size is zero\n"); returnCode = TPM_BAD_PARAM_SIZE; } } /* 10. Create D1 a TPM_NV_DATA_SENSITIVE structure */ /* NOTE Created and initialized d1_new directly in the TPM_NV_INDEX_ENTRIES array */ /* a. Set D1 -> pubInfo to pubInfo */ /* NOTE deserialized in place */ if ((returnCode == TPM_SUCCESS) && !done) { /* b. Set D1 -> authValue to A1 */ TPM_Digest_Copy(d1_new->authValue, a1Auth); /* c. Set D1 -> pubInfo -> bReadSTClear to FALSE */ /* d. Set D1 -> pubInfo -> bWriteSTClear to FALSE */ /* e. Set D1 -> pubInfo -> bWriteDefine to FALSE */ pubInfo->bReadSTClear = FALSE; pubInfo->bWriteSTClear = FALSE; pubInfo->bWriteDefine = FALSE; } if ((returnCode == TPM_SUCCESS) && !done) { /* assign the empty slot to the index now so it will be counted as used space during the serialization. */ pubInfo->nvIndex = newNVIndex; /* 12.a. Reserve NV space for pubInfo -> dataSize NOTE: Action is out or order. Must allocate data space now so that the serialization inherent in TPM_NVIndexEntries_GetFreeSpace() is valid */ returnCode = TPM_Malloc(&(d1_new->data), pubInfo->dataSize); } /* 11. Validate that sufficient NV is available to store D1 and pubInfo -> dataSize bytes of data*/ /* a. return TPM_NOSPACE if pubInfo -> dataSize is not available in the TPM */ if ((returnCode == TPM_SUCCESS) && !done) { printf("TPM_Process_NVDefineSpace: Allocated %u data bytes at %p\n", pubInfo->dataSize, d1_new->data); printf("TPM_Process_NVDefineSpace: Checking for %u bytes free space\n", pubInfo->dataSize); returnCode = TPM_NVIndexEntries_GetFreeSpace(&freeSpace, &(tpm_state->tpm_nv_index_entries)); if (returnCode != TPM_SUCCESS) { printf("TPM_Process_NVDefineSpace: Error: No space\n"); } } /* if there is no free space, free the NV index in-memory structure. This implicitly removes the entry from tpm_nv_index_entries. If pubInfo -> nvIndex is TPM_NV_INDEX_TRIAL, the entry should also be removed. */ if ((returnCode != TPM_SUCCESS) || (newNVIndex == TPM_NV_INDEX_TRIAL)) { if (newNVIndex == TPM_NV_INDEX_TRIAL) { printf("TPM_Process_NVDefineSpace: nvIndex is TPM_NV_INDEX_TRIAL, done\n"); /* don't actually write, just return success or failure */ done = TRUE; } TPM_NVDataSensitive_Delete(d1_new); } /* 12. If pubInfo -> nvIndex is not TPM_NV_INDEX_TRIAL */ if ((returnCode == TPM_SUCCESS) && !done) { printf("TPM_Process_NVDefineSpace: Creating index %08x\n", newNVIndex); /* b. Set all bytes in the newly defined area to 0xFF */ memset(d1_new->data, 0xff, pubInfo->dataSize); /* must write newly defined space back to NVRAM */ writeAllNV = TRUE; } if (returnCode == TPM_SUCCESS) { /* c. If NV1_INCREMENTED is TRUE */ if (nv1Incremented) { /* i. Set TPM_PERMANENT_DATA -> noOwnerNVWrite to NV1 */ tpm_state->tpm_permanent_data.noOwnerNVWrite = nv1; } /* 13. Ignore continueAuthSession on input and set to FALSE on output */ continueAuthSession = FALSE; } /* write the file to NVRAM */ /* write back TPM_PERMANENT_DATA and TPM_PERMANENT_FLAGS if required */ returnCode = TPM_PermanentAll_NVStore(tpm_state, writeAllNV, returnCode); /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_NVDefineSpace: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* owner HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ return rcf; } /* 27.3 DIR commands rev 87 The DIR commands are replaced by the NV storage commands. The DIR [0] in 1.1 is now TPM_PERMANENT_DATA -> authDIR[0] and is always available for the TPM to use. It is accessed by DIR commands using dirIndex 0 and by NV commands using nvIndex TPM_NV_INDEX_DIR. If the TPM vendor supports additional DIR registers, the TPM vendor may return errors or provide vendor specific mappings for those DIR registers to NV storage locations. 1. A dirIndex value of 0 MUST corresponds to an NV storage nvIndex value TPM_NV_INDEX_DIR. 2. The TPM vendor MAY return errors or MAY provide vendor specific mappings for DIR dirIndex values greater than 0 to NV storage locations. */ /* 27.3.1 TPM_DirWriteAuth rev 87 The TPM_DirWriteAuth operation provides write access to the Data Integrity Registers. DIRs are non-volatile memory registers held in a TPM-shielded location. Owner authentication is required to authorize this action. Access is also provided through the NV commands with nvIndex TPM_NV_INDEX_DIR. Owner authorization is not required when nvLocked is FALSE. Version 1.2 requires only one DIR. If the DIR named does not exist, the TPM_DirWriteAuth operation returns TPM_BADINDEX. */ TPM_RESULT TPM_Process_DirWriteAuth(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_DIRINDEX dirIndex; /* Index of the DIR */ TPM_DIRVALUE newContents; /* New value to be stored in named DIR */ TPM_AUTHHANDLE authHandle; /* The authorization session handle used for command. */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization session handle */ TPM_AUTHDATA ownerAuth; /* The authorization session digest for inputs. HMAC key: ownerAuth. */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_SECRET *hmacKey; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_DirWriteAuth: Ordinal Entry\n"); /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get dirIndex parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&dirIndex, &command, ¶mSize); } /* get newContents parameter */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_DirWriteAuth: dirIndex %08x\n", dirIndex); returnCode = TPM_Digest_Load(newContents, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { TPM_PrintFour("TPM_Process_DirWriteAuth: newContents", newContents); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag1(tag); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, ownerAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_DirWriteAuth: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* 1. Validate that authHandle contains a TPM Owner AuthData to execute the TPM_DirWriteAuth command */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_OWNER, ordinal, NULL, &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ } if (returnCode == TPM_SUCCESS) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, ownerAuth); /* Authorization digest for input */ } /* 2. Validate that dirIndex points to a valid DIR on this TPM */ if (returnCode == TPM_SUCCESS) { if (dirIndex != 0) { /* only one TPM_PERMANENT_DATA -> authDIR */ printf("TPM_Process_DirWriteAuth: Error, Invalid index %08x\n", dirIndex); returnCode = TPM_BADINDEX; } } /* 3. Write newContents into the DIR pointed to by dirIndex */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_DirWriteAuth: Writing data\n"); TPM_Digest_Copy(tpm_state->tpm_permanent_data.authDIR, newContents); /* write back TPM_PERMANENT_DATA */ returnCode = TPM_PermanentAll_NVStore(tpm_state, TRUE, returnCode); } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_DirWriteAuth: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* owner HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ return rcf; } /* 27.3.2 TPM_DirRead rev 87 The TPM_DirRead operation provides read access to the DIRs. No authentication is required to perform this action because typically no cryptographically useful AuthData is available early in boot. TSS implementors may choose to provide other means of authorizing this action. Version 1.2 requires only one DIR. If the DIR named does not exist, the TPM_DirRead operation returns TPM_BADINDEX. */ TPM_RESULT TPM_Process_DirRead(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_DIRINDEX dirIndex; /* Index of the DIR to be read */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_DirRead: Ordinal Entry\n"); /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get dirIndex parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&dirIndex, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_DirRead: dirIndex %08x\n", dirIndex); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_DirRead: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ /* 1. Validate that dirIndex points to a valid DIR on this TPM */ if (returnCode == TPM_SUCCESS) { if (dirIndex != 0) { /* only one TPM_PERMANENT_DATA -> authDIR */ printf("TPM_Process_DirRead: Error, Invalid index %08x\n", dirIndex); returnCode = TPM_BADINDEX; } } /* 2. Return the contents of the DIR in dirContents */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_DirRead: Reading data\n"); TPM_PrintFour("TPM_Process_DirRead:", tpm_state->tpm_permanent_data.authDIR); } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_DirRead: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* append dirContents */ returnCode = TPM_Digest_Store(response, tpm_state->tpm_permanent_data.authDIR); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* cleanup */ return rcf; } libtpms-0.9.3/src/tpm12/tpm_nvram.h000066400000000000000000000233631421143571500171150ustar00rootroot00000000000000/********************************************************************************/ /* */ /* NVRAM Utilities */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_nvram.h 4528 2011-03-29 22:16:28Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_NVRAM_H #define TPM_NVRAM_H #include #include "tpm_global.h" #include "tpm_types.h" /* NVRAM common functions */ /* TPM_NV_ATTRIBUTES */ void TPM_NVAttributes_Init(TPM_NV_ATTRIBUTES *tpm_nv_attributes); TPM_RESULT TPM_NVAttributes_Load(TPM_NV_ATTRIBUTES *tpm_nv_attributes, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_NVAttributes_Store(TPM_STORE_BUFFER *sbuffer, const TPM_NV_ATTRIBUTES *tpm_nv_attributes); void TPM_NVAttributes_Delete(TPM_NV_ATTRIBUTES *tpm_nv_attributes); void TPM_NVAttributes_Copy(TPM_NV_ATTRIBUTES *tpm_nv_attributes_dest, TPM_NV_ATTRIBUTES *tpm_nv_attributes_src); /* TPM_NV_DATA_PUBLIC */ void TPM_NVDataPublic_Init(TPM_NV_DATA_PUBLIC *tpm_nv_data_public); TPM_RESULT TPM_NVDataPublic_Load(TPM_NV_DATA_PUBLIC *tpm_nv_data_public, unsigned char **stream, uint32_t *stream_size, TPM_BOOL optimize); TPM_RESULT TPM_NVDataPublic_Store(TPM_STORE_BUFFER *sbuffer, const TPM_NV_DATA_PUBLIC *tpm_nv_data_public, TPM_BOOL optimize); void TPM_NVDataPublic_Delete(TPM_NV_DATA_PUBLIC *tpm_nv_data_public); /* TPM_NV_DATA_SENSITIVE */ void TPM_NVDataSensitive_Init(TPM_NV_DATA_SENSITIVE *tpm_nv_data_sensitive); TPM_RESULT TPM_NVDataSensitive_Load(TPM_NV_DATA_SENSITIVE *tpm_nv_data_sensitive, TPM_TAG nvEntriesVersion, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_NVDataSensitive_Store(TPM_STORE_BUFFER *sbuffer, const TPM_NV_DATA_SENSITIVE *tpm_nv_data_sensitive); void TPM_NVDataSensitive_Delete(TPM_NV_DATA_SENSITIVE *tpm_nv_data_sensitive); TPM_RESULT TPM_NVDataSensitive_IsValidIndex(TPM_NV_INDEX nvIndex); TPM_RESULT TPM_NVDataSensitive_IsGPIO(TPM_BOOL *isGPIO, TPM_NV_INDEX nvIndex); TPM_RESULT TPM_NVDataSensitive_IsValidPlatformIndex(TPM_NV_INDEX nvIndex); /* NV Index Entries */ void TPM_NVIndexEntries_Init(TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries); void TPM_NVIndexEntries_Delete(TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries); void TPM_NVIndexEntries_Trace(TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries); TPM_RESULT TPM_NVIndexEntries_Load(TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_NVIndexEntries_Store(TPM_STORE_BUFFER *sbuffer, TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries); void TPM_NVIndexEntries_StClear(TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries); TPM_RESULT TPM_NVIndexEntries_LoadVolatile(TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_NVIndexEntries_StoreVolatile(TPM_STORE_BUFFER *sbuffer, TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries); TPM_RESULT TPM_NVIndexEntries_GetVolatile(TPM_NV_DATA_ST **tpm_nv_data_st, TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries); TPM_RESULT TPM_NVIndexEntries_SetVolatile(TPM_NV_DATA_ST *tpm_nv_data_st, TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries); TPM_RESULT TPM_NVIndexEntries_GetFreeEntry(TPM_NV_DATA_SENSITIVE **tpm_nv_data_sensitive, TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries); TPM_RESULT TPM_NVIndexEntries_GetEntry(TPM_NV_DATA_SENSITIVE **tpm_nv_data_sensitive, TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries, TPM_NV_INDEX nvIndex); TPM_RESULT TPM_NVIndexEntries_GetUsedCount(uint32_t *count, TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries); TPM_RESULT TPM_NVIndexEntries_GetNVList(TPM_STORE_BUFFER *sbuffer, TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries); TPM_RESULT TPM_NVIndexEntries_GetUsedSpace(uint32_t *usedSpace, TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries); TPM_RESULT TPM_NVIndexEntries_DeleteOwnerAuthorized(TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries, TPM_BOOL deleteAllNvram); TPM_RESULT TPM_NVIndexEntries_GetUsedSpace(uint32_t *usedSpace, TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries); TPM_RESULT TPM_NVIndexEntries_GetFreeSpace(uint32_t *freeSpace, TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries); TPM_RESULT TPM_NVIndexEntries_GetDataPublic(TPM_NV_DATA_PUBLIC **tpm_nv_data_public, TPM_NV_INDEX_ENTRIES *tpm_nv_index_entries, TPM_NV_INDEX nvIndex); /* Processing Functions */ TPM_RESULT TPM_Process_NVReadValue(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_NVReadValueAuth(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_NVWriteValue(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_NVWriteValueAuth(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_NVDefineSpace(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_DirRead(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_DirWriteAuth(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); #endif libtpms-0.9.3/src/tpm12/tpm_nvram_const.h000066400000000000000000000111541421143571500203160ustar00rootroot00000000000000/********************************************************************************/ /* */ /* NVRAM Constants */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_nvram_const.h 4528 2011-03-29 22:16:28Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_NVRAM_CONST_H #define TPM_NVRAM_CONST_H /* These are implementation specific constants */ /* TPMS_MAX defines the maximum number of TPM instances. */ #define TPMS_MAX 1 /* NVRAM storage directory path */ #ifdef TPM_NV_DISK /* TPM_NV_DISK uses the TPM_PATH environment variable */ #endif /* Defines the maximum size of the NV defined space, the NV indexes created by TPM_NV_DefineSpace. The PC Client requires 2048 bytes. There is at least (currently) 6 bytes of overhead, a tag and a count. */ #ifndef TPM_MAX_NV_DEFINED_SIZE #define TPM_MAX_NV_DEFINED_SIZE 2100 #endif /* TPM_MAX_NV_SPACE defines the maximum NV space for non-volatile state. It does not include the area used for TPM_SaveState. See TPM_OWNER_EVICT_KEY_HANDLES, TPM_MIN_COUNTERS, TPM_NUM_FAMILY_TABLE_ENTRY_MIN, TPM_NUM_DELEGATE_TABLE_ENTRY_MIN, etc. and the platform specific requirements for NV defined space. */ #ifndef TPM_MAX_NV_SPACE #ifdef TPM_NV_DISK #define TPM_MAX_NV_SPACE 100000 /* arbitrary value */ #endif #endif /* TPM_MAX_NV_SPACE */ #ifndef TPM_MAX_NV_SPACE #error "TPM_MAX_NV_SPACE is not defined" #endif /* TPM_MAX_SAVESTATE_SPACE defines the maximum NV space for TPM saved state. It is used by TPM_SaveState NOTE This macro is based on the maximum number of loaded keys and session. For example, 3 loaded keys, 3 OSAP sessions, and 1 transport session consumes about 2500 bytes. See TPM_KEY_HANDLES, TPM_NUM_PCR, TPM_MIN_AUTH_SESSIONS, TPM_MIN_TRANS_SESSIONS, TPM_MIN_DAA_SESSIONS, TPM_MIN_SESSION_LIST, etc. */ #ifndef TPM_MAX_SAVESTATE_SPACE #ifdef TPM_NV_DISK #define TPM_MAX_SAVESTATE_SPACE 100000 /* arbitrary value */ #endif #endif /* TPM_MAX_SAVESTATE_SPACE */ #ifndef TPM_MAX_SAVESTATE_SPACE #error "TPM_MAX_SAVESTATE_SPACE is not defined" #endif /* TPM_MAX_VOLATILESTATE_SPACE defines the maximum NV space for TPM volatile state. It is used for applications that save and restore the entire TPM volatile is a non-standard way. */ #ifndef TPM_MAX_VOLATILESTATE_SPACE #ifdef TPM_NV_DISK #define TPM_MAX_VOLATILESTATE_SPACE 524288 /* arbitrary value */ #endif #endif /* TPM_MAX_VOLATILESTATE_SPACE */ #ifndef TPM_MAX_VOLATILESTATE_SPACE #error "TPM_MAX_VOLATILESTATE_SPACE is not defined" #endif #endif libtpms-0.9.3/src/tpm12/tpm_openssl_helpers.c000066400000000000000000000110171421143571500211630ustar00rootroot00000000000000/********************************************************************************/ /* */ /* OpenSSL helper functions */ /* Written by Stefan Berger */ /* IBM Thomas J. Watson Research Center */ /* */ /* (c) Copyright IBM Corporation 2020. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include #include #include #include "tpm_debug.h" #include "tpm_error.h" #include "tpm_openssl_helpers.h" #include "tpm_crypto.h" #if USE_OPENSSL_FUNCTIONS_RSA TPM_RESULT TPM_RSAGenerateEVP_PKEY(EVP_PKEY **pkey, /* out: pkey */ unsigned char *narr, /* public modulus */ uint32_t nbytes, unsigned char *earr, /* public exponent */ uint32_t ebytes, unsigned char *darr, /* private exponent */ uint32_t dbytes) { TPM_RESULT rc = 0; int irc; BIGNUM * n = NULL; BIGNUM * e = NULL; BIGNUM * d = NULL; RSA * rsakey = NULL; /* sanity check for the free */ if (rc == 0) { if (*pkey != NULL) { printf("TPM_RSAGeneratePrivateToken: Error (fatal), pkey %p should be NULL\n", *pkey); rc = TPM_FAIL; } } /* construct the OpenSSL private key object */ if (rc == 0) { *pkey = EVP_PKEY_new(); /* freed by caller */ if (*pkey == NULL) { printf("TPM_RSAGeneratePrivateToken: Error in EVP_PKEY_new()\n"); rc = TPM_FAIL; } } if (rc == 0) { rc = TPM_bin2bn((TPM_BIGNUM *)&n, narr, nbytes); /* freed by caller */ } if (rc == 0) { rc = TPM_bin2bn((TPM_BIGNUM *)&e, earr, ebytes); /* freed by caller */ } if (rc == 0) { if (darr != NULL) { rc = TPM_bin2bn((TPM_BIGNUM *)&d, darr, dbytes); /* freed by caller */ } } if (rc == 0) { rsakey = RSA_new(); if (rsakey == NULL) { printf("TPM_RSAGeneratePrivateToken: Error in RSA_new()\n"); rc = TPM_FAIL; } } if (rc == 0) { irc = RSA_set0_key(rsakey, n, e, d); if (irc != 1) { printf("TPM_RSAGeneratePrivateToken: Error in RSA_set0_key()\n"); rc = TPM_FAIL; } else { n = NULL; e = NULL; d = NULL; } } if (rc == 0) { RSA_set_flags(rsakey, RSA_FLAG_NO_BLINDING); irc = EVP_PKEY_assign_RSA(*pkey, rsakey); if (irc == 0) { printf("TPM_RSAGeneratePrivateToken: Error in EVP_PKEY_assign_RSA()\n"); rc = TPM_FAIL; } else { rsakey = NULL; } } if (rc != 0) { EVP_PKEY_free(*pkey); *pkey = NULL; RSA_free(rsakey); BN_free(n); BN_free(e); BN_clear_free(d); } return rc; } #endif libtpms-0.9.3/src/tpm12/tpm_openssl_helpers.h000066400000000000000000000046311421143571500211740ustar00rootroot00000000000000/********************************************************************************/ /* */ /* OpenSSL helper functions */ /* Written by Stefan Berger */ /* IBM Thomas J. Watson Research Center */ /* */ /* (c) Copyright IBM Corporation 2020. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_OPENSSL_HELPERS_H #define TPM_OPENSSL_HELPERS_H TPM_RESULT TPM_RSAGenerateEVP_PKEY(EVP_PKEY **pkey, /* out: pkey */ unsigned char *narr, /* public modulus */ uint32_t nbytes, unsigned char *earr, /* public exponent */ uint32_t ebytes, unsigned char *darr, /* private exponent */ uint32_t dbytes); #endif libtpms-0.9.3/src/tpm12/tpm_owner.c000066400000000000000000002304561421143571500171220ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Ownership Processing */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_owner.c 4620 2011-09-07 21:43:19Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include #include #include "tpm_audit.h" #include "tpm_auth.h" #include "tpm_counter.h" #include "tpm_crypto.h" #include "tpm_cryptoh.h" #include "tpm_debug.h" #include "tpm_delegate.h" #include "tpm_error.h" #include "tpm_init.h" #include "tpm_io.h" #include "tpm_key.h" #include "tpm_nonce.h" #include "tpm_nvram.h" #include "tpm_pcr.h" #include "tpm_permanent.h" #include "tpm_process.h" #include "tpm_secret.h" #include "tpm_session.h" #include "tpm_sizedbuffer.h" #include "tpm_transport.h" #include "tpm_owner.h" /* Flags involved with clearing an owner: pFlags.disableOwnerClear set by TPM_DisableOwnerClear clear by successful owner clear vFlags.disableForceClear set by TPM_DisableForceClear clear by TPM_Init TPM_OwnerClear requires ownerAuth pFlags.disableOwnerClear == FALSE TPM_ForceClear requires physical presence vFlags.disableForceClear == FALSE */ /* 6.1 TPM_TakeOwnership rev 114 This command inserts the TPM Ownership value into the TPM. */ TPM_RESULT TPM_Process_TakeOwnership(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, /* bytes left in command */ TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_PROTOCOL_ID protocolID; /* The ownership protocol in use */ TPM_SIZED_BUFFER encOwnerAuth; /* The owner authorization data encrypted with PUBEK */ TPM_SIZED_BUFFER encSrkAuth; /* The SRK authorization data encrypted with PUBEK */ TPM_KEY srkParams; /* Structure containing all parameters of new SRK. pubKey.keyLength & encSize are both 0. This structure MAY be TPM_KEY12. */ TPM_AUTHHANDLE authHandle; /* The authorization handle used for this command */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession; /* The continue use flag for the authorization handle */ TPM_AUTHDATA ownerAuth; /* Authorization digest for input params. HMAC key: the new ownerAuth */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_AUTH_SESSION_DATA *auth_session_data; /* session data for authHandle */ TPM_SECRET *hmacKey; TPM_SECRET a1Auth; /* decrypt of encOwnerAuth */ uint32_t a1Auth_length; /* length of decrypted A1 */ TPM_SECRET a2SrkAuth; /* decrypt of encSrkAuth */ uint32_t a2SrkAuth_length; /* length of decrypted A2 */ TPM_RSA_KEY_PARMS *srkRSAKeyParms; TPM_STORE_ASYMKEY *srkStoreAsymkey; TPM_STORE_BUFFER asymKeySbuffer; /* serialized SRK asymkey */ TPM_KEY *srk; /* pointer to SRK in permanent data */ TPM_SIZED_BUFFER exponent; /* default exponent */ TPM_BOOL writeAllNV1 = FALSE; /* flags to write back NV */ TPM_BOOL writeAllNV2 = FALSE; /* flags to write back NV */ int ver; /* TPM_KEY or TPM_KEY12 */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_KEY srkPub; /* Structure containing all parameters of new SRK, srkPub.encData is set to 0. */ printf("TPM_Process_TakeOwnership: Ordinal Entry\n"); srk = &(tpm_state->tpm_permanent_data.srk); /* get pointer to SRK in permanent data */ /* so that Delete's are safe */ TPM_SizedBuffer_Init(&encOwnerAuth); /* freed @1 */ TPM_SizedBuffer_Init(&encSrkAuth); /* freed @2 */ TPM_Key_Init(&srkParams); /* freed @3 */ TPM_Key_Init(&srkPub); /* freed @5 */ TPM_SizedBuffer_Init(&exponent); /* freed @6 */ TPM_Sbuffer_Init(&asymKeySbuffer); /* freed @7 */ /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get protocolID parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load16(&protocolID, &command, ¶mSize); } /* get encOwnerAuth parameter */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_TakeOwnership: protocolID %04hx\n", protocolID); returnCode = TPM_SizedBuffer_Load(&encOwnerAuth, &command, ¶mSize); } /* get encSrkAuth parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_Load(&encSrkAuth, &command, ¶mSize); } /* get srkParams parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Key_Load(&srkParams, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | TPM_CHECK_ENABLED | TPM_CHECK_NO_LOCKOUT)); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag1(tag); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, ownerAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_TakeOwnership: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* 1. If TPM_PERMANENT_DATA -> ownerAuth is valid return TPM_OWNER_SET */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_TakeOwnership: Checking TPM state\n"); if (tpm_state->tpm_permanent_data.ownerInstalled) { printf("TPM_Process_TakeOwnership: Error, owner already installed\n"); returnCode = TPM_OWNER_SET; } } /* 2. If TPM_PERMANENT_FLAGS -> ownership is FALSE return TPM_INSTALL_DISABLED */ if (returnCode == TPM_SUCCESS) { if (!(tpm_state->tpm_permanent_flags.ownership)) { printf("TPM_Process_TakeOwnership: Error, ownership is false\n"); returnCode = TPM_INSTALL_DISABLED; } } /* 3. If TPM_PERMANENT_DATA -> endorsementKey is invalid return TPM_NO_ENDORSEMENT */ if (returnCode == TPM_SUCCESS) { if (tpm_state->tpm_permanent_data.endorsementKey.keyUsage == TPM_KEY_UNINITIALIZED) { printf("TPM_Process_TakeOwnership: Error, endorsement key is invalid\n"); returnCode = TPM_NO_ENDORSEMENT; } } /* 4. Verify that authHandle is of type OIAP on error return TPM_AUTHFAIL */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_OIAP, 0, /* OSAP entity type */ ordinal, NULL, NULL, /* no OIAP authorization */ NULL); } /* 5. If protocolID is not TPM_PID_OWNER, the TPM MAY return TPM_BAD_PARAMETER */ if (returnCode == TPM_SUCCESS) { if (protocolID != TPM_PID_OWNER) { printf("TPM_Process_TakeOwnership: Error, bad protocolID\n"); returnCode = TPM_BAD_PARAMETER; } } /* 6. Create A1 a TPM_SECRET by decrypting encOwnerAuth using PRIVEK as the key */ /* a. This requires that A1 was encrypted using the PUBEK */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_RSAPrivateDecryptH(a1Auth, /* decrypted data */ &a1Auth_length, /* actual size of A1 */ TPM_SECRET_SIZE, /* size of A1 buffer */ encOwnerAuth.buffer, /* encrypted data */ encOwnerAuth.size, /* encrypted data size */ &(tpm_state->tpm_permanent_data.endorsementKey)); } /* b. Validate that A1 is a length of 20 bytes, on error return TPM_BAD_KEY_PROPERTY */ if (returnCode == TPM_SUCCESS) { if (a1Auth_length != TPM_SECRET_SIZE) { printf("TPM_Process_TakeOwnership: Error, A1 length %u, should be %u\n", a1Auth_length, TPM_SECRET_SIZE); returnCode = TPM_BAD_KEY_PROPERTY; } } /* 7. Validate the command and parameters using A1 and ownerAuth, on error return TPM_AUTHFAIL */ if (returnCode == TPM_SUCCESS) { TPM_PrintFour("TPM_Process_TakeOwnership: A1 secret", a1Auth); returnCode = TPM_Authdata_Check(tpm_state, a1Auth, /* HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, ownerAuth); /* Authorization digest for input */ } /* 8. Validate srkParams */ /* a. If srkParams -> keyUsage is not TPM_KEY_STORAGE return TPM_INVALID_KEYUSAGE */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_TakeOwnership: Validating SRK parameters\n"); if (srkParams.keyUsage != TPM_KEY_STORAGE) { printf("TPM_Process_TakeOwnership: Error, " "srkParams->keyUsage is not TPM_KEY_STORAGE\n"); returnCode = TPM_INVALID_KEYUSAGE; } } /* b. If srkParams -> migratable is TRUE return TPM_INVALID_KEYUSAGE */ if (returnCode == TPM_SUCCESS) { if (srkParams.keyFlags & TPM_MIGRATABLE) { printf("TPM_Process_TakeOwnership: Error, srkParams->keyFlags migratable is TRUE\n"); returnCode = TPM_INVALID_KEYUSAGE; } } /* c. If srkParams -> algorithmParms -> algorithmID is NOT TPM_ALG_RSA return TPM_BAD_KEY_PROPERTY */ if (returnCode == TPM_SUCCESS) { if (srkParams.algorithmParms.algorithmID != TPM_ALG_RSA) { printf("TPM_Process_TakeOwnership: Error, " "srkParams->algorithmParms->algorithmID is NOT TPM_ALG_RSA\n"); returnCode = TPM_BAD_KEY_PROPERTY; } } /* d. If srkParams -> algorithmParms -> encScheme is NOT TPM_ES_RSAESOAEP_SHA1_MGF1 return TPM_BAD_KEY_PROPERTY */ if (returnCode == TPM_SUCCESS) { if (srkParams.algorithmParms.encScheme != TPM_ES_RSAESOAEP_SHA1_MGF1) { printf("TPM_Process_TakeOwnership: Error, " "srkParams->algorithmParms->encScheme is NOT TPM_ES_RSAESOAEP_SHA1_MGF1\n"); returnCode = TPM_BAD_KEY_PROPERTY; } } /* e. If srkParams -> algorithmParms -> sigScheme is NOT TPM_SS_NONE return TPM_BAD_KEY_PROPERTY */ if (returnCode == TPM_SUCCESS) { if (srkParams.algorithmParms.sigScheme != TPM_SS_NONE) { printf("TPM_Process_TakeOwnership: Error, " "srkParams->algorithmParms->sigScheme is NOT TPM_SS_NONE\n"); returnCode = TPM_BAD_KEY_PROPERTY; } } /* f. srkParams -> algorithmParms -> parms -> keyLength MUST be greater than or equal to 2048, on error return TPM_BAD_KEY_PROPERTY */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyParms_GetRSAKeyParms(&srkRSAKeyParms, &(srkParams.algorithmParms)); } if (returnCode == TPM_SUCCESS) { if (srkRSAKeyParms->keyLength < 2048) { printf("TPM_Process_TakeOwnership: Error, " "srkParams->algorithmParms->parms->keyLength " "MUST be greater than or equal to 2048\n"); returnCode = TPM_BAD_KEY_PROPERTY; } } /* g .If srkParams -> algorithmParms -> parms -> exponentSize is not 0, return TPM_BAD_KEY_PROPERTY */ if (returnCode == TPM_SUCCESS) { if (srkRSAKeyParms->exponent.size != 0) { printf("TPM_Process_TakeOwnership: Error, " "srkParams->algorithmParms->parms->exponentSize %u is not zero\n", srkRSAKeyParms->exponent.size); returnCode = TPM_BAD_KEY_PROPERTY; } } /* h. If TPM_PERMANENT_FLAGS -> FIPS is TRUE */ /* i. If srkParams -> authDataUsage specifies TPM_AUTH_NEVER return TPM_NOTFIPS */ if (returnCode == TPM_SUCCESS) { if (tpm_state -> tpm_permanent_flags.FIPS) { if (srkParams.authDataUsage == TPM_AUTH_NEVER) { printf("TPM_Process_TakeOwnership: Error, " "FIPS and authDataUsage is TPM_AUTH_NEVER\n"); returnCode = TPM_NOTFIPS; } } } /* check that srkParams is TPM_KEY or TPM_KEY12 */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Key_CheckStruct(&ver, &srkParams); } /* 9. Generate K1 (SRK) according to the srkParams on error return TPM_BAD_KEY_PROPERTY */ /* a.This includes copying PCRInfo from srkParams to K1 */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_TakeOwnership: SRK key length %u\n", srkRSAKeyParms->keyLength); if (ver == 1) { if (srkParams.tpm_pcr_info != NULL) { TPM_PCRInfo_Trace("TPM_Process_TakeOwnership: SRK PCRs", srkParams.tpm_pcr_info->pcrSelection, srkParams.tpm_pcr_info->digestAtRelease); } else { printf("TPM_Process_TakeOwnership: No SRK PCRs\n"); } } else { if (srkParams.tpm_pcr_info_long != NULL) { TPM_PCRInfo_Trace("TPM_Process_TakeOwnership: SRK PCRs", srkParams.tpm_pcr_info_long->releasePCRSelection, srkParams.tpm_pcr_info_long->digestAtRelease); } else { printf("TPM_Process_TakeOwnership: No SRK PCRs\n"); } } printf("TPM_Process_TakeOwnership: Creating SRK, authDataUsage %u\n", srkParams.authDataUsage); /* The old keys should already be deleted from an OwnerClear, but it can't hurt to do it again to prevent memory leaks on errors. */ TPM_Key_Delete(srk); /* not freed, in permanent store */ returnCode = TPM_Key_GenerateRSA(srk, tpm_state, NULL, /* parent key */ tpm_state->tpm_stclear_data.PCRS, /* PCR array */ ver, TPM_KEY_STORAGE, /* keyUsage */ srkParams.keyFlags, srkParams.authDataUsage, &(srkParams.algorithmParms), /* TPM_KEY_PARMS */ srkParams.tpm_pcr_info, srkParams.tpm_pcr_info_long); writeAllNV1 = TRUE; } /* 15. Create TPM_PERMANENT_DATA -> tpmProof by using the TPM RNG */ /* NOTE: Moved here so tpmProof can be inserted into SRK -> migrationAuth */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_TakeOwnership: Creating tpmProof\n"); returnCode = TPM_Secret_Generate(tpm_state->tpm_permanent_data.tpmProof); } /* 10. Create A2 a TPM_SECRET by decrypting encSrkAuth using the PRIVEK */ /* a. This requires A2 to be encrypted using the PUBEK */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_RSAPrivateDecryptH(a2SrkAuth, /* decrypted data */ &a2SrkAuth_length, /* actual size of A2 */ TPM_SECRET_SIZE, /* size of A2 buffer */ encSrkAuth.buffer, /* encrypted data */ encSrkAuth.size, /* encrypted data size */ &(tpm_state->tpm_permanent_data.endorsementKey)); } /* b. Validate that A2 is a length of 20 bytes, on error return TPM_BAD_KEY_PROPERTY */ if (returnCode == TPM_SUCCESS) { if (a2SrkAuth_length != TPM_SECRET_SIZE) { printf("TPM_Process_TakeOwnership: Error, A2 length %u, should be %u\n", a2SrkAuth_length, TPM_SECRET_SIZE); returnCode = TPM_BAD_KEY_PROPERTY; } } /* c. Store A2 in K1 (SRK) -> usageAuth */ if (returnCode == TPM_SUCCESS) { TPM_PrintFour("TPM_Process_TakeOwnership: Insert usageAuth into SRK", a2SrkAuth); /* get the TPM_STORE_ASYMKEY from the TPM_KEY srk */ returnCode = TPM_Key_GetStoreAsymkey(&srkStoreAsymkey, srk); } if (returnCode == TPM_SUCCESS) { /* insert the authData into the TPM_STORE_ASYMKEY */ TPM_Secret_Copy(srkStoreAsymkey->usageAuth, a2SrkAuth); /* store tpmProof in migrationAuth to indicate that this is a non-migratable key */ TPM_Secret_Copy(srkStoreAsymkey->migrationAuth, tpm_state->tpm_permanent_data.tpmProof); /* serialize the TPM_STORE_ASYMKEY object */ returnCode = TPM_StoreAsymkey_Store(&asymKeySbuffer, FALSE, srkStoreAsymkey); } /* store the serialized TPM_STORE_ASYMKEY as encData */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_SetFromStore(&(srk->encData), &asymKeySbuffer); } /* 11. Store K1 in TPM_PERMANENT_DATA -> srk */ /* NOTE Generated directly in srk */ /* 12. Store A1 in TPM_PERMANENT_DATA -> ownerAuth */ if (returnCode == TPM_SUCCESS) { TPM_Secret_Copy(tpm_state->tpm_permanent_data.ownerAuth, a1Auth); tpm_state->tpm_permanent_data.ownerInstalled = TRUE; } /* 13. Create TPM_PERMANENT_DATA -> contextKey according to the rules for the algorithm in use by the TPM to save context blobs */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_TakeOwnership: Creating contextKey\n"); returnCode = TPM_SymmetricKeyData_GenerateKey(tpm_state->tpm_permanent_data.contextKey); } /* 14. Create TPM_PERMANENT_DATA -> delegateKey according to the rules for the algorithm in use by the TPM to save delegate blobs */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_TakeOwnership: Creating delegateKey\n"); returnCode = TPM_SymmetricKeyData_GenerateKey(tpm_state->tpm_permanent_data.delegateKey); } /* 15. Create TPM_PERMANENT_DATA -> tpmProof by using the TPM RNG */ /* NOTE: This Action done earlier */ /* 16. Export TPM_PERMANENT_DATA -> srk as srkPub */ if (returnCode == TPM_SUCCESS) { /* copy the srk */ printf("TPM_Process_TakeOwnership: Creating srkPub for response\n"); returnCode = TPM_Key_Copy(&srkPub, srk, FALSE); /* don't copy encData */ } /* 17. Set TPM_PERMANENT_FLAGS -> readPubek to FALSE */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_TakeOwnership: Clear readPubek\n"); TPM_SetCapability_Flag(&writeAllNV2, /* altered */ &(tpm_state->tpm_permanent_flags.readPubek), /* flag */ FALSE); /* value */ } /* Store the permanent data and flags back to NVRAM */ returnCode = TPM_PermanentAll_NVStore(tpm_state, (TPM_BOOL)(writeAllNV1 || writeAllNV2), returnCode); /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_TakeOwnership: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* append srkPub */ returnCode = TPM_Key_Store(response, &srkPub); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ /* 18. Calculate resAuth using the newly established TPM_PERMANENT_DATA -> ownerAuth */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Set(response, tpm_state->tpm_permanent_data.ownerAuth, /* owner HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } TPM_SizedBuffer_Delete(&encOwnerAuth); /* @1 */ TPM_SizedBuffer_Delete(&encSrkAuth); /* @2 */ TPM_Key_Delete(&srkParams); /* @3 */ TPM_Key_Delete(&srkPub); /* @5 */ TPM_SizedBuffer_Delete(&exponent); /* @6 */ TPM_Sbuffer_Delete(&asymKeySbuffer); /* @7 */ return rcf; } /* 6.2 TPM_OwnerClear rev 101 The OwnerClear command performs the clear operation under authorization. This command is available until the Owner executes the DisableOwnerClear, at which time any further invocation of this command returns TPM_CLEAR_DISABLED. */ TPM_RESULT TPM_Process_OwnerClear(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_AUTHHANDLE authHandle; /* The authorization handle used for owner authorization */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* Ignored */ TPM_AUTHDATA ownerAuth; /* The authorization digest for inputs and owner authorization. HMAC key: permanent_data.ownerAuth. */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ TPM_SECRET *hmacKey; TPM_SECRET oldOwnerAuth; /* saved copy for response */ TPM_BOOL writeAllNV = FALSE; /* flag to write back permanent */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_OwnerClear: Ordinal Entry\n"); /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag1(tag); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, ownerAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_OwnerClear: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* 1. Verify that the TPM Owner authorizes the command and all of the input, on error return TPM_AUTHFAIL. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_OWNER, ordinal, NULL, &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ } if (returnCode == TPM_SUCCESS) { /* make a copy of the TPM_PERMANENT_DATA.ownerAuth for the response, since it gets invalidated in step 5. */ TPM_Secret_Copy(oldOwnerAuth, *hmacKey); TPM_PrintFour("TPM_Process_OwnerClear: ownerAuth secret", *hmacKey); returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* owner HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, ownerAuth); /* Authorization digest for input */ } /* 2. If TPM_PERMANENT_FLAGS -> disableOwnerClear is TRUE then return TPM_CLEAR_DISABLED. */ if (returnCode == TPM_SUCCESS) { if (tpm_state->tpm_permanent_flags.disableOwnerClear) { printf("TPM_Process_OwnerClear: Error, disableOwnerClear is TRUE\n"); returnCode = TPM_CLEAR_DISABLED; } } /* owner clear common code */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_OwnerClearCommon(tpm_state, FALSE); /* don't delete if D bit set */ continueAuthSession = FALSE; /* Fixed value FALSE */ writeAllNV = TRUE; } /* Store the permanent data and flags back to NVRAM */ returnCode = TPM_PermanentAll_NVStore(tpm_state, writeAllNV, returnCode); /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_OwnerClear: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Set(response, oldOwnerAuth, /* old owner HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, terminate the session. NOTE: Normally this will fail because all sessions have been closed. */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } return rcf; } /* 6.3 TPM_ForceClear rev 109 The ForceClear command performs the Clear operation under physical access. This command is available until the execution of the DisableForceClear, at which time any further invocation of this command returns TPM_CLEAR_DISABLED. TPM_ForceClear can succeed even if no owner is installed. In that case, it does whatever TPM_OwnerClear actions that it can. */ TPM_RESULT TPM_Process_ForceClear(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL writeAllNV = FALSE; /* flag to write back data */ TPM_BOOL physicalPresence; /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_ForceClear: Ordinal Entry\n"); /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_ForceClear: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ /* 1. The TPM SHALL check for the assertion of physical presence, if not present return TPM_BAD_PRESENCE */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Global_GetPhysicalPresence(&physicalPresence, tpm_state); } if (returnCode == TPM_SUCCESS) { if (!physicalPresence) { printf("TPM_Process_ForceClear: Error, physicalPresence is FALSE\n"); returnCode = TPM_BAD_PRESENCE; } } /* 2. If TPM_STCLEAR_FLAGS -> disableForceClear is TRUE return TPM_CLEAR_DISABLED */ if (returnCode == TPM_SUCCESS) { if (tpm_state->tpm_stclear_flags.disableForceClear) { printf("TPM_Process_ForceClear: Error, disableForceClear is TRUE\n"); returnCode = TPM_CLEAR_DISABLED; } } /* 3. The TPM SHALL execute the actions of TPM_OwnerClear (except for the TPM Owner authentication check) */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_OwnerClearCommon(tpm_state, FALSE); /* don't delete if D bit set */ writeAllNV = TRUE; } /* Store the permanent data and flags back to NVRAM */ returnCode = TPM_PermanentAll_NVStore(tpm_state, writeAllNV, returnCode); /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_ForceClear: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } return rcf; } /* TPM_OwnerClearCommon() rev 116 Performs owner clear operations common to TPM_OwnerClear, TPM_ForceClear, and TPM_RevokeTrust. It assumes that any required authorization is performed by the caller If deleteAllNvram is TRUE, all NVRAM is deleted. If it is FALSE, indexes with the D bit set are not cleared. Data is not written back to NV space here. It is written by the caller. */ TPM_RESULT TPM_OwnerClearCommon(tpm_state_t *tpm_state, TPM_BOOL deleteAllNvram) { TPM_RESULT rc = 0; size_t start; size_t current; TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry; /* 3. Unload all loaded keys. */ /* a. If TPM_PERMANENT_FLAGS -> FIPS is TRUE, the memory locations containing secret or private keys MUST be set to all zeros. */ start = 0; while ((rc == 0) && /* returns TPM_RETRY when at the end of the table, terminates loop */ (TPM_KeyHandleEntries_GetNextEntry(&tpm_key_handle_entry, ¤t, tpm_state->tpm_key_handle_entries, start)) == 0) { printf("TPM_OwnerClearCommon: Flushing key handle %08x\n", tpm_key_handle_entry->handle); rc = TPM_KeyHandleEntry_FlushSpecific(tpm_state, tpm_key_handle_entry); start = current + 1; } #ifdef TPM_V11 /* 5. The TPM sets all DIR registers to their default value. */ if (rc == 0) { TPM_Digest_Init(tpm_state->tpm_permanent_data.authDIR); } #endif /* a.This includes owner evict keys */ if (rc == 0) { printf("TPM_OwnerClearCommon: Deleting owner evict keys\n"); TPM_KeyHandleEntries_OwnerEvictDelete(tpm_state->tpm_key_handle_entries); } /* 4. The TPM MUST NOT modify the following TPM_PERMANENT_DATA items a. endorsementKey b. revMajor c. revMinor d. manuMaintPub e. auditMonotonicCounter NOTE: TPMWG email: Don't touch the base value. f. monotonicCounter g. pcrAttrib h. rngState i. EKReset j. lastFamilyID k. tpmDAASeed l. DIR[1] m. daaProof n. daaBlobKey */ /* 5. The TPM MUST invalidate the following TPM_PERMANENT_DATA items and any internal resources associated with these items */ if (rc == 0) { printf("TPM_OwnerClearCommon: Invalidate TPM_PERMANENT_DATA items\n"); /* a. ownerAuth */ TPM_Secret_Init(tpm_state->tpm_permanent_data.ownerAuth); tpm_state->tpm_permanent_data.ownerInstalled = FALSE; /* b. srk */ TPM_Key_Delete(&(tpm_state->tpm_permanent_data.srk)); /* c. delegateKey */ printf("TPM_OwnerClearCommon: Invalidate delegateKey\n"); TPM_SymmetricKeyData_Init(tpm_state->tpm_permanent_data.delegateKey); /* d. delegateTable */ TPM_DelegateTable_Delete(&(tpm_state->tpm_permanent_data.delegateTable)); /* e. contextKey */ printf("TPM_OwnerClearCommon: Invalidate contextKey\n"); TPM_SymmetricKeyData_Init(tpm_state->tpm_permanent_data.contextKey); /* f. tpmProof */ TPM_Secret_Init(tpm_state->tpm_permanent_data.tpmProof); /* g. operatorAuth */ TPM_Secret_Init(tpm_state->tpm_permanent_data.operatorAuth); /* 6. The TPM MUST reset to manufacturing defaults the following TPM_PERMANENT_DATA items */ /* a. noOwnerNVWrite MUST be set to 0 */ tpm_state->tpm_permanent_data.noOwnerNVWrite = 0; /* b. ordinalAuditStatus */ rc = TPM_OrdinalAuditStatus_Init(&(tpm_state->tpm_permanent_data)); /* c. restrictDelegate */ tpm_state->tpm_permanent_data.restrictDelegate = 0; } if (rc == 0) { /* 7. The TPM MUST invalidate or reset all fields of TPM_STANY_DATA a. Nonces SHALL be reset b. Lists (e.g. contextList) SHALL be invalidated NOTE This also terminates all sessions */ printf("TPM_OwnerClearCommon: Invalidate TPM_STANY_DATA\n"); TPM_StanyData_Delete(&(tpm_state->tpm_stany_data)); /* 8. The TPM MUST invalidate all fields of TPM_STCLEAR_DATA except the PCR's a. Nonces SHALL be reset b. Lists (e.g. contextList) SHALL be invalidated c. deferredPhysicalPresence MUST be set to 0 */ printf("TPM_OwnerClearCommon: Invalidate TPM_STCLEAR_DATA\n"); TPM_StclearData_Delete(&(tpm_state->tpm_stclear_data), tpm_state->tpm_permanent_data.pcrAttrib, FALSE); /* don't reset the PCR's */ /* 9. The TPM MUST set the following TPM_PERMANENT_FLAGS to their default values */ /* a. disable */ printf("TPM_OwnerClearCommon: Set disable TRUE\n"); tpm_state->tpm_permanent_flags.disable = TRUE; /* b. deactivated */ printf("TPM_OwnerClearCommon: Set deactivated TRUE\n"); tpm_state->tpm_permanent_flags.deactivated = TRUE; /* c. readPubek */ printf("TPM_OwnerClearCommon: Set readPubek TRUE\n"); tpm_state->tpm_permanent_flags.readPubek = TRUE; /* d. disableOwnerClear */ tpm_state->tpm_permanent_flags.disableOwnerClear = FALSE; #if (TPM_REVISION >= 103) /* added for rev 103 */ /* e. disableFullDALogicInfo */ tpm_state->tpm_permanent_flags.disableFullDALogicInfo = FALSE; #endif /* f. allowMaintenance */ #if defined(TPM_NOMAINTENANCE) || defined(TPM_NOMAINTENANCE_COMMANDS) tpm_state->tpm_permanent_flags.allowMaintenance = FALSE; #else tpm_state->tpm_permanent_flags.allowMaintenance = TRUE; #endif /* #if (TPM_REVISION >= 104) This was added in rev 104, but was implemented by vendors earlier */ /* g. readSRKPub */ tpm_state->tpm_permanent_flags.readSRKPub = FALSE; /* 10. The TPM MUST set the following TPM_PERMANENT_FLAGS */ /* a. ownership to TRUE */ tpm_state->tpm_permanent_flags.ownership = TRUE; /* b. operator to FALSE */ tpm_state->tpm_permanent_flags.tpmOperator = FALSE; /* c. maintenanceDone to FALSE */ tpm_state->tpm_permanent_flags.maintenanceDone = FALSE; /* 11. The TPM releases all TPM_PERMANENT_DATA -> monotonicCounter settings a. This includes invalidating all currently allocated counters. The result will be no currently allocated counters and the new owner will need to allocate counters. The actual count value will continue to increase. */ rc = TPM_Counters_Release(tpm_state->tpm_permanent_data.monotonicCounter); /* NOTE: v1.1 says to set all TPM_PERSISTENT_FLAGS to the default value, but I doubt this is correct. I assume that physicalPresenceLifetimeLock which is a one-way flag, should not be reset. A similar comment goes for tpmPost and tpmPostLock. */ } /* TPM_OwnerClear 12. The TPM MUST deallocate all defined NV storage areas where a. TPM_NV_PER_OWNERWRITE is TRUE if nvIndex does not have the "D" bit set b. TPM_NV_PER_OWNERREAD is TRUE if nvIndex does not have the "D" bit set c. The TPM MUST NOT deallocate any other currently defined NV storage areas. d.This default behavior MAY be superseded for GPIO indexes by the platform specific specification. TPM_RevokeTrust: a. NV items with the pubInfo -> nvIndex D value set MUST be deleted. This changes the TPM_OwnerClear handling of the same NV areas */ if (rc == 0) { rc = TPM_NVIndexEntries_DeleteOwnerAuthorized(&(tpm_state->tpm_nv_index_entries), deleteAllNvram); } #if defined TPM_PCCLIENT /* From the PC Client TIS 1.When there is no TPM Owner, the TPM_NV_INDEX_GPIO_00 area MUST be deallocated (see main specification part 3 on TPM_OwnerClear). */ if (rc == 0) { TPM_NV_DATA_SENSITIVE *tpm_nv_data_sensitive; rc = TPM_NVIndexEntries_GetEntry(&tpm_nv_data_sensitive, &(tpm_state->tpm_nv_index_entries), TPM_NV_INDEX_GPIO_00); /* if found, delete */ if (rc == 0) { TPM_NVDataSensitive_Delete(tpm_nv_data_sensitive); } else if (rc == TPM_BADINDEX) { rc = TPM_SUCCESS; /* non-existent index is not an error */ } } #endif /* 13. The TPM MUST invalidate all familyTable entries */ if (rc == 0) { TPM_FamilyTable_Delete(&(tpm_state->tpm_permanent_data.familyTable)); } /* 14. The TPM MUST terminate all sessions, active or saved. */ /* NOTE: Done by TPM_StclearData_Delete() */ /* NOTE The TPM_PERMANENT_DATA and TPM_PERMANENT_FLAGS NVRAM store cannot be factored out here, since some callers do other functions before the store. */ return rc; } /* 6.6 TSC_PhysicalPresence rev 87 Some TPM operations require the indication of a human's physical presence at the platform. The presence of the human either provides another indication of platform ownership or a mechanism to ensure that the execution of the command is not the result of a remote software process. This command allows a process on the platform to indicate the assertion of physical presence. As this command is executable by software there must be protections against the improper invocation of this command. The physicalPresenceHWEnable and physicalPresenceCMDEnable indicate the ability for either SW or HW to indicate physical presence. These flags can be reset until the physicalPresenceLifetimeLock is set. The platform manufacturer should set these flags to indicate the capabilities of the platform the TPM is bound to. The command provides two sets of functionality. The first is to enable, permanently, either the HW or the SW ability to assert physical presence. The second is to allow SW, if enabled, to assert physical presence. */ TPM_RESULT TPM_Process_PhysicalPresence(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_PHYSICAL_PRESENCE physicalPresence; /* The state to set the TPM's Physical Presence flags */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus = FALSE; /* audit the ordinal */ TPM_BOOL transportEncrypt = FALSE; /* wrapped in encrypted transport session */ #ifdef TPM_V12 uint16_t a1 = TRUE; /* lifetime settings */ uint16_t a2 = TRUE; /* assertion settings */ #endif TPM_BOOL writeAllNV = FALSE; /* flag to write back flags */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_PhysicalPresence: Ordinal Entry\n"); /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get physicalPresence parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load16(&physicalPresence, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_PhysicalPresence: physicalPresence parameter %04x\n", physicalPresence); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | TPM_CHECK_NO_LOCKOUT)); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_PhysicalPresence: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ #ifdef TPM_V12 if (returnCode == TPM_SUCCESS) { if (physicalPresence & TPM_PHYSICAL_PRESENCE_MASK) { printf("TPM_Process_PhysicalPresence: Error, physicalPresence extra bits\n"); returnCode = TPM_BAD_PARAMETER; } } /* 1. For documentation ease, the bits break into two categories. The first is the lifetime settings and the second is the assertion settings. */ if (returnCode == TPM_SUCCESS) { /* a. Define A1 to be the lifetime settings: TPM_PHYSICAL_PRESENCE_LIFETIME_LOCK, TPM_PHYSICAL_PRESENCE_HW_ENABLE, TPM_PHYSICAL_make contingent!!!PRESENCE_CMD_ENABLE, TPM_PHYSICAL_PRESENCE_HW_DISABLE, and TPM_PHYSICAL_PRESENCE_CMD_DISABLE */ a1 = physicalPresence & (TPM_PHYSICAL_PRESENCE_LIFETIME_LOCK | TPM_PHYSICAL_PRESENCE_HW_ENABLE | TPM_PHYSICAL_PRESENCE_CMD_ENABLE | TPM_PHYSICAL_PRESENCE_HW_DISABLE | TPM_PHYSICAL_PRESENCE_CMD_DISABLE); /* b. Define A2 to be the assertion settings: TPM_PHYSICAL_PRESENCE_LOCK, TPM_PHYSICAL_PRESENCE_PRESENT, and TPM_PHYSICAL_PRESENCE_NOTPRESENT */ a2 = physicalPresence & (TPM_PHYSICAL_PRESENCE_LOCK | TPM_PHYSICAL_PRESENCE_PRESENT | TPM_PHYSICAL_PRESENCE_NOTPRESENT); printf("TPM_Process_PhysicalPresence: a1 %04x a2 %04x\n", a1, a2); } /* Lifetime lock settings */ /* 2. If any A1 setting is present */ if ((returnCode == TPM_SUCCESS) && a1) { if (returnCode == TPM_SUCCESS) { /* a. If TPM_PERMANENT_FLAGS -> physicalPresenceLifetimeLock is TRUE, return TPM_BAD_PARAMETER */ if (tpm_state->tpm_permanent_flags.physicalPresenceLifetimeLock) { printf("TPM_Process_PhysicalPresence: Error, " "physicalPresenceLifetimeLock is TRUE\n"); returnCode = TPM_BAD_PARAMETER; } } /* b. If any A2 setting is present return TPM_BAD_PARAMETER */ if (returnCode == TPM_SUCCESS) { if (a2) { printf("TPM_Process_PhysicalPresence: Error, a1 and a2 TRUE\n"); returnCode = TPM_BAD_PARAMETER; } } /* c. If both physicalPresence -> TPM_PHYSICAL_PRESENCE_HW_ENABLE and physicalPresence -> TPM_PHYSICAL_PRESENCE_HW_DISABLE are TRUE, return TPM_BAD_PARAMETER. */ if (returnCode == TPM_SUCCESS) { if ((physicalPresence & TPM_PHYSICAL_PRESENCE_HW_ENABLE) && (physicalPresence & TPM_PHYSICAL_PRESENCE_HW_DISABLE)) { printf("TPM_Process_PhysicalPresence: Error, HW enable and disable both TRUE \n"); returnCode = TPM_BAD_PARAMETER; } } /* d. If both physicalPresence -> TPM_PHYSICAL_PRESENCE_CMD_ENABLE and physicalPresence -> TPM_PHYSICAL_PRESENCE_CMD_DISABLE are TRUE, return TPM_BAD_PARAMETER. */ if (returnCode == TPM_SUCCESS) { if ((physicalPresence & TPM_PHYSICAL_PRESENCE_CMD_ENABLE ) && (physicalPresence & TPM_PHYSICAL_PRESENCE_CMD_DISABLE )) { printf("TPM_Process_PhysicalPresence: Error, CMD enable and disable both TRUE \n"); returnCode = TPM_BAD_PARAMETER; } } if (returnCode == TPM_SUCCESS) { /* e. If physicalPresence -> TPM_PHYSICAL_PRESENCE_HW_ENABLE is TRUE Set TPM_PERMANENT_FLAGS -> physicalPresenceHWEnable to TRUE */ if (physicalPresence & TPM_PHYSICAL_PRESENCE_HW_ENABLE) { printf("TPM_Process_PhysicalPresence: Setting physicalPresenceHWEnable TRUE\n"); TPM_SetCapability_Flag(&writeAllNV, /* altered */ &(tpm_state->tpm_permanent_flags.physicalPresenceHWEnable), TRUE); /* value */ } /* f. If physicalPresence -> TPM_PHYSICAL_PRESENCE_HW_DISABLE is TRUE Set TPM_PERMANENT_FLAGS -> physicalPresenceHWEnable to FALSE */ if (physicalPresence & TPM_PHYSICAL_PRESENCE_HW_DISABLE) { printf("TPM_Process_PhysicalPresence: Setting physicalPresenceHWEnable FALSE\n"); TPM_SetCapability_Flag(&writeAllNV, /* altered */ &(tpm_state->tpm_permanent_flags.physicalPresenceHWEnable), FALSE); /* value */ } /* g. If physicalPresence -> TPM_PHYSICAL_PRESENCE_CMD_ENABLE is TRUE, Set TPM_PERMANENT_FLAGS -> physicalPresenceCMDEnable to TRUE. */ if (physicalPresence & TPM_PHYSICAL_PRESENCE_CMD_ENABLE) { printf("TPM_Process_PhysicalPresence: Setting physicalPresenceCMDEnable TRUE\n"); TPM_SetCapability_Flag(&writeAllNV, /* altered */ &(tpm_state->tpm_permanent_flags.physicalPresenceCMDEnable), TRUE); /* value */ } /* h. If physicalPresence -> TPM_PHYSICAL_PRESENCE_CMD_DISABLE is TRUE, Set TPM_PERMANENT_FLAGS -> physicalPresenceCMDEnable to FALSE. */ if (physicalPresence & TPM_PHYSICAL_PRESENCE_CMD_DISABLE) { printf("TPM_Process_PhysicalPresence: Setting physicalPresenceCMDEnable FALSE\n"); TPM_SetCapability_Flag(&writeAllNV, /* altered */ &(tpm_state->tpm_permanent_flags.physicalPresenceCMDEnable), FALSE); /* value */ } /* i. If physicalPresence -> TPM_PHYSICAL_PRESENCE_LIFETIME_LOCK is TRUE */ if (physicalPresence & TPM_PHYSICAL_PRESENCE_LIFETIME_LOCK) { /* i. Set TPM_PERMANENT_FLAGS -> physicalPresenceLifetimeLock to TRUE */ printf("TPM_Process_PhysicalPresence: Setting physicalPresenceLifetimeLock\n"); TPM_SetCapability_Flag(&writeAllNV, /* altered */ &(tpm_state->tpm_permanent_flags.physicalPresenceLifetimeLock), TRUE); /* value */ } } /* j. Return TPM_SUCCESS */ } /* SW physical presence assertion */ /* 3. If any A2 setting is present */ if ((returnCode == TPM_SUCCESS) && a2) { /* a. If any A1 setting is present return TPM_BAD_PARAMETER */ /* i. This check here just for consistency, the prior checks would have already ensured that this was OK */ if (returnCode == TPM_SUCCESS) { if (a1) { printf("TPM_Process_PhysicalPresence: Error, a1 and a2 TRUE\n"); returnCode = TPM_BAD_PARAMETER; } } /* b. If TPM_PERMANENT_FLAGS -> physicalPresenceCMDEnable is FALSE, return TPM_BAD_PARAMETER */ if (returnCode == TPM_SUCCESS) { if (!tpm_state->tpm_permanent_flags.physicalPresenceCMDEnable) { printf("TPM_Process_PhysicalPresence: Error, physicalPresenceCMDEnable is FALSE\n"); returnCode = TPM_BAD_PARAMETER; } } /* c. If both physicalPresence -> TPM_PHYSICAL_PRESENCE_LOCK and physicalPresence -> TPM_PHYSICAL_PRESENCE_PRESENT are TRUE, return TPM_BAD_PARAMETER */ if (returnCode == TPM_SUCCESS) { if ((physicalPresence & TPM_PHYSICAL_PRESENCE_LOCK ) && (physicalPresence & TPM_PHYSICAL_PRESENCE_PRESENT)) { printf("TPM_Process_PhysicalPresence: Error, LOCK and PRESENT both TRUE \n"); returnCode = TPM_BAD_PARAMETER; } } /* d. If both physicalPresence -> TPM_PHYSICAL_PRESENCE_PRESENT and physicalPresence -> TPM_PHYSICAL_PRESENCE_NOTPRESENT are TRUE, return TPM_BAD_PARAMETER */ if (returnCode == TPM_SUCCESS) { if ((physicalPresence & TPM_PHYSICAL_PRESENCE_PRESENT) && (physicalPresence & TPM_PHYSICAL_PRESENCE_NOTPRESENT)) { printf("TPM_Process_PhysicalPresence: Error, PRESENT and NOT_PRESENT both TRUE \n"); returnCode = TPM_BAD_PARAMETER; } } /* e. If TPM_STCLEAR_FLAGS -> physicalPresenceLock is TRUE, return TPM_BAD_PARAMETER */ if (returnCode == TPM_SUCCESS) { if (tpm_state->tpm_stclear_flags.physicalPresenceLock) { printf("TPM_Process_PhysicalPresence: Error, physicalPresenceLock is TRUE\n"); returnCode = TPM_BAD_PARAMETER; } } if (returnCode == TPM_SUCCESS) { /* f. If physicalPresence -> TPM_PHYSICAL_PRESENCE_LOCK is TRUE */ if (physicalPresence & TPM_PHYSICAL_PRESENCE_LOCK) { /* i. Set TPM_STCLEAR_FLAGS -> physicalPresence to FALSE */ printf("TPM_Process_PhysicalPresence: Setting physicalPresence FALSE\n"); tpm_state->tpm_stclear_flags.physicalPresence = FALSE; /* ii. Set TPM_STCLEAR_FLAGS -> physicalPresenceLock to TRUE */ printf("TPM_Process_PhysicalPresence: Setting physicalPresenceLock TRUE\n"); tpm_state->tpm_stclear_flags.physicalPresenceLock = TRUE; /* iii. Return TPM_SUCCESS */ } /* g. If physicalPresence -> TPM_PHYSICAL_PRESENCE_PRESENT is TRUE */ if (physicalPresence & TPM_PHYSICAL_PRESENCE_PRESENT) { /* i. Set TPM_STCLEAR_FLAGS -> physicalPresence to TRUE */ printf("TPM_Process_PhysicalPresence: Setting physicalPresence TRUE\n"); tpm_state->tpm_stclear_flags.physicalPresence = TRUE; } /* h. If physicalPresence -> TPM_PHYSICAL_PRESENCE_NOTPRESENT is TRUE */ if (physicalPresence & TPM_PHYSICAL_PRESENCE_NOTPRESENT) { /* i. Set TPM_STCLEAR_FLAGS -> physicalPresence to FALSE */ printf("TPM_Process_PhysicalPresence: Setting physicalPresence FALSE\n"); tpm_state->tpm_stclear_flags.physicalPresence = FALSE; } /* i. Return TPM_SUCCESS */ } } /* 4. Else There were no A1 or A2 parameters set */ if (returnCode == TPM_SUCCESS) { if (!a1 && !a2) { /* a. Return TPM_BAD_PARAMETER */ printf("TPM_Process_PhysicalPresence: Error, a1 and a2 FALSE\n"); returnCode = TPM_BAD_PARAMETER; } } #else /* TPM v1.1 */ /* 2. Once the PhysicalPresenceLock flag is set to TRUE, the TPM MUST not modify the PhysicalPresence flag until a TPM_Init followed by TPM_Startup(stType = TCPA_ST_CLEAR). Upon a TPM_Init and TPM_Startup(stType = TCPA_ST_STATE) the TPM MUST set the PhysicalPresenceLock flag to FALSE. */ /* NOTE: I assume this is a typo, that PhysicalPresenceLock is restored by TPM_ST_STATE and set false on TPM_ST_CLEAR. Other places in the specification certainly say that. */ /* 3.If the PhysicalPresenceLock flag is set to TRUE upon any call to this operation, the TPM MUST cause no action and MUST return the error TCPA_BAD_PARAMETER. */ if (returnCode == TPM_SUCCESS) { if (tpm_state->tpm_stclear_flags.physicalPresenceLock) { printf("TPM_Process_PhysicalPresence: Error, physicalPresenceLock is TRUE\n"); returnCode = TPM_BAD_PARAMETER; } /* NOTE: The specification doesn't say what to do if both flags are set. Following the 1.2 specification seems reasonable. */ if ((physicalPresence & TPM_PHYSICAL_PRESENCE_PRESENT) && (physicalPresence & TPM_PHYSICAL_PRESENCE_NOTPRESENT)) { printf("TPM_Process_PhysicalPresence: Error, PRESENT and NOT_PRESENT both TRUE \n"); returnCode = TPM_BAD_PARAMETER; } if ((tpm_state->tpm_permanent_flags.physicalPresenceLifetimeLock) && (physicalPresence & (TPM_PHYSICAL_PRESENCE_LIFETIME_LOCK | TPM_PHYSICAL_PRESENCE_HW_ENABLE | TPM_PHYSICAL_PRESENCE_CMD_ENABLE))) { printf("TPM_Process_PhysicalPresence: Error, physicalPresenceLifetimeLock is TRUE\n"); returnCode = TPM_BAD_PARAMETER; } if ((!tpm_state->tpm_permanent_flags.physicalPresenceCMDEnable) && (physicalPresence & (TPM_PHYSICAL_PRESENCE_LOCK | TPM_PHYSICAL_PRESENCE_PRESENT | TPM_PHYSICAL_PRESENCE_NOTPRESENT))) { printf("TPM_Process_PhysicalPresence: Error, physicalPresenceCMDEnable is FALSE\n"); returnCode = TPM_BAD_PARAMETER; } } /* 1. This operation MUST be implemented to process the values in the following order: */ if (returnCode == TPM_SUCCESS) { /* a. physicalPresenceHWEnable and physicalPresenceCMDEnable */ if (physicalPresence & TPM_PHYSICAL_PRESENCE_HW_ENABLE) { printf("TPM_Process_PhysicalPresence: Setting physicalPresenceHWEnable TRUE\n"); TPM_SetCapability_Flag(&writeAllNV, /* altered */ &(tpm_state->tpm_permanent_flags.physicalPresenceHWEnable), TRUE); /* value */ } if (physicalPresence & TPM_PHYSICAL_PRESENCE_CMD_ENABLE) { printf("TPM_Process_PhysicalPresence: Setting physicalPresenceCMDEnable TRUE\n"); TPM_SetCapability_Flag(&writeAllNV, /* altered */ &(tpm_state->tpm_permanent_flags.physicalPresenceCMDEnable), TRUE); /* value */ } /* b. physicalPresenceLifetimeLock */ if (physicalPresence & TPM_PHYSICAL_PRESENCE_LIFETIME_LOCK) { printf("TPM_Process_PhysicalPresence: Setting physicalPresenceLifetimeLock\n"); TPM_SetCapability_Flag(&writeAllNV, /* altered */ &(tpm_state->tpm_permanent_flags.physicalPresenceLifetimeLock), TRUE); /* value */ } /* c. PhysicalPresence */ if (physicalPresence & TPM_PHYSICAL_PRESENCE_PRESENT) { printf("TPM_Process_PhysicalPresence: Setting physicalPresence TRUE\n"); tpm_state->tpm_stclear_flags.physicalPresence = TRUE; } if (physicalPresence & TPM_PHYSICAL_PRESENCE_NOTPRESENT) { printf("TPM_Process_PhysicalPresence: Setting physicalPresence FALSE\n"); tpm_state->tpm_stclear_flags.physicalPresence = FALSE; } /* d. PhysicalPresenceLock */ if (physicalPresence & TPM_PHYSICAL_PRESENCE_LOCK) { printf("TPM_Process_PhysicalPresence: Setting physicalPresenceLock TRUE\n"); tpm_state->tpm_stclear_flags.physicalPresenceLock = TRUE; } } #endif /* Store the permanent flags back to NVRAM */ returnCode = TPM_PermanentAll_NVStore(tpm_state, writeAllNV, returnCode); /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_PhysicalPresence: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } return rcf; } /* 6.4 TPM_DisableOwnerClear rev 87 The DisableOwnerClear command disables the ability to execute the TPM_OwnerClear command permanently. Once invoked the only method of clearing the TPM will require physical access to the TPM. After the execution of TPM_ForceClear, ownerClear is re-enabled and must be explicitly disabled again by the new TPM Owner. */ TPM_RESULT TPM_Process_DisableOwnerClear(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_AUTHHANDLE authHandle; /* The authorization handle used for owner authorization */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization handle */ TPM_AUTHDATA ownerAuth; /* The authorization digest for inputs and owner authentication. HMAC key: ownerAuth. */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ TPM_SECRET *hmacKey = NULL; TPM_BOOL writeAllNV = FALSE; /* flag to write back NV */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_DisableOwnerClear: Ordinal Entry\n"); /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag1(tag); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, ownerAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_DisableOwnerClear: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* 1. The TPM verifies that the authHandle properly authorizes the owner. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_OWNER, ordinal, NULL, &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ } if (returnCode == TPM_SUCCESS) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* owner HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, ownerAuth); /* Authorization digest for input */ } /* 2. The TPM sets the TPM_PERMANENT_FLAGS -> disableOwnerClear flag to TRUE. */ /* 3. When this flag is TRUE the only mechanism that can clear the TPM is the TPM_ForceClear command. The TPM_ForceClear command requires physical access to the TPM to execute. */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_DisableOwnerClear: Set disableOwnerClear\n"); TPM_SetCapability_Flag(&writeAllNV, /* altered */ &(tpm_state->tpm_permanent_flags.disableOwnerClear), /* flag */ TRUE); /* value */ } /* Store the permanent flags back to NVRAM */ returnCode = TPM_PermanentAll_NVStore(tpm_state, writeAllNV, returnCode); /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_DisableOwnerClear: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* owner HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, terminate the session. */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } return rcf; } /* 6.5 TPM_DisableForceClear rev 97 The DisableForceClear command disables the execution of the ForceClear command until the next startup cycle. Once this command is executed, the TPM_ForceClear is disabled until another startup cycle is run. */ TPM_RESULT TPM_Process_DisableForceClear(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_DisableForceClear: Ordinal Entry\n"); /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_DisableForceClear: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ /* 1. The TPM sets the TPM_STCLEAR_FLAGS.disableForceClear flag in the TPM that disables the execution of the TPM_ForceClear command. */ if (returnCode == TPM_SUCCESS) { tpm_state->tpm_stclear_flags.disableForceClear = TRUE; } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_DisableForceClear: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } return rcf; } /* 6.7 TSC_ResetEstablishmentBit rev 98 The PC TPM Interface Specification (TIS) specifies setting tpmEstablished to TRUE upon execution of the HASH_START sequence. The setting implies the creation of a Trusted Operating System on the platform. Platforms will use the value of tpmEstablished to determine if operations necessary to maintain the security perimeter are necessary. The tpmEstablished bit provides a non-volatile, secure reporting that a HASH_START was previously run on the platform. When a platform makes use of the tpmEstablished bit, the platform can reset tpmEstablished as the operation is no longer necessary. For example, a platform could use tpmEstablished to ensure that, if HASH_START had ever been, executed the platform could use the value to invoke special processing. Once the processing is complete the platform will wish to reset tpmEstablished to avoid invoking the special process again. The TPM_PERMANENT_FLAGS -> tpmEstablished bit described in the TPM specifications uses positive logic. The TPM_ACCESS register uses negative logic, so that TRUE is reflected as a 0. */ TPM_RESULT TPM_Process_ResetEstablishmentBit(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL writeAllNV = FALSE; /* flag to write back flags */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_ResetEstablishmentBit: Ordinal Entry\n"); /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | TPM_CHECK_NO_LOCKOUT)); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_ResetEstablishmentBit: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ /* 1. Validate the assertion of locality 3 or locality 4 */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Locality_Check(TPM_LOC_THREE | TPM_LOC_FOUR, /* BYTE bitmap */ tpm_state->tpm_stany_flags.localityModifier); } /* 2. Set TPM_PERMANENT_FLAGS -> tpmEstablished to FALSE */ if (returnCode == TPM_SUCCESS) { TPM_SetCapability_Flag(&writeAllNV, /* altered */ &(tpm_state->tpm_permanent_flags.tpmEstablished), /* flag */ FALSE); /* value */ } /* Store the permanent flags back to NVRAM */ returnCode = TPM_PermanentAll_NVStore(tpm_state, writeAllNV, returnCode); /* 3. Return TPM_SUCCESS */ /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_ResetEstablishmentBit: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } return rcf; } libtpms-0.9.3/src/tpm12/tpm_owner.h000066400000000000000000000134141421143571500171200ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Ownership Processing */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_owner.h 4071 2010-04-29 19:26:45Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_OWNER_H #define TPM_OWNER_H #include "tpm_global.h" #include "tpm_secret.h" #include "tpm_store.h" #include "tpm_types.h" TPM_RESULT TPM_OwnerClearCommon(tpm_state_t *tpm_state, TPM_BOOL deleteAllNvram); TPM_RESULT TPM_Process_TakeOwnership(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_OwnerClear(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_PhysicalPresence(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_DisableOwnerClear(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_ForceClear(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_DisableForceClear(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_ResetEstablishmentBit(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); #endif libtpms-0.9.3/src/tpm12/tpm_pcr.c000066400000000000000000003641411421143571500165530ustar00rootroot00000000000000/********************************************************************************/ /* */ /* PCR Handler */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_pcr.c 4730 2014-09-08 22:02:18Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include #include #include #include "tpm_auth.h" #include "tpm_constants.h" #include "tpm_cryptoh.h" #include "tpm_digest.h" #include "tpm_debug.h" #include "tpm_error.h" #include "tpm_global.h" #include "tpm_io.h" #include "tpm_key.h" #include "tpm_memory.h" #include "tpm_nonce.h" #include "tpm_process.h" #include "tpm_sizedbuffer.h" #include "tpm_types.h" #include "tpm_ver.h" #include "tpm_pcr.h" /* Locality Utilities */ /* TPM_Locality_Set() sets a bit in the TPM_LOCALITY_SELECTION (BYTE) bitmap based on the TPM_STANY_FLAGS -> TPM_MODIFIER_INDICATOR (uint32_t) -> localityModifier */ TPM_RESULT TPM_Locality_Set(TPM_LOCALITY_SELECTION *tpm_locality_selection, /* BYTE bitmap */ TPM_MODIFIER_INDICATOR tpm_modifier_indicator) /* uint32_t from TPM_STANY_FLAGS */ { TPM_RESULT rc = 0; printf(" TPM_Locality_Set:\n"); switch (tpm_modifier_indicator) { case 0: *tpm_locality_selection = TPM_LOC_ZERO; break; case 1: *tpm_locality_selection = TPM_LOC_ONE; break; case 2: *tpm_locality_selection = TPM_LOC_TWO; break; case 3: *tpm_locality_selection = TPM_LOC_THREE; break; case 4: *tpm_locality_selection = TPM_LOC_FOUR; break; default: /* This should never occur. The code that sets TPM_STANY_FLAGS should screen out bad values */ printf("TPM_Locality_Set: Error (fatal), tpm_modifier_indicator %u out of range\n", tpm_modifier_indicator); rc = TPM_FAIL; } return rc; } /* TPM_Locality_Check() checks that a bit in the TPM_LOCALITY_SELECTION (BYTE) bitmap is set for bit TPM_STANY_FLAGS -> TPM_MODIFIER_INDICATOR (uint32_t) -> localityModifier 'tpm_locality_selection' is typically localityAtRelease, pcrResetLocal, pcrExtendLocal 'localityModifier' is TPM_STANY_FLAGS.localityModifier */ TPM_RESULT TPM_Locality_Check(TPM_LOCALITY_SELECTION tpm_locality_selection, /* BYTE bitmap */ TPM_MODIFIER_INDICATOR localityModifier) /* uint32_t from TPM_STANY_FLAGS */ { TPM_RESULT rc = 0; printf(" TPM_Locality_Check:\n"); switch (localityModifier) { case 0: if ((tpm_locality_selection & TPM_LOC_ZERO) == 0) { rc = TPM_BAD_LOCALITY; } break; case 1: if ((tpm_locality_selection & TPM_LOC_ONE) == 0) { rc = TPM_BAD_LOCALITY; } break; case 2: if ((tpm_locality_selection & TPM_LOC_TWO) == 0) { rc = TPM_BAD_LOCALITY; } break; case 3: if ((tpm_locality_selection & TPM_LOC_THREE) == 0) { rc = TPM_BAD_LOCALITY; } break; case 4: if ((tpm_locality_selection & TPM_LOC_FOUR) == 0) { rc = TPM_BAD_LOCALITY; } break; default: /* This should never occur. The code that sets TPM_STANY_FLAGS should screen out bad values */ printf("TPM_Locality_Check: Error (fatal), localityModifier %u out of range\n", localityModifier); rc = TPM_FAIL; } if (rc != 0) { printf("TPM_Locality_Check: Error, " "localityModifier %u tpm_locality_selection %02x\n", localityModifier, tpm_locality_selection); } return rc; } TPM_RESULT TPM_LocalitySelection_CheckLegal(TPM_LOCALITY_SELECTION tpm_locality_selection) /* BYTE bitmap */ { TPM_RESULT rc = 0; printf(" TPM_LocalitySelection_CheckLegal: TPM_LOCALITY_SELECTION %02x\n", tpm_locality_selection); /* if any extra bits are set, illegal value */ if ((tpm_locality_selection & ~TPM_LOC_ALL) || /* This value MUST not be zero (0). (can never be satisfied) */ (tpm_locality_selection == 0)) { printf("TPM_LocalitySelection_CheckLegal: Error, bad locality selection %02x\n", tpm_locality_selection); rc = TPM_INVALID_STRUCTURE; } return rc; } TPM_RESULT TPM_LocalityModifier_CheckLegal(TPM_MODIFIER_INDICATOR localityModifier) { TPM_RESULT rc = 0; printf(" TPM_LocalityModifier_CheckLegal: TPM_MODIFIER_INDICATOR %08x\n", localityModifier); /* if past the maximum, illegal value */ if (localityModifier > TPM_LOC_MAX) { printf("TPM_LocalityModifier_CheckLegal: Error, bad locality modifier %u\n", localityModifier); rc = TPM_BAD_LOCALITY; } return rc; } void TPM_PCRLocality_Compare(TPM_BOOL *match, TPM_LOCALITY_SELECTION tpm_locality_selection1, TPM_LOCALITY_SELECTION tpm_locality_selection2) { if (tpm_locality_selection1 == tpm_locality_selection2) { *match = TRUE; } else { *match = FALSE; } return; } /* state PCR's */ TPM_RESULT TPM_PCR_CheckRange(TPM_PCRINDEX index) { TPM_RESULT rc = 0; if (index >= TPM_NUM_PCR) { printf("TPM_PCR_CheckRange: Error, PCR index was %u should be <= %u\n", index, TPM_NUM_PCR); rc = TPM_BADINDEX; } return rc; } /* TPM_PCR_Init() initializes the PCR based on the platform specification. This should be called by TPM_Init. The caller must check that the PCR index is in range! */ void TPM_PCR_Init(TPM_PCRVALUE *tpm_pcrs, /* points to the TPM PCR array */ const TPM_PCR_ATTRIBUTES *tpm_pcr_attributes, size_t pcrIndex) { printf(" TPM_PCR_Init: pcrIndex %lu\n", (unsigned long)pcrIndex); #if defined TPM_PCCLIENT /* These values are from the PC Client specification */ tpm_pcr_attributes = tpm_pcr_attributes; if ((pcrIndex >= 17) && (pcrIndex <= 22)) { TPM_Digest_Set(tpm_pcrs[pcrIndex]); /* 17-22 init to ff */ } else { TPM_Digest_Init(tpm_pcrs[pcrIndex]); /* 0-16,23 init to 0 */ } /* #elif Add other platform specific values here */ #else /* This is the default case for the main specification */ if (!(tpm_pcr_attributes[pcrIndex].pcrReset)) { /* FALSE- Default value of the PCR MUST be 0x00..00 */ TPM_Digest_Init(tpm_pcrs[pcrIndex]); } else { /* TRUE - Default value of the PCR MUST be 0xFF..FF. */ TPM_Digest_Set(tpm_pcrs[pcrIndex]); } #endif return; } /* TPM_PCR_Reset() resets the PCR based on the platform specification. This should be called by the TPM_PCR_Reset ordinal. The caller must check that the PCR index is in range and that pcrReset is TRUE! */ void TPM_PCR_Reset(TPM_PCRVALUE *tpm_pcrs, /* points to the TPM PCR array */ TPM_BOOL TOSPresent, TPM_PCRINDEX pcrIndex) { TPM_PCRVALUE zeroPCR; TPM_PCRVALUE onesPCR; TPM_Digest_Init(zeroPCR); TPM_Digest_Set(onesPCR); #if defined TPM_PCCLIENT /* These values are from the PC Client specification */ if (TOSPresent || /* TOSPresent -> 00 */ (pcrIndex == 16) || /* PCR 16 -> 00 */ (pcrIndex == 23)) { /* PCR 23 -> 00 */ TPM_PCR_Store(tpm_pcrs, pcrIndex, zeroPCR); } else { TPM_PCR_Store(tpm_pcrs, pcrIndex, onesPCR); /* PCR 17-22 -> ff */ } /* #elif Add other platform specific values here */ #else /* This is the default case for the main specification */ if (TOSPresent) { TPM_PCR_Store(tpm_pcrs, pcrIndex, zeroPCR); } else { TPM_PCR_Store(tpm_pcrs, pcrIndex, onesPCR); } #endif return; } /* TPM_PCR_Load() copies the PCR at 'index' to 'dest_pcr' */ TPM_RESULT TPM_PCR_Load(TPM_PCRVALUE dest_pcr, TPM_PCRVALUE *tpm_pcrs, TPM_PCRINDEX index) { TPM_RESULT rc = 0; /* range check pcrNum */ if (rc == 0) { rc = TPM_PCR_CheckRange(index); } if (rc == 0) { TPM_Digest_Copy(dest_pcr, tpm_pcrs[index]); } return rc; } /* TPM_PCR_Store() copies 'src_pcr' to the PCR at 'index' */ TPM_RESULT TPM_PCR_Store(TPM_PCRVALUE *tpm_pcrs, TPM_PCRINDEX index, TPM_PCRVALUE src_pcr) { TPM_RESULT rc = 0; /* range check pcrNum */ if (rc == 0) { rc = TPM_PCR_CheckRange(index); } if (rc == 0) { TPM_Digest_Copy(tpm_pcrs[index], src_pcr); } return rc; } /* TPM_SELECT_SIZE */ /* TPM_SelectSize_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_SelectSize_Init(TPM_SELECT_SIZE *tpm_select_size) { printf(" TPM_SelectSize_Init:\n"); tpm_select_size->major = TPM_MAJOR; tpm_select_size->minor = TPM_MINOR; tpm_select_size->reqSize = TPM_NUM_PCR/CHAR_BIT; return; } /* TPM_SelectSize_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_SelectSize_Init() */ TPM_RESULT TPM_SelectSize_Load(TPM_SELECT_SIZE *tpm_select_size, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_SelectSize_Load:\n"); /* load major */ if (rc == 0) { rc = TPM_Load8(&(tpm_select_size->major), stream, stream_size); } /* This SHALL indicate the major version of the TPM. This MUST be 0x01 */ if (rc == 0) { if (tpm_select_size->major != 0x01) { printf("TPM_SelectSize_Load: Error, major %02x should be 01\n", tpm_select_size->major); rc = TPM_BAD_PARAMETER; } } /* load minor */ if (rc == 0) { rc = TPM_Load8(&(tpm_select_size->minor), stream, stream_size); } /* This SHALL indicate the minor version of the TPM. This MAY be 0x01 or 0x02 */ if (rc == 0) { if ((tpm_select_size->minor != 0x01) && (tpm_select_size->minor != 0x02)) { printf("TPM_SelectSize_Load: Error, minor %02x should be 01\n", tpm_select_size->minor); rc = TPM_BAD_PARAMETER; } } /* load reqSize */ if (rc == 0) { rc = TPM_Load16(&(tpm_select_size->reqSize), stream, stream_size); } return rc; } /* TPM_PCR_ATTRIBUTES */ /* 8.9 Debug PCR register There is a need to define a PCR that allows for debugging. The attributes of the debug register are such that it is easy to reset but the register provides no measurement value that can not be spoofed. Production applications should not use the debug PCR for any SEAL or other operations. The anticipation is that the debug PCR is set and used by application developers during the application development cycle. Developers are responsible for ensuring that a conflict between two programs does not invalidate the settings they are interested in. The specific register that is the debug PCR MUST be set by the platform specific specification. The attributes for the debug PCR SHALL be the following: pcrReset = TRUE; pcrResetLocal = 0x1f; pcrExtendLocal = 0x1f; pcrUseLocal = 0x1f These settings are to create a PCR register that developers can use to reset at any time during their development cycle. The debug PCR does NOT need to be saved during TPM_SaveState. 8.7 PCR Attributes 1. The PCR attributes MUST be set during manufacturing. 2. For a specific PCR register, the PCR attributes MUST match the requirements of the TCG platform specific specification that describes the platform. */ void TPM_PCRAttributes_Init(TPM_PCR_ATTRIBUTES *tpm_pcr_attributes) { size_t i; printf(" TPM_PCRAttributes_Init:\n"); for (i = 0 ; i < TPM_NUM_PCR ; i++) { #if defined TPM_PCCLIENT /* These values are from the PC Client specification */ #if TPM_NUM_PCR != 24 #error "Number of PCRs must be 24 for PC Client" #endif if (i <=15) { tpm_pcr_attributes[i].pcrReset = FALSE; /* 0-15 are not resettable */ tpm_pcr_attributes[i].pcrResetLocal = 0; tpm_pcr_attributes[i].pcrExtendLocal = TPM_LOC_ALL; } else { tpm_pcr_attributes[i].pcrReset = TRUE; switch (i) { case 16: case 23: tpm_pcr_attributes[i].pcrResetLocal = TPM_LOC_ALL; tpm_pcr_attributes[i].pcrExtendLocal = TPM_LOC_ALL; break; case 17: case 18: tpm_pcr_attributes[i].pcrResetLocal = TPM_LOC_FOUR; tpm_pcr_attributes[i].pcrExtendLocal = TPM_LOC_FOUR | TPM_LOC_THREE | TPM_LOC_TWO; break; case 19: tpm_pcr_attributes[i].pcrResetLocal = TPM_LOC_FOUR; tpm_pcr_attributes[i].pcrExtendLocal = TPM_LOC_THREE | TPM_LOC_TWO; break; case 20: tpm_pcr_attributes[i].pcrResetLocal = TPM_LOC_FOUR | TPM_LOC_TWO; tpm_pcr_attributes[i].pcrExtendLocal = TPM_LOC_THREE | TPM_LOC_TWO | TPM_LOC_ONE; break; case 21: case 22: tpm_pcr_attributes[i].pcrResetLocal = TPM_LOC_TWO; tpm_pcr_attributes[i].pcrExtendLocal = TPM_LOC_TWO; break; } } /* #elif Add other platform specific values here */ #else /* This is the default case for the main specification */ if (i != TPM_DEBUG_PCR) { tpm_pcr_attributes[i].pcrReset = FALSE; tpm_pcr_attributes[i].pcrResetLocal = 0; /* not relevant when pcrReset is FALSE */ tpm_pcr_attributes[i].pcrExtendLocal = TPM_LOC_ALL; } else { /* debug PCR */ tpm_pcr_attributes[i].pcrReset = TRUE; tpm_pcr_attributes[i].pcrResetLocal = TPM_LOC_ALL; tpm_pcr_attributes[i].pcrExtendLocal = TPM_LOC_ALL; } #endif } return; } /* TPM_PCRInfo_Trace() traces some PCR Info components */ void TPM_PCRInfo_Trace(const char *message, TPM_PCR_SELECTION pcrSelection, TPM_COMPOSITE_HASH digestAtRelease) { printf("%s\n", message); printf("\tsizeOfSelect %hu\n", pcrSelection.sizeOfSelect); printf("\tpcrSelect %02x %02x %02x\n", pcrSelection.pcrSelect[0], pcrSelection.pcrSelect[1], pcrSelection.pcrSelect[2]); TPM_PrintFour("\tdigestAtRelease", digestAtRelease); return; } /* PCRs - Functions that act on the entire set of PCRs */ /* TPM_PCRs_Init() initializes the entire PCR array. Typically called from TPM_Init. */ void TPM_PCRs_Init(TPM_PCRVALUE *tpm_pcrs, /* points to the TPM PCR array */ const TPM_PCR_ATTRIBUTES *tpm_pcr_attributes) { size_t i; printf(" TPM_PCRs_Init:\n"); for (i = 0 ; i < TPM_NUM_PCR ; i++) { TPM_PCR_Init(tpm_pcrs, tpm_pcr_attributes, i); /* initialize a single PCR */ } return; } TPM_RESULT TPM_PCRs_Load(TPM_PCRVALUE *tpm_pcrs, /* points to the TPM PCR array */ const TPM_PCR_ATTRIBUTES *tpm_pcr_attributes, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; size_t i; printf(" TPM_PCRs_Load:\n"); for (i = 0 ; (rc == 0) && (i < TPM_NUM_PCR) ; i++) { /* FALSE: Saved by TPM_SaveState TRUE: MUST not be part of any state stored by TPM_SaveState */ if (!(tpm_pcr_attributes[i].pcrReset)) { rc = TPM_Digest_Load(tpm_pcrs[i], stream, stream_size); } } return rc; } TPM_RESULT TPM_PCRs_Store(TPM_STORE_BUFFER *sbuffer, TPM_PCRVALUE *tpm_pcrs, /* points to the TPM PCR array */ const TPM_PCR_ATTRIBUTES *tpm_pcr_attributes) { TPM_RESULT rc = 0; size_t i; printf(" TPM_PCRs_Store:\n"); for (i = 0 ; (rc == 0) && (i < TPM_NUM_PCR) ; i++) { /* FALSE: Saved by TPM_SaveState TRUE: MUST not be part of any state stored by TPM_SaveState */ if (!(tpm_pcr_attributes[i].pcrReset)) { rc = TPM_Digest_Store(sbuffer, tpm_pcrs[i]); } } return rc; } /* TPM_PCR_COMPOSITE */ /* TPM_PCRComposite_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_PCRComposite_Init(TPM_PCR_COMPOSITE *tpm_pcr_composite) { TPM_PCRSelection_Init(&(tpm_pcr_composite->select)); TPM_SizedBuffer_Init(&(tpm_pcr_composite->pcrValue)); return; } /* TPM_PCRComposite_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes After use, call TPM_PCRComposite_Delete() to free memory */ TPM_RESULT TPM_PCRComposite_Store(TPM_STORE_BUFFER *sbuffer, const TPM_PCR_COMPOSITE *tpm_pcr_composite) { TPM_RESULT rc = 0; printf(" TPM_PCRComposite_Store:\n"); /* store TPM_PCR_SELECTION select */ if (rc == 0) { rc = TPM_PCRSelection_Store(sbuffer, &(tpm_pcr_composite->select)); } /* store pcrValue */ if (rc == 0) { rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_pcr_composite->pcrValue)); } return rc; } /* TPM_PCRComposite_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_PCRComposite_Init to set members back to default values The object itself is not freed */ void TPM_PCRComposite_Delete(TPM_PCR_COMPOSITE *tpm_pcr_composite) { printf(" TPM_PCRComposite_Delete:\n"); if (tpm_pcr_composite != NULL) { TPM_PCRSelection_Delete(&(tpm_pcr_composite->select)); TPM_SizedBuffer_Delete(&(tpm_pcr_composite->pcrValue)); TPM_PCRComposite_Init(tpm_pcr_composite); } return; } /* TPM_PCRComposite_Set() sets members to input parameter values allocates memory as required to fill in pointers returns 0 or error codes After use, call TPM_PCRComposite_Delete() to free memory */ TPM_RESULT TPM_PCRComposite_Set(TPM_PCR_COMPOSITE *tpm_pcr_composite, TPM_PCR_SELECTION *tpm_pcr_selection, /* input selection map */ TPM_PCRVALUE *tpm_pcrs) /* points to the TPM PCR array */ { TPM_RESULT rc = 0; size_t i; /* byte in map */ size_t j; /* bit map in byte */ size_t pcrs = 0; /* number of selected PCR's */ TPM_PCRINDEX pcr_num; /* selected PCR being copied */ size_t comp_num; /* index into composite */ printf(" TPM_PCRComposite_Set:\n"); /* test sizeOfSelect value */ if (rc == 0) { rc = TPM_PCRSelection_CheckRange(tpm_pcr_selection); } /* construct the TPM_PCR_COMPOSITE structure */ if (rc == 0) { /* copy the TPM_PCR_SELECTION member */ rc = TPM_PCRSelection_Copy(&(tpm_pcr_composite->select), tpm_pcr_selection); } /* iterate through all bytes in tpm_pcr_selection to count the number of selected PCR's */ if (rc == 0) { for (i = 0, pcrs = 0 ; i < tpm_pcr_selection->sizeOfSelect ; i++) { /* iterate through all bits in each byte */ for (j = 0x0001 ; j != (0x0001 << CHAR_BIT) ; j <<= 1) { if (tpm_pcr_selection->pcrSelect[i] & j) { /* if the bit is set in the map */ pcrs++; } } } } /* allocate memory for the pcrValue member (a TPM_PCRVALUE for each selected PCR) */ if ((rc == 0) && (pcrs > 0)) { printf(" TPM_PCRComposite_Set: Digesting %lu pcrs\n", (unsigned long)pcrs); rc = TPM_SizedBuffer_Allocate(&(tpm_pcr_composite->pcrValue), pcrs * sizeof(TPM_PCRVALUE)); } /* Next iterate through all bytes in tpm_pcr_selection and copy to TPM_PCR_COMPOSITE */ if ((rc == 0) && (pcrs > 0)) { for (i = 0, pcr_num = 0, comp_num = 0 ; i < tpm_pcr_selection->sizeOfSelect ; i++) { /* iterate through all bits in each byte */ for (j = 0x0001 ; j != (0x0001 << CHAR_BIT) ; j <<= 1, pcr_num++) { if (tpm_pcr_selection->pcrSelect[i] & j) { /* if the bit is set in the map */ printf(" TPM_PCRComposite_Set: Adding PCR %u\n", pcr_num); /* append the the PCR value to TPM_PCR_COMPOSITE.pcrValue */ /* NOTE: Ignore return code since range checked by TPM_PCRSelection_CheckRange() */ TPM_PCR_Load(&(tpm_pcr_composite->pcrValue.buffer[comp_num]), tpm_pcrs, pcr_num); comp_num += sizeof(TPM_PCRVALUE); } } } } return rc; } /* TPM_PCR_INFO_SHORT */ void TPM_PCRInfoShort_Init(TPM_PCR_INFO_SHORT *tpm_pcr_info_short) { TPM_PCRSelection_Init(&(tpm_pcr_info_short->pcrSelection)); tpm_pcr_info_short->localityAtRelease = TPM_LOC_ALL; TPM_Digest_Init(tpm_pcr_info_short->digestAtRelease); return; } /* TPM_PCRInfoShort_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes optimize invokes a special version used to an load TPM_NV_DATA_PUBLIC that may not include digestAtRelease After use, call TPM_PCRInfoShort_Delete() to free memory */ TPM_RESULT TPM_PCRInfoShort_Load(TPM_PCR_INFO_SHORT *tpm_pcr_info_short, unsigned char **stream, uint32_t *stream_size, TPM_BOOL optimize) { TPM_RESULT rc = 0; TPM_BOOL pcrUsage = TRUE; printf(" TPM_PCRInfoShort_Load:\n"); /* load pcrSelection */ if (rc == 0) { rc = TPM_PCRSelection_Load(&(tpm_pcr_info_short->pcrSelection), stream, stream_size); } /* load the localityAtRelease */ if (rc == 0) { rc = TPM_Load8(&(tpm_pcr_info_short->localityAtRelease), stream, stream_size); } /* check locality value */ if (rc == 0) { rc = TPM_LocalitySelection_CheckLegal(tpm_pcr_info_short->localityAtRelease); } /* if the store was optimized, check whether the pcrSelection specifies PCRs */ if ((rc == 0) && optimize) { rc = TPM_PCRSelection_GetPCRUsage(&pcrUsage, &(tpm_pcr_info_short->pcrSelection), 0); /* start_index */ } /* load the digestAtRelease */ if (rc == 0) { if (pcrUsage) { rc = TPM_Digest_Load(tpm_pcr_info_short->digestAtRelease, stream, stream_size); } /* A pcrSelect of 0 indicates that the digestAsRelease is not checked. In this case, the TPM is not required to consume NVRAM space to store the digest, although it may do so. When TPM_GetCapability (TPM_CAP_NV_INDEX) returns the structure, a TPM that does not store the digest can return zero. A TPM that does store the digest may return either the digest or zero. Software should not be written to depend on either implementation. */ else { TPM_Digest_Init(tpm_pcr_info_short->digestAtRelease); } } return rc; } /* TPM_PCRInfoShort_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes optimize invokes a special version used to an store TPM_NV_DATA_PUBLIC that may not include digestAtRelease After use, call TPM_Sbuffer_Delete() to free memory */ TPM_RESULT TPM_PCRInfoShort_Store(TPM_STORE_BUFFER *sbuffer, const TPM_PCR_INFO_SHORT *tpm_pcr_info_short, TPM_BOOL optimize) { TPM_RESULT rc = 0; TPM_BOOL pcrUsage = TRUE; printf(" TPM_PCRInfoShort_Store:\n"); /* store pcrSelection */ if (rc == 0) { rc = TPM_PCRSelection_Store(sbuffer, &(tpm_pcr_info_short->pcrSelection)); } /* store the localityAtRelease */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_pcr_info_short->localityAtRelease), sizeof(TPM_LOCALITY_SELECTION)); } /* check whether the pcrSelection specifies PCRs */ if ((rc == 0) && optimize) { rc = TPM_PCRSelection_GetPCRUsage(&pcrUsage, &(tpm_pcr_info_short->pcrSelection), 0); /* start_index */ } /* store the digestAtRelease */ /* A pcrSelect of 0 indicates that the digestAsRelease is not checked. In this case, the TPM is not required to consume NVRAM space to store the digest, although it may do so. When TPM_GetCapability (TPM_CAP_NV_INDEX) returns the structure, a TPM that does not store the digest can return zero. A TPM that does store the digest may return either the digest or zero. Software should not be written to depend on either implementation. */ if ((rc == 0) && pcrUsage) { rc = TPM_Digest_Store(sbuffer, tpm_pcr_info_short->digestAtRelease); } return rc; } /* TPM_PCRInfoShort_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the PCRInfoShort sets pointers to NULL calls TPM_PCRInfoShort_Init to set members back to default values The PCRInfoShort itself is not freed returns 0 or error codes */ void TPM_PCRInfoShort_Delete(TPM_PCR_INFO_SHORT *tpm_pcr_info_short) { printf(" TPM_PCRInfoShort_Delete:\n"); if (tpm_pcr_info_short != NULL) { TPM_PCRSelection_Delete(&(tpm_pcr_info_short->pcrSelection)); TPM_PCRInfoShort_Init(tpm_pcr_info_short); } return; } /* TPM_PCRInfoShort_Create() allocates memory for a TPM_PCR_INFO_SHORT */ TPM_RESULT TPM_PCRInfoShort_Create(TPM_PCR_INFO_SHORT **tpm_pcr_info_short) { TPM_RESULT rc = 0; printf(" TPM_PCRInfoShort_Create:\n"); /* This function should never be called when the TPM_PCR_INFO_SHORT structure has already been loaded. This indicates an internal error. */ if (rc == 0) { if (*tpm_pcr_info_short != NULL) { printf("TPM_PCRInfoShort_Create: Error (fatal), TPM_PCR_INFO_SHORT already loaded\n"); rc = TPM_FAIL; } } if (rc == 0) { rc = TPM_Malloc((unsigned char **)tpm_pcr_info_short, sizeof(TPM_PCR_INFO_SHORT)); } return rc; } /* TPM_PCRInfoShort_SetFromBuffer() sets a TPM_PCR_INFO_SHORT from a stream specified by a TPM_SIZED_BUFFER. The TPM_SIZED_BUFFER is not modified. */ TPM_RESULT TPM_PCRInfoShort_LoadFromBuffer(TPM_PCR_INFO_SHORT *tpm_pcr_info_short, const TPM_SIZED_BUFFER *tpm_sized_buffer) { TPM_RESULT rc = 0; unsigned char *stream; uint32_t stream_size; printf(" TPM_PCRInfoShort_LoadFromBuffer:\n"); if (rc == 0) { TPM_PCRInfoShort_Init(tpm_pcr_info_short); stream = tpm_sized_buffer->buffer; stream_size = tpm_sized_buffer->size; /* deserialize the TPM_SIZED_BUFFER into a TPM_PCR_INFO_SHORT structure */ rc = TPM_PCRInfoShort_Load(tpm_pcr_info_short, &stream, &stream_size, FALSE); } return rc; } /* TPM_PCRInfoShort_CreateFromBuffer() allocates the TPM_PCR_INFO_SHORT structure, typically a cache within another structure. It then deserializes the TPM_SIZED_BUFFER into the structure. The TPM_SIZED_BUFFER is not modified. */ TPM_RESULT TPM_PCRInfoShort_CreateFromBuffer(TPM_PCR_INFO_SHORT **tpm_pcr_info_short, const TPM_SIZED_BUFFER *tpm_sized_buffer) { TPM_RESULT rc = 0; TPM_BOOL done = FALSE; printf(" TPM_PCRInfoShort_CreateFromBuffer:\n"); /* if there is no TPM_PCR_INFO_SHORT - done */ if (rc == 0) { if (tpm_sized_buffer->size == 0) { done = TRUE; } } if ((rc == 0) && !done) { rc = TPM_PCRInfoShort_Create(tpm_pcr_info_short); } if ((rc == 0) && !done) { rc = TPM_PCRInfoShort_LoadFromBuffer(*tpm_pcr_info_short, tpm_sized_buffer); } return rc; } /* TPM_PCRInfoShort_Copy() copies the source pcrSelection, digestAtRelease, and digestAtCreation. */ TPM_RESULT TPM_PCRInfoShort_Copy(TPM_PCR_INFO_SHORT *dest_tpm_pcr_info_short, TPM_PCR_INFO_SHORT *src_tpm_pcr_info_short) { TPM_RESULT rc = 0; printf(" TPM_PCRInfoShort_Copy:\n"); /* copy TPM_PCR_SELECTION pcrSelection */ if (rc == 0) { rc = TPM_PCRSelection_Copy(&(dest_tpm_pcr_info_short->pcrSelection), &(src_tpm_pcr_info_short->pcrSelection)); } if (rc == 0) { /* copy TPM_LOCALITY_SELECTION localityAtRelease */ dest_tpm_pcr_info_short->localityAtRelease = src_tpm_pcr_info_short->localityAtRelease; /* copy TPM_COMPOSITE_HASH digestAtRelease */ TPM_Digest_Copy(dest_tpm_pcr_info_short->digestAtRelease, src_tpm_pcr_info_short->digestAtRelease); } return rc; } /* TPM_PCRInfoShort_CopyInfo() copies the source TPM_PCR_INFO to the destination TPM_PCR_INFO_SHORT. It copies pcrSelection and digestAtRelease. It handles localityAtRelease as per the specification. */ TPM_RESULT TPM_PCRInfoShort_CopyInfo(TPM_PCR_INFO_SHORT *dest_tpm_pcr_info_short, TPM_PCR_INFO *src_tpm_pcr_info) { TPM_RESULT rc = 0; printf(" TPM_PCRInfoShort_CopyInfo:\n"); /* 4. To set IS from IN */ /* a. Set IS -> pcrSelection to IN -> pcrSelection */ if (rc == 0) { rc = TPM_PCRSelection_Copy(&(dest_tpm_pcr_info_short->pcrSelection), &(src_tpm_pcr_info->pcrSelection)); } /* b. Set IS -> digestAtRelease to IN -> digestAtRelease */ if (rc == 0) { TPM_Digest_Copy(dest_tpm_pcr_info_short->digestAtRelease, src_tpm_pcr_info->digestAtRelease); /* c. Set IS -> localityAtRelease to 0x1F to indicate all localities are valid */ dest_tpm_pcr_info_short->localityAtRelease = TPM_LOC_ALL; /* d. Ignore IN -> digestAtCreation */ } return rc; } /* TPM_PCRInfoShort_CopyInfoLong() copies the source TPM_PCR_INFO_LONG to the destination TPM_PCR_INFO_SHORT. It copies creationPCRSelection, localityAtRelease, digestAtRelease. */ TPM_RESULT TPM_PCRInfoShort_CopyInfoLong(TPM_PCR_INFO_SHORT *dest_tpm_pcr_info_short, TPM_PCR_INFO_LONG *src_tpm_pcr_info_long) { TPM_RESULT rc = 0; printf(" TPM_PCRInfoShort_CopyInfoLong:\n"); /* 5. To set IS from IL */ /* a. Set IS -> pcrSelection to IL -> releasePCRSelection */ if (rc == 0) { rc = TPM_PCRSelection_Copy(&(dest_tpm_pcr_info_short->pcrSelection), &(src_tpm_pcr_info_long->releasePCRSelection)); } /* b. Set IS -> localityAtRelease to IL -> localityAtRelease */ if (rc == 0) { dest_tpm_pcr_info_short->localityAtRelease = src_tpm_pcr_info_long->localityAtRelease; /* c. Set IS -> digestAtRelease to IL -> digestAtRelease */ TPM_Digest_Copy(dest_tpm_pcr_info_short->digestAtRelease, src_tpm_pcr_info_long->digestAtRelease); /* d. Ignore all other IL values */ } return rc; } /* TPM_PCRInfoShort_CreateFromInfo() allocates memory for the TPM_PCR_INFO_SHORT structure. It copies the source to the destination. If the source is NULL, the destination is NULL. */ TPM_RESULT TPM_PCRInfoShort_CreateFromInfo(TPM_PCR_INFO_SHORT **dest_tpm_pcr_info_short, TPM_PCR_INFO *src_tpm_pcr_info) { TPM_RESULT rc = 0; TPM_BOOL done = FALSE; printf(" TPM_PCRInfoShort_CreateFromInfo:\n"); if (rc == 0) { /* if there is no source, leave the destination NULL */ if (src_tpm_pcr_info == NULL) { done = TRUE; } } /* create the structure */ if ((rc == 0) && !done) { rc = TPM_PCRInfoShort_Create(dest_tpm_pcr_info_short); } /* copy source to destination */ if ((rc == 0) && !done) { rc = TPM_PCRInfoShort_CopyInfo(*dest_tpm_pcr_info_short, src_tpm_pcr_info); } return rc; } /* TPM_PCRInfo_CreateFromInfoLong() allocates memory for the TPM_PCR_INFO structure. It copies the source to the destination. If the source is NULL, the destination is NULL. */ TPM_RESULT TPM_PCRInfoShort_CreateFromInfoLong(TPM_PCR_INFO_SHORT **dest_tpm_pcr_info_short, TPM_PCR_INFO_LONG *src_tpm_pcr_info_long) { TPM_RESULT rc = 0; TPM_BOOL done = FALSE; printf(" TPM_PCRInfoShort_CreateFromInfoLong:\n"); /* if there is no source, leave the destination NULL */ if (rc == 0) { if (src_tpm_pcr_info_long == NULL) { done = TRUE; } } /* create the structure */ if ((rc == 0) && !done) { rc = TPM_PCRInfoShort_Create(dest_tpm_pcr_info_short); } /* copy source to destination */ if ((rc == 0) && !done) { rc = TPM_PCRInfoShort_CopyInfoLong(*dest_tpm_pcr_info_short, src_tpm_pcr_info_long); } return rc; } /* TPM_PCRInfoShort_CreateFromKey() allocates memory for the TPM_PCR_INFO_SHORT structure. If the input is a TPM_KEY, it copies the TPM_PCR_INFO cache. If the input is a TPM_KEY12, it copies the TPM_PCR_INFO_LONG cache. If the source is NULL, the destination is NULL. */ TPM_RESULT TPM_PCRInfoShort_CreateFromKey(TPM_PCR_INFO_SHORT **dest_tpm_pcr_info_short, TPM_KEY *tpm_key) { TPM_RESULT rc = 0; printf(" TPM_PCRInfoShort_CreateFromKey:\n"); if (rc == 0) { if (((TPM_KEY12 *)tpm_key)->tag != TPM_TAG_KEY12) { /* TPM_KEY */ rc = TPM_PCRInfoShort_CreateFromInfo(dest_tpm_pcr_info_short, tpm_key->tpm_pcr_info); } else { /* TPM_KEY12 */ rc = TPM_PCRInfoShort_CreateFromInfoLong(dest_tpm_pcr_info_short, tpm_key->tpm_pcr_info_long); } } return rc; } /* TPM_PCRInfoShort_GenerateDigest() generates a Part 2 5.3.1 PCR composite hash */ TPM_RESULT TPM_PCRInfoShort_GenerateDigest(TPM_DIGEST tpm_digest, /* output digest */ TPM_PCR_INFO_SHORT *tpm_pcr_info_short, /* input */ TPM_PCRVALUE *tpm_pcrs) /* points to the TPM PCR array */ { TPM_RESULT rc = 0; TPM_PCR_SELECTION *tpm_pcr_selection; printf(" TPM_PCRInfoShort_GenerateDigest:\n"); if (rc == 0) { if (tpm_pcr_info_short == NULL) { printf("TPM_PCRInfoShort_GenerateDigest: Error (fatal), TPM_PCR_INFO_SHORT is NULL\n"); rc = TPM_FAIL; /* should never occur */ } } if (rc == 0) { tpm_pcr_selection = &(tpm_pcr_info_short->pcrSelection); /* get the TPM_PCR_SELECTION */ rc = TPM_PCRSelection_GenerateDigest(tpm_digest, /* output digest */ tpm_pcr_selection, /* input selection map */ tpm_pcrs); /* points to the TPM PCR array */ } return rc; } /* TPM_PCRInfoShort_CheckDigest() calculates a digestAtRelease based on the TPM_PCR_SELECTION and compares it to digestAtRelease in the structure. */ TPM_RESULT TPM_PCRInfoShort_CheckDigest(TPM_PCR_INFO_SHORT *tpm_pcr_info_short, TPM_PCRVALUE *tpm_pcrs, /* points to the TPM PCR array */ TPM_MODIFIER_INDICATOR localityModifier) { TPM_RESULT rc = 0; TPM_COMPOSITE_HASH tpm_composite_hash; TPM_BOOL pcrUsage; /* TRUE if PCR's are specified */ printf(" TPM_PCRInfoShort_CheckDigest:\n"); /* returns FALSE if tpm_pcr_info_short is NULL or selection bitmap is zero */ if (rc == 0) { rc = TPM_PCRInfoShort_GetPCRUsage(&pcrUsage, tpm_pcr_info_short); } /* Calculate a TPM_COMPOSITE_HASH of the PCR selected by tpm_pcr_info_short -> pcrSelection */ if ((rc == 0) && pcrUsage) { rc = TPM_PCRSelection_GenerateDigest(tpm_composite_hash, &(tpm_pcr_info_short->pcrSelection), tpm_pcrs); /* array of PCR's */ } /* Compare to tpm_pcr_info_short -> digestAtRelease on mismatch return TPM_WRONGPCRVAL */ if ((rc == 0) && pcrUsage) { rc = TPM_Digest_Compare(tpm_composite_hash, tpm_pcr_info_short->digestAtRelease); if (rc != 0) { printf("TPM_PCRInfoShort_CheckDigest: Error, wrong digestAtRelease value\n"); rc = TPM_WRONGPCRVAL; } } /* If localityAtRelease is NOT 0x1f */ if ((rc == 0) && (tpm_pcr_info_short != NULL)) { if (tpm_pcr_info_short->localityAtRelease != TPM_LOC_ALL) { /* Validate that TPM_STANY_FLAGS -> localityModifier is matched by tpm_pcr_info_short -> localityAtRelease on mismatch return TPM_BAD_LOCALITY */ rc = TPM_Locality_Check(tpm_pcr_info_short->localityAtRelease, localityModifier); } } return rc; } /* TPM_PCRInfoShort_GetPCRUsage() returns 'pcrUsage' TRUE if any bit is set in the pcrSelect bit mask. Returns FALSE if the TPM_PCR_INFO_SHORT is NULL. */ TPM_RESULT TPM_PCRInfoShort_GetPCRUsage(TPM_BOOL *pcrUsage, TPM_PCR_INFO_SHORT *tpm_pcr_info_short) { TPM_RESULT rc = 0; TPM_BOOL done = FALSE; printf(" TPM_PCRInfoShort_GetPCRUsage\n"); if (rc == 0) { /* if a loaded key had no pcrInfoShort, the structure remains NULL */ if (tpm_pcr_info_short == NULL) { *pcrUsage = FALSE; done = TRUE; } } if ((rc == 0) && !done) { rc = TPM_PCRSelection_GetPCRUsage(pcrUsage, &(tpm_pcr_info_short->pcrSelection), 0); } if (rc == 0) { printf(" TPM_PCRInfoShort_GetPCRUsage: Result %d\n", *pcrUsage); } return rc; } /* TPM_PCR_INFO */ void TPM_PCRInfo_Init(TPM_PCR_INFO *tpm_pcr_info) { TPM_PCRSelection_Init(&(tpm_pcr_info->pcrSelection)); TPM_Digest_Init(tpm_pcr_info->digestAtRelease); TPM_Digest_Init(tpm_pcr_info->digestAtCreation); return; } /* TPM_PCRInfo_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes After use, call TPM_PCRInfo_Delete() to free memory */ TPM_RESULT TPM_PCRInfo_Load(TPM_PCR_INFO *tpm_pcr_info, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_PCRInfo_Load:\n"); /* load pcrSelection */ if (rc == 0) { rc = TPM_PCRSelection_Load(&(tpm_pcr_info->pcrSelection), stream, stream_size); } /* load the digestAtRelease */ if (rc == 0) { rc = TPM_Digest_Load(tpm_pcr_info->digestAtRelease, stream, stream_size); } /* load the digestAtCreation */ if (rc == 0) { rc = TPM_Digest_Load(tpm_pcr_info->digestAtCreation, stream, stream_size); } return rc; } /* TPM_PCRInfo_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes After use, call TPM_Sbuffer_Delete() to free memory */ TPM_RESULT TPM_PCRInfo_Store(TPM_STORE_BUFFER *sbuffer, const TPM_PCR_INFO *tpm_pcr_info) { TPM_RESULT rc = 0; printf(" TPM_PCRInfo_Store:\n"); /* store pcrSelection */ if (rc == 0) { rc = TPM_PCRSelection_Store(sbuffer, &(tpm_pcr_info->pcrSelection)); } /* store digestAtRelease */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_pcr_info->digestAtRelease); } /* store digestAtCreation */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_pcr_info->digestAtCreation); } return rc; } /* TPM_PCRInfo_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the PCRInfo sets pointers to NULL2 calls TPM_PCRInfo_Init to set members back to default values The PCRInfo itself is not freed returns 0 or error codes */ void TPM_PCRInfo_Delete(TPM_PCR_INFO *tpm_pcr_info) { printf(" TPM_PCRInfo_Delete:\n"); if (tpm_pcr_info != NULL) { TPM_PCRSelection_Delete(&(tpm_pcr_info->pcrSelection)); TPM_PCRInfo_Init(tpm_pcr_info); } return; } /* TPM_PCRInfo_Create() allocates memory for a TPM_PCR_INFO */ TPM_RESULT TPM_PCRInfo_Create(TPM_PCR_INFO **tpm_pcr_info) { TPM_RESULT rc = 0; printf(" TPM_PCRInfo_Create:\n"); /* This function should never be called when the TPM_PCR_INFO structure has already been loaded. This indicates an internal error. */ if (rc == 0) { if (*tpm_pcr_info != NULL) { printf("TPM_PCRInfo_Create: Error (fatal), TPM_PCR_INFO already loaded\n"); rc = TPM_FAIL; /* should never occur */ } } if (rc == 0) { rc = TPM_Malloc((unsigned char **)tpm_pcr_info, sizeof(TPM_PCR_INFO)); } return rc; } /* TPM_PCRInfo_LoadFromBuffer() sets a TPM_PCR_INFO from a stream specified by a TPM_SIZED_BUFFER. The TPM_SIZED_BUFFER is not modified. */ TPM_RESULT TPM_PCRInfo_LoadFromBuffer(TPM_PCR_INFO *tpm_pcr_info, const TPM_SIZED_BUFFER *tpm_sized_buffer) { TPM_RESULT rc = 0; unsigned char *stream; uint32_t stream_size; printf(" TPM_PCRInfo_LoadFromBuffer:\n"); if (rc == 0) { TPM_PCRInfo_Init(tpm_pcr_info); stream = tpm_sized_buffer->buffer; stream_size = tpm_sized_buffer->size; /* deserialize the TPM_SIZED_BUFFER into a TPM_PCR_INFO structure */ rc = TPM_PCRInfo_Load(tpm_pcr_info, &stream, &stream_size); } return rc; } /* TPM_PCRInfo_CreateFromBuffer() allocates the TPM_PCR_INFO structure, typically a cache within another structure. It then deserializes the TPM_SIZED_BUFFER into the structure. If the stream is empty, a NULL is returned. The TPM_SIZED_BUFFER is not modified. */ TPM_RESULT TPM_PCRInfo_CreateFromBuffer(TPM_PCR_INFO **tpm_pcr_info, const TPM_SIZED_BUFFER *tpm_sized_buffer) { TPM_RESULT rc = 0; TPM_BOOL done = FALSE; printf(" TPM_PCRInfo_CreateFromBuffer:\n"); /* if there is no TPM_PCR_INFO - done */ if (rc == 0) { if (tpm_sized_buffer->size == 0) { done = TRUE; } } if ((rc == 0) && !done) { rc = TPM_PCRInfo_Create(tpm_pcr_info); } if ((rc == 0) && !done) { rc = TPM_PCRInfo_LoadFromBuffer(*tpm_pcr_info, tpm_sized_buffer); } return rc; } /* TPM_PCRInfo_Copy() copies the source to the destination. It copies pcrSelection, digestAtRelease, and digestAtCreation. */ TPM_RESULT TPM_PCRInfo_Copy(TPM_PCR_INFO *dest_tpm_pcr_info, TPM_PCR_INFO *src_tpm_pcr_info) { TPM_RESULT rc = 0; printf(" TPM_PCRInfo_Copy:\n"); /* copy TPM_PCR_SELECTION pcrSelection */ if (rc == 0) { rc = TPM_PCRSelection_Copy(&(dest_tpm_pcr_info->pcrSelection), &(src_tpm_pcr_info->pcrSelection)); } /* copy TPM_COMPOSITE_HASH's */ if (rc == 0) { TPM_Digest_Copy(dest_tpm_pcr_info->digestAtRelease, src_tpm_pcr_info->digestAtRelease); TPM_Digest_Copy(dest_tpm_pcr_info->digestAtCreation, src_tpm_pcr_info->digestAtCreation); } return rc; } /* TPM_PCRInfo_CopyInfoLong() copies the source TPM_PCR_INFO_LONG to the destination TPM_PCR_INFO. It copies pcrSelection and digestAtRelease. It handles digestAtCreation as per the specification. */ TPM_RESULT TPM_PCRInfo_CopyInfoLong(TPM_PCR_INFO *dest_tpm_pcr_info, TPM_PCR_INFO_LONG *src_tpm_pcr_info_long) { TPM_RESULT rc = 0; TPM_BOOL selectMatch; TPM_BOOL localityMatch; printf(" TPM_PCRInfo_Copy:\n"); /* 9. To set IN from IL */ /* a. Set IN -> pcrSelection to IL -> releasePCRSelection */ if (rc == 0) { rc = TPM_PCRSelection_Copy(&(dest_tpm_pcr_info->pcrSelection), &(src_tpm_pcr_info_long->releasePCRSelection)); } /* copy TPM_COMPOSITE_HASH's */ if (rc == 0) { /* b. Set IN -> digestAtRelease to IL -> digestAtRelease */ TPM_Digest_Copy(dest_tpm_pcr_info->digestAtRelease, src_tpm_pcr_info_long->digestAtRelease); TPM_PCRSelection_Compare(&selectMatch, &(src_tpm_pcr_info_long->creationPCRSelection), &(src_tpm_pcr_info_long->releasePCRSelection)); TPM_PCRLocality_Compare(&localityMatch, src_tpm_pcr_info_long->localityAtCreation, src_tpm_pcr_info_long->localityAtRelease); /* c. If IL -> creationPCRSelection and IL -> localityAtCreation both match IL -> releasePCRSelection and IL -> localityAtRelease */ if (selectMatch && localityMatch) { /* i. Set IN -> digestAtCreation to IL -> digestAtCreation */ TPM_Digest_Copy(dest_tpm_pcr_info->digestAtCreation, src_tpm_pcr_info_long->digestAtCreation); } /* d. Else */ else { /* i. Set IN -> digestAtCreation to NULL */ TPM_Digest_Init(dest_tpm_pcr_info->digestAtCreation); } } return rc; } /* TPM_PCRInfo_CreateFromInfo() allocates memory for the TPM_PCR_INFO structure. It copies the source to the destination. If the source is NULL, the destination is NULL. */ TPM_RESULT TPM_PCRInfo_CreateFromInfo(TPM_PCR_INFO **dest_tpm_pcr_info, TPM_PCR_INFO *src_tpm_pcr_info) { TPM_RESULT rc = 0; TPM_BOOL done = FALSE; printf(" TPM_PCRInfo_CreateFromInfo:\n"); /* if there is no source, leave the destination NULL */ if (rc == 0) { if (src_tpm_pcr_info == NULL) { done = TRUE; } } /* create the structure */ if ((rc == 0) && !done) { rc = TPM_PCRInfo_Create(dest_tpm_pcr_info); } /* copy source to destination */ if ((rc == 0) && !done) { rc = TPM_PCRInfo_Copy(*dest_tpm_pcr_info, src_tpm_pcr_info); } return rc; } /* TPM_PCRInfo_CreateFromInfoLong() allocates memory for the TPM_PCR_INFO structure. It copies the source to the destination. If the source is NULL, the destination is NULL. */ TPM_RESULT TPM_PCRInfo_CreateFromInfoLong(TPM_PCR_INFO **dest_tpm_pcr_info, TPM_PCR_INFO_LONG *src_tpm_pcr_info_long) { TPM_RESULT rc = 0; TPM_BOOL done = FALSE; printf(" TPM_PCRInfo_CreateFromInfoLong:\n"); /* if there is no source, leave the destination NULL */ if (rc == 0) { if (src_tpm_pcr_info_long == NULL) { done = TRUE; } } /* create the structure */ if ((rc == 0) && !done) { rc = TPM_PCRInfo_Create(dest_tpm_pcr_info); } /* copy source to destination */ if ((rc == 0) && !done) { rc = TPM_PCRInfo_CopyInfoLong(*dest_tpm_pcr_info, src_tpm_pcr_info_long); } return rc; } /* TPM_PCRInfo_CreateFromKey() allocates memory for the TPM_PCR_INFO structure. If the input is a TPM_KEY, it copies the TPM_PCR_INFO cache. If the input is a TPM_KEY12, it copies the TPM_PCR_INFO_LONG cache. If the source is NULL, the destination is NULL. */ TPM_RESULT TPM_PCRInfo_CreateFromKey(TPM_PCR_INFO **dest_tpm_pcr_info, TPM_KEY *tpm_key) { TPM_RESULT rc = 0; printf(" TPM_PCRInfo_CreateFromKey:\n"); if (rc == 0) { if (((TPM_KEY12 *)tpm_key)->tag != TPM_TAG_KEY12) { /* TPM_KEY */ rc = TPM_PCRInfo_CreateFromInfo(dest_tpm_pcr_info, tpm_key->tpm_pcr_info); } else { /* TPM_KEY12 */ rc = TPM_PCRInfo_CreateFromInfoLong(dest_tpm_pcr_info, tpm_key->tpm_pcr_info_long); } } return rc; } /* TPM_PCRInfo_GenerateDigest() generates a Part 2 5.3.1 PCR composite hash */ TPM_RESULT TPM_PCRInfo_GenerateDigest(TPM_DIGEST tpm_digest, /* output digest */ TPM_PCR_INFO *tpm_pcr_info, /* input */ TPM_PCRVALUE *tpm_pcrs) /* points to the TPM PCR array */ { TPM_RESULT rc = 0; TPM_PCR_SELECTION *tpm_pcr_selection; printf(" TPM_PCRInfo_GenerateDigest:\n"); if (rc == 0) { if (tpm_pcr_info == NULL) { printf("TPM_PCRInfo_GenerateDigest: Error (fatal), TPM_PCR_INFO is NULL\n"); rc = TPM_FAIL; /* should never occur */ } } if (rc == 0) { tpm_pcr_selection = &(tpm_pcr_info->pcrSelection); /* get the TPM_PCR_SELECTION */ rc = TPM_PCRSelection_GenerateDigest(tpm_digest, /* output digest */ tpm_pcr_selection, /* input selection map */ tpm_pcrs); /* points to the TPM PCR array */ } return rc; } /* TPM_PCRInfo_CheckDigest() calculates a digestAtRelease based on the TPM_PCR_SELECTION and compares it to digestAtRelease in the structure. */ TPM_RESULT TPM_PCRInfo_CheckDigest(TPM_PCR_INFO *tpm_pcr_info, TPM_PCRVALUE *tpm_pcrs) /* points to the TPM PCR array */ { TPM_RESULT rc = 0; TPM_COMPOSITE_HASH tpm_composite_hash; TPM_BOOL pcrUsage; /* TRUE if PCR's are specified */ printf(" TPM_PCRInfo_CheckDigest:\n"); /* Calculate a TPM_COMPOSITE_HASH of the PCR selected by tpm_pcr_info -> pcrSelection */ if (rc == 0) { rc = TPM_PCRInfo_GetPCRUsage(&pcrUsage, tpm_pcr_info, 0); } if ((rc == 0) && pcrUsage) { rc = TPM_PCRSelection_GenerateDigest(tpm_composite_hash, &(tpm_pcr_info->pcrSelection), tpm_pcrs); /* array of PCR's */ } /* Compare to pcrInfo -> digestAtRelease on mismatch return TPM_WRONGPCRVAL */ if ((rc == 0) && pcrUsage) { rc = TPM_Digest_Compare(tpm_composite_hash, tpm_pcr_info->digestAtRelease); if (rc != 0) { printf("TPM_PCRInfo_CheckDigest: Error, wrong digestAtRelease value\n"); rc = TPM_WRONGPCRVAL; } } return rc; } /* TPM_PCRInfo_SetDigestAtCreation() calculates a digestAtCreation based on the TPM_PCR_SELECTION already set in the TPM_PCR_INFO structure. */ TPM_RESULT TPM_PCRInfo_SetDigestAtCreation(TPM_PCR_INFO *tpm_pcr_info, TPM_PCRVALUE *tpm_pcrs) /* points to the TPM PCR array */ { TPM_RESULT rc = 0; printf(" TPM_PCRInfo_SetDigestAtCreation:\n"); if (rc == 0) { rc = TPM_PCRInfo_GenerateDigest(tpm_pcr_info->digestAtCreation, tpm_pcr_info, tpm_pcrs); } return rc; } /* TPM_PCRInfo_GetPCRUsage() returns 'pcrUsage' TRUE if any bit is set in the pcrSelect bit mask. 'start_pcr' indicates the starting byte index into pcrSelect[] */ TPM_RESULT TPM_PCRInfo_GetPCRUsage(TPM_BOOL *pcrUsage, TPM_PCR_INFO *tpm_pcr_info, size_t start_index) { TPM_RESULT rc = 0; TPM_BOOL done = FALSE; printf(" TPM_PCRInfo_GetPCRUsage: Start %lu\n", (unsigned long)start_index); if (rc == 0) { /* if a loaded key had no pcrInfo, the structure remains NULL */ if (tpm_pcr_info == NULL) { *pcrUsage = FALSE; done = TRUE; } } if ((rc == 0) && !done) { rc = TPM_PCRSelection_GetPCRUsage(pcrUsage, &(tpm_pcr_info->pcrSelection), start_index); } if (rc == 0) { printf(" TPM_PCRInfo_GetPCRUsage: Result %d\n", *pcrUsage); } return rc; } /* TPM_PCR_INFO_LONG */ /* TPM_PCRInfoLong_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_PCRInfoLong_Init(TPM_PCR_INFO_LONG *tpm_pcr_info_long) { printf(" TPM_PCRInfoLong_Init:\n"); /* tpm_pcr_info_long->tag = TPM_TAG_PCR_INFO_LONG; */ tpm_pcr_info_long->localityAtCreation = TPM_LOC_ZERO; tpm_pcr_info_long->localityAtRelease = TPM_LOC_ALL; TPM_PCRSelection_Init(&(tpm_pcr_info_long->creationPCRSelection)); TPM_PCRSelection_Init(&(tpm_pcr_info_long->releasePCRSelection)); TPM_Digest_Init(tpm_pcr_info_long->digestAtCreation); TPM_Digest_Init(tpm_pcr_info_long->digestAtRelease); return; } /* TPM_PCRInfoLong_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_PCRInfoLong_Init() After use, call TPM_PCRInfoLong_Delete() to free memory */ TPM_RESULT TPM_PCRInfoLong_Load(TPM_PCR_INFO_LONG *tpm_pcr_info_long, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_PCRInfoLong_Load:\n"); /* check tag */ if (rc == 0) { rc = TPM_CheckTag(TPM_TAG_PCR_INFO_LONG, stream, stream_size); } /* load localityAtCreation */ if (rc == 0) { rc = TPM_Load8(&(tpm_pcr_info_long->localityAtCreation), stream, stream_size); } /* check locality value. The TPM MAY treat a localityAtCreation value of 0 as an error. */ if (rc == 0) { rc = TPM_LocalitySelection_CheckLegal(tpm_pcr_info_long->localityAtCreation); } /* load localityAtRelease */ if (rc == 0) { rc = TPM_Load8(&(tpm_pcr_info_long->localityAtRelease), stream, stream_size); } /* check locality value */ if (rc == 0) { rc = TPM_LocalitySelection_CheckLegal(tpm_pcr_info_long->localityAtRelease); } /* load creationPCRSelection */ if (rc == 0) { rc = TPM_PCRSelection_Load(&(tpm_pcr_info_long->creationPCRSelection), stream, stream_size); } /* load releasePCRSelection */ if (rc == 0) { rc = TPM_PCRSelection_Load(&(tpm_pcr_info_long->releasePCRSelection), stream, stream_size); } /* load digestAtCreation */ if (rc == 0) { rc = TPM_Digest_Load(tpm_pcr_info_long->digestAtCreation, stream, stream_size); } /* load digestAtRelease */ if (rc == 0) { rc = TPM_Digest_Load(tpm_pcr_info_long->digestAtRelease, stream, stream_size); } return rc; } /* TPM_PCRInfoLong_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_PCRInfoLong_Store(TPM_STORE_BUFFER *sbuffer, const TPM_PCR_INFO_LONG *tpm_pcr_info_long) { TPM_RESULT rc = 0; printf(" TPM_PCRInfoLong_Store:\n"); /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_PCR_INFO_LONG); } /* store localityAtCreation */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_pcr_info_long->localityAtCreation), sizeof(TPM_LOCALITY_SELECTION)); } /* store localityAtRelease */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_pcr_info_long->localityAtRelease), sizeof(TPM_LOCALITY_SELECTION)); } /* store creationPCRSelection */ if (rc == 0) { rc = TPM_PCRSelection_Store(sbuffer, &(tpm_pcr_info_long->creationPCRSelection)); } /* store releasePCRSelection */ if (rc == 0) { rc = TPM_PCRSelection_Store(sbuffer, &(tpm_pcr_info_long->releasePCRSelection)); } /* store digestAtCreation */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_pcr_info_long->digestAtCreation); } /* store digestAtRelease */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_pcr_info_long->digestAtRelease); } return rc; } /* TPM_PCRInfoLong_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_PCRInfoLong_Init to set members back to default values The object itself is not freed */ void TPM_PCRInfoLong_Delete(TPM_PCR_INFO_LONG *tpm_pcr_info_long) { printf(" TPM_PCRInfoLong_Delete:\n"); if (tpm_pcr_info_long != NULL) { TPM_PCRSelection_Delete(&(tpm_pcr_info_long->creationPCRSelection)); TPM_PCRSelection_Delete(&(tpm_pcr_info_long->releasePCRSelection)); TPM_PCRInfoLong_Init(tpm_pcr_info_long); } return; } /* TPM_PCRInfoLong_Create() allocates memory for a TPM_PCR_INFO_LONG */ TPM_RESULT TPM_PCRInfoLong_Create(TPM_PCR_INFO_LONG **tpm_pcr_info_long) { TPM_RESULT rc = 0; printf(" TPM_PCRInfoLong_Create:\n"); /* This function should never be called when the TPM_PCR_INFO_LONG structure has already been loaded. This indicates an internal error. */ if (rc == 0) { if (*tpm_pcr_info_long != NULL) { printf("TPM_PCRInfoLong_Create: Error (fatal), TPM_PCR_INFO_LONG already loaded\n"); rc = TPM_FAIL; } } if (rc == 0) { rc = TPM_Malloc((unsigned char **)tpm_pcr_info_long, sizeof(TPM_PCR_INFO_LONG)); } return rc; } /* TPM_PCRInfoLong_LoadFromBuffer() sets a TPM_PCR_INFO_LONG from a stream specified by a TPM_SIZED_BUFFER. The TPM_SIZED_BUFFER is not modified. */ TPM_RESULT TPM_PCRInfoLong_LoadFromBuffer(TPM_PCR_INFO_LONG *tpm_pcr_info_long, const TPM_SIZED_BUFFER *tpm_sized_buffer) { TPM_RESULT rc = 0; unsigned char *stream; uint32_t stream_size; printf(" TPM_PCRInfoLong_LoadFromBuffer:\n"); if (rc == 0) { TPM_PCRInfoLong_Init(tpm_pcr_info_long); stream = tpm_sized_buffer->buffer; stream_size = tpm_sized_buffer->size; /* deserialize the TPM_SIZED_BUFFER into a TPM_PCR_INFO_LONG structure */ rc = TPM_PCRInfoLong_Load(tpm_pcr_info_long, &stream, &stream_size); } return rc; } /* TPM_PCRInfoLong_CreateFromBuffer() allocates the TPM_PCR_INFO_LONG structure, typically a cache within another structure. It then deserializes the TPM_SIZED_BUFFER into the structure. If the stream is empty, a NULL is returned. The TPM_SIZED_BUFFER is not modified. */ TPM_RESULT TPM_PCRInfoLong_CreateFromBuffer(TPM_PCR_INFO_LONG **tpm_pcr_info_long, const TPM_SIZED_BUFFER *tpm_sized_buffer) { TPM_RESULT rc = 0; TPM_BOOL done = FALSE; printf(" TPM_PCRInfoLong_CreateFromBuffer:\n"); /* if there is no TPM_PCR_INFO_LONG - done */ if (rc == 0) { if (tpm_sized_buffer->size == 0) { done = TRUE; } } /* allocate memory for the buffer */ if ((rc == 0) && !done) { rc = TPM_PCRInfoLong_Create(tpm_pcr_info_long); } /* deserialize the input stream */ if ((rc == 0) && !done) { rc = TPM_PCRInfoLong_LoadFromBuffer(*tpm_pcr_info_long, tpm_sized_buffer); } return rc; } /* TPM_PCRInfoLong_Copy() copies the source to the destination */ TPM_RESULT TPM_PCRInfoLong_Copy(TPM_PCR_INFO_LONG *dest_tpm_pcr_info_long, TPM_PCR_INFO_LONG *src_tpm_pcr_info_long) { TPM_RESULT rc = 0; printf(" TPM_PCRInfoLong_Copy:\n"); if (rc == 0) { /* copy the localityAtCreation, localityAtRelease */ dest_tpm_pcr_info_long->localityAtCreation = src_tpm_pcr_info_long->localityAtCreation; dest_tpm_pcr_info_long->localityAtRelease = src_tpm_pcr_info_long->localityAtRelease; /* copy TPM_PCR_SELECTION creationPCRSelection */ rc = TPM_PCRSelection_Copy(&(dest_tpm_pcr_info_long->creationPCRSelection), &(src_tpm_pcr_info_long->creationPCRSelection)); } if (rc == 0) { /* copy TPM_PCR_SELECTION releasePCRSelection*/ rc = TPM_PCRSelection_Copy(&(dest_tpm_pcr_info_long->releasePCRSelection), &(src_tpm_pcr_info_long->releasePCRSelection)); } /* copy TPM_COMPOSITE_HASH's */ if (rc == 0) { TPM_Digest_Copy(dest_tpm_pcr_info_long->digestAtRelease, src_tpm_pcr_info_long->digestAtRelease); TPM_Digest_Copy(dest_tpm_pcr_info_long->digestAtCreation, src_tpm_pcr_info_long->digestAtCreation); } return rc; } /* TPM_PCRInfoLong_CreateFromInfoLong() allocates memory for the TPM_PCR_INFO_LONG structure. It copies the source tag, localityAtCreation, localityAtRelease, creationPCRSelection, releasePCRSelection digestAtCreation, and digestAtRelease. If the source is NULL, the destination is NULL. */ TPM_RESULT TPM_PCRInfoLong_CreateFromInfoLong(TPM_PCR_INFO_LONG **dest_tpm_pcr_info_long, TPM_PCR_INFO_LONG *src_tpm_pcr_info_long) { TPM_RESULT rc = 0; TPM_BOOL done = FALSE; printf(" TPM_PCRInfoLong_CreateFromInfoLong:\n"); if (rc == 0) { /* if there is no source, leave the destination NULL */ if (src_tpm_pcr_info_long == NULL) { done = TRUE; } } /* create the structure */ if ((rc == 0) && !done) { rc = TPM_PCRInfoLong_Create(dest_tpm_pcr_info_long); } /* copy source to destination */ if ((rc == 0) && !done) { rc = TPM_PCRInfoLong_Copy(*dest_tpm_pcr_info_long, src_tpm_pcr_info_long); } return rc; } /* TPM_PCRInfoLong_GenerateDigest() generates a Part 2 5.3.1 PCR composite hash */ TPM_RESULT TPM_PCRInfoLong_GenerateDigest(TPM_DIGEST tpm_digest, /* output digest */ TPM_PCR_INFO_LONG *tpm_pcr_info_long, /* input */ TPM_PCRVALUE *tpm_pcrs) /* points to the TPM PCR array */ { TPM_RESULT rc = 0; TPM_PCR_SELECTION *tpm_pcr_selection; printf(" TPM_PCRInfoLong_GenerateDigest:\n"); if (rc == 0) { if (tpm_pcr_info_long == NULL) { printf("TPM_PCRInfoLong_GenerateDigest: Error (fatal), TPM_PCR_INFO_LONG is NULL\n"); rc = TPM_FAIL; /* should never occur */ } } if (rc == 0) { tpm_pcr_selection = &(tpm_pcr_info_long->creationPCRSelection); /* get TPM_PCR_SELECTION */ rc = TPM_PCRSelection_GenerateDigest(tpm_digest, /* output digest */ tpm_pcr_selection, /* input selection map */ tpm_pcrs); /* points to the TPM PCR array */ } return rc; } /* TPM_PCRInfoLong_CheckDigest() calculates a digestAtRelease based on the TPM_PCR_SELECTION and compares it to digestAtRelease in the structure. */ TPM_RESULT TPM_PCRInfoLong_CheckDigest(TPM_PCR_INFO_LONG *tpm_pcr_info_long, TPM_PCRVALUE *tpm_pcrs, /* points to the TPM PCR array */ TPM_MODIFIER_INDICATOR localityModifier) { TPM_RESULT rc = 0; TPM_COMPOSITE_HASH tpm_composite_hash; TPM_BOOL pcrUsage; /* TRUE if PCR's are specified */ printf(" TPM_PCRInfoLong_CheckDigest:\n"); /* returns FALSE if tpm_pcr_info_long is NULL or selection bitmap is zero */ if (rc == 0) { rc = TPM_PCRInfoLong_GetPCRUsage(&pcrUsage, tpm_pcr_info_long, 0); } /* Calculate a TPM_COMPOSITE_HASH of the PCR selected by tpm_pcr_info_long -> releasePCRSelection */ if ((rc == 0) && pcrUsage) { rc = TPM_PCRSelection_GenerateDigest(tpm_composite_hash, &(tpm_pcr_info_long->releasePCRSelection), tpm_pcrs); /* array of PCR's */ } /* Compare to tpm_pcr_info_long -> digestAtRelease on mismatch return TPM_WRONGPCRVAL */ if ((rc == 0) && pcrUsage) { rc = TPM_Digest_Compare(tpm_composite_hash, tpm_pcr_info_long->digestAtRelease); if (rc != 0) { printf("TPM_PCRInfoLong_CheckDigest: Error, wrong digestAtRelease value\n"); rc = TPM_WRONGPCRVAL; } } /* If localityAtRelease is NOT 0x1f */ if ((rc == 0) && (tpm_pcr_info_long != NULL)) { if (tpm_pcr_info_long->localityAtRelease != TPM_LOC_ALL) { /* Validate that TPM_STANY_FLAGS -> localityModifier is matched by tpm_pcr_info_short -> localityAtRelease on mismatch return TPM_BAD_LOCALITY */ rc = TPM_Locality_Check(tpm_pcr_info_long->localityAtRelease, localityModifier); } } return rc; } /* TPM_PCRInfoLong_SetDigestAtCreation() calculates a digestAtCreation based on the TPM_PCR_SELECTION creationPCRSelection already set in the TPM_PCR_INFO_LONG structure. */ TPM_RESULT TPM_PCRInfoLong_SetDigestAtCreation(TPM_PCR_INFO_LONG *tpm_pcr_info_long, TPM_PCRVALUE *tpm_pcrs) /* points to the TPM PCR array */ { TPM_RESULT rc = 0; printf(" TPM_PCRInfoLong_SetDigestAtCreation:\n"); if (rc == 0) { rc = TPM_PCRInfoLong_GenerateDigest(tpm_pcr_info_long->digestAtCreation, tpm_pcr_info_long, tpm_pcrs); } return rc; } /* TPM_PCRInfoLong_GetPCRUsage() returns 'pcrUsage' TRUE if any bit is set in the pcrSelect bit mask. Returns FALSE if the TPM_PCR_INFO_LONG is NULL. 'start_pcr' indicates the starting byte index into pcrSelect[] */ TPM_RESULT TPM_PCRInfoLong_GetPCRUsage(TPM_BOOL *pcrUsage, TPM_PCR_INFO_LONG *tpm_pcr_info_long, size_t start_index) { TPM_RESULT rc = 0; TPM_BOOL done = FALSE; printf(" TPM_PCRInfoLong_GetPCRUsage: Start %lu\n", (unsigned long)start_index);; if (rc == 0) { /* if a loaded key had no pcrInfo, the structure remains NULL */ if (tpm_pcr_info_long == NULL) { *pcrUsage = FALSE; done = TRUE; } } if ((rc == 0) && !done) { rc = TPM_PCRSelection_GetPCRUsage(pcrUsage, &(tpm_pcr_info_long->releasePCRSelection), start_index); } if (rc == 0) { printf(" TPM_PCRInfoLong_GetPCRUsage: Result %d\n", *pcrUsage); } return rc; } /* TPM_PCR_SELECTION */ void TPM_PCRSelection_Init(TPM_PCR_SELECTION *tpm_pcr_selection) { size_t i; printf(" TPM_PCRSelection_Init:\n"); tpm_pcr_selection->sizeOfSelect = TPM_NUM_PCR/CHAR_BIT; for (i = 0 ; i < (TPM_NUM_PCR/CHAR_BIT) ; i++) { tpm_pcr_selection->pcrSelect[i] = 0; } return; } /* TPM_PCRSelection_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes After use, call TPM_PCRSelection_Delete() to free memory */ TPM_RESULT TPM_PCRSelection_Load(TPM_PCR_SELECTION *tpm_pcr_selection, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; size_t i; printf(" TPM_PCRSelection_Load:\n"); /* load sizeOfSelect */ if (rc == 0) { rc = TPM_Load16(&(tpm_pcr_selection->sizeOfSelect), stream, stream_size); } /* test sizeOfSelect value */ if (rc == 0) { rc = TPM_PCRSelection_CheckRange(tpm_pcr_selection); } /* load pcrSelect map */ for (i = 0 ; (rc == 0) && (i < tpm_pcr_selection->sizeOfSelect) ; i++) { rc = TPM_Load8(&(tpm_pcr_selection->pcrSelect[i]), stream, stream_size); } /* if there was insufficient input, zero the rest of the map */ for ( ; (rc == 0) && (i < (TPM_NUM_PCR/CHAR_BIT)) ; i++) { rc = tpm_pcr_selection->pcrSelect[i] = 0; } return rc; } /* TPM_PCRSelection_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes After use, call TPM_Sbuffer_Delete() to free memory */ TPM_RESULT TPM_PCRSelection_Store(TPM_STORE_BUFFER *sbuffer, const TPM_PCR_SELECTION *tpm_pcr_selection) { TPM_RESULT rc = 0; printf(" TPM_PCRSelection_Store:\n"); /* NOTE: Cannot use TPM_SizedBuffer_Store since the first parameter is a uint16_t */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, tpm_pcr_selection->sizeOfSelect); } if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, tpm_pcr_selection->pcrSelect, tpm_pcr_selection->sizeOfSelect); } return rc; } /* TPM_PCRSelection_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the PCRSelection sets pointers to NULL calls TPM_PCRSelection_Init to set members back to default values The PCRSelection itself is not freed returns 0 or error codes */ void TPM_PCRSelection_Delete(TPM_PCR_SELECTION *tpm_pcr_selection) { printf(" TPM_PCRSelection_Delete:\n"); if (tpm_pcr_selection != NULL) { TPM_PCRSelection_Init(tpm_pcr_selection); } return; } /* TPM_PCRSelection_Copy() copies the source to the destination It returns an error if the source -> sizeOfSelect is too large. If the source is smaller than the internally defined, fixed size of the destination, the remainder of the destination is filled with 0's. */ TPM_RESULT TPM_PCRSelection_Copy(TPM_PCR_SELECTION *destination, TPM_PCR_SELECTION *source) { TPM_RESULT rc = 0; size_t i; printf(" TPM_PCRSelection_Copy:\n"); if (rc == 0) { rc = TPM_PCRSelection_CheckRange(source); } if (rc == 0) { /* copy sizeOfSelect member */ destination->sizeOfSelect = source->sizeOfSelect; /* copy pcrSelect map up to the size of the source */ for (i = 0 ; i < source->sizeOfSelect ; i++) { destination->pcrSelect[i] = source->pcrSelect[i]; } /* if the input wasn't sufficient, zero the rest of the map */ for ( ; i < (TPM_NUM_PCR/CHAR_BIT) ; i++) { destination->pcrSelect[i] = 0; } } return rc; } /* TPM_PCRSelection_GenerateDigest() generates a digest based on the TPM_PCR_SELECTION and the current TPM PCR values. It internally generates a TPM_PCR_COMPOSITE according to Part 2 5.4.1. To return this structure as well, use TPM_PCRSelection_GenerateDigest2(). */ TPM_RESULT TPM_PCRSelection_GenerateDigest(TPM_DIGEST tpm_digest, /* output digest */ TPM_PCR_SELECTION *tpm_pcr_selection, /* input selection map */ TPM_PCRVALUE *tpm_pcrs) /* points to the TPM PCR array */ { TPM_RESULT rc = 0; TPM_PCR_COMPOSITE tpm_pcr_composite; /* structure to be hashed */ printf(" TPM_PCRSelection_GenerateDigest:\n"); TPM_PCRComposite_Init(&tpm_pcr_composite); /* freed @1 */ rc = TPM_PCRSelection_GenerateDigest2(tpm_digest, &tpm_pcr_composite, tpm_pcr_selection, tpm_pcrs); TPM_PCRComposite_Delete(&tpm_pcr_composite); /* @1 */ return rc; } /* TPM_PCRSelection_GenerateDigest2() generates a digest based on the TPM_PCR_SELECTION and the current TPM PCR values. It first generates a TPM_PCR_COMPOSITE according to Part 2 5.4.1. That structure is also returned. TPM_PCR_COMPOSITE should be initialized and deleted by the caller. To generate and delete the structure internally, use TPM_PCRSelection_GenerateDigest(). */ TPM_RESULT TPM_PCRSelection_GenerateDigest2(TPM_DIGEST tpm_digest, /* output digest */ TPM_PCR_COMPOSITE *tpm_pcr_composite, /* output structure */ TPM_PCR_SELECTION *tpm_pcr_selection, /* input selection map */ TPM_PCRVALUE *tpm_pcrs) /* points to the TPM PCR array */ { TPM_RESULT rc = 0; TPM_BOOL pcrUsage; printf(" TPM_PCRSelection_GenerateDigest2:\n"); /* assemble the TPM_PCR_COMPOSITE structure */ if (rc == 0) { rc = TPM_PCRComposite_Set(tpm_pcr_composite, tpm_pcr_selection, tpm_pcrs); } if (rc == 0) { rc = TPM_PCRSelection_GetPCRUsage(&pcrUsage, tpm_pcr_selection, 0); } if (rc == 0) { printf(" TPM_PCRSelection_GenerateDigest2: pcrUsage %02x\n", pcrUsage); if (pcrUsage) { /* serialize and hash TPM_PCR_COMPOSITE */ if (rc == 0) { rc = TPM_SHA1_GenerateStructure(tpm_digest, tpm_pcr_composite, (TPM_STORE_FUNCTION_T)TPM_PCRComposite_Store); } } /* 4. If TPM_PCR_SELECTION.pcrSelect is all 0's */ /* a. a.For digestAtCreation, the TPM MUST set TPM_COMPOSITE_HASH to be all 0's. */ else { TPM_Digest_Init(tpm_digest); } } return rc; } /* TPM_PCRSelection_GetPCRUsage() returns 'pcrUsage' TRUE if any bit is set in the pcrSelect bit mask. 'start_pcr' indicates the starting byte index into pcrSelect[]. */ TPM_RESULT TPM_PCRSelection_GetPCRUsage(TPM_BOOL *pcrUsage, const TPM_PCR_SELECTION *tpm_pcr_selection, size_t start_index) { TPM_RESULT rc = 0; size_t i; printf(" TPM_PCRSelection_GetPCRUsage: Start %lu\n", (unsigned long)start_index); if (rc == 0) { rc = TPM_PCRSelection_CheckRange(tpm_pcr_selection); } if (rc == 0) { *pcrUsage = FALSE; /* If sizeOfSelect is 0 or start_index is past the end, this loop won't be entered and FALSE will be returned */ for (i = start_index ; i < tpm_pcr_selection->sizeOfSelect ; i++) { if (tpm_pcr_selection->pcrSelect[i] != 0) { /* is any bit set in the mask */ *pcrUsage = TRUE; break; } } } return rc; } /* TPM_PCRSelection_CheckRange() checks the sizeOfSelect index */ TPM_RESULT TPM_PCRSelection_CheckRange(const TPM_PCR_SELECTION *tpm_pcr_selection) { TPM_RESULT rc = 0; if (tpm_pcr_selection->sizeOfSelect > (TPM_NUM_PCR/CHAR_BIT)) { printf("TPM_PCRSelection_CheckRange: Error, sizeOfSelect %u must be 0 - %u\n", tpm_pcr_selection->sizeOfSelect, TPM_NUM_PCR/CHAR_BIT); rc = TPM_INVALID_PCR_INFO; } return rc; } /* TPM_PCRSelection_Compare() compares the TPM_PCR_SELECTION's for equality */ void TPM_PCRSelection_Compare(TPM_BOOL *match, TPM_PCR_SELECTION *tpm_pcr_selection1, TPM_PCR_SELECTION *tpm_pcr_selection2) { size_t i; *match = TRUE; if (tpm_pcr_selection1->sizeOfSelect != tpm_pcr_selection2->sizeOfSelect) { *match = FALSE; } for (i = 0 ; *match && (i < tpm_pcr_selection1->sizeOfSelect) ; i++) { if (tpm_pcr_selection1->pcrSelect[i] != tpm_pcr_selection2->pcrSelect[i]) { *match = FALSE; } } return; } #if 0 /* TPM_PCRSelection_LessThan() compares the new selection to the old selection. It returns lessThan TRUE is the new selection does not select a PCR that was selected by the old selection. */ void TPM_PCRSelection_LessThan(TPM_BOOL *lessThan, TPM_PCR_SELECTION *tpm_pcr_selection_new, TPM_PCR_SELECTION *tpm_pcr_selection_old) { size_t i; *lessThan = TRUE; if (tpm_pcr_selection_new->sizeOfSelect != tpm_pcr_selection_old->sizeOfSelect) { *lessThan = FALSE; } for (i = 0 ; *lessThan && (i < tpm_pcr_selection_new->sizeOfSelect) ; i++) { /* if there's a 0 in the new selection and a 1 on the old selection */ if (~(tpm_pcr_selection_new->pcrSelect[i]) & tpm_pcr_selection_old->pcrSelect[i]) { *lessThan = FALSE; } } return; } #endif /* TPM_QUOTE_INFO */ /* TPM_QuoteInfo_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_QuoteInfo_Init(TPM_QUOTE_INFO *tpm_quote_info) { printf(" TPM_QuoteInfo_Init:\n"); TPM_StructVer_Init(&(tpm_quote_info->version)); memcpy(&(tpm_quote_info->fixed), "QUOT", 4); TPM_Digest_Init(tpm_quote_info->digestValue); TPM_Nonce_Init(tpm_quote_info->externalData); return; } #if 0 /* TPM_QuoteInfo_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_QuoteInfo_Init() After use, call TPM_QuoteInfo_Delete() to free memory NOTE: Never called. */ TPM_RESULT TPM_QuoteInfo_Load(TPM_QUOTE_INFO *tpm_quote_info, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_QuoteInfo_Load:\n"); /* load version */ if (rc == 0) { rc = TPM_StructVer_Load(&(tpm_quote_info->version), stream, stream_size); } /* check ver immediately to ease debugging */ if (rc == 0) { rc = TPM_StructVer_CheckVer(&(tpm_quote_info->version)); } /* load fixed */ if (rc == 0) { rc = TPM_Loadn(tpm_quote_info->fixed, 4, stream, stream_size); } /* load digestValue */ if (rc == 0) { rc = TPM_Digest_Load(tpm_quote_info->digestValue, stream, stream_size); } /* load externalData */ if (rc == 0) { rc = TPM_Nonce_Load(tpm_quote_info->externalData, stream, stream_size); } return rc; } #endif /* TPM_QuoteInfo_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_QuoteInfo_Store(TPM_STORE_BUFFER *sbuffer, const TPM_QUOTE_INFO *tpm_quote_info) { TPM_RESULT rc = 0; printf(" TPM_QuoteInfo_Store:\n"); /* store version */ if (rc == 0) { rc = TPM_StructVer_Store(sbuffer, &(tpm_quote_info->version)); } /* store fixed */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, tpm_quote_info->fixed, 4); } /* store digestValue */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_quote_info->digestValue); } /* store externalData */ if (rc == 0) { rc = TPM_Nonce_Store(sbuffer, tpm_quote_info->externalData); } return rc; } /* TPM_QuoteInfo_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_QuoteInfo_Init to set members back to default values The object itself is not freed */ void TPM_QuoteInfo_Delete(TPM_QUOTE_INFO *tpm_quote_info) { printf(" TPM_QuoteInfo_Delete:\n"); if (tpm_quote_info != NULL) { TPM_QuoteInfo_Init(tpm_quote_info); } return; } /* TPM_QUOTE_INFO2 */ /* TPM_QuoteInfo2_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_QuoteInfo2_Init(TPM_QUOTE_INFO2 *tpm_quote_info2) { printf(" TPM_QuoteInfo2_Init:\n"); memcpy(tpm_quote_info2->fixed, "QUT2", 4); TPM_Nonce_Init(tpm_quote_info2->externalData); TPM_PCRInfoShort_Init(&(tpm_quote_info2->infoShort)); return; } #if 0 /* TPM_QuoteInfo2_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_QuoteInfo2_Init() After use, call TPM_QuoteInfo2_Delete() to free memory */ TPM_RESULT TPM_QuoteInfo2_Load(TPM_QUOTE_INFO2 *tpm_quote_info2, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_QuoteInfo2_Load:\n"); /* check tag */ if (rc == 0) { rc = TPM_CheckTag(TPM_TAG_QUOTE_INFO2, stream, stream_size); } /* load fixed */ if (rc == 0) { rc = TPM_Loadn(tpm_quote_info2->fixed, 4, stream, stream_size); } /* load externalData */ if (rc == 0) { rc = TPM_Nonce_Load(tpm_quote_info2->externalData, stream, stream_size); } /* load infoShort */ if (rc == 0) { rc = TPM_PCRInfoShort_Load(&(tpm_quote_info2->infoShort), stream, stream_size, FALSE); } return rc; } #endif /* TPM_QuoteInfo2_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_QuoteInfo2_Store(TPM_STORE_BUFFER *sbuffer, const TPM_QUOTE_INFO2 *tpm_quote_info2) { TPM_RESULT rc = 0; printf(" TPM_QuoteInfo2_Store:\n"); /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_QUOTE_INFO2); } /* store fixed */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, tpm_quote_info2->fixed, 4); } /* store externalData */ if (rc == 0) { rc = TPM_Nonce_Store(sbuffer, tpm_quote_info2->externalData); } /* store infoShort */ if (rc == 0) { rc = TPM_PCRInfoShort_Store(sbuffer, &(tpm_quote_info2->infoShort), FALSE); } return rc; } /* TPM_QuoteInfo2_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_QuoteInfo2_Init to set members back to default values The object itself is not freed */ void TPM_QuoteInfo2_Delete(TPM_QUOTE_INFO2 *tpm_quote_info2) { printf(" TPM_QuoteInfo2_Delete:\n"); if (tpm_quote_info2 != NULL) { TPM_PCRInfoShort_Delete(&(tpm_quote_info2->infoShort)); TPM_QuoteInfo2_Init(tpm_quote_info2); } return; } /* Command Processing Functions */ /* 16.2 TPM_PCRRead rev 109 The TPM_PCRRead operation provides non-cryptographic reporting of the contents of a named PCR. */ TPM_RESULT TPM_Process_PcrRead(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_PCRINDEX pcrIndex; /* Index of the PCR to be read */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_PCRVALUE outDigest; printf("TPM_Process_PcrRead: Ordinal Entry\n"); /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get pcrIndex parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&pcrIndex, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_PcrRead: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ /* 1.Validate that pcrIndex represents a legal PCR number. On error, return TPM_BADINDEX. */ /* 2. Set outDigest to TPM_STCLEAR_DATA -> PCR[pcrIndex] */ /* NOTE Done by TPM_PCR_Load() */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_PcrRead: pcrIndex %u\n", pcrIndex); returnCode = TPM_PCR_Load(outDigest, tpm_state->tpm_stclear_data.PCRS, pcrIndex); } if (returnCode == TPM_SUCCESS) { TPM_PrintFour("TPM_Process_PcrRead: PCR value", outDigest); } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_PcrRead: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* append outDigest */ returnCode = TPM_Digest_Store(response, outDigest); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } return rcf; } /* 16.3 TPM_Quote rev 101 The TPM_Quote operation provides cryptographic reporting of PCR values. A loaded key is required for operation. TPM_Quote uses a key to sign a statement that names the current value of a chosen PCR and externally supplied data (which may be a nonce supplied by a Challenger). The term "ExternalData" is used because an important use of TPM_Quote is to provide a digital signature on arbitrary data, where the signature includes the PCR values of the platform at time of signing. Hence the "ExternalData" is not just for anti-replay purposes, although it is (of course) used for that purpose in an integrity challenge. */ TPM_RESULT TPM_Process_Quote(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_KEY_HANDLE keyHandle; /* The keyHandle identifier of a loaded key that can sign the PCR values. */ TPM_NONCE externalData; /* 160 bits of externally supplied data (typically a nonce provided by a server to prevent replay-attacks) */ TPM_PCR_SELECTION targetPCR; /* The indices of the PCRs that are to be reported. */ TPM_AUTHHANDLE authHandle; /* The authorization handle used for keyHandle authorization. */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization handle */ TPM_AUTHDATA privAuth; /* The authorization digest for inputs and keyHandle. HMAC key: key -> usageAuth. */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ TPM_SECRET *hmacKey; TPM_KEY *sigKey = NULL; /* the key specified by keyHandle */ TPM_SECRET *keyUsageAuth; TPM_BOOL parentPCRStatus; TPM_QUOTE_INFO q1QuoteInfo; TPM_DIGEST q1_digest; /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_PCR_COMPOSITE pcrData; /* A structure containing the same indices as targetPCR, plus the corresponding current PCR values. */ TPM_SIZED_BUFFER sig; /* The signed data blob. */ printf("TPM_Process_Quote: Ordinal Entry\n"); TPM_PCRSelection_Init(&targetPCR); /* freed @1 */ TPM_PCRComposite_Init(&pcrData); /* freed @2 */ TPM_QuoteInfo_Init(&q1QuoteInfo); /* freed @3 */ TPM_SizedBuffer_Init(&sig); /* freed @4 */ /* get inputs */ /* get keyHandle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&keyHandle, &command, ¶mSize); } /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get externalData parameter */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_Quote: keyHandle %08x\n", keyHandle); returnCode = TPM_Nonce_Load(externalData, &command, ¶mSize); } /* get targetPCR parameter */ if (returnCode == TPM_SUCCESS) { TPM_PrintFour("TPM_Process_Quote: externalData", externalData); returnCode = TPM_PCRSelection_Load(&targetPCR, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag10(tag); } /* get the optional 'below the line' authorization parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, privAuth, &command, ¶mSize); } if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { printf("TPM_Process_Quote: authHandle %08x\n", authHandle); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_Quote: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* get the key corresponding to the keyHandle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyHandleEntries_GetKey(&sigKey, &parentPCRStatus, tpm_state, keyHandle, FALSE, /* not r/o, used to sign */ FALSE, /* do not ignore PCRs */ FALSE); /* cannot use EK */ } if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)) { if (sigKey->authDataUsage != TPM_AUTH_NEVER) { printf("TPM_Process_Quote: Error, authorization required\n"); returnCode = TPM_AUTHFAIL; } } /* get keyHandle -> usageAuth */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_Key_GetUsageAuth(&keyUsageAuth, sigKey); } /* get the session data */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_KEYHANDLE, ordinal, sigKey, keyUsageAuth, /* OIAP */ sigKey->tpm_store_asymkey->pubDataDigest); /* OSAP */ } /* 1. The TPM MUST validate the authorization to use the key pointed to by keyHandle. */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, privAuth); /* Authorization digest for input */ } /* 2. Validate that keyHandle -> sigScheme is TPM_SS_RSASSAPKCS1v15_SHA1 or TPM_SS_RSASSAPKCS1v15_INFO,, if not return TPM_INAPPROPRIATE_SIG. */ if (returnCode == TPM_SUCCESS) { if ((sigKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1) && (sigKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_INFO)) { printf("TPM_Process_Quote: Error, invalid sigKey sigScheme %04hx\n", sigKey->algorithmParms.sigScheme); returnCode = TPM_INAPPROPRIATE_SIG; } } /* 3. Validate that keyHandle -> keyUsage is TPM_KEY_SIGNING, TPM_KEY_IDENTITY or TPM_KEY_LEGACY, if not return TPM_INVALID_KEYUSAGE */ if (returnCode == TPM_SUCCESS) { if ((sigKey->keyUsage != TPM_KEY_SIGNING) && ((sigKey->keyUsage) != TPM_KEY_IDENTITY) && ((sigKey->keyUsage) != TPM_KEY_LEGACY)) { printf("TPM_Process_Quote: Error, keyUsage %04hx is invalid\n", sigKey->keyUsage); returnCode = TPM_INVALID_KEYUSAGE; } } /* 4. Validate targetPCR */ /* a. targetPCR is a valid TPM_PCR_SELECTION structure */ /* b. On errors return TPM_INVALID_PCR_INFO */ /* NOTE: done during TPM_PCRSelection_Load() */ /* 5. Create H1 a SHA-1 hash of a TPM_PCR_COMPOSITE using the PCRs indicated by targetPCR -> pcrSelect */ /* NOTE TPM_PCRSelection_GenerateDigest2() generates the TPM_PCR_COMPOSITE as well. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_PCRSelection_GenerateDigest2(q1QuoteInfo.digestValue, &pcrData, /* TPM_PCR_COMPOSITE */ &targetPCR, tpm_state->tpm_stclear_data.PCRS); } /* 6. Create Q1 a TPM_QUOTE_INFO structure */ /* a. Set Q1 -> version to 1.1.0.0 */ /* b. Set Q1 -> fixed to "QUOT" */ /* NOTE: done at TPM_QuoteInfo_Init() */ /* c. Set Q1 -> digestValue to H1 */ /* NOTE: Generated directly in Q1 */ /* d. Set Q1 -> externalData to externalData */ if (returnCode == TPM_SUCCESS) { TPM_Nonce_Copy(q1QuoteInfo.externalData, externalData); } /* 7. Sign SHA-1 hash of Q1 using keyHandle as the signature key */ /* digest Q1 */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SHA1_GenerateStructure(q1_digest, &q1QuoteInfo, (TPM_STORE_FUNCTION_T)TPM_QuoteInfo_Store); } /* sign the Q1 digest */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_RSASignToSizedBuffer(&sig, /* signature */ q1_digest, /* message */ TPM_DIGEST_SIZE, /* message size */ sigKey); /* signing key and parameters */ } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_Quote: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* return the pcrData */ returnCode = TPM_PCRComposite_Store(response, &pcrData); } /* 8. Return the signature in sig */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_Store(response, &sig); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* owner HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ TPM_PCRSelection_Delete(&targetPCR); /* @1 */ TPM_PCRComposite_Delete(&pcrData); /* @2 */ TPM_QuoteInfo_Delete(&q1QuoteInfo); /* @3 */ TPM_SizedBuffer_Delete(&sig); /* @4 */ return rcf; } /* 16.5 TPM_Quote2 rev 96 The TPM_Quote operation provides cryptographic reporting of PCR values. A loaded key is required for operation. TPM_Quote uses a key to sign a statement that names the current value of a chosen PCR and externally supplied data (which may be a nonce supplied by a Challenger). The term "ExternalData" is used because an important use of TPM_Quote is to provide a digital signature on arbitrary data, where the signature includes the PCR values of the platform at time of signing. Hence the "ExternalData" is not just for anti-replay purposes, although it is (of course) used for that purpose in an integrity challenge. Quote2 differs from quote in that Quote2 uses TPM_PCR_INFO_SHORT to hold information relative to the PCR registers. INFO_SHORT includes locality information to provide the requester a more complete view of the current platform configuration. */ TPM_RESULT TPM_Process_Quote2(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_KEY_HANDLE keyHandle; /* The keyHandle identifier of a loaded key that can sign the PCR values. */ TPM_NONCE externalData; /* 160 bits of externally supplied data (typically a nonce provided by a server to prevent replay-attacks) */ TPM_PCR_SELECTION targetPCR; /* The indices of the PCRs that are to be reported. */ TPM_BOOL addVersion; /* When TRUE add TPM_CAP_VERSION_INFO to the output */ TPM_AUTHHANDLE authHandle; /* The authorization session handle used for keyHandle authorization. */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization session handle */ TPM_AUTHDATA privAuth; /* The authorization session digest for inputs and keyHandle. HMAC key: key -> usageAuth. */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ TPM_SECRET *hmacKey; TPM_KEY *sigKey = NULL; /* the key specified by keyHandle */ TPM_SECRET *keyUsageAuth; TPM_BOOL parentPCRStatus; TPM_COMPOSITE_HASH h1CompositeHash; TPM_QUOTE_INFO2 q1; TPM_PCR_INFO_SHORT *s1 = NULL; TPM_STORE_BUFFER q1_sbuffer; TPM_STORE_BUFFER versionInfo_sbuffer; const unsigned char *versionInfo_buffer; TPM_DIGEST q1_digest; /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; uint32_t versionInfoSize; /* Size of the version info */ TPM_CAP_VERSION_INFO versionInfo; /* The version info */ TPM_SIZED_BUFFER sig; /* The signed data blob. */ printf("TPM_Process_Quote2: Ordinal Entry\n"); TPM_PCRSelection_Init(&targetPCR); /* freed @1 */ TPM_CapVersionInfo_Set(&versionInfo, &(tpm_state->tpm_permanent_data)); /* freed @2 */ TPM_SizedBuffer_Init(&sig); /* freed @3 */ TPM_QuoteInfo2_Init(&q1); /* freed @4 */ TPM_Sbuffer_Init(&q1_sbuffer); /* freed @5 */ TPM_Sbuffer_Init(&versionInfo_sbuffer); /* freed @6 */ /* get inputs */ /* get keyHandle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&keyHandle, &command, ¶mSize); } /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get externalData */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_Quote2: keyHandle %08x\n", keyHandle); returnCode = TPM_Nonce_Load(externalData, &command, ¶mSize); } /* get targetPCR parameter */ if (returnCode == TPM_SUCCESS) { TPM_PrintFour("TPM_Process_Quote2: externalData", externalData); returnCode = TPM_PCRSelection_Load(&targetPCR, &command, ¶mSize); } /* get addVersion parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_LoadBool(&addVersion, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_Quote2: addVersion %02x\n", addVersion); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag10(tag); } /* get the optional 'below the line' authorization parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, privAuth, &command, ¶mSize); } if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { printf("TPM_Process_Quote2: authHandle %08x\n", authHandle); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_Quote2: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* get the key corresponding to the keyHandle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyHandleEntries_GetKey(&sigKey, &parentPCRStatus, tpm_state, keyHandle, FALSE, /* not r/o, used to sign */ FALSE, /* do not ignore PCRs */ FALSE); /* cannot use EK */ } if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)) { if (sigKey->authDataUsage != TPM_AUTH_NEVER) { printf("TPM_Process_Quote2: Error, authorization required\n"); returnCode = TPM_AUTHFAIL; } } /* get keyHandle -> usageAuth */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_Key_GetUsageAuth(&keyUsageAuth, sigKey); } /* get the session data */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_KEYHANDLE, ordinal, sigKey, keyUsageAuth, /* OIAP */ sigKey->tpm_store_asymkey->pubDataDigest); /* OSAP */ } /* 1. The TPM MUST validate the AuthData to use the key pointed to by keyHandle. */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, privAuth); /* Authorization digest for input */ } /* 2. Validate that keyHandle -> sigScheme is TPM_SS_RSASSAPKCS1v15_SHA1, if not return TPM_INAPPROPRIATE_SIG. */ if (returnCode == TPM_SUCCESS) { if ((sigKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1) && (sigKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_INFO)) { printf("TPM_Process_Quote2: Error, inappropriate signature scheme %04x\n", sigKey->algorithmParms.sigScheme); returnCode = TPM_INAPPROPRIATE_SIG; } } /* 3. Validate that keyHandle -> keyUsage is TPM_KEY_SIGNING, TPM_KEY_IDENTITY or TPM_KEY_LEGACY, if not return TPM_INVALID_KEYUSAGE */ if (returnCode == TPM_SUCCESS) { if ((sigKey->keyUsage != TPM_KEY_SIGNING) && ((sigKey->keyUsage) != TPM_KEY_IDENTITY) && ((sigKey->keyUsage) != TPM_KEY_LEGACY)) { printf("TPM_Process_Quote2: Error, keyUsage %04hx is invalid\n", sigKey->keyUsage); returnCode = TPM_INVALID_KEYUSAGE; } } /* 4. Validate targetPCR is a valid TPM_PCR_SELECTION structure, on errors return TPM_INVALID_PCR_INFO */ /* NOTE: done during TPM_PCRSelection_Load() */ /* 5. Create H1 a SHA-1 hash of a TPM_PCR_COMPOSITE using the PCRs indicated by targetPCR -> pcrSelect */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_PCRSelection_GenerateDigest(h1CompositeHash, &targetPCR, tpm_state->tpm_stclear_data.PCRS); } if (returnCode == TPM_SUCCESS) { /* 6. Create S1 a TPM_PCR_INFO_SHORT */ s1 = &(q1.infoShort); /* a. Set S1->pcrSelection to pcrSelect */ returnCode = TPM_PCRSelection_Copy(&(s1->pcrSelection), &targetPCR); } /* b. Set S1->localityAtRelease to TPM_STANY_DATA -> localityModifier */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Locality_Set(&(s1->localityAtRelease), tpm_state->tpm_stany_flags.localityModifier); } /* c. Set S1->digestAtRelease to H1 */ if (returnCode == TPM_SUCCESS) { TPM_Digest_Copy(s1->digestAtRelease, h1CompositeHash); /* 7. Create Q1 a TPM_QUOTE_INFO2 structure */ /* a. Set Q1 -> fixed to "QUT2" */ /* NOTE: done at TPM_QuoteInfo2_Init() */ /* b. Set Q1 -> infoShort to S1 */ /* NOTE: created S1 in place */ /* c. Set Q1 -> externalData to externalData */ TPM_Nonce_Copy(q1.externalData, externalData); /* serialize q1 */ returnCode = TPM_QuoteInfo2_Store(&q1_sbuffer, &q1); } if (returnCode == TPM_SUCCESS) { /* 8. If addVersion is TRUE */ if (addVersion) { if (returnCode == TPM_SUCCESS) { /* a. Concatenate to Q1 a TPM_CAP_VERSION_INFO structure */ /* b. Set the output parameters for versionInfo */ /* serialize versionInfo. The result cannot be added directly to q1_sbuffer because it is needed as an outgoing parameter */ /* NOTE: Created at TPM_CapVersionInfo_Set() */ returnCode = TPM_CapVersionInfo_Store(&versionInfo_sbuffer, &versionInfo); } if (returnCode == TPM_SUCCESS) { /* get the serialized results */ TPM_Sbuffer_Get(&versionInfo_sbuffer, &versionInfo_buffer, &versionInfoSize); /* concatenate TPM_CAP_VERSION_INFO versionInfo to TPM_QUOTE_INFO2 q1 buffer */ returnCode = TPM_Sbuffer_Append(&q1_sbuffer, versionInfo_buffer, versionInfoSize); } } /* 9. Else */ else { /* a. Set versionInfoSize to 0 */ versionInfoSize = 0; /* b. Return no bytes in versionInfo */ /* NOTE Done at response, (&& addVersion) */ } } /* 10. Sign a SHA-1 hash of Q1 using keyHandle as the signature key */ /* hash q1 */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SHA1Sbuffer(q1_digest, &q1_sbuffer); } /* sign the Q1 digest */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_RSASignToSizedBuffer(&sig, /* signature */ q1_digest, /* message */ TPM_DIGEST_SIZE, /* message size */ sigKey); /* signing key and parameters */ } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_Quote2: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* return the TPM_PCR_INFO_SHORT pcrData */ returnCode = TPM_PCRInfoShort_Store(response, s1, FALSE); } /* An email clarification said that, if addVersion is FALSE, a versionInfoSize is 0 is returned. This indicates the missing versionInfo. */ /* return the versionInfoSize */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Sbuffer_Append32(response, versionInfoSize); } /* return the versionInfo */ if ((returnCode == TPM_SUCCESS) && addVersion) { returnCode = TPM_Sbuffer_Append(response, versionInfo_buffer, versionInfoSize); } /* 11. Return the signature in sig */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_Store(response, &sig); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* owner HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ TPM_PCRSelection_Delete(&targetPCR); /* @1 */ TPM_CapVersionInfo_Delete(&versionInfo); /* @2 */ TPM_SizedBuffer_Delete(&sig); /* @3 */ TPM_QuoteInfo2_Delete(&q1); /* @4 */ TPM_Sbuffer_Delete(&q1_sbuffer); /* @5 */ TPM_Sbuffer_Delete(&versionInfo_sbuffer); /* @6 */ return rcf; } /* TPM_ExtendCommon() rev 109 Contains code common to TPM_Process_Extend() and TPM_Process_SHA1CompleteExtend(). Add a measurement value to a PCR */ TPM_RESULT TPM_ExtendCommon(TPM_PCRVALUE outDigest, /* The PCR value after execution of the command */ tpm_state_t *tpm_state, TPM_COMMAND_CODE ordinal, /* command ordinal */ TPM_PCRINDEX pcrNum, /* Index of the PCR to be modified */ TPM_DIGEST inDigest) /* the event to be recorded */ { TPM_RESULT rc = 0; TPM_PCRVALUE currentPcrValue; TPM_DIGEST h1; printf("TPM_ExtendCommon: pcrNum %u\n", pcrNum); /* 1. Validate that pcrNum represents a legal PCR number. On error, return TPM_BADINDEX. */ if (rc == 0) { rc = TPM_PCR_CheckRange(pcrNum); } if (rc == 0) { /* 2. Map V1 to TPM_STANY_FLAGS */ /* 3. Map L1 to V1 -> localityModifier */ /* 4. If the current locality, held in L1, is not selected in TPM_PERMANENT_DATA -> pcrAttrib[PCRIndex].pcrExtendLocal, return TPM_BAD_LOCALITY */ rc = TPM_Locality_Check(tpm_state->tpm_permanent_data.pcrAttrib[pcrNum].pcrExtendLocal, tpm_state->tpm_stany_flags.localityModifier); } /* get the current PCR digest value */ if (rc == 0) { rc = TPM_PCR_Load(currentPcrValue, tpm_state->tpm_stclear_data.PCRS, pcrNum); } #if defined TPM_PCCLIENT /* From the PC Client TIS spec 1. When the locality 4 PCR is at its reset value of 0, the entry for the locality 4 PCR in section 7.2 SHALL be interpreted as if the column labeled pcrExtendLocal for locality 4,3,2,1,0 contains the bit field definitions: 1,0,0,0,0. 2. Once the locality 4 PCR is no longer at its reset value of 0, table 4 in section 7.2 applies as written. */ if (rc == 0) { TPM_BOOL isZero; if ((pcrNum == 17) && /* PCR 17 is the Locality 4 PCR */ (tpm_state->tpm_stany_flags.localityModifier != 4)) { /* if not locality 4, must not be at the reset value */ TPM_Digest_IsZero(&isZero, currentPcrValue); if (isZero) { printf("TPM_ExtendCommon: Error, " "pcrNum %u and locality %u and PCR at reset value\n", pcrNum, tpm_state->tpm_stany_flags.localityModifier); rc = TPM_BAD_LOCALITY; } } } #endif /* 5. Create c1 by concatenating (PCRindex TPM_PCRVALUE || inDigest). This takes the current PCR value and concatenates the inDigest parameter. */ /* NOTE: Not required, SHA1 uses varargs */ /* 6. Create h1 by performing a SHA-1 digest of c1. */ if (rc == 0) { TPM_PrintFour("TPM_ExtendCommon: Current PCR ", currentPcrValue); /* TPM_PrintFour("TPM_ExtendCommon: Current PCR ", tpm_state->tpm_stclear_data.PCR[pcrNum]); */ TPM_PrintFour("TPM_ExtendCommon: Input Digest", inDigest); rc = TPM_SHA1(h1, TPM_DIGEST_SIZE, currentPcrValue, TPM_DIGEST_SIZE, inDigest, 0, NULL); } if (rc == 0) { TPM_PrintFour("TPM_ExtendCommon: New PCR", h1); /* 7. Store h1 as the new TPM_PCRVALUE of PCRindex */ rc = TPM_PCR_Store(tpm_state->tpm_stclear_data.PCRS, pcrNum, h1); } if (rc == 0) { /* 8. If TPM_PERMANENT_FLAGS -> disable is TRUE or TPM_STCLEAR_FLAGS -> deactivated is TRUE */ if ((tpm_state->tpm_permanent_flags.disable) || (tpm_state->tpm_stclear_flags.deactivated)) { /* a. Set outDigest to 20 bytes of 0x00 */ TPM_Digest_Init(outDigest); } /* 9. Else */ else { /* a. Set outDigest to h1 */ TPM_Digest_Copy(outDigest, h1); } } if (rc == 0) { ordinal = ordinal; } return rc; } /* 16.1 TPM_Extend rev 109 This adds a new measurement to a PCR. */ TPM_RESULT TPM_Process_Extend(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_PCRINDEX pcrNum; /* The PCR to be updated. */ TPM_DIGEST inDigest; /* The 160 bit value representing the event to be recorded. */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_PCRVALUE outDigest; /* The PCR value after execution of the command. */ printf("TPM_Process_Extend: Ordinal Entry\n"); /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get pcrNum parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&pcrNum, &command, ¶mSize); } /* get inDigest parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Digest_Load(inDigest, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | TPM_CHECK_NO_LOCKOUT)); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_Extend: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ /* extend the resultant digest into a PCR */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_ExtendCommon(outDigest, tpm_state, ordinal, pcrNum, inDigest); } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_Extend: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* append outDigest */ returnCode = TPM_Digest_Store(response, outDigest); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } return rcf; } /* 16.4 TPM_PCR_Reset rev 87 For PCR with the pcrReset attribute set to TRUE, this command resets the PCR back to the default value, this mimics the actions of TPM_Init. The PCR may have restrictions as to which locality can perform the reset operation. Sending a null pcrSelection results in an error is due to the requirement that the command actually do something. If pcrSelection is null there are no PCR to reset and the command would then do nothing. For PCR that are resettable, the presence of a Trusted Operating System (TOS) can change the behavior of TPM_PCR_Reset. The following pseudo code shows how the behavior changes At TPM_Startup If TPM_PCR_ATTRIBUTES->pcrReset is FALSE Set PCR to 0x00...00 Else Set PCR to 0xFF...FF At TPM_PCR_Reset If TPM_PCR_ATTRIBUTES->pcrReset is TRUE If TOSPresent Set PCR to 0x00...00 Else Set PCR to 0xFF...FF Else Return error The above pseudocode is for example only, for the details of a specific platform, the reader must review the platform specific specification. The purpose of the above pseudocode is to show that both pcrReset and the TOSPresent bit control the value in use to when the PCR resets. */ TPM_RESULT TPM_Process_PcrReset(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_PCR_SELECTION pcrSelection; /* The PCR's to reset*/ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL pcrUsage; /* TRUE if pcrSelection specifies one or more PCR's */ TPM_PERMANENT_DATA *tpm_permanent_data = NULL; size_t i; /* PCR selection iterator */ size_t j; /* PCR selection bit map in byte */ TPM_PCRINDEX pcr_num; /* PCR iterator */ TPM_MODIFIER_INDICATOR localityModifier = 0; uint16_t sizeOfSelect = 0; /* from pcrSelection input parameter */ /* output parameters */ uint16_t outParamStart; /* starting point of outParam's */ uint16_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_PcrReset: Ordinal Entry\n"); TPM_PCRSelection_Init(&pcrSelection); /* freed @1 */ /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get pcrSelection */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_PCRSelection_Load(&pcrSelection, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | TPM_CHECK_NO_LOCKOUT)); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_PcrReset: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ /* 1. Validate that pcrSelection is valid */ /* a. is a valid TPM_PCR_SELECTION structure */ /* NOTE: Done during TPM_PCRSelection_Load() */ /* b. pcrSelection -> pcrSelect is non-zero */ /* NOTE: TPM_PCRSelection_GetPCRUsage() range checks pcrSelection */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_PcrReset: Getting input PCR usage\n"); returnCode = TPM_PCRSelection_GetPCRUsage(&pcrUsage, &pcrSelection, 0); } /* c. On errors return TPM_INVALID_PCR_INFO */ if (returnCode == TPM_SUCCESS) { if (!pcrUsage) { printf("TPM_Process_PcrReset: Error, pcrSelect is zero\n"); returnCode = TPM_INVALID_PCR_INFO; } } /* 2. Map L1 to TPM_STANY_FLAGS -> localityModifier (NOTE and other optimizations of the inner loop) */ if (returnCode == TPM_SUCCESS) { localityModifier = tpm_state->tpm_stany_flags.localityModifier; tpm_permanent_data = &(tpm_state->tpm_permanent_data); sizeOfSelect = pcrSelection.sizeOfSelect; /* bytes of input PCR selection */ } /* 3. For each PCR selected perform the following */ for (i = 0, pcr_num = 0 ; (returnCode == TPM_SUCCESS) && (i < sizeOfSelect) ; i++) { /* iterate through all bits in each selection byte */ for (j = 0x0001 ; (returnCode == TPM_SUCCESS) && (j != (0x0001 << CHAR_BIT)) ; j <<= 1, pcr_num++) { if (pcrSelection.pcrSelect[i] & j) { /* if the bit is set in the selection map */ /* a. If pcrAttrib[pcrIndex].pcrReset is FALSE */ if (!(tpm_permanent_data->pcrAttrib[pcr_num].pcrReset)) { printf("TPM_Process_PcrReset: Error, PCR %u not resettable\n", pcr_num); /* a. Return TPM_NOTRESETABLE */ returnCode = TPM_NOTRESETABLE; } /* b. If, for the value L1, the corresponding bit is clear in the bit map TPM_PERMANENT_DATA -> pcrAttrib[pcrIndex].pcrResetLocal, return TPM_NOTLOCAL */ else { returnCode = TPM_Locality_Check(tpm_permanent_data->pcrAttrib[pcr_num].pcrResetLocal, localityModifier); if (returnCode != TPM_SUCCESS) { printf("TPM_Process_PcrReset: Error, PCR %u bad pcrResetLocal %02x\n", pcr_num, tpm_permanent_data->pcrAttrib[pcr_num].pcrResetLocal); returnCode = TPM_NOTLOCAL; } } /* NOTE: No 'else reset' here. The command MUST validate that all PCR registers that are selected are available to be reset before resetting any PCR. */ } } } /* 3. For each PCR selected perform the following */ if (returnCode == TPM_SUCCESS) { for (i = 0, pcr_num = 0 ; i < sizeOfSelect ; i++) { /* iterate through all bits in each selection byte */ for (j = 0x0001 ; j != (0x0001 << CHAR_BIT) ; j <<= 1, pcr_num++) { if (pcrSelection.pcrSelect[i] & j) { /* if the bit is set in the selection map */ printf("TPM_Process_PcrReset: Resetting PCR %u\n", pcr_num); /* a. The PCR MAY only reset to 0x00...00 or 0xFF...FF */ /* b. The logic to determine which value to use MUST be described by a platform specific specification */ /* Ignore errors here since PCR selection has already been validated. pcr_num is guaranteed to be in range from from 'for' iterator, and pcrReset is guaranteed to be TRUE from the previous loop. */ TPM_PCR_Reset(tpm_state->tpm_stclear_data.PCRS, tpm_state->tpm_stany_flags.TOSPresent, pcr_num); } } } } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_PcrReset: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* cleanup */ TPM_PCRSelection_Delete(&pcrSelection); /* @1 */ return rcf; } libtpms-0.9.3/src/tpm12/tpm_pcr.h000066400000000000000000000421001421143571500165440ustar00rootroot00000000000000/********************************************************************************/ /* */ /* PCR Handler */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_pcr.h 4620 2011-09-07 21:43:19Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_PCR_H #define TPM_PCR_H #include "tpm_global.h" #include "tpm_sizedbuffer.h" #include "tpm_store.h" /* Locality Utilities */ TPM_RESULT TPM_Locality_Set(TPM_LOCALITY_SELECTION *tpm_locality_selection, TPM_MODIFIER_INDICATOR tpm_modifier_indicator); TPM_RESULT TPM_Locality_Check(TPM_LOCALITY_SELECTION tpm_locality_selection, TPM_MODIFIER_INDICATOR localityModifier); TPM_RESULT TPM_LocalitySelection_CheckLegal(TPM_LOCALITY_SELECTION tpm_locality_selection); TPM_RESULT TPM_LocalityModifier_CheckLegal(TPM_MODIFIER_INDICATOR localityModifier); void TPM_PCRLocality_Compare(TPM_BOOL *match, TPM_LOCALITY_SELECTION tpm_locality_selection1, TPM_LOCALITY_SELECTION tpm_locality_selection2); /* state PCR's */ TPM_RESULT TPM_PCR_CheckRange(TPM_PCRINDEX index); void TPM_PCR_Init(TPM_PCRVALUE *tpm_pcrs, const TPM_PCR_ATTRIBUTES *tpm_pcr_attributes, size_t pcrIndex); void TPM_PCR_Reset(TPM_PCRVALUE *tpm_pcrs, TPM_BOOL TOSPresent, TPM_PCRINDEX pcrIndex); TPM_RESULT TPM_PCR_Load(TPM_PCRVALUE dest_pcr, TPM_PCRVALUE *tpm_pcrs, TPM_PCRINDEX index); TPM_RESULT TPM_PCR_Store(TPM_PCRVALUE *tpm_pcrs, TPM_PCRINDEX index, TPM_PCRVALUE src_pcr); /* TPM_SELECT_SIZE */ void TPM_SelectSize_Init(TPM_SELECT_SIZE *tpm_select_size); TPM_RESULT TPM_SelectSize_Load(TPM_SELECT_SIZE *tpm_select_size, unsigned char **stream, uint32_t *stream_size); /* TPM_PCR_SELECTION */ void TPM_PCRSelection_Init(TPM_PCR_SELECTION *tpm_pcr_selection); TPM_RESULT TPM_PCRSelection_Load(TPM_PCR_SELECTION *tpm_pcr_selection, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_PCRSelection_Store(TPM_STORE_BUFFER *sbuffer, const TPM_PCR_SELECTION *tpm_pcr_selection); void TPM_PCRSelection_Delete(TPM_PCR_SELECTION *tpm_pcr_selection); /* copy */ TPM_RESULT TPM_PCRSelection_Copy(TPM_PCR_SELECTION *destination, TPM_PCR_SELECTION *source); /* setters */ TPM_RESULT TPM_PCRSelection_GenerateDigest(TPM_DIGEST tpm_digest, TPM_PCR_SELECTION *tpm_pcr_selection, TPM_PCRVALUE *tpm_pcrs); TPM_RESULT TPM_PCRSelection_GenerateDigest2(TPM_DIGEST tpm_digest, TPM_PCR_COMPOSITE *tpm_pcr_composite, TPM_PCR_SELECTION *tpm_pcr_selection, TPM_PCRVALUE *tpm_pcrs); /* getters */ TPM_RESULT TPM_PCRSelection_GetPCRUsage(TPM_BOOL *pcrUsage, const TPM_PCR_SELECTION *tpm_pcr_selection, size_t start_index); /* checkers */ TPM_RESULT TPM_PCRSelection_CheckRange(const TPM_PCR_SELECTION *tpm_pcr_selection); void TPM_PCRSelection_Compare(TPM_BOOL *match, TPM_PCR_SELECTION *tpm_pcr_selection1, TPM_PCR_SELECTION *tpm_pcr_selection2); #if 0 void TPM_PCRSelection_LessThan(TPM_BOOL *lessThan, TPM_PCR_SELECTION *tpm_pcr_selection_new, TPM_PCR_SELECTION *tpm_pcr_selection_old); #endif /* TPM_PCR_ATTRIBUTES */ void TPM_PCRAttributes_Init(TPM_PCR_ATTRIBUTES *tpm_pcr_attributes); void TPM_PCRInfo_Trace(const char *message, TPM_PCR_SELECTION pcrSelection, TPM_COMPOSITE_HASH digestAtRelease); /* PCRs - Functions that act on the entire set of PCRs */ void TPM_PCRs_Init(TPM_PCRVALUE *tpm_pcrs, const TPM_PCR_ATTRIBUTES *tpm_pcr_attributes); TPM_RESULT TPM_PCRs_Load(TPM_PCRVALUE *tpm_pcrs, const TPM_PCR_ATTRIBUTES *tpm_pcr_attributes, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_PCRs_Store(TPM_STORE_BUFFER *sbuffer, TPM_PCRVALUE *tpm_pcrs, const TPM_PCR_ATTRIBUTES *tpm_pcr_attributes); /* TPM_PCR_INFO */ void TPM_PCRInfo_Init(TPM_PCR_INFO *tpm_pcr_info); TPM_RESULT TPM_PCRInfo_Load(TPM_PCR_INFO *tpm_pcr_info, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_PCRInfo_Store(TPM_STORE_BUFFER *sbuffer, const TPM_PCR_INFO *tpm_pcr_info); void TPM_PCRInfo_Delete(TPM_PCR_INFO *tpm_pcr_info); /* create */ TPM_RESULT TPM_PCRInfo_Create(TPM_PCR_INFO **tpm_pcr_info); /* load */ TPM_RESULT TPM_PCRInfo_LoadFromBuffer(TPM_PCR_INFO *tpm_pcr_info, const TPM_SIZED_BUFFER *tpm_sized_buffer); TPM_RESULT TPM_PCRInfo_CreateFromBuffer(TPM_PCR_INFO **tpm_pcr_info, const TPM_SIZED_BUFFER *tpm_sized_buffer); /* copy */ TPM_RESULT TPM_PCRInfo_Copy(TPM_PCR_INFO *dest_tpm_pcr_info, TPM_PCR_INFO *src_tpm_pcr_info); TPM_RESULT TPM_PCRInfo_CopyInfoLong(TPM_PCR_INFO *dest_tpm_pcr_info, TPM_PCR_INFO_LONG *src_tpm_pcr_info_long); TPM_RESULT TPM_PCRInfo_CreateFromInfo(TPM_PCR_INFO **dest_tpm_pcr_info, TPM_PCR_INFO *src_tpm_pcr_info); TPM_RESULT TPM_PCRInfo_CreateFromInfoLong(TPM_PCR_INFO **dest_tpm_pcr_info, TPM_PCR_INFO_LONG *src_tpm_pcr_info_long); TPM_RESULT TPM_PCRInfo_CreateFromKey(TPM_PCR_INFO **dest_tpm_pcr_info, TPM_KEY *tpm_key); /* setters */ TPM_RESULT TPM_PCRInfo_GenerateDigest(TPM_DIGEST tpm_digest, TPM_PCR_INFO *tpm_pcr_info, TPM_PCRVALUE *tpm_pcrs); TPM_RESULT TPM_PCRInfo_CheckDigest(TPM_PCR_INFO *tpm_pcr_info, TPM_PCRVALUE *tpm_pcrs); TPM_RESULT TPM_PCRInfo_SetDigestAtCreation(TPM_PCR_INFO *tpm_pcr_info, TPM_PCRVALUE *tpm_pcrs); /* getters */ TPM_RESULT TPM_PCRInfo_GetPCRUsage(TPM_BOOL *pcrUsage, TPM_PCR_INFO *tpm_pcr_info, size_t start_index); /* TPM_PCR_INFO_LONG */ void TPM_PCRInfoLong_Init(TPM_PCR_INFO_LONG *tpm_pcr_info_long); TPM_RESULT TPM_PCRInfoLong_Load(TPM_PCR_INFO_LONG *tpm_pcr_info_long, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_PCRInfoLong_Store(TPM_STORE_BUFFER *sbuffer, const TPM_PCR_INFO_LONG *tpm_pcr_info_long); void TPM_PCRInfoLong_Delete(TPM_PCR_INFO_LONG *tpm_pcr_info_long); /* create */ TPM_RESULT TPM_PCRInfoLong_Create(TPM_PCR_INFO_LONG **tpm_pcr_info_long); /* load */ TPM_RESULT TPM_PCRInfoLong_LoadFromBuffer(TPM_PCR_INFO_LONG *tpm_pcr_info_long, const TPM_SIZED_BUFFER *tpm_sized_buffer); TPM_RESULT TPM_PCRInfoLong_CreateFromBuffer(TPM_PCR_INFO_LONG **tpm_pcr_info_long, const TPM_SIZED_BUFFER *tpm_sized_buffer); /* copy */ TPM_RESULT TPM_PCRInfoLong_Copy(TPM_PCR_INFO_LONG *dest_tpm_pcr_info_long, TPM_PCR_INFO_LONG *src_tpm_pcr_info_long); TPM_RESULT TPM_PCRInfoLong_CreateFromInfoLong(TPM_PCR_INFO_LONG **dest_tpm_pcr_info_long, TPM_PCR_INFO_LONG *src_tpm_pcr_info_long); /* setters */ TPM_RESULT TPM_PCRInfoLong_GenerateDigest(TPM_DIGEST tpm_digest, TPM_PCR_INFO_LONG *tpm_pcr_info_long, TPM_PCRVALUE *tpm_pcrs); TPM_RESULT TPM_PCRInfoLong_CheckDigest(TPM_PCR_INFO_LONG *tpm_pcr_info_long, TPM_PCRVALUE *tpm_pcrs, TPM_MODIFIER_INDICATOR localityModifier); TPM_RESULT TPM_PCRInfoLong_SetDigestAtCreation(TPM_PCR_INFO_LONG *tpm_pcr_info_long, TPM_PCRVALUE *tpm_pcrs); /* getters */ TPM_RESULT TPM_PCRInfoLong_GetPCRUsage(TPM_BOOL *pcrUsage, TPM_PCR_INFO_LONG *tpm_pcr_info_long, size_t start_index); /* TPM_PCR_INFO_SHORT */ void TPM_PCRInfoShort_Init(TPM_PCR_INFO_SHORT *tpm_pcr_info_short); TPM_RESULT TPM_PCRInfoShort_Load(TPM_PCR_INFO_SHORT *tpm_pcr_info_short, unsigned char **stream, uint32_t *stream_size, TPM_BOOL optimize); TPM_RESULT TPM_PCRInfoShort_Store(TPM_STORE_BUFFER *sbuffer, const TPM_PCR_INFO_SHORT *tpm_pcr_info_short, TPM_BOOL optimize); void TPM_PCRInfoShort_Delete(TPM_PCR_INFO_SHORT *tpm_pcr_info_short); /* create */ TPM_RESULT TPM_PCRInfoShort_Create(TPM_PCR_INFO_SHORT **tpm_pcr_info_short); /* load */ TPM_RESULT TPM_PCRInfoShort_LoadFromBuffer(TPM_PCR_INFO_SHORT *tpm_pcr_info_short, const TPM_SIZED_BUFFER *tpm_sized_buffer); TPM_RESULT TPM_PCRInfoShort_CreateFromBuffer(TPM_PCR_INFO_SHORT **tpm_pcr_info_short, const TPM_SIZED_BUFFER *tpm_sized_buffer); /* copy */ TPM_RESULT TPM_PCRInfoShort_Copy(TPM_PCR_INFO_SHORT *dest_tpm_pcr_info_short, TPM_PCR_INFO_SHORT *src_tpm_pcr_info_short); TPM_RESULT TPM_PCRInfoShort_CopyInfo(TPM_PCR_INFO_SHORT *dest_tpm_pcr_info_short, TPM_PCR_INFO *src_tpm_pcr_info); TPM_RESULT TPM_PCRInfoShort_CopyInfoLong(TPM_PCR_INFO_SHORT *dest_tpm_pcr_info_short, TPM_PCR_INFO_LONG *src_tpm_pcr_info_long); TPM_RESULT TPM_PCRInfoShort_CreateFromInfo(TPM_PCR_INFO_SHORT **dest_tpm_pcr_info_short, TPM_PCR_INFO *src_tpm_pcr_info); TPM_RESULT TPM_PCRInfoShort_CreateFromInfoLong(TPM_PCR_INFO_SHORT **dest_tpm_pcr_info_short, TPM_PCR_INFO_LONG *src_tpm_pcr_info_long); TPM_RESULT TPM_PCRInfoShort_CreateFromKey(TPM_PCR_INFO_SHORT **dest_tpm_pcr_info_short, TPM_KEY *tpm_key); /* setters */ TPM_RESULT TPM_PCRInfoShort_GenerateDigest(TPM_DIGEST tpm_digest, TPM_PCR_INFO_SHORT *tpm_pcr_info_short, TPM_PCRVALUE *tpm_pcrs); TPM_RESULT TPM_PCRInfoShort_CheckDigest(TPM_PCR_INFO_SHORT *tpm_pcr_info_short, TPM_PCRVALUE *tpm_pcrs, TPM_MODIFIER_INDICATOR localityModifier); /* getters */ TPM_RESULT TPM_PCRInfoShort_GetPCRUsage(TPM_BOOL *pcrUsage, TPM_PCR_INFO_SHORT *tpm_pcr_info_short); /* TPM_PCR_COMPOSITE */ void TPM_PCRComposite_Init(TPM_PCR_COMPOSITE *tpm_pcr_composite); TPM_RESULT TPM_PCRComposite_Store(TPM_STORE_BUFFER *sbuffer, const TPM_PCR_COMPOSITE *tpm_pcr_composite); void TPM_PCRComposite_Delete(TPM_PCR_COMPOSITE *tpm_pcr_composite); TPM_RESULT TPM_PCRComposite_Set(TPM_PCR_COMPOSITE *tpm_pcr_composite, TPM_PCR_SELECTION *tpm_pcr_selection, TPM_PCRVALUE *tpm_pcrs); /* TPM_QUOTE_INFO */ void TPM_QuoteInfo_Init(TPM_QUOTE_INFO *tpm_quote_info); #if 0 TPM_RESULT TPM_QuoteInfo_Load(TPM_QUOTE_INFO *tpm_quote_info, unsigned char **stream, uint32_t *stream_size); #endif TPM_RESULT TPM_QuoteInfo_Store(TPM_STORE_BUFFER *sbuffer, const TPM_QUOTE_INFO *tpm_quote_info); void TPM_QuoteInfo_Delete(TPM_QUOTE_INFO *tpm_quote_info); /* TPM_QUOTE_INFO2 */ void TPM_QuoteInfo2_Init(TPM_QUOTE_INFO2 *tpm_quote_info2); #if 0 TPM_RESULT TPM_QuoteInfo2_Load(TPM_QUOTE_INFO2 *tpm_quote_info2, unsigned char **stream, uint32_t *stream_size); #endif TPM_RESULT TPM_QuoteInfo2_Store(TPM_STORE_BUFFER *sbuffer, const TPM_QUOTE_INFO2 *tpm_quote_info2); void TPM_QuoteInfo2_Delete(TPM_QUOTE_INFO2 *tpm_quote_info2); /* Common command processing */ TPM_RESULT TPM_ExtendCommon(TPM_PCRVALUE outDigest, tpm_state_t *tpm_state, TPM_COMMAND_CODE ordinal, TPM_PCRINDEX pcrNum, TPM_DIGEST inDigest); /* Command Processing */ TPM_RESULT TPM_Process_PcrRead(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_Quote(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_Quote2(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_Extend(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_PcrReset(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); #endif libtpms-0.9.3/src/tpm12/tpm_permanent.c000066400000000000000000001256731421143571500177650ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Permanent Flag and Data Handler */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_permanent.c 4623 2011-09-28 15:15:09Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include #include #include #include "tpm_audit.h" #include "tpm_counter.h" #include "tpm_crypto.h" #include "tpm_cryptoh.h" #include "tpm_debug.h" #include "tpm_delegate.h" #include "tpm_digest.h" #include "tpm_error.h" #include "tpm_global.h" #include "tpm_key.h" #include "tpm_nonce.h" #include "tpm_nvfile.h" #include "tpm_nvfilename.h" #include "tpm_nvram.h" #include "tpm_pcr.h" #include "tpm_secret.h" #include "tpm_storage.h" #include "tpm_structures.h" #include "tpm_types.h" #include "tpm_svnrevision.h" #include "tpm_permanent.h" /* TPM_PERMANENT_FLAGS */ void TPM_PermanentFlags_Init(TPM_PERMANENT_FLAGS *tpm_permanent_flags) { printf(" TPM_PermanentFlags_Init:\n"); #ifndef TPM_ENABLE_ACTIVATE tpm_permanent_flags->disable = TRUE; #else /* for servers, not TCG standard */ tpm_permanent_flags->disable = FALSE; #endif tpm_permanent_flags->ownership = TRUE; #ifndef TPM_ENABLE_ACTIVATE tpm_permanent_flags->deactivated = TRUE; #else /* for servers, not TCG standard */ tpm_permanent_flags->deactivated = FALSE; #endif tpm_permanent_flags->readPubek = TRUE; tpm_permanent_flags->disableOwnerClear = FALSE; tpm_permanent_flags->allowMaintenance = TRUE; tpm_permanent_flags->physicalPresenceLifetimeLock = FALSE; tpm_permanent_flags->physicalPresenceHWEnable = FALSE; #ifndef TPM_PP_CMD_ENABLE /* TCG standard */ tpm_permanent_flags->physicalPresenceCMDEnable = FALSE; #else /* 'ship' TRUE */ tpm_permanent_flags->physicalPresenceCMDEnable = TRUE; #endif /* tpm_permanent_flags->CEKPUsed = ; This flag has no default value */ tpm_permanent_flags->TPMpost = FALSE; tpm_permanent_flags->TPMpostLock = FALSE; tpm_permanent_flags->FIPS = FALSE; /* if TRUE, could not test no-auth commands */ tpm_permanent_flags->tpmOperator = FALSE; tpm_permanent_flags->enableRevokeEK = TRUE; tpm_permanent_flags->nvLocked = FALSE; tpm_permanent_flags->readSRKPub = FALSE; tpm_permanent_flags->tpmEstablished = FALSE; tpm_permanent_flags->maintenanceDone = FALSE; #if (TPM_REVISION >= 103) /* added for rev 103 */ tpm_permanent_flags->disableFullDALogicInfo = FALSE; #endif } /* TPM_PermanentFlags_Load() deserializes the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes It is used when deserializing the structure from storage in NVRAM. */ TPM_RESULT TPM_PermanentFlags_Load(TPM_PERMANENT_FLAGS *tpm_permanent_flags, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; uint32_t tpm_bitmap; TPM_TAG permanentFlagsVersion; printf(" TPM_PermanentFlags_Load:\n"); /* load the TPM_PERMANENT_FLAGS version tag from the stream */ if (rc == 0) { rc = TPM_Load16(&permanentFlagsVersion, stream, stream_size); } /* load the TPM_PERMANENT_FLAGS from the stream */ if (rc == 0) { rc = TPM_Load32(&tpm_bitmap, stream, stream_size); } /* load the TPM_PERMANENT_FLAGS from the bitmap */ if (rc == 0) { rc = TPM_PermanentFlags_LoadBitmap(tpm_permanent_flags, permanentFlagsVersion, tpm_bitmap); } return rc; } /* TPM_PermanentFlags_Store() serializes the TPM_PERMANENT_FLAGS structure as a bitmap. It is used when serializing the structure for storage in NVRAM. */ TPM_RESULT TPM_PermanentFlags_Store(TPM_STORE_BUFFER *sbuffer, const TPM_PERMANENT_FLAGS *tpm_permanent_flags) { TPM_RESULT rc = 0; uint32_t tpm_bitmap; printf(" TPM_PermanentFlags_Store:\n"); /* store the TPM_PERMANENT_FLAGS structure in a bit map */ if (rc == 0) { rc = TPM_PermanentFlags_StoreBitmap(&tpm_bitmap, tpm_permanent_flags); } /* append a TPM_PERMANENT_FLAGS version tag */ #if (TPM_REVISION >= 103) if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_NVSTATE_PF103); } #else if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_NVSTATE_PF94); } #endif /* append the bitmap to the stream */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_bitmap); } return rc; } /* TPM_PermanentFlags_StoreBytes() serializes the TPM_PERMANENT_FLAGS structure as bytes */ TPM_RESULT TPM_PermanentFlags_StoreBytes(TPM_STORE_BUFFER *sbuffer, const TPM_PERMANENT_FLAGS *tpm_permanent_flags) { TPM_RESULT rc = 0; printf(" TPM_PermanentFlags_StoreBytes:\n"); /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_PERMANENT_FLAGS); } /* store disable */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->disable), sizeof(BYTE)); } /* store ownership */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->ownership), sizeof(BYTE)); } /* store deactivated */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->deactivated), sizeof(BYTE)); } /* store readPubek */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->readPubek), sizeof(BYTE)); } /* store disableOwnerClear */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->disableOwnerClear), sizeof(BYTE)); } /* store allowMaintenance */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->allowMaintenance), sizeof(BYTE)); } /* store physicalPresenceLifetimeLock */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->physicalPresenceLifetimeLock), sizeof(BYTE)); } /* store physicalPresenceHWEnable */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->physicalPresenceHWEnable), sizeof(BYTE)); } /* store physicalPresenceCMDEnable */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->physicalPresenceCMDEnable), sizeof(BYTE)); } /* store CEKPUsed */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->CEKPUsed), sizeof(BYTE)); } /* store TPMpost */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->TPMpost), sizeof(BYTE)); } /* store TPMpostLock */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->TPMpostLock), sizeof(BYTE)); } /* store FIPS */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->FIPS), sizeof(BYTE)); } /* store operator */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->tpmOperator), sizeof(BYTE)); } /* store enableRevokeEK */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->enableRevokeEK), sizeof(BYTE)); } /* store nvLocked */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->nvLocked), sizeof(BYTE)); } /* store readSRKPub */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->readSRKPub), sizeof(BYTE)); } /* store tpmEstablished */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->tpmEstablished), sizeof(BYTE)); } /* store maintenanceDone */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->maintenanceDone), sizeof(BYTE)); } #if (TPM_REVISION >= 103) /* added for rev 103 */ /* store disableFullDALogicInfo */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_flags->disableFullDALogicInfo), sizeof(BYTE)); } #endif return rc; } /* TPM_PermanentFlags_LoadBitmap() loads the TPM_PERMANENT_FLAGS structure from the bit map permanentFlagsVersion indicates the version being loaded from NVRAM */ TPM_RESULT TPM_PermanentFlags_LoadBitmap(TPM_PERMANENT_FLAGS *tpm_permanent_flags, TPM_TAG permanentFlagsVersion, uint32_t tpm_bitmap) { TPM_RESULT rc = 0; uint32_t pos = 0; /* position in bitmap */ if (rc == 0) { switch (permanentFlagsVersion) { case TPM_TAG_NVSTATE_PF94: break; case TPM_TAG_NVSTATE_PF103: /* if the TPM_REVISION supports the permanentFlagsVersion, break with no error. If it doesn't, omit the break and fall through to the unsupported case. */ #if (TPM_REVISION >= 103) break; #endif default: /* no forward compatibility */ printf("TPM_PermanentFlags_LoadBitmap: Error (fatal) unsupported version tag %04x\n", permanentFlagsVersion); rc = TPM_FAIL; break; } } printf(" TPM_PermanentFlags_LoadBitmap:\n"); /* load disable */ if (rc == 0) { rc = TPM_Bitmap_Load(&(tpm_permanent_flags->disable), tpm_bitmap, &pos); } /* load ownership */ if (rc == 0) { rc = TPM_Bitmap_Load(&(tpm_permanent_flags->ownership), tpm_bitmap, &pos); } /* load deactivated */ if (rc == 0) { rc = TPM_Bitmap_Load(&(tpm_permanent_flags->deactivated), tpm_bitmap, &pos); } /* load readPubek */ if (rc == 0) { rc = TPM_Bitmap_Load(&(tpm_permanent_flags->readPubek), tpm_bitmap, &pos); } /* load disableOwnerClear */ if (rc == 0) { rc = TPM_Bitmap_Load(&(tpm_permanent_flags->disableOwnerClear), tpm_bitmap, &pos); } /* load allowMaintenance */ if (rc == 0) { rc = TPM_Bitmap_Load(&(tpm_permanent_flags->allowMaintenance), tpm_bitmap, &pos); } /* load physicalPresenceLifetimeLock */ if (rc == 0) { rc = TPM_Bitmap_Load(&(tpm_permanent_flags->physicalPresenceLifetimeLock), tpm_bitmap, &pos); } /* load physicalPresenceHWEnable */ if (rc == 0) { rc = TPM_Bitmap_Load(&(tpm_permanent_flags->physicalPresenceHWEnable), tpm_bitmap, &pos); } /* load physicalPresenceCMDEnable */ if (rc == 0) { rc = TPM_Bitmap_Load(&(tpm_permanent_flags->physicalPresenceCMDEnable), tpm_bitmap, &pos); } /* load CEKPUsed */ if (rc == 0) { rc = TPM_Bitmap_Load(&(tpm_permanent_flags->CEKPUsed), tpm_bitmap, &pos); } /* load TPMpost */ if (rc == 0) { rc = TPM_Bitmap_Load(&(tpm_permanent_flags->TPMpost), tpm_bitmap, &pos); } /* load TPMpostLock */ if (rc == 0) { rc = TPM_Bitmap_Load(&(tpm_permanent_flags->TPMpostLock), tpm_bitmap, &pos); } /* load FIPS */ if (rc == 0) { rc = TPM_Bitmap_Load(&(tpm_permanent_flags->FIPS), tpm_bitmap, &pos); } /* load operator */ if (rc == 0) { rc = TPM_Bitmap_Load(&(tpm_permanent_flags->tpmOperator), tpm_bitmap, &pos); } /* load enableRevokeEK */ if (rc == 0) { rc = TPM_Bitmap_Load(&(tpm_permanent_flags->enableRevokeEK), tpm_bitmap, &pos); } /* load nvLocked */ if (rc == 0) { rc = TPM_Bitmap_Load(&(tpm_permanent_flags->nvLocked), tpm_bitmap, &pos); } /* load readSRKPub */ if (rc == 0) { rc = TPM_Bitmap_Load(&(tpm_permanent_flags->readSRKPub), tpm_bitmap, &pos); } /* load tpmEstablished */ if (rc == 0) { rc = TPM_Bitmap_Load(&(tpm_permanent_flags->tpmEstablished), tpm_bitmap, &pos); } /* load maintenanceDone */ if (rc == 0) { rc = TPM_Bitmap_Load(&(tpm_permanent_flags->maintenanceDone), tpm_bitmap, &pos); } #if (TPM_REVISION >= 103) /* added for rev 103 */ if (rc == 0) { switch (permanentFlagsVersion) { case TPM_TAG_NVSTATE_PF94: /* 94 to 103, set extra flags to default value */ tpm_permanent_flags->disableFullDALogicInfo = FALSE; break; case TPM_TAG_NVSTATE_PF103: /* 103 to 103, process normally */ /* load disableFullDALogicInfo */ rc = TPM_Bitmap_Load(&(tpm_permanent_flags->disableFullDALogicInfo), tpm_bitmap, &pos); break; } } #endif return rc; } /* TPM_PermanentFlags_StoreBitmap() stores the TPM_PERMANENT_FLAGS structure in a bit map It is used when serializing the structure for storage in NVRAM and as the return to TPM_GetCapability. */ TPM_RESULT TPM_PermanentFlags_StoreBitmap(uint32_t *tpm_bitmap, const TPM_PERMANENT_FLAGS *tpm_permanent_flags) { TPM_RESULT rc = 0; uint32_t pos = 0; /* position in bitmap */ printf(" TPM_PermanentFlags_StoreBitmap:\n"); *tpm_bitmap = 0; /* set unused bits to 0 */ /* store disable */ if (rc == 0) { rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->disable, &pos); } /* store ownership */ if (rc == 0) { rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->ownership, &pos); } /* store deactivated */ if (rc == 0) { rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->deactivated, &pos); } /* store readPubek */ if (rc == 0) { rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->readPubek, &pos); } /* store disableOwnerClear */ if (rc == 0) { rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->disableOwnerClear, &pos); } /* store allowMaintenance */ if (rc == 0) { rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->allowMaintenance, &pos); } /* store physicalPresenceLifetimeLock */ if (rc == 0) { rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->physicalPresenceLifetimeLock, &pos); } /* store physicalPresenceHWEnable */ if (rc == 0) { rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->physicalPresenceHWEnable, &pos); } /* store physicalPresenceCMDEnable */ if (rc == 0) { rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->physicalPresenceCMDEnable, &pos); } /* store CEKPUsed */ if (rc == 0) { rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->CEKPUsed, &pos); } /* store TPMpost */ if (rc == 0) { rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->TPMpost, &pos); } /* store TPMpostLock */ if (rc == 0) { rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->TPMpostLock, &pos); } /* store FIPS */ if (rc == 0) { rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->FIPS, &pos); } /* store operator */ if (rc == 0) { rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->tpmOperator, &pos); } /* store enableRevokeEK */ if (rc == 0) { rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->enableRevokeEK, &pos); } /* store nvLocked */ if (rc == 0) { rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->nvLocked, &pos); } /* store readSRKPub */ if (rc == 0) { rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->readSRKPub, &pos); } /* store tpmEstablished */ if (rc == 0) { rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->tpmEstablished, &pos); } /* store maintenanceDone */ if (rc == 0) { rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->maintenanceDone, &pos); } #if (TPM_REVISION >= 103) /* added for rev 103 */ /* store disableFullDALogicInfo */ if (rc == 0) { rc = TPM_Bitmap_Store(tpm_bitmap, tpm_permanent_flags->disableFullDALogicInfo, &pos); } #endif return rc; } /* TPM_PERMANENT_DATA */ /* TPM_PermanentData_Init() sets members to default values sets all pointers to NULL and sizes to 0 This function generates a new contextKey, delegateKey, daaBlobKey. */ TPM_RESULT TPM_PermanentData_Init(TPM_PERMANENT_DATA *tpm_permanent_data, TPM_BOOL instanceData) { TPM_RESULT rc = 0; printf(" TPM_PermanentData_Init:\n"); if (rc == 0) { tpm_permanent_data->revMajor = ((tpm_svn_revision >> 8) & 0xff); tpm_permanent_data->revMinor = ((tpm_svn_revision ) & 0xff); printf(" TPM_PermanentData_Init: revMajor %02x revMinor %02x\n", tpm_permanent_data->revMajor, tpm_permanent_data->revMinor); /* zero all secrets */ TPM_PermanentData_Zero(tpm_permanent_data, instanceData); #ifndef TPM_NOMAINTENANCE TPM_Pubkey_Init(&(tpm_permanent_data->manuMaintPub)); #endif TPM_Key_Init(&(tpm_permanent_data->endorsementKey)); TPM_Key_Init(&(tpm_permanent_data->srk)); tpm_permanent_data->contextKey = NULL; rc = TPM_SymmetricKeyData_New(&(tpm_permanent_data->contextKey)); } if (rc == 0) { tpm_permanent_data->delegateKey = NULL; rc = TPM_SymmetricKeyData_New(&(tpm_permanent_data->delegateKey)); } if (rc == 0) { TPM_CounterValue_Init(&(tpm_permanent_data->auditMonotonicCounter)); TPM_Counters_Init(tpm_permanent_data->monotonicCounter); TPM_PCRAttributes_Init(tpm_permanent_data->pcrAttrib); rc = TPM_OrdinalAuditStatus_Init(tpm_permanent_data); } if (rc == 0) { TPM_FamilyTable_Init(&(tpm_permanent_data->familyTable)); TPM_DelegateTable_Init(&(tpm_permanent_data->delegateTable)); tpm_permanent_data->lastFamilyID = 0; tpm_permanent_data->noOwnerNVWrite = 0; tpm_permanent_data->restrictDelegate = 0; /* tpmDAASeed done by TPM_PermanentData_Zero() */ /* daaProof done by TPM_PermanentData_Zero() */ rc = TPM_SymmetricKeyData_New(&(tpm_permanent_data->daaBlobKey)); } if (rc == 0) { tpm_permanent_data->ownerInstalled = FALSE; /* tscOrdinalAuditStatus initialized by TPM_OrdinalAuditStatus_Init() */ /* instanceOrdinalAuditStatus initialized by TPM_OrdinalAuditStatus_Init() */ tpm_permanent_data->allowLoadMaintPub = TRUE; if (instanceData) { } } return rc; } /* TPM_PermanentData_Load() deserializes the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes */ TPM_RESULT TPM_PermanentData_Load(TPM_PERMANENT_DATA *tpm_permanent_data, unsigned char **stream, uint32_t *stream_size, TPM_BOOL instanceData) { TPM_RESULT rc = 0; size_t i; TPM_BOOL tpm_bool; printf(" TPM_PermanentData_Load:\n"); /* check tag */ if (rc == 0) { rc = TPM_CheckTag(TPM_TAG_PERMANENT_DATA, stream, stream_size); } /* load revMajor */ /* load revMinor */ /* not stored, loaded from hard coded value */ if (rc == 0) { tpm_permanent_data->revMajor = (tpm_svn_revision >> 8) & 0xff; tpm_permanent_data->revMinor = tpm_svn_revision & 0xff; } /* load tpmProof */ if (rc == 0) { printf(" TPM_PermanentData_Load: Loading tpmProof\n"); rc = TPM_Secret_Load(tpm_permanent_data->tpmProof, stream, stream_size); } /* load EKReset */ if (rc == 0) { rc = TPM_Nonce_Load(tpm_permanent_data->EKReset, stream, stream_size); } /* load ownerAuth */ if (rc == 0) { printf(" TPM_PermanentData_Load: Loading ownerAuth \n"); rc = TPM_Secret_Load(tpm_permanent_data->ownerAuth, stream, stream_size); } /* load operatorAuth */ if (rc == 0) { rc = TPM_Secret_Load(tpm_permanent_data->operatorAuth, stream, stream_size); } /* load authDIR */ if (rc == 0) { rc = TPM_Digest_Load(tpm_permanent_data->authDIR, stream, stream_size); } /* load manuMaintPub present marker */ if (rc == 0) { rc = TPM_Load8(&tpm_bool, stream, stream_size); } #ifndef TPM_NOMAINTENANCE /* check that manuMaintPub is present */ if (rc == 0) { if (!tpm_bool) { printf(" TPM_PermanentData_Load: Error (fatal) missing manuMaintPub\n"); rc = TPM_FAIL; } } /* load manuMaintPub */ if (rc == 0) { printf(" TPM_PermanentData_Load: Load manuMaintPub\n"); rc = TPM_Pubkey_Load(&(tpm_permanent_data->manuMaintPub), stream, stream_size); } #else /* check that manuMaintPub is absent */ if (tpm_bool) { printf(" TPM_PermanentData_Load: Error (fatal) contains manuMaintPub\n"); rc = TPM_FAIL; } #endif /* load endorsementKey */ if (rc == 0) { printf(" TPM_PermanentData_Load: Load endorsement key\n"); rc = TPM_Key_LoadClear(&(tpm_permanent_data->endorsementKey), TRUE, stream, stream_size); } /* load srk */ if (rc == 0) { printf(" TPM_PermanentData_Load: Load SRK\n"); rc = TPM_Key_LoadClear(&(tpm_permanent_data->srk), FALSE, stream, stream_size); } /* load contextKey */ if (rc == 0) { printf(" TPM_PermanentData_Load: Load contextKey\n"); rc = TPM_SymmetricKeyData_Load(tpm_permanent_data->contextKey, stream, stream_size); } /* load delegateKey */ if (rc == 0) { printf(" TPM_PermanentData_Load: Load delegateKey\n"); rc = TPM_SymmetricKeyData_Load(tpm_permanent_data->delegateKey, stream, stream_size); } /* load auditMonotonicCounter */ if (rc == 0) { rc = TPM_CounterValue_Load(&(tpm_permanent_data->auditMonotonicCounter), stream, stream_size); } /* load monotonicCounter's */ if (rc == 0) { rc = TPM_Counters_Load(tpm_permanent_data->monotonicCounter, stream, stream_size); } /* load pcrAttrib's, since they are constants, no need to load from NV space */ if (rc == 0) { TPM_PCRAttributes_Init(tpm_permanent_data->pcrAttrib); } if (rc == 0) { printf(" TPM_PermanentData_Load: Load ordinalAuditStatus\n"); } /* load ordinalAuditStatus's */ for (i = 0 ; (rc == 0) && (i < (TPM_ORDINALS_MAX/CHAR_BIT)) ; i++) { rc = TPM_Load8(&(tpm_permanent_data->ordinalAuditStatus[i]), stream, stream_size); } /* load familyTable */ if (rc == 0) { rc = TPM_FamilyTable_Load(&(tpm_permanent_data->familyTable), stream, stream_size); } /* load delegateTable */ if (rc == 0) { rc = TPM_DelegateTable_Load(&(tpm_permanent_data->delegateTable), stream, stream_size); } /* load lastFamilyID */ if (rc == 0) { rc = TPM_Load32(&(tpm_permanent_data->lastFamilyID), stream, stream_size); } /* load noOwnerNVWrite */ if (rc == 0) { rc = TPM_Load32(&(tpm_permanent_data->noOwnerNVWrite), stream, stream_size); } /* load restrictDelegate */ if (rc == 0) { rc = TPM_Load32(&(tpm_permanent_data->restrictDelegate), stream, stream_size); } /* load tpmDAASeed */ if (rc == 0) { rc = TPM_Nonce_Load(tpm_permanent_data->tpmDAASeed, stream, stream_size); } /* load ownerInstalled */ if (rc == 0) { rc = TPM_LoadBool(&(tpm_permanent_data->ownerInstalled), stream, stream_size); } /* load tscOrdinalAuditStatus */ if (rc == 0) { rc = TPM_Load8(&(tpm_permanent_data->tscOrdinalAuditStatus), stream, stream_size); } /* load allowLoadMaintPub */ if (rc == 0) { rc = TPM_LoadBool(&(tpm_permanent_data->allowLoadMaintPub), stream, stream_size); } /* load daaProof */ if (rc == 0) { rc = TPM_Nonce_Load(tpm_permanent_data->daaProof, stream, stream_size); } /* load daaBlobKey */ if (rc == 0) { printf(" TPM_PermanentData_Load: Loading DAA Blob key\n"); rc = TPM_SymmetricKeyData_Load(tpm_permanent_data->daaBlobKey, stream, stream_size); } instanceData = instanceData; /* to quiet the compiler */ return rc; } /* TPM_PermanentData_Store() serializes the TPM_PERMANENT_DATA structure */ TPM_RESULT TPM_PermanentData_Store(TPM_STORE_BUFFER *sbuffer, TPM_PERMANENT_DATA *tpm_permanent_data, TPM_BOOL instanceData) { TPM_RESULT rc = 0; size_t i; printf(" TPM_PermanentData_Store:\n"); /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_PERMANENT_DATA); } /* store revMajor */ /* store revMinor */ /* not stored, loaded from hard coded value */ /* store tpmProof */ if (rc == 0) { rc = TPM_Secret_Store(sbuffer, tpm_permanent_data->tpmProof); } /* store EKReset */ if (rc == 0) { rc = TPM_Nonce_Store(sbuffer, tpm_permanent_data->EKReset); } /* store ownerAuth */ if (rc == 0) { rc = TPM_Secret_Store(sbuffer, tpm_permanent_data->ownerAuth); } /* store operatorAuth */ if (rc == 0) { rc = TPM_Secret_Store(sbuffer, tpm_permanent_data->operatorAuth); } /* store authDIR */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_permanent_data->authDIR); } #ifndef TPM_NOMAINTENANCE /* mark that manuMaintPub is present */ if (rc == 0) { rc = TPM_Sbuffer_Append8(sbuffer, TRUE); } /* store manuMaintPub */ if (rc == 0) { rc = TPM_Pubkey_Store(sbuffer, &(tpm_permanent_data->manuMaintPub)); } #else /* mark that manuMaintPub is absent */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, FALSE); } #endif /* store endorsementKey */ if (rc == 0) { rc = TPM_Key_StoreClear(sbuffer, TRUE, &(tpm_permanent_data->endorsementKey)); } /* store srk */ if (rc == 0) { rc = TPM_Key_StoreClear(sbuffer, FALSE, &(tpm_permanent_data->srk)); } /* store contextKey */ if (rc == 0) { rc = TPM_SymmetricKeyData_Store(sbuffer, tpm_permanent_data->contextKey); } /* store delegateKey */ if (rc == 0) { rc = TPM_SymmetricKeyData_Store(sbuffer, tpm_permanent_data->delegateKey); } /* store auditMonotonicCounter */ if (rc == 0) { rc = TPM_CounterValue_Store(sbuffer, &(tpm_permanent_data->auditMonotonicCounter)); } /* store monotonicCounter */ if (rc == 0) { rc = TPM_Counters_Store(sbuffer, tpm_permanent_data->monotonicCounter); } /* store pcrAttrib, since they are constants, no need to store to NV space */ /* store ordinalAuditStatus */ for (i = 0 ; (rc == 0) && (i < (TPM_ORDINALS_MAX/CHAR_BIT)) ; i++) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_data->ordinalAuditStatus[i]), sizeof(BYTE)); } /* store familyTable */ if (rc == 0) { rc = TPM_FamilyTable_Store(sbuffer, &(tpm_permanent_data->familyTable), FALSE); /* don't store the tag, to save NV space */ } /* store delegateTable */ if (rc == 0) { rc = TPM_DelegateTable_Store(sbuffer, &(tpm_permanent_data->delegateTable)); } /* store lastFamilyID */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_permanent_data->lastFamilyID); } /* store noOwnerNVWrite */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_permanent_data->noOwnerNVWrite); } /* store restrictDelegate */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_permanent_data->restrictDelegate); } /* store tpmDAASeed */ if (rc == 0) { rc = TPM_Nonce_Store(sbuffer, tpm_permanent_data->tpmDAASeed); } /* store ownerInstalled */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_data->ownerInstalled), sizeof(BYTE)); } /* store tscOrdinalAuditStatus */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_data->tscOrdinalAuditStatus), sizeof(BYTE)); } /* store allowLoadMaintPub */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_permanent_data->allowLoadMaintPub), sizeof(BYTE)); } /* store daaProof */ if (rc == 0) { rc = TPM_Nonce_Store(sbuffer, tpm_permanent_data->daaProof); } /* store daaBlobKey */ if (rc == 0) { rc = TPM_SymmetricKeyData_Store(sbuffer, tpm_permanent_data->daaBlobKey); } instanceData = instanceData; /* to quiet the compiler */ return rc; } /* TPM_PermanentData_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_PermanentData_Zero to zero secrets that are not Delete'd The object itself is not freed */ void TPM_PermanentData_Delete(TPM_PERMANENT_DATA *tpm_permanent_data, TPM_BOOL instanceData) { printf(" TPM_PermanentData_Delete:\n"); if (tpm_permanent_data != NULL) { #ifndef TPM_NOMAINTENANCE TPM_Pubkey_Delete(&(tpm_permanent_data->manuMaintPub)); #endif TPM_Key_Delete(&(tpm_permanent_data->endorsementKey)); TPM_Key_Delete(&(tpm_permanent_data->srk)); TPM_SymmetricKeyData_Free(&(tpm_permanent_data->contextKey)); TPM_SymmetricKeyData_Free(&(tpm_permanent_data->delegateKey)); TPM_FamilyTable_Delete(&(tpm_permanent_data->familyTable)); TPM_DelegateTable_Delete(&(tpm_permanent_data->delegateTable)); TPM_SymmetricKeyData_Free(&(tpm_permanent_data->daaBlobKey)); /* zero all secrets */ TPM_PermanentData_Zero(tpm_permanent_data, instanceData); } return; } /* TPM_PermanentData_Zero() zeros all secrets not already zeroed and freed by TPM_PermanentData_Delete() It is called by TPM_PermanentData_Delete() and TPM_PermanentData_Init(). It does a subset of TPM_PermanentData_Init() that will never fail. */ void TPM_PermanentData_Zero(TPM_PERMANENT_DATA *tpm_permanent_data, TPM_BOOL instanceData) { printf(" TPM_PermanentData_Zero:\n"); instanceData = instanceData; if (tpm_permanent_data != NULL) { TPM_Secret_Init(tpm_permanent_data->tpmProof); TPM_Nonce_Init(tpm_permanent_data->EKReset); TPM_Secret_Init(tpm_permanent_data->ownerAuth); TPM_Secret_Init(tpm_permanent_data->operatorAuth); TPM_Digest_Init(tpm_permanent_data->authDIR); /* endorsementKey handled by TPM_Key_Delete() */ /* srk handled by TPM_Key_Delete() */ /* contextKey handled by TPM_SymmetricKeyData_Free() */ /* delegateKey handled by TPM_SymmetricKeyData_Free() */ TPM_Nonce_Init(tpm_permanent_data->tpmDAASeed); TPM_Nonce_Init(tpm_permanent_data->daaProof); /* daaBlobKey handled by TPM_SymmetricKeyData_Free() */ } return; } /* TPM_PermanentData_InitDaa() generates new values for the 3 DAA elements: tpmDAASeed, daaProof, and daaBlobKey. This is common code, use when creating the EK, revoke trust, and the set capability used by the owner to invalidate DAA blobs. */ TPM_RESULT TPM_PermanentData_InitDaa(TPM_PERMANENT_DATA *tpm_permanent_data) { TPM_RESULT rc = 0; printf(" TPM_PermanentData_InitDaa:\n"); /* generate tpmDAASeed */ if (rc == 0) { rc = TPM_Nonce_Generate(tpm_permanent_data->tpmDAASeed); } /* generate daaProof*/ if (rc == 0) { rc = TPM_Nonce_Generate(tpm_permanent_data->daaProof); } /* generate daaBlobKey */ if (rc == 0) { rc = TPM_SymmetricKeyData_GenerateKey(tpm_permanent_data->daaBlobKey); } return rc; } /* PermanentAll is TPM_PERMANENT_DATA, TPM_PERMANENT_FLAGS, owner evict keys, and NV defined space. */ /* TPM_PermanentAll_Load() deserializes all TPM NV data from a stream created by TPM_PermanentAll_Store(). The two functions must be kept in sync. Data includes TPM_PERMANENT_DATA, TPM_PERMANENT_FLAGS, Owner Evict keys, and NV defined space. */ TPM_RESULT TPM_PermanentAll_Load(tpm_state_t *tpm_state, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; unsigned char *stream_start = *stream; /* copy for integrity check */ uint32_t stream_size_start = *stream_size; printf(" TPM_PermanentAll_Load:\n"); /* check format tag */ /* In the future, if multiple formats are supported, this check will be replaced by a 'switch' on the tag */ if (rc == 0) { rc = TPM_CheckTag(TPM_TAG_NVSTATE_V1, stream, stream_size); } /* TPM_PERMANENT_DATA deserialize from stream */ if (rc == 0) { rc = TPM_PermanentData_Load(&(tpm_state->tpm_permanent_data), stream, stream_size, TRUE); } /* TPM_PERMANENT_FLAGS deserialize from stream */ if (rc == 0) { rc = TPM_PermanentFlags_Load(&(tpm_state->tpm_permanent_flags), stream, stream_size); } /* owner evict keys deserialize from stream */ if (rc == 0) { rc = TPM_KeyHandleEntries_OwnerEvictLoad(tpm_state->tpm_key_handle_entries, stream, stream_size); } /* NV defined space deserialize from stream */ if (rc == 0) { rc = TPM_NVIndexEntries_Load(&(tpm_state->tpm_nv_index_entries), stream, stream_size); } /* sanity check the stream size */ if (rc == 0) { if (*stream_size != TPM_DIGEST_SIZE) { printf("TPM_PermanentAll_Load: Error (fatal) stream size %u not %u\n", *stream_size, TPM_DIGEST_SIZE); rc = TPM_FAIL; } } /* check the integrity digest */ if (rc == 0) { printf(" TPM_PermanentAll_Load: Checking integrity digest\n"); rc = TPM_SHA1_Check(*stream, /* currently points to integrity digest */ stream_size_start - TPM_DIGEST_SIZE, stream_start, 0, NULL); } /* remove the integrity digest from the stream */ if (rc == 0) { *stream_size -= TPM_DIGEST_SIZE; } return rc; } /* TPM_PermanentAll_Store() serializes all TPM NV data into a stream that can be restored through TPM_PermanentAll_Load(). The two functions must be kept in sync. Data includes TPM_PERMANENT_DATA, TPM_PERMANENT_FLAGS, Owner Evict keys, and NV defined space. The TPM_STORE_BUFFER, buffer and length are returned for convenience. This has two uses: - It is called before the actual NV store to serialize the data - It is called by TPM_NV_DefineSpace to determine if there is enough NV space for the new index */ TPM_RESULT TPM_PermanentAll_Store(TPM_STORE_BUFFER *sbuffer, /* freed by caller */ const unsigned char **buffer, uint32_t *length, tpm_state_t *tpm_state) { TPM_RESULT rc = 0; TPM_DIGEST tpm_digest; printf(" TPM_PermanentAll_Store:\n"); /* overall format tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_NVSTATE_V1); } /* serialize TPM_PERMANENT_DATA */ if (rc == 0) { rc = TPM_PermanentData_Store(sbuffer, &(tpm_state->tpm_permanent_data), TRUE); } /* serialize TPM_PERMANENT_FLAGS */ if (rc == 0) { rc = TPM_PermanentFlags_Store(sbuffer, &(tpm_state->tpm_permanent_flags)); } /* serialize owner evict keys */ if (rc == 0) { rc = TPM_KeyHandleEntries_OwnerEvictStore(sbuffer, tpm_state->tpm_key_handle_entries); } /* serialize NV defined space */ if (rc == 0) { rc = TPM_NVIndexEntries_Store(sbuffer, &(tpm_state->tpm_nv_index_entries)); } if (rc == 0) { /* get the current serialized buffer and its length */ TPM_Sbuffer_Get(sbuffer, buffer, length); /* generate the integrity digest */ rc = TPM_SHA1(tpm_digest, *length, *buffer, 0, NULL); } /* append the integrity digest to the stream */ if (rc == 0) { printf(" TPM_PermanentAll_Store: Appending integrity digest\n"); rc = TPM_Sbuffer_Append(sbuffer, tpm_digest, TPM_DIGEST_SIZE); } /* get the final serialized buffer and its length */ if (rc == 0) { TPM_Sbuffer_Get(sbuffer, buffer, length); } return rc; } /* TPM_PermanentAll_NVLoad() Deserialize the TPM_PERMANENT_DATA, TPM_PERMANENT_FLAGS, owner evict keys, and NV defined space from a stream read from the NV file TPM_PERMANENT_ALL_NAME. Returns: 0 success TPM_RETRY if file does not exist (first time) TPM_FAIL on failure to load (fatal), since they should never occur */ TPM_RESULT TPM_PermanentAll_NVLoad(tpm_state_t *tpm_state) { TPM_RESULT rc = 0; unsigned char *stream = NULL; unsigned char *stream_start = NULL; uint32_t stream_size; printf(" TPM_PermanentAll_NVLoad:\n"); if (rc == 0) { /* try loading from NVRAM */ /* Returns TPM_RETRY on non-existent file */ rc = TPM_NVRAM_LoadData(&stream, /* freed @1 */ &stream_size, tpm_state->tpm_number, TPM_PERMANENT_ALL_NAME); } /* deserialize from stream */ if (rc == 0) { stream_start = stream; /* save starting point for free() */ rc = TPM_PermanentAll_Load(tpm_state, &stream, &stream_size); if (rc != 0) { printf("TPM_PermanentAll_NVLoad: Error (fatal) loading deserializing NV state\n"); rc = TPM_FAIL; } } free(stream_start); /* @1 */ return rc; } /* TPM_PermanentAll_NVStore() serializes all NV data and stores it in the NV file TPM_PERMANENT_ALL_NAME If the writeAllNV flag is FALSE, the function is a no-op, and returns the input 'rcIn'. If writeAllNV is TRUE and rcIn is not TPM_SUCCESS, this indicates that the ordinal modified the in-memory TPM_PERMANENT_DATA and/or TPM_PERMANENT_FLAGS structures (perhaps only partially) and then detected an error. Since the command is failing, roll back the structure by reading the NV file. If the read then fails, this is a fatal error. Similarly, if writeAllNV is TRUE and the actual NV write fails, this is a fatal error. */ TPM_RESULT TPM_PermanentAll_NVStore(tpm_state_t *tpm_state, TPM_BOOL writeAllNV, TPM_RESULT rcIn) { TPM_RESULT rc = 0; TPM_STORE_BUFFER sbuffer; /* safe buffer for storing binary data */ const unsigned char *buffer; uint32_t length; TPM_NV_DATA_ST *tpm_nv_data_st = NULL; /* array of saved NV index volatile flags */ printf(" TPM_PermanentAll_NVStore: write flag %u\n", writeAllNV); TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ if (writeAllNV) { if (rcIn == TPM_SUCCESS) { /* serialize state to be written to NV */ if (rc == 0) { rc = TPM_PermanentAll_Store(&sbuffer, &buffer, &length, tpm_state); } /* validate the length of the stream against the maximum provided NV space */ if (rc == 0) { printf(" TPM_PermanentAll_NVStore: Require %u bytes\n", length); if (length > TPM_MAX_NV_SPACE) { printf("TPM_PermanentAll_NVStore: Error, No space, need %u max %u\n", length, TPM_MAX_NV_SPACE); rc = TPM_NOSPACE; } } /* store the buffer in NVRAM */ if (rc == 0) { rc = TPM_NVRAM_StoreData(buffer, length, tpm_state->tpm_number, TPM_PERMANENT_ALL_NAME); } if (rc != 0) { printf("TPM_PermanentAll_NVStore: Error (fatal), " "NV structure in-memory caches are in invalid state\n"); rc = TPM_FAIL; } } else { /* An in-memory structure was altered, but the ordinal had a subsequent error. Since the structure is in an invalid state, roll back to the previous value by reading the NV file. */ printf(" TPM_PermanentAll_NVStore: Ordinal error, " "rolling back NV structure cache\n"); /* Save a copy of the NV defined space volatile state. It is not stored in NV, so it will be destroyed during the rollback. */ /* get a copy of the NV volatile flags, to be used during a rollback */ if (rc == 0) { rc = TPM_NVIndexEntries_GetVolatile(&tpm_nv_data_st, /* freed @2 */ &(tpm_state->tpm_nv_index_entries)); } /* Returns TPM_RETRY on non-existent file */ if (rc == 0) { printf(" TPM_PermanentAllNVStore: Deleting TPM_PERMANENT_DATA structure\n"); TPM_PermanentData_Delete(&(tpm_state->tpm_permanent_data), TRUE); printf(" TPM_PermanentAllNVStore: Deleting owner evict keys\n"); TPM_KeyHandleEntries_OwnerEvictDelete(tpm_state->tpm_key_handle_entries); printf(" TPM_PermanentAllNVStore: Deleting NV defined space \n"); TPM_NVIndexEntries_Delete(&(tpm_state->tpm_nv_index_entries)); printf(" TPM_PermanentAllNVStore: " "Rereading TPM_PERMANENT_DATA, TPM_PERMANENT_FLAGS, owner evict keys\n"); /* re-allocate TPM_PERMANENT_DATA data structures */ rc = TPM_PermanentData_Init(&(tpm_state->tpm_permanent_data), TRUE); } if (rc == 0) { rc = TPM_PermanentAll_NVLoad(tpm_state); } if (rc == 0) { rc = TPM_NVIndexEntries_SetVolatile(tpm_nv_data_st, &(tpm_state->tpm_nv_index_entries)); } /* after a successful rollback, return the ordinal's original error code */ if (rc == 0) { rc = rcIn; } /* a failure during rollback is fatal */ else { printf("TPM_PermanentAll_NVStore: Error (fatal), " "Permanent Data, Flags, or owner evict keys structure is invalid\n"); rc = TPM_FAIL; } } } /* no write required, no-op */ else { rc = rcIn; } TPM_Sbuffer_Delete(&sbuffer); /* @1 */ free(tpm_nv_data_st); /* @2 */ return rc; } /* TPM_PermanentAll_NVDelete() deletes ann NV data in the NV file TPM_PERMANENT_ALL_NAME. If mustExist is TRUE, returns an error if the file does not exist. It does not delete the in-memory copy. */ TPM_RESULT TPM_PermanentAll_NVDelete(uint32_t tpm_number, TPM_BOOL mustExist) { TPM_RESULT rc = 0; printf(" TPM_PermanentAll_NVDelete:\n"); /* remove the NVRAM file */ if (rc == 0) { rc = TPM_NVRAM_DeleteName(tpm_number, TPM_PERMANENT_ALL_NAME, mustExist); } return rc; } /* TPM_PermanentAll_IsSpace() determines if there is enough NV space for the serialized NV state. It does this by serializing the entire state and comparing the length to the configured maximum. */ TPM_RESULT TPM_PermanentAll_IsSpace(tpm_state_t *tpm_state) { TPM_RESULT rc = 0; TPM_STORE_BUFFER sbuffer; /* safe buffer for storing binary data */ const unsigned char *buffer; uint32_t length; printf("TPM_PermanentAll_IsSpace :\n"); TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ if (rc == 0) { rc = TPM_PermanentAll_Store(&sbuffer, &buffer, &length, tpm_state); } if (rc == 0) { printf(" TPM_PermanentAll_IsSpace: Require %u bytes\n", length); if (length > TPM_MAX_NV_SPACE) { printf("TPM_PermanentAll_IsSpace: No space, need %u max %u\n", length, TPM_MAX_NV_SPACE); rc = TPM_NOSPACE; } } TPM_Sbuffer_Delete(&sbuffer); /* @1 */ return rc; } /* TPM_PermanentAll_GetSpace() returns the NV free space. It does this by serializing the entire state and comparing the length to the configured maximum. */ TPM_RESULT TPM_PermanentAll_GetSpace(uint32_t *bytes_free, tpm_state_t *tpm_state) { TPM_RESULT rc = 0; TPM_STORE_BUFFER sbuffer; /* safe buffer for storing binary data */ const unsigned char *buffer; uint32_t length; printf(" TPM_NVRAM_IsSpace:\n"); TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ if (rc == 0) { rc = TPM_PermanentAll_Store(&sbuffer, &buffer, &length, tpm_state); } if (rc == 0) { printf(" TPM_PermanentAll_GetSpace: Used %u max %u bytes\n", length, TPM_MAX_NV_SPACE); if (length > TPM_MAX_NV_SPACE) { /* This should never occur */ printf("TPM_PermanentAll_GetSpace: Error (fatal) Used more than maximum\n"); rc = TPM_FAIL; } } if (rc == 0) { *bytes_free = TPM_MAX_NV_SPACE - length; printf(" TPM_PermanentAll_GetSpace: Free space %u\n", *bytes_free); } TPM_Sbuffer_Delete(&sbuffer); /* @1 */ return rc; } libtpms-0.9.3/src/tpm12/tpm_permanent.h000066400000000000000000000116621421143571500177620ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Permanent Flag and Data Handler */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_permanent.h 4623 2011-09-28 15:15:09Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_PERMANENT_H #define TPM_PERMANENT_H #include "tpm_global.h" #include "tpm_structures.h" /* TPM_PERMANENT_FLAGS */ void TPM_PermanentFlags_Init(TPM_PERMANENT_FLAGS *tpm_permanent_flags); TPM_RESULT TPM_PermanentFlags_Load(TPM_PERMANENT_FLAGS *tpm_permanent_flags, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_PermanentFlags_Store(TPM_STORE_BUFFER *sbuffer, const TPM_PERMANENT_FLAGS *tpm_permanent_flags); TPM_RESULT TPM_PermanentFlags_LoadBitmap(TPM_PERMANENT_FLAGS *tpm_permanent_flags, TPM_TAG permanentFlagsVersion, uint32_t tpm_bitmap); TPM_RESULT TPM_PermanentFlags_StoreBitmap(uint32_t *tpm_bitmap, const TPM_PERMANENT_FLAGS *tpm_permanent_flags); TPM_RESULT TPM_PermanentFlags_StoreBytes(TPM_STORE_BUFFER *sbuffer, const TPM_PERMANENT_FLAGS *tpm_permanent_flags); /* TPM_PERMANENT_DATA */ TPM_RESULT TPM_PermanentData_Init(TPM_PERMANENT_DATA *tpm_permanent_data, TPM_BOOL instanceData); TPM_RESULT TPM_PermanentData_Load(TPM_PERMANENT_DATA *tpm_permanent_data, unsigned char **stream, uint32_t *stream_size, TPM_BOOL instanceData); TPM_RESULT TPM_PermanentData_Store(TPM_STORE_BUFFER *sbuffer, TPM_PERMANENT_DATA *tpm_permanent_data, TPM_BOOL instanceData); void TPM_PermanentData_Delete(TPM_PERMANENT_DATA *tpm_permanent_data, TPM_BOOL instanceData); void TPM_PermanentData_Zero(TPM_PERMANENT_DATA *tpm_permanent_data, TPM_BOOL instanceData); TPM_RESULT TPM_PermanentData_InitDaa(TPM_PERMANENT_DATA *tpm_permanent_data); /* PermanentAll is TPM_PERMANENT_DATA plus TPM_PERMANENT_FLAGS */ TPM_RESULT TPM_PermanentAll_Load(tpm_state_t *tpm_state, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_PermanentAll_Store(TPM_STORE_BUFFER *sbuffer, const unsigned char **buffer, uint32_t *length, tpm_state_t *tpm_state); TPM_RESULT TPM_PermanentAll_NVLoad(tpm_state_t *tpm_state); TPM_RESULT TPM_PermanentAll_NVStore(tpm_state_t *tpm_state, TPM_BOOL writeAllNV, TPM_RESULT rcIn); TPM_RESULT TPM_PermanentAll_NVDelete(uint32_t tpm_number, TPM_BOOL mustExist); TPM_RESULT TPM_PermanentAll_IsSpace(tpm_state_t *tpm_state); TPM_RESULT TPM_PermanentAll_GetSpace(uint32_t *bytes_free, tpm_state_t *tpm_state); #endif libtpms-0.9.3/src/tpm12/tpm_platform.c000066400000000000000000000145331421143571500176100ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM Platform I/O */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_platform.c 4621 2011-09-09 20:19:42Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include #include #include "tpm_debug.h" #include "tpm_pcr.h" #include "tpm_platform.h" #ifdef TPM_LIBTPMS_CALLBACKS #include "tpm_library_intern.h" #endif #ifndef TPM_IO_LOCALITY /* TPM_IO_GetLocality() is platform specific code to set the localityModifier before an ordinal is processed. Place holder, to be modified for the platform. */ TPM_RESULT TPM_IO_GetLocality(TPM_MODIFIER_INDICATOR *localityModifier, uint32_t tpm_number) { TPM_RESULT rc = 0; #ifdef TPM_LIBTPMS_CALLBACKS struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks(); /* call user-provided function if available, otherwise execute default behavior */ if (cbs->tpm_io_getlocality) { rc = cbs->tpm_io_getlocality(localityModifier, tpm_number); return rc; } #else tpm_number = tpm_number; /* to silence the compiler */ #endif if (rc == 0) { *localityModifier = 0; printf(" TPM_IO_GetLocality: localityModifier %u\n", *localityModifier); rc = TPM_LocalityModifier_CheckLegal(*localityModifier); } return rc; } #endif /* TPM_IO_LOCALITY */ #ifndef TPM_IO_PHYSICAL_PRESENCE /* TPM_IO_GetPhysicalPresence() is platform specific code to get the hardware physicalPresence state. Place holder, to be modified for the platform. */ TPM_RESULT TPM_IO_GetPhysicalPresence(TPM_BOOL *physicalPresence, uint32_t tpm_number) { TPM_RESULT rc = 0; #ifdef TPM_LIBTPMS_CALLBACKS struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks(); /* call user-provided function if available, otherwise execute default behavior */ if (cbs->tpm_io_getphysicalpresence) { rc = cbs->tpm_io_getphysicalpresence(physicalPresence, tpm_number); return rc; } #else tpm_number = tpm_number; /* to silence the compiler */ #endif *physicalPresence = FALSE; return rc; } #endif /* TPM_IO_PHYSICAL_PRESENCE */ #ifndef TPM_IO_GPIO /* TPM_IO_GPIO_Write() should write 'dataSize' bytes of 'data' to 'nvIndex' at the GPIO port. Place holder, to be modified for the platform. */ TPM_RESULT TPM_IO_GPIO_Write(TPM_NV_INDEX nvIndex, uint32_t dataSize, BYTE *data, uint32_t tpm_number) { TPM_RESULT rc = 0; tpm_number = tpm_number; /* to silence the compiler */ #if defined TPM_PCCLIENT /* These values are from the PC Client specification */ printf(" TPM_IO_GPIO_Write: nvIndex %08x\n", nvIndex); TPM_PrintAll(" TPM_IO_GPIO_Write: Stub", data, dataSize); /* #elif Add other platform specific values here */ #else /* This is the default case for the main specification */ nvIndex = nvIndex; /* unused parameter, to quiet the compiler */ dataSize = dataSize; data = data; printf("TPM_IO_GPIO_Write: Error (fatal), platform does not support GPIO\n"); rc = TPM_FAIL; /* Should never get here. The invalid address be detected earlier */ #endif return rc; } /* TPM_IO_GPIO_Read() Place holder, to be modified for the platform. */ TPM_RESULT TPM_IO_GPIO_Read(TPM_NV_INDEX nvIndex, uint32_t dataSize, BYTE *data, uint32_t tpm_number) { TPM_RESULT rc = 0; tpm_number = tpm_number; /* to silence the compiler */ #if defined TPM_PCCLIENT /* These values are from the PC Client specification */ printf(" TPM_IO_GPIO_Read: nvIndex %08x\n", nvIndex); memset(data, 0, dataSize); /* #elif Add other platform specific values here */ #else /* This is the default case for the main specification */ nvIndex = nvIndex;; /* unused parameter, to quiet the compiler */ dataSize = dataSize;; data = data; printf("TPM_IO_GPIO_Read: Error (fatal), platform does not support GPIO\n"); rc = TPM_FAIL; /* Should never get here. The invalid address be detected earlier */ #endif return rc; } #endif /* TPM_IO_GPIO */ libtpms-0.9.3/src/tpm12/tpm_platform.h000066400000000000000000000061761421143571500176210ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM Platform I/O */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_platform.h 4621 2011-09-09 20:19:42Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ /* Interface independent platform I/O Functions */ #ifndef TPM_PLATFORM_H #define TPM_PLATFORM_H #include "tpm_types.h" /* Every platform will need this function, as TPM_MainInit() calls it. */ TPM_RESULT TPM_IO_Init(void); TPM_RESULT TPM_IO_GetLocality(TPM_MODIFIER_INDICATOR *localityModifier, uint32_t tpm_number); TPM_RESULT TPM_IO_GetPhysicalPresence(TPM_BOOL *physicalPresence, uint32_t tpm_number); TPM_RESULT TPM_IO_GPIO_Write(TPM_NV_INDEX nvIndex, uint32_t dataSize, BYTE *data, uint32_t tpm_number); TPM_RESULT TPM_IO_GPIO_Read(TPM_NV_INDEX nvIndex, uint32_t dataSize, BYTE *data, uint32_t tpm_number); #endif libtpms-0.9.3/src/tpm12/tpm_process.c000066400000000000000000005521641421143571500174510ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM Command Processor */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_process.c 4621 2011-09-09 20:19:42Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include #include #include #ifdef TPM_POSIX #include #include #endif #include "tpm_admin.h" #include "tpm_audit.h" #include "tpm_auth.h" #include "tpm_constants.h" #include "tpm_commands.h" #include "tpm_counter.h" #include "tpm_cryptoh.h" #include "tpm_crypto.h" #include "tpm_daa.h" #include "tpm_debug.h" #include "tpm_delegate.h" #include "tpm_error.h" #include "tpm_identity.h" #include "tpm_init.h" #include "tpm_io.h" #include "tpm_key.h" #include "tpm_maint.h" #include "tpm_memory.h" #include "tpm_migration.h" #include "tpm_nonce.h" #include "tpm_nvram.h" #include "tpm_owner.h" #include "tpm_pcr.h" #include "tpm_permanent.h" #include "tpm_platform.h" #include "tpm_session.h" #include "tpm_sizedbuffer.h" #include "tpm_startup.h" #include "tpm_storage.h" #include "tpm_ticks.h" #include "tpm_transport.h" #include "tpm_ver.h" #include "tpm_process.h" /* local prototypes */ /* get capabilities */ static TPM_RESULT TPM_GetCapability_CapOrd(TPM_STORE_BUFFER *capabilityResponse, uint32_t ordinal); static TPM_RESULT TPM_GetCapability_CapAlg(TPM_STORE_BUFFER *capabilityResponse, uint32_t algorithmID); static TPM_RESULT TPM_GetCapability_CapPid(TPM_STORE_BUFFER *capabilityResponse, uint16_t protocolID); static TPM_RESULT TPM_GetCapability_CapFlag(TPM_STORE_BUFFER *capabilityResponse, tpm_state_t *tpm_state, uint32_t capFlag); static TPM_RESULT TPM_GetCapability_CapProperty(TPM_STORE_BUFFER *capabilityResponse, tpm_state_t *tpm_state, uint32_t capProperty); static TPM_RESULT TPM_GetCapability_CapVersion(TPM_STORE_BUFFER *capabilityResponse); static TPM_RESULT TPM_GetCapability_CapCheckLoaded(TPM_STORE_BUFFER *capabilityResponse, const TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry, TPM_SIZED_BUFFER *subCap); static TPM_RESULT TPM_GetCapability_CapSymMode(TPM_STORE_BUFFER *capabilityResponse, TPM_SYM_MODE symMode); static TPM_RESULT TPM_GetCapability_CapKeyStatus(TPM_STORE_BUFFER *capabilityResponse, TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries, uint32_t tpm_key_handle); static TPM_RESULT TPM_GetCapability_CapMfr(TPM_STORE_BUFFER *capabilityResponse, tpm_state_t *tpm_state, TPM_SIZED_BUFFER *subCap); static TPM_RESULT TPM_GetCapability_CapNVIndex(TPM_STORE_BUFFER *capabilityResponse, tpm_state_t *tpm_state, uint32_t nvIndex); static TPM_RESULT TPM_GetCapability_CapTransAlg(TPM_STORE_BUFFER *capabilityResponse, TPM_ALGORITHM_ID algorithmID); static TPM_RESULT TPM_GetCapability_CapHandle(TPM_STORE_BUFFER *capabilityResponse, tpm_state_t *tpm_state, TPM_RESOURCE_TYPE resourceType); static TPM_RESULT TPM_GetCapability_CapTransEs(TPM_STORE_BUFFER *capabilityResponse, TPM_ENC_SCHEME encScheme); static TPM_RESULT TPM_GetCapability_CapAuthEncrypt(TPM_STORE_BUFFER *capabilityResponse, uint32_t algorithmID); static TPM_RESULT TPM_GetCapability_CapSelectSize(TPM_STORE_BUFFER *capabilityResponse, TPM_SIZED_BUFFER *subCap); #if (TPM_REVISION >= 103) /* added for rev 103 */ static TPM_RESULT TPM_GetCapability_CapDaLogic(TPM_STORE_BUFFER *capabilityResponse, TPM_SIZED_BUFFER *subCap, tpm_state_t *tpm_state); #endif static TPM_RESULT TPM_GetCapability_CapVersionVal(TPM_STORE_BUFFER *capabilityResponse, TPM_PERMANENT_DATA *tpm_permanent_data); static TPM_RESULT TPM_GetCapability_CapPropTisTimeout(TPM_STORE_BUFFER *capabilityResponse); static TPM_RESULT TPM_GetCapability_CapPropDuration(TPM_STORE_BUFFER *capabilityResponse); /* set capabilities */ static TPM_RESULT TPM_SetCapability_CapPermFlags(tpm_state_t *tpm_state, TPM_BOOL ownerAuthorized, TPM_BOOL presenceAuthorized, uint32_t subCap32, TPM_BOOL valueBool); static TPM_RESULT TPM_SetCapability_CapPermData(tpm_state_t *tpm_state, TPM_BOOL ownerAuthorized, TPM_BOOL presenceAuthorized, uint32_t subCap32, uint32_t valueUint32); static TPM_RESULT TPM_SetCapability_CapStclearFlags(tpm_state_t *tpm_state, TPM_BOOL ownerAuthorized, TPM_BOOL presenceAuthorized, uint32_t subCap32, TPM_BOOL valueBool); static TPM_RESULT TPM_SetCapability_CapStclearData(tpm_state_t *tpm_state, TPM_BOOL ownerAuthorized, TPM_BOOL presenceAuthorized, uint32_t subCap32, uint32_t valueUint32); static TPM_RESULT TPM_SetCapability_CapStanyFlags(tpm_state_t *tpm_state, TPM_BOOL ownerAuthorized, TPM_BOOL presenceAuthorized, uint32_t subCap32, TPM_BOOL valueBool); static TPM_RESULT TPM_SetCapability_CapStanyData(tpm_state_t *tpm_state, TPM_BOOL ownerAuthorized, TPM_BOOL presenceAuthorized, uint32_t subCap32, TPM_SIZED_BUFFER *setValue); static TPM_RESULT TPM_SetCapability_CapVendor(tpm_state_t *tpm_state, TPM_BOOL ownerAuthorized, TPM_BOOL presenceAuthorized, uint32_t subCap32, TPM_SIZED_BUFFER *setValue); /* TPM_CAP_VERSION_INFO */ /* TPM_CapVersionInfo_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_CapVersionInfo_Init(TPM_CAP_VERSION_INFO *tpm_cap_version_info) { printf(" TPM_CapVersionInfo_Init:\n"); TPM_Version_Init(&(tpm_cap_version_info->version)); tpm_cap_version_info->specLevel = TPM_SPEC_LEVEL; tpm_cap_version_info->errataRev = TPM_ERRATA_REV; memcpy(&(tpm_cap_version_info->tpmVendorID), TPM_VENDOR_ID, sizeof(tpm_cap_version_info->tpmVendorID)); tpm_cap_version_info->vendorSpecificSize = 0; tpm_cap_version_info->vendorSpecific = NULL; return; } /* TPM_CapVersionInfo_Set() sets members to software specific data */ void TPM_CapVersionInfo_Set(TPM_CAP_VERSION_INFO *tpm_cap_version_info, TPM_PERMANENT_DATA *tpm_permanent_data) { printf(" TPM_CapVersionInfo_Set:\n"); TPM_Version_Set(&(tpm_cap_version_info->version), tpm_permanent_data); tpm_cap_version_info->specLevel = TPM_SPEC_LEVEL; tpm_cap_version_info->errataRev = TPM_ERRATA_REV; memcpy(&(tpm_cap_version_info->tpmVendorID), TPM_VENDOR_ID, sizeof(tpm_cap_version_info->tpmVendorID)); tpm_cap_version_info->vendorSpecificSize = 0; tpm_cap_version_info->vendorSpecific = NULL; return; } #if 0 /* not required */ /* TPM_CapVersionInfo_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_CapVersionInfo_Init() or TPM_CapVersionInfo_Set() After use, call TPM_CapVersionInfo_Delete() to free memory */ TPM_RESULT TPM_CapVersionInfo_Load(TPM_CAP_VERSION_INFO *tpm_cap_version_info, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_CapVersionInfo_Load:\n"); /* check tag */ if (rc == 0) { rc = TPM_CheckTag(TPM_TAG_CAP_VERSION_INFO, stream, stream_size); } /* load version */ if (rc == 0) { rc = TPM_Version_Load(&(tpm_cap_version_info->version), stream, stream_size); } /* load specLevel */ if (rc == 0) { rc = TPM_Load16(&(tpm_cap_version_info->specLevel), stream, stream_size); } /* load errataRev */ if (rc == 0) { rc = TPM_Loadn(&(tpm_cap_version_info->errataRev), sizeof(tpm_cap_version_info->errataRev), stream, stream_size); } /* load tpmVendorID */ if (rc == 0) { rc = TPM_Loadn(tpm_cap_version_info->tpmVendorID, sizeof(tpm_cap_version_info->tpmVendorID), stream, stream_size); } /* load vendorSpecificSize */ if (rc == 0) { rc = TPM_Load16(&(tpm_cap_version_info->vendorSpecificSize), stream, stream_size); } /* allocate memory for vendorSpecific */ if ((rc == 0) && (tpm_cap_version_info->vendorSpecificSize > 0)) { rc = TPM_Malloc(&(tpm_cap_version_info->vendorSpecific), tpm_cap_version_info->vendorSpecificSize); } /* load vendorSpecific */ if ((rc == 0) && (tpm_cap_version_info->vendorSpecificSize > 0)) { rc = TPM_Loadn(tpm_cap_version_info->vendorSpecific, tpm_cap_version_info->vendorSpecificSize, stream, stream_size); } return rc; } #endif /* TPM_CapVersionInfo_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_CapVersionInfo_Store(TPM_STORE_BUFFER *sbuffer, const TPM_CAP_VERSION_INFO *tpm_cap_version_info) { TPM_RESULT rc = 0; printf(" TPM_CapVersionInfo_Store:\n"); /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_CAP_VERSION_INFO); } /* store version */ if (rc == 0) { rc = TPM_Version_Store(sbuffer, &(tpm_cap_version_info->version)); } /* store specLevel */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, tpm_cap_version_info->specLevel); } /* store errataRev */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_cap_version_info->errataRev), sizeof(tpm_cap_version_info->errataRev)); } /* store tpmVendorID */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, tpm_cap_version_info->tpmVendorID, sizeof(tpm_cap_version_info->tpmVendorID)); } /* store vendorSpecificSize */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, tpm_cap_version_info->vendorSpecificSize); } /* store vendorSpecific */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, tpm_cap_version_info->vendorSpecific, tpm_cap_version_info->vendorSpecificSize); } return rc; } /* TPM_CapVersionInfo_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_CapVersionInfo_Init to set members back to default values The object itself is not freed */ void TPM_CapVersionInfo_Delete(TPM_CAP_VERSION_INFO *tpm_cap_version_info) { printf(" TPM_CapVersionInfo_Delete:\n"); if (tpm_cap_version_info != NULL) { free(tpm_cap_version_info->vendorSpecific); TPM_CapVersionInfo_Init(tpm_cap_version_info); } return; } /* Processing Commands */ /* 17. Ordinals rev 107 This structure maps the specification Ordinals table to software functions and parameters. It provides direct mapping that easier to understand and maintain than scattering and hard coding these values. The functions currently supported are: - processing jump table for 1.1 and 1.2 (implied get capability - ordinals supported) - allow audit - audit default value - owner delegation permissions - key delegation permissions - wrappable Future possibilities include: - no owner, disabled, deactivated - 0,1,2 auth typedef struct tdTPM_ORDINAL_TABLE { TPM_COMMAND_CODE ordinal; tpm_process_function_t process_function_v11; tpm_process_function_t process_function_v12; TPM_BOOL auditable; TPM_BOOL auditDefault; uint16_t ownerPermissionBlock; uint32_t ownerPermissionPosition; uint16_t keyPermissionBlock; uint32_t keyPermissionPosition; uint32_t inputHandleSize; uint32_t keyHandles; uint32_t outputHandleSize; TPM_BOOL transportWrappable; TPM_BOOL instanceWrappable; TPM_BOOL hardwareWrappable; } TPM_ORDINAL_TABLE; */ static TPM_ORDINAL_TABLE tpm_ordinal_table[] = { {TPM_ORD_ActivateIdentity, TPM_Process_ActivateIdentity, TPM_Process_ActivateIdentity, TRUE, TRUE, 1, TPM_DELEGATE_ActivateIdentity, 1, TPM_KEY_DELEGATE_ActivateIdentity, sizeof(TPM_KEY_HANDLE), 1, 0, TRUE, FALSE, FALSE}, {TPM_ORD_AuthorizeMigrationKey, TPM_Process_AuthorizeMigrationKey, TPM_Process_AuthorizeMigrationKey, TRUE, TRUE, 1, TPM_DELEGATE_AuthorizeMigrationKey, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_CertifyKey, TPM_Process_CertifyKey, TPM_Process_CertifyKey, TRUE, FALSE, 0, 0, 1, TPM_KEY_DELEGATE_CertifyKey, sizeof(TPM_KEY_HANDLE) + sizeof(TPM_KEY_HANDLE), 2, 0, TRUE, FALSE, FALSE}, {TPM_ORD_CertifyKey2, TPM_Process_Unused, TPM_Process_CertifyKey2, TRUE, FALSE, 0, 0, 1, TPM_KEY_DELEGATE_CertifyKey2, sizeof(TPM_KEY_HANDLE) + sizeof(TPM_KEY_HANDLE), 2, 0, TRUE, FALSE, FALSE}, {TPM_ORD_CertifySelfTest, TPM_Process_CertifySelfTest, TPM_Process_Unused, TRUE, FALSE, 0, 0, 0, 0, sizeof(TPM_KEY_HANDLE), 1, 0, TRUE, FALSE, FALSE}, {TPM_ORD_ChangeAuth, TPM_Process_ChangeAuth, TPM_Process_ChangeAuth, TRUE, FALSE, 0, 0, 1, TPM_KEY_DELEGATE_ChangeAuth, sizeof(TPM_KEY_HANDLE), 1, 0, TRUE, FALSE, FALSE}, {TPM_ORD_ChangeAuthAsymFinish, TPM_Process_ChangeAuthAsymFinish, TPM_Process_ChangeAuthAsymFinish, TRUE, FALSE, 0, 0, 1, TPM_KEY_DELEGATE_ChangeAuthAsymFinish, sizeof(TPM_KEY_HANDLE), 1, 0, TRUE, FALSE, FALSE}, {TPM_ORD_ChangeAuthAsymStart, TPM_Process_ChangeAuthAsymStart, TPM_Process_ChangeAuthAsymStart, TRUE, FALSE, 0, 0, 1, TPM_KEY_DELEGATE_ChangeAuthAsymStart, sizeof(TPM_KEY_HANDLE), 1, 0, TRUE, FALSE, FALSE}, {TPM_ORD_ChangeAuthOwner, TPM_Process_ChangeAuthOwner, TPM_Process_ChangeAuthOwner, TRUE, TRUE, 0, 0, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_CMK_ApproveMA, TPM_Process_Unused, TPM_Process_CMK_ApproveMA, TRUE, FALSE, 1, TPM_DELEGATE_CMK_ApproveMA, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_CMK_ConvertMigration, TPM_Process_Unused, TPM_Process_CMK_ConvertMigration, TRUE, FALSE, 1, TPM_KEY_DELEGATE_CMK_ConvertMigration, 0, 0, sizeof(TPM_KEY_HANDLE), 1, 0, TRUE, FALSE, FALSE}, {TPM_ORD_CMK_CreateBlob, TPM_Process_Unused, TPM_Process_CMK_CreateBlob, TRUE, FALSE, 0, 0, 1, TPM_KEY_DELEGATE_CMK_CreateBlob, sizeof(TPM_KEY_HANDLE), 1, 0, TRUE, FALSE, FALSE}, {TPM_ORD_CMK_CreateKey, TPM_Process_Unused, TPM_Process_CMK_CreateKey, TRUE, FALSE, 0, 0, 1, TPM_KEY_DELEGATE_CMK_CreateKey, sizeof(TPM_KEY_HANDLE), 1, 0, TRUE, FALSE, FALSE}, {TPM_ORD_CMK_CreateTicket, TPM_Process_Unused, TPM_Process_CMK_CreateTicket, TRUE, FALSE, 1, TPM_DELEGATE_CMK_CreateTicket, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_CMK_SetRestrictions, TPM_Process_Unused, TPM_Process_CMK_SetRestrictions, TRUE, FALSE, 0, 0, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_ContinueSelfTest, TPM_Process_ContinueSelfTest, TPM_Process_ContinueSelfTest, TRUE, FALSE, 0, 0, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_ConvertMigrationBlob, TPM_Process_ConvertMigrationBlob, TPM_Process_ConvertMigrationBlob, TRUE, TRUE, 0, 0, 1, TPM_KEY_DELEGATE_ConvertMigrationBlob, sizeof(TPM_KEY_HANDLE), 1, 0, TRUE, FALSE, FALSE}, {TPM_ORD_CreateCounter, TPM_Process_Unused, TPM_Process_CreateCounter, TRUE, FALSE, 1, TPM_DELEGATE_CreateCounter, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_CreateEndorsementKeyPair, TPM_Process_CreateEndorsementKeyPair, TPM_Process_CreateEndorsementKeyPair, TRUE, FALSE, 0, 0, 0, 0, 0, 0, 0, TRUE, TRUE, FALSE}, {TPM_ORD_CreateMaintenanceArchive, #if defined(TPM_NOMAINTENANCE) || defined(TPM_NOMAINTENANCE_COMMANDS) TPM_Process_Unused, TPM_Process_Unused, FALSE, FALSE, #else TPM_Process_CreateMaintenanceArchive, TPM_Process_CreateMaintenanceArchive, TRUE, TRUE, #endif 1, TPM_DELEGATE_CreateMaintenanceArchive, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_CreateMigrationBlob, TPM_Process_CreateMigrationBlob, TPM_Process_CreateMigrationBlob, TRUE, TRUE, 0, 0, 1, TPM_KEY_DELEGATE_CreateMigrationBlob, sizeof(TPM_KEY_HANDLE), 1, 0, TRUE, FALSE, FALSE}, {TPM_ORD_CreateRevocableEK, TPM_Process_Unused, TPM_Process_CreateRevocableEK, TRUE, FALSE, 0, 0, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_CreateWrapKey, TPM_Process_CreateWrapKey, TPM_Process_CreateWrapKey, TRUE, TRUE, 0, 0, 1, TPM_KEY_DELEGATE_CreateWrapKey, sizeof(TPM_KEY_HANDLE), 1, 0, TRUE, FALSE, FALSE}, {TPM_ORD_DAA_Join, TPM_Process_Unused, TPM_Process_DAAJoin, TRUE, FALSE, 1, TPM_DELEGATE_DAA_Join, 0, 0, sizeof(TPM_HANDLE), 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_DAA_Sign, TPM_Process_Unused, TPM_Process_DAASign, TRUE, FALSE, 1, TPM_DELEGATE_DAA_Sign, 0, 0, sizeof(TPM_HANDLE), 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_Delegate_CreateKeyDelegation, TPM_Process_Unused, TPM_Process_DelegateCreateKeyDelegation, TRUE, FALSE, 0, 0, 1, TPM_KEY_DELEGATE_Delegate_CreateKeyDelegation, sizeof(TPM_KEY_HANDLE), 1, 0, TRUE, FALSE, FALSE}, {TPM_ORD_Delegate_CreateOwnerDelegation, TPM_Process_Unused, TPM_Process_DelegateCreateOwnerDelegation, TRUE, FALSE, 1, TPM_DELEGATE_Delegate_CreateOwnerDelegation, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_Delegate_LoadOwnerDelegation, TPM_Process_Unused, TPM_Process_DelegateLoadOwnerDelegation, TRUE, FALSE, 1, TPM_DELEGATE_Delegate_LoadOwnerDelegation, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_Delegate_Manage, TPM_Process_Unused, TPM_Process_DelegateManage, TRUE, FALSE, 1, TPM_DELEGATE_Delegate_Manage, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_Delegate_ReadTable, TPM_Process_Unused, TPM_Process_DelegateReadTable, TRUE, FALSE, 0, 0, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_Delegate_UpdateVerification, TPM_Process_Unused, TPM_Process_DelegateUpdateVerification, TRUE, FALSE, 1, TPM_DELEGATE_Delegate_UpdateVerification, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_Delegate_VerifyDelegation, TPM_Process_Unused, TPM_Process_DelegateVerifyDelegation, TRUE, FALSE, 0, 0, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_DirRead, TPM_Process_DirRead, TPM_Process_DirRead, TRUE, FALSE, 0, 0, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_DirWriteAuth, TPM_Process_DirWriteAuth, TPM_Process_DirWriteAuth, TRUE, FALSE, 1, TPM_DELEGATE_DirWriteAuth, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_DisableForceClear, TPM_Process_DisableForceClear, TPM_Process_DisableForceClear, TRUE, TRUE, 0, 0, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_DisableOwnerClear, TPM_Process_DisableOwnerClear, TPM_Process_DisableOwnerClear, TRUE, TRUE, 1, TPM_DELEGATE_DisableOwnerClear, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_DisablePubekRead, TPM_Process_DisablePubekRead, TPM_Process_DisablePubekRead, TRUE, TRUE, 1, TPM_DELEGATE_DisablePubekRead, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_DSAP, TPM_Process_Unused, TPM_Process_DSAP, TRUE, FALSE, 0, 0, 0, 0, sizeof(TPM_ENTITY_TYPE) + sizeof(TPM_KEY_HANDLE) + TPM_NONCE_SIZE + sizeof(uint32_t), 0xffffffff, sizeof(TPM_AUTHHANDLE) + TPM_NONCE_SIZE + TPM_NONCE_SIZE, TRUE, TRUE, TRUE}, {TPM_ORD_EstablishTransport, TPM_Process_Unused, TPM_Process_EstablishTransport, TRUE, FALSE, 0, 0, 1, TPM_KEY_DELEGATE_EstablishTransport, sizeof(TPM_KEY_HANDLE), 1, 0, FALSE, FALSE, FALSE}, {TPM_ORD_EvictKey, TPM_Process_EvictKey, TPM_Process_EvictKey, TRUE, FALSE, 0, 0, 0, 0, sizeof(TPM_KEY_HANDLE), 1, 0, TRUE, FALSE, FALSE}, {TPM_ORD_ExecuteTransport, TPM_Process_Unused, TPM_Process_ExecuteTransport, TRUE, FALSE, 0, 0, 0, 0, 0, 0, 0, FALSE, FALSE, FALSE}, {TPM_ORD_Extend, TPM_Process_Extend, TPM_Process_Extend, TRUE, FALSE, 0, 0, 0, 0, 0, 0, 0, TRUE, TRUE, FALSE}, {TPM_ORD_FieldUpgrade, TPM_Process_Unused, TPM_Process_Unused, TRUE, FALSE, 1, TPM_DELEGATE_FieldUpgrade, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_FlushSpecific, TPM_Process_Unused, TPM_Process_FlushSpecific, TRUE, FALSE, 0, 0, 0, 0, sizeof(TPM_HANDLE), 0xffffffff, 0, TRUE, TRUE, TRUE}, {TPM_ORD_ForceClear, TPM_Process_ForceClear, TPM_Process_ForceClear, TRUE, TRUE, 0, 0, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_GetAuditDigest, TPM_Process_Unused, TPM_Process_GetAuditDigest, FALSE, FALSE, 0, 0, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_GetAuditDigestSigned, TPM_Process_Unused, TPM_Process_GetAuditDigestSigned, FALSE, FALSE, 0, 0, 1, TPM_KEY_DELEGATE_GetAuditDigestSigned, sizeof(TPM_KEY_HANDLE), 1, 0, TRUE, FALSE, FALSE}, {TPM_ORD_GetAuditEvent, TPM_Process_Unused, TPM_Process_Unused, FALSE, FALSE, 0, 0, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_GetAuditEventSigned, TPM_Process_Unused, TPM_Process_Unused, FALSE, FALSE, 0, 0, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_GetCapability, TPM_Process_GetCapability, TPM_Process_GetCapability, TRUE, FALSE, 0, 0, 0, 0, 0, 0, 0, TRUE, TRUE, FALSE}, {TPM_ORD_GetCapabilityOwner, TPM_Process_GetCapabilityOwner, TPM_Process_GetCapabilityOwner, TRUE, FALSE, 0, 0, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_GetCapabilitySigned, TPM_Process_GetCapabilitySigned, TPM_Process_Unused, TRUE, FALSE, 0, 0, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_GetOrdinalAuditStatus, TPM_Process_Unused, TPM_Process_Unused, FALSE, FALSE, 0, 0, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_GetPubKey, TPM_Process_GetPubKey, TPM_Process_GetPubKey, TRUE, FALSE, 0, 0, 1, TPM_KEY_DELEGATE_GetPubKey, sizeof(TPM_KEY_HANDLE), 1, 0, TRUE, FALSE, FALSE}, {TPM_ORD_GetRandom, TPM_Process_GetRandom, TPM_Process_GetRandom, TRUE, FALSE, 0, 0, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_GetTestResult, TPM_Process_GetTestResult, TPM_Process_GetTestResult, TRUE, FALSE, 0, 0, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_GetTicks, TPM_Process_Unused, TPM_Process_GetTicks, TRUE, FALSE, 0, 0, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_IncrementCounter, TPM_Process_Unused, TPM_Process_IncrementCounter, TRUE, FALSE, 0, 0, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_Init, TPM_Process_Init, TPM_Process_Init, TRUE, FALSE, 0, 0, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_KeyControlOwner, TPM_Process_Unused, TPM_Process_KeyControlOwner, TRUE, FALSE, 1, TPM_DELEGATE_KeyControlOwner, 0, 0, sizeof(TPM_KEY_HANDLE), 1, 0, TRUE, FALSE, FALSE}, {TPM_ORD_KillMaintenanceFeature, #if defined(TPM_NOMAINTENANCE) || defined(TPM_NOMAINTENANCE_COMMANDS) TPM_Process_Unused, TPM_Process_Unused, FALSE, FALSE, #else TPM_Process_KillMaintenanceFeature, TPM_Process_KillMaintenanceFeature, TRUE, TRUE, #endif 1, TPM_DELEGATE_KillMaintenanceFeature, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_LoadAuthContext, TPM_Process_LoadAuthContext, TPM_Process_LoadAuthContext, TRUE, FALSE, 0, 0, 0, 0, 0, 0, sizeof(TPM_HANDLE), TRUE, FALSE, FALSE}, {TPM_ORD_LoadContext, TPM_Process_Unused, TPM_Process_LoadContext, TRUE, FALSE, 0, 0, 0, 0, sizeof(TPM_HANDLE), 0, sizeof(TPM_HANDLE), TRUE, TRUE, FALSE}, {TPM_ORD_LoadKey, TPM_Process_LoadKey, TPM_Process_LoadKey, TRUE, FALSE, 0, 0, 1, TPM_KEY_DELEGATE_LoadKey, sizeof(TPM_KEY_HANDLE), 1, 0, TRUE, FALSE, FALSE}, {TPM_ORD_LoadKey2, TPM_Process_Unused, TPM_Process_LoadKey2, TRUE, FALSE, 0, 0, 1, TPM_KEY_DELEGATE_LoadKey2, sizeof(TPM_KEY_HANDLE), 1, sizeof(TPM_KEY_HANDLE), TRUE, FALSE, FALSE}, {TPM_ORD_LoadKeyContext, TPM_Process_LoadKeyContext, TPM_Process_LoadKeyContext, TRUE, FALSE, 0, 0, 0, 0, 0, 0, sizeof(TPM_KEY_HANDLE), TRUE, FALSE, FALSE}, {TPM_ORD_LoadMaintenanceArchive, #if defined(TPM_NOMAINTENANCE) || defined(TPM_NOMAINTENANCE_COMMANDS) TPM_Process_Unused, TPM_Process_Unused, FALSE, FALSE, #else TPM_Process_LoadMaintenanceArchive, TPM_Process_LoadMaintenanceArchive, TRUE, TRUE, #endif 1, TPM_DELEGATE_LoadMaintenanceArchive, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_LoadManuMaintPub, #if defined(TPM_NOMAINTENANCE) || defined(TPM_NOMAINTENANCE_COMMANDS) TPM_Process_Unused, TPM_Process_Unused, FALSE, FALSE, #else TPM_Process_LoadManuMaintPub, TPM_Process_LoadManuMaintPub, TRUE, TRUE, #endif 0, 0, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_MakeIdentity, TPM_Process_MakeIdentity, TPM_Process_MakeIdentity, TRUE, TRUE, 1, TPM_DELEGATE_MakeIdentity, 1, TPM_KEY_DELEGATE_MakeIdentity, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_MigrateKey, TPM_Process_Unused, TPM_Process_MigrateKey, TRUE, FALSE, 0, 0, 1, TPM_KEY_DELEGATE_MigrateKey, sizeof(TPM_KEY_HANDLE), 1, 0, TRUE, FALSE, FALSE}, {TPM_ORD_NV_DefineSpace, TPM_Process_Unused, TPM_Process_NVDefineSpace, TRUE, FALSE, 1, TPM_DELEGATE_NV_DefineSpace, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_NV_ReadValue, TPM_Process_Unused, TPM_Process_NVReadValue, TRUE, FALSE, 1, TPM_DELEGATE_NV_ReadValue, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_NV_ReadValueAuth, TPM_Process_Unused, TPM_Process_NVReadValueAuth, TRUE, FALSE, 0, 0, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_NV_WriteValue, TPM_Process_Unused, TPM_Process_NVWriteValue, TRUE, FALSE, 1, TPM_DELEGATE_NV_WriteValue, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_NV_WriteValueAuth, TPM_Process_Unused, TPM_Process_NVWriteValueAuth, TRUE, FALSE, 0, 0, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_OIAP, TPM_Process_OIAP, TPM_Process_OIAP, TRUE, FALSE, 0, 0, 0, 0, 0, 0, sizeof(TPM_AUTHHANDLE) + TPM_NONCE_SIZE, TRUE, TRUE, TRUE}, {TPM_ORD_OSAP, TPM_Process_OSAP, TPM_Process_OSAP, TRUE, FALSE, 0, 0, 0, 0, sizeof(TPM_ENTITY_TYPE) + sizeof(uint32_t) + TPM_NONCE_SIZE, 0, /* TPM_OSAP: no input or output parameters are encrypted or logged */ sizeof(TPM_AUTHHANDLE) + TPM_NONCE_SIZE + TPM_NONCE_SIZE, TRUE, TRUE, TRUE}, {TPM_ORD_OwnerClear, TPM_Process_OwnerClear, TPM_Process_OwnerClear, TRUE, TRUE, 1, TPM_DELEGATE_OwnerClear, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_OwnerReadInternalPub, TPM_Process_Unused, TPM_Process_OwnerReadInternalPub, TRUE, FALSE, 1, TPM_DELEGATE_OwnerReadInternalPub, 0, 0, 0, 1, 0, TRUE, FALSE, FALSE}, {TPM_ORD_OwnerReadPubek, TPM_Process_OwnerReadPubek, TPM_Process_OwnerReadPubek, TRUE, TRUE, 1, TPM_DELEGATE_OwnerReadPubek, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_OwnerSetDisable, TPM_Process_OwnerSetDisable, TPM_Process_OwnerSetDisable, TRUE, TRUE, 1, TPM_DELEGATE_OwnerSetDisable, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_PCR_Reset, TPM_Process_Unused, TPM_Process_PcrReset, TRUE, FALSE, 0, 0, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_PcrRead, TPM_Process_PcrRead, TPM_Process_PcrRead, TRUE, FALSE, 0, 0, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_PhysicalDisable, TPM_Process_PhysicalDisable, TPM_Process_PhysicalDisable, TRUE, TRUE, 0, 0, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_PhysicalEnable, TPM_Process_PhysicalEnable, TPM_Process_PhysicalEnable, TRUE, TRUE, 0, 0, 0, 0, 0, 0, 0, TRUE, TRUE, FALSE}, {TPM_ORD_PhysicalSetDeactivated, TPM_Process_PhysicalSetDeactivated, TPM_Process_PhysicalSetDeactivated, TRUE, TRUE, 0, 0, 0, 0, 0, 0, 0, TRUE, TRUE, FALSE}, {TPM_ORD_Quote, TPM_Process_Quote, TPM_Process_Quote, TRUE, FALSE, 0, 0, 1, TPM_KEY_DELEGATE_Quote, sizeof(TPM_KEY_HANDLE), 1, 0, TRUE, FALSE, TRUE}, {TPM_ORD_Quote2, TPM_Process_Unused, TPM_Process_Quote2, TRUE, FALSE, 0, 0, 1, TPM_KEY_DELEGATE_Quote2, sizeof(TPM_KEY_HANDLE), 1, 0, TRUE, FALSE, TRUE}, {TPM_ORD_ReadCounter, TPM_Process_Unused, TPM_Process_ReadCounter, TRUE, FALSE, 0, 0, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_ReadManuMaintPub, #if defined(TPM_NOMAINTENANCE) || defined(TPM_NOMAINTENANCE_COMMANDS) TPM_Process_Unused, TPM_Process_Unused, FALSE, FALSE, #else TPM_Process_ReadManuMaintPub, TPM_Process_ReadManuMaintPub, TRUE, TRUE, #endif 0, 0, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_ReadPubek, TPM_Process_ReadPubek, TPM_Process_ReadPubek, TRUE, TRUE, 0, 0, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_ReleaseCounter, TPM_Process_Unused, TPM_Process_ReleaseCounter, TRUE, FALSE, 0, 0, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_ReleaseCounterOwner, TPM_Process_Unused, TPM_Process_ReleaseCounterOwner, TRUE, FALSE, 1, TPM_DELEGATE_ReleaseCounterOwner, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_ReleaseTransportSigned, TPM_Process_Unused, TPM_Process_ReleaseTransportSigned, TRUE, FALSE, 0, 0, 1, TPM_KEY_DELEGATE_ReleaseTransportSigned, 0, 0, 0, FALSE, FALSE, FALSE}, {TPM_ORD_Reset, TPM_Process_Reset, TPM_Process_Reset, TRUE, FALSE, 0, 0, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_ResetLockValue, TPM_Process_Unused, TPM_Process_ResetLockValue, TRUE, FALSE, 1, TPM_DELEGATE_ResetLockValue, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_RevokeTrust, TPM_Process_Unused, TPM_Process_RevokeTrust, TRUE, FALSE, 0, 0, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_SaveAuthContext, TPM_Process_SaveAuthContext, TPM_Process_SaveAuthContext, TRUE, FALSE, 0, 0, 0, 0, sizeof(TPM_AUTHHANDLE), 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_SaveContext, TPM_Process_Unused, TPM_Process_SaveContext, TRUE, FALSE, 0, 0, 0, 0, sizeof(TPM_HANDLE), 0xffffffff, 0, TRUE, TRUE, FALSE}, {TPM_ORD_SaveKeyContext, TPM_Process_SaveKeyContext, TPM_Process_SaveKeyContext, TRUE, FALSE, 0, 0, 0, 0, sizeof(TPM_KEY_HANDLE), 1, 0, TRUE, FALSE, FALSE}, {TPM_ORD_SaveState, TPM_Process_SaveState, TPM_Process_SaveState, TRUE, FALSE, 0, 0, 0, 0, 0, 0, 0, TRUE, TRUE, FALSE}, {TPM_ORD_Seal, TPM_Process_Seal, TPM_Process_Seal, TRUE, FALSE, 0, 0, 1, TPM_KEY_DELEGATE_Seal, sizeof(TPM_KEY_HANDLE), 1, 0, TRUE, FALSE, FALSE}, {TPM_ORD_Sealx, TPM_Process_Unused, TPM_Process_Sealx, TRUE, FALSE, 0, 0, 1, TPM_KEY_DELEGATE_Sealx, sizeof(TPM_KEY_HANDLE), 1, 0, TRUE, FALSE, FALSE}, {TPM_ORD_SelfTestFull, TPM_Process_SelfTestFull, TPM_Process_SelfTestFull, TRUE, FALSE, 0, 0, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_SetCapability, TPM_Process_Unused, TPM_Process_SetCapability, TRUE, FALSE, 1, TPM_DELEGATE_SetCapability, 0, 0, 0, 0, 0, TRUE, TRUE, FALSE}, {TPM_ORD_SetOperatorAuth, TPM_Process_Unused, TPM_Process_SetOperatorAuth, TRUE, FALSE, 0, 0, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_SetOrdinalAuditStatus, TPM_Process_SetOrdinalAuditStatus, TPM_Process_SetOrdinalAuditStatus, TRUE, TRUE, 1, TPM_DELEGATE_SetOrdinalAuditStatus, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_SetOwnerInstall, TPM_Process_SetOwnerInstall, TPM_Process_SetOwnerInstall, TRUE, TRUE, 0, 0, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_SetOwnerPointer, TPM_Process_Unused, TPM_Process_SetOwnerPointer, TRUE, FALSE, 0, 0, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_SetRedirection, TPM_Process_Unused, TPM_Process_Unused, TRUE, FALSE, 1, TPM_DELEGATE_SetRedirection, 0, 0, sizeof(TPM_KEY_HANDLE), 1, 0, TRUE, FALSE, FALSE}, {TPM_ORD_SetTempDeactivated, TPM_Process_SetTempDeactivated, TPM_Process_SetTempDeactivated, TRUE, TRUE, 0, 0, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_SHA1Complete, TPM_Process_SHA1Complete, TPM_Process_SHA1Complete, TRUE, FALSE, 0, 0, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_SHA1CompleteExtend, TPM_Process_SHA1CompleteExtend, TPM_Process_SHA1CompleteExtend, TRUE, FALSE, 0, 0, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_SHA1Start, TPM_Process_SHA1Start, TPM_Process_SHA1Start, TRUE, FALSE, 0, 0, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_SHA1Update, TPM_Process_SHA1Update, TPM_Process_SHA1Update, TRUE, FALSE, 0, 0, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_Sign, TPM_Process_Sign, TPM_Process_Sign, TRUE, FALSE, 0, 0, 1, TPM_KEY_DELEGATE_Sign, sizeof(TPM_KEY_HANDLE), 1, 0, TRUE, FALSE, FALSE}, {TPM_ORD_Startup, TPM_Process_Startup, TPM_Process_Startup, TRUE, FALSE, 0, 0, 0, 0, 0, 0, 0, TRUE, TRUE, FALSE}, {TPM_ORD_StirRandom, TPM_Process_StirRandom, TPM_Process_StirRandom, TRUE, FALSE, 0, 0, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_TakeOwnership, TPM_Process_TakeOwnership, TPM_Process_TakeOwnership, TRUE, TRUE, 0, 0, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE}, {TPM_ORD_Terminate_Handle, TPM_Process_TerminateHandle, TPM_Process_TerminateHandle, TRUE, FALSE, 0, 0, 0, 0, sizeof(TPM_AUTHHANDLE), 0, 0, TRUE, TRUE, TRUE}, {TPM_ORD_TickStampBlob, TPM_Process_Unused, TPM_Process_TickStampBlob, TRUE, FALSE, 0, 0, 1, TPM_KEY_DELEGATE_TickStampBlob, sizeof(TPM_KEY_HANDLE), 1, 0, TRUE, FALSE, FALSE}, {TPM_ORD_UnBind, TPM_Process_UnBind, TPM_Process_UnBind, TRUE, FALSE, 0, 0, 1, TPM_KEY_DELEGATE_UnBind, sizeof(TPM_KEY_HANDLE), 1, 0, TRUE, FALSE, FALSE}, {TPM_ORD_Unseal, TPM_Process_Unseal, TPM_Process_Unseal, TRUE, FALSE, 0, 0, 1, TPM_KEY_DELEGATE_Unseal, sizeof(TPM_KEY_HANDLE), 1, 0, TRUE, FALSE, FALSE}, {TSC_ORD_PhysicalPresence, TPM_Process_PhysicalPresence, TPM_Process_PhysicalPresence, TRUE, FALSE, 0, 0, 0, 0, 0, 0, 0, TRUE, TRUE, FALSE}, {TSC_ORD_ResetEstablishmentBit, TPM_Process_Unused, TPM_Process_ResetEstablishmentBit, TRUE, FALSE, 0, 0, 0, 0, 0, 0, 0, TRUE, FALSE, FALSE} }; /* Ordinal Table Utilities */ /* TPM_OrdinalTable_GetEntry() gets the table entry for the ordinal. If the ordinal is not in the table, TPM_BAD_ORDINAL is returned */ TPM_RESULT TPM_OrdinalTable_GetEntry(TPM_ORDINAL_TABLE **entry, TPM_ORDINAL_TABLE *ordinalTable, TPM_COMMAND_CODE ordinal) { TPM_RESULT rc = TPM_BAD_ORDINAL; size_t i; /* printf(" TPM_OrdinalTable_GetEntry: Ordinal %08x\n", ordinal); */ *entry = NULL; for (i = 0 ; i < (sizeof(tpm_ordinal_table)/sizeof(TPM_ORDINAL_TABLE)) ; i++) { if (ordinalTable[i].ordinal == ordinal) { /* if found */ *entry = &(ordinalTable[i]); /* return the entry */ rc = 0; /* return found */ break; } } return rc; } /* TPM_OrdinalTable_GetProcessFunction() returns the processing function for the ordinal. If the ordinal is not in the table, the function TPM_Process_Unused() is returned. */ void TPM_OrdinalTable_GetProcessFunction(tpm_process_function_t *tpm_process_function, TPM_ORDINAL_TABLE *ordinalTable, TPM_COMMAND_CODE ordinal) { TPM_RESULT rc = 0; TPM_ORDINAL_TABLE *entry; printf(" TPM_OrdinalTable_GetProcessFunction: Ordinal %08x\n", ordinal); if (rc == 0) { rc = TPM_OrdinalTable_GetEntry(&entry, ordinalTable, ordinal); } if (rc == 0) { /* if found */ #ifdef TPM_V12 *tpm_process_function = entry->process_function_v12; #else *tpm_process_function = entry->process_function_v11; #endif } else { /* if not found, default processing function */ *tpm_process_function = TPM_Process_Unused; } return; } /* TPM_OrdinalTable_GetAuditable() determines whether the ordinal can ever be audited. Used by TPM_Process_SetOrdinalAuditStatus() */ void TPM_OrdinalTable_GetAuditable(TPM_BOOL *auditable, TPM_COMMAND_CODE ordinal) { TPM_RESULT rc = 0; TPM_ORDINAL_TABLE *entry; printf(" TPM_OrdinalTable_GetAuditable: Ordinal %08x\n", ordinal); if (rc == 0) { rc = TPM_OrdinalTable_GetEntry(&entry, tpm_ordinal_table, ordinal); } /* if not found, unimplemented, not auditable */ if (rc != 0) { *auditable = FALSE; } /* if unimplemented, not auditable */ #ifdef TPM_V12 else if (entry->process_function_v12 == TPM_Process_Unused) { *auditable = FALSE; } #else else if (entry->process_function_v11 == TPM_Process_Unused) { *auditable = FALSE; } #endif /* if found an entry, use it */ else { *auditable = entry->auditable; } return; } /* TPM_OrdinalTable_GetAuditDefault() determines whether the ordinal is audited by default. Used to initialize TPM_PERMANENT_DATA -> ordinalAuditStatus Returns FALSE if the ordinal is not in the ordinals table. */ void TPM_OrdinalTable_GetAuditDefault(TPM_BOOL *auditDefault, TPM_COMMAND_CODE ordinal) { TPM_RESULT rc = 0; TPM_ORDINAL_TABLE *entry; if (rc == 0) { rc = TPM_OrdinalTable_GetEntry(&entry, tpm_ordinal_table, ordinal); } /* if not found, unimplemented, not auditable */ if (rc != 0) { *auditDefault = FALSE; } /* found an entry, return it */ else { *auditDefault = entry->auditDefault; } return; } /* TPM_OrdinalTable_GetOwnerPermission() gets the owner permission block and the position within the block for a permission bit based on the ordinal */ TPM_RESULT TPM_OrdinalTable_GetOwnerPermission(uint16_t *ownerPermissionBlock, uint32_t *ownerPermissionPosition, TPM_COMMAND_CODE ordinal) { TPM_RESULT rc = 0; TPM_ORDINAL_TABLE *entry; if (rc == 0) { rc = TPM_OrdinalTable_GetEntry(&entry, tpm_ordinal_table, ordinal); } if (rc == 0) { *ownerPermissionBlock = entry->ownerPermissionBlock; *ownerPermissionPosition = entry->ownerPermissionPosition; /* sanity check ordinal table entry value */ if (*ownerPermissionPosition >= (sizeof(uint32_t) * CHAR_BIT)) { printf("TPM_OrdinalTable_GetOwnerPermission: Error (fatal): " "ownerPermissionPosition out of range %u\n", *ownerPermissionPosition); rc = TPM_FAIL; /* should never occur */ } } return rc; } /* TPM_OrdinalTable_GetKeyPermission() gets the key permission block and the position within the block for a permission bit based on the ordinal */ TPM_RESULT TPM_OrdinalTable_GetKeyPermission(uint16_t *keyPermissionBlock, uint32_t *keyPermissionPosition, TPM_COMMAND_CODE ordinal) { TPM_RESULT rc = 0; TPM_ORDINAL_TABLE *entry; if (rc == 0) { rc = TPM_OrdinalTable_GetEntry(&entry, tpm_ordinal_table, ordinal); } if (rc == 0) { *keyPermissionBlock = entry->keyPermissionBlock; *keyPermissionPosition = entry->keyPermissionPosition; if (*keyPermissionPosition >= (sizeof(uint32_t) * CHAR_BIT)) { printf("TPM_OrdinalTable_GetKeyPermission: Error (fatal): " "keyPermissionPosition out of range %u\n", *keyPermissionPosition); rc = TPM_FAIL; /* should never occur */ } } return rc; } /* TPM_OrdinalTable_ParseWrappedCmd() parses a transport wrapped command, extracting - index into DATAw - length of DATAw - number of key handles and their indexes - ordinal - transportWrappable FALSE if the command cannot be wrapped in a transport session FIXME if audit has to occur before command parsing, this command becomes more generally useful, and might do the auditing and return the inParamDigest as well. This function cannot get the actual key handle(s) because the value may be encrypted, and the decryption has not occurred yet. */ TPM_RESULT TPM_OrdinalTable_ParseWrappedCmd(uint32_t *datawStart, uint32_t *datawLen, uint32_t *keyHandles, uint32_t *keyHandle1Index, uint32_t *keyHandle2Index, TPM_COMMAND_CODE *ordinal, TPM_BOOL *transportWrappable, TPM_SIZED_BUFFER *wrappedCmd) { TPM_RESULT rc = 0; uint32_t stream_size; unsigned char *stream; TPM_TAG tag = 0; uint32_t paramSize = 0; TPM_ORDINAL_TABLE *entry; /* table entry for the ordinal */ uint32_t authLen; /* length of below the line parameters */ printf(" TPM_OrdinalTable_ParseWrappedCmd:\n"); /* Extract the standard command parameters from the command stream. This also validates paramSize against wrappedCmdSize */ if (rc == 0) { /* make temporary copies so the wrappedCmd is not touched */ /* FIXME might want to return paramSize and tag and move the wrappedCmd pointers */ stream = wrappedCmd->buffer; stream_size = wrappedCmd->size; /* parse the three standard input parameters, check paramSize against wrappedCmd->size */ rc = TPM_Process_GetCommandParams(&tag, ¶mSize, ordinal, &stream, &stream_size); } /* get the entry from the ordinal table */ if (rc == 0) { printf(" TPM_OrdinalTable_ParseWrappedCmd: ordinal %08x\n", *ordinal); rc = TPM_OrdinalTable_GetEntry(&entry, tpm_ordinal_table, *ordinal); } if (rc == 0) { /* datawStart indexes into the dataW area, skip the standard 3 inputs and the handles */ *datawStart = sizeof(TPM_TAG) + sizeof(uint32_t) + sizeof(TPM_COMMAND_CODE) + entry->inputHandleSize; /* authLen is the length of the below-the-line auth parameters that are excluded from the dataW area */ switch (tag) { case TPM_TAG_RQU_AUTH1_COMMAND: authLen = sizeof(TPM_AUTHHANDLE) + TPM_NONCE_SIZE + sizeof(TPM_BOOL) + TPM_AUTHDATA_SIZE; break; case TPM_TAG_RQU_AUTH2_COMMAND: authLen = 2 * (sizeof(TPM_AUTHHANDLE) + TPM_NONCE_SIZE + sizeof(TPM_BOOL) + TPM_AUTHDATA_SIZE); break; case TPM_TAG_RQU_COMMAND: /* if the tag is illegal, assume the dataW area goes to the end of the command */ default: authLen = 0; break; } if (paramSize < *datawStart + authLen) { printf("TPM_OrdinalTable_ParseWrappedCmd: Error, " "paramSize %u less than datawStart %u + authLen %u\n", paramSize, *datawStart, authLen); rc = TPM_BAD_PARAM_SIZE; } } if (rc == 0) { /* subtract safe, cannot be negative after above check */ *datawLen = paramSize - *datawStart - authLen; printf(" TPM_OrdinalTable_ParseWrappedCmd: datawStart %u datawLen %u\n", *datawStart, *datawLen); /* determine whether the command can be wrapped in a transport session */ *transportWrappable = entry->transportWrappable; /* return the number of key handles */ *keyHandles = entry->keyHandles; } if (rc == 0) { printf(" TPM_OrdinalTable_ParseWrappedCmd: key handles %u\n", *keyHandles); switch (*keyHandles) { case 0: /* no key handles */ break; case 1: /* one key handle */ *keyHandle1Index = sizeof(TPM_TAG) + sizeof(uint32_t) + sizeof(TPM_COMMAND_CODE); break; case 2: /* first key handle */ *keyHandle1Index = sizeof(TPM_TAG) + sizeof(uint32_t) + sizeof(TPM_COMMAND_CODE); /* second key handle */ *keyHandle2Index = sizeof(TPM_TAG) + sizeof(uint32_t) + sizeof(TPM_COMMAND_CODE) + sizeof(TPM_KEY_HANDLE); break; case 0xffffffff: printf(" TPM_OrdinalTable_ParseWrappedCmd: key handles special case\n"); /* potential key handle */ *keyHandle1Index = sizeof(TPM_TAG) + sizeof(uint32_t) + sizeof(TPM_COMMAND_CODE); /* can't determine handle type here since resourceType is encrypted */ break; default: /* sanity check ordinal table */ printf("TPM_OrdinalTable_ParseWrappedCmd: Error (fatal), " "invalid key handles for %08x for ordinal %08x\n", *keyHandles, *ordinal); rc = TPM_FAIL; /* should never occur */ break; } } return rc; } /* TPM_OrdinalTable_ParseWrappedRsp() parses a transport wrapped response, extracting - index into DATAw - length of DATAw - return code RCw FIXME this command might do the auditing and return the outParamDigest as well. */ TPM_RESULT TPM_OrdinalTable_ParseWrappedRsp(uint32_t *datawStart, uint32_t *datawLen, TPM_RESULT *rcw, TPM_COMMAND_CODE ordinal, const unsigned char *wrappedRspStream, uint32_t wrappedRspStreamSize) { TPM_RESULT rc = 0; TPM_TAG tag = 0; uint32_t paramSize = 0; TPM_ORDINAL_TABLE *entry; /* table entry for the ordinal */ uint32_t authLen; /* length of below the line parameters */ printf(" TPM_OrdinalTable_ParseWrappedRsp: ordinal %08x\n", ordinal); /* Extract the standard response parameters from the response stream. This also validates paramSize against wrappedRspSize */ if (rc == 0) { rc = TPM_Process_GetResponseParams(&tag, ¶mSize, rcw, (unsigned char **)&wrappedRspStream, &wrappedRspStreamSize); } /* get the entry from the ordinal table */ if (rc == 0) { printf(" TPM_OrdinalTable_ParseWrappedRsp: returnCode %08x\n", *rcw); rc = TPM_OrdinalTable_GetEntry(&entry, tpm_ordinal_table, ordinal); } /* parse the success return code case */ if ((rc == 0) && (*rcw == TPM_SUCCESS)) { if (rc == 0) { /* datawStart indexes into the dataW area, skip the standard 3 inputs and the handles */ *datawStart = sizeof(TPM_TAG) + sizeof(uint32_t) + sizeof(TPM_RESULT) + entry->outputHandleSize; /* authLen is the length of the below-the-line auth parameters that are excluded from the dataW area */ switch (tag) { case TPM_TAG_RSP_AUTH1_COMMAND: authLen = TPM_NONCE_SIZE + sizeof(TPM_BOOL) + TPM_AUTHDATA_SIZE; break; case TPM_TAG_RSP_AUTH2_COMMAND: authLen = 2 * (TPM_NONCE_SIZE + sizeof(TPM_BOOL) + TPM_AUTHDATA_SIZE); break; case TPM_TAG_RSP_COMMAND: /* if the tag is illegal, assume the dataW area goes to the end of the response */ default: authLen = 0; break; } if (paramSize < *datawStart + authLen) { printf("TPM_OrdinalTable_ParseWrappedRsp: Error, " "paramSize %u less than datawStart %u + authLen %u\n", paramSize, *datawStart, authLen); rc = TPM_BAD_PARAM_SIZE; /* FIXME not clear what to do here */ } } if (rc == 0) { /* subtract safe, cannot be negative after about check */ *datawLen = paramSize - *datawStart - authLen; printf(" TPM_OrdinalTable_ParseWrappedRsp: datawStart %u datawLen %u\n", *datawStart, *datawLen); } } /* if the wrapped command failed, datawStart is not used, and datawLen is 0 */ else if ((rc == 0) && (*rcw != TPM_SUCCESS)) { *datawStart = sizeof(TPM_TAG) + sizeof(uint32_t) + sizeof(TPM_RESULT); *datawLen = 0; printf(" TPM_OrdinalTable_ParseWrappedRsp: datawLen %u\n", *datawLen); } return rc; } void TPM_KeyHandleEntries_Trace(TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries); void TPM_KeyHandleEntries_Trace(TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries) { size_t i; for (i = 0 ; (i < 4) && (i < TPM_KEY_HANDLES) ; i++) { printf("TPM_KeyHandleEntries_Trace: %lu handle %08x tpm_key %p\n", (unsigned long)i, tpm_key_handle_entries[i].handle, tpm_key_handle_entries[i].key); } return; } void TPM_State_Trace(tpm_state_t *tpm_state); void TPM_State_Trace(tpm_state_t *tpm_state) { printf("TPM_State_Trace: disable %u p_deactive %u v_deactive %u owned %u state %u\n", tpm_state->tpm_permanent_flags.disable, tpm_state->tpm_permanent_flags.deactivated, tpm_state->tpm_stclear_flags.deactivated, tpm_state->tpm_permanent_data.ownerInstalled, tpm_state->testState); return; } /* TPM_ProcessA() is an alternate to TPM_Process() that uses standard C types. It provides an entry point to the TPM without requiring the TPM_STORE_BUFFER class. The design pattern for the response is: - set '*response' to NULL at the first call - on subsequent calls, pass 'response' and 'response_total' back in. Set 'response_size' back to 0. On input: '*response' - pointer to a buffer that was allocated (can be NULL) 'response_size' - the number of valid bytes in buffer (ignored if buffer is NULL, can be 0, cannot be greater than total. Set to zero, unless one wants the TPM_Process() function to append a response to some existing data. '*response_total' - the total number of allocated bytes (ignored if buffer is NULL) On output: '*response' - pointer to a buffer that was allocated or reallocated 'response_size' - the number of valid bytes in buffer '*response_total' - the total number of allocated or reallocated bytes */ TPM_RESULT TPM_ProcessA(unsigned char **response, uint32_t *response_size, uint32_t *response_total, unsigned char *command, /* complete command array */ uint32_t command_size) /* actual bytes in command */ { TPM_RESULT rc = 0; TPM_STORE_BUFFER responseSbuffer; /* set the sbuffer from the response parameters */ if (rc == 0) { rc = TPM_Sbuffer_Set(&responseSbuffer, *response, *response_size, *response_total); } if (rc == 0) { rc = TPM_Process(&responseSbuffer, command, /* complete command array */ command_size); /* actual bytes in command */ } /* get the response parameters from the sbuffer */ if (rc == 0) { TPM_Sbuffer_GetAll(&responseSbuffer, response, response_size, response_total); } return rc; } /* Process the command from the host to the TPM. 'command_size' is the actual size of the command stream. Returns: 0 on success non-zero on a fatal error preventing the command from being processed. The response is invalid in this case. */ TPM_RESULT TPM_Process(TPM_STORE_BUFFER *response, unsigned char *command, /* complete command array */ uint32_t command_size) /* actual bytes in command */ { TPM_RESULT rc = 0; /* fatal error, no response */ TPM_RESULT returnCode = TPM_SUCCESS; /* fatal error in ordinal processing, can be returned */ TPM_TAG tag = 0; uint32_t paramSize = 0; TPM_COMMAND_CODE ordinal = 0; tpm_process_function_t tpm_process_function = NULL; /* based on ordinal */ tpm_state_t *targetInstance = NULL; /* TPM global state */ TPM_STORE_BUFFER localBuffer; /* for response if instance was not found */ TPM_STORE_BUFFER *sbuffer; /* either localBuffer or the instance response buffer */ TPM_Sbuffer_Init(&localBuffer); /* freed @1 */ /* get the global TPM state */ if ((rc == 0) && (returnCode == TPM_SUCCESS)) { targetInstance = tpm_instances[0]; } if ((rc == 0) && (returnCode == TPM_SUCCESS)) { /* clear the response form the previous ordinal, the response buffer is reused */ TPM_Sbuffer_Clear(&(targetInstance->tpm_stclear_data.ordinalResponse)); /* extract the standard command parameters from the command stream */ returnCode = TPM_Process_GetCommandParams(&tag, ¶mSize, &ordinal, &command, &command_size); } /* preprocessing common to all ordinals */ if ((rc == 0) && (returnCode == TPM_SUCCESS)) { returnCode = TPM_Process_Preprocess(targetInstance, ordinal, NULL); } /* NOTE Only for debugging */ if ((rc == 0) && (returnCode == TPM_SUCCESS)) { TPM_KeyHandleEntries_Trace(targetInstance->tpm_key_handle_entries); } /* process the ordinal */ if ((rc == 0) && (returnCode == TPM_SUCCESS)) { /* get the processing function from the ordinal table */ TPM_OrdinalTable_GetProcessFunction(&tpm_process_function, tpm_ordinal_table, ordinal); /* call the processing function to execute the command */ returnCode = tpm_process_function(targetInstance, &(targetInstance->tpm_stclear_data.ordinalResponse), tag, command_size, ordinal, command, NULL); /* not from encrypted transport */ } /* NOTE Only for debugging */ if ((rc == 0) && (returnCode == TPM_SUCCESS)) { TPM_KeyHandleEntries_Trace(targetInstance->tpm_key_handle_entries); } /* NOTE Only for debugging */ if ((rc == 0) && (returnCode == TPM_SUCCESS)) { TPM_State_Trace(targetInstance); } #ifdef TPM_VOLATILE_STORE /* save the volatile state after each command to handle fail-over restart */ if ((rc == 0) && (returnCode == TPM_SUCCESS)) { returnCode = TPM_VolatileAll_NVStore(targetInstance); } #endif /* TPM_VOLATILE_STORE */ /* If the ordinal processing function returned without a fatal error, append its ordinalResponse to the output response buffer */ if ((rc == 0) && (returnCode == TPM_SUCCESS)) { returnCode = TPM_Sbuffer_AppendSBuffer(response, &(targetInstance->tpm_stclear_data.ordinalResponse)); } if ((rc == 0) && (returnCode != TPM_SUCCESS)) { /* gets here if: - there was an error before the ordinal was processed - the ordinal returned a fatal error - an error occurred appending the ordinal response returnCode should be the response errors here are fatal, can't create an error response */ /* if it failed after the target instance was found, use the instance's response buffer */ if (targetInstance != NULL) { sbuffer = &(targetInstance->tpm_stclear_data.ordinalResponse); } /* if it failed before even the target instance was found, use a local buffer */ else { sbuffer = &localBuffer; } if (rc == 0) { /* it's not even known whether the initial response was stored, so just start over */ TPM_Sbuffer_Clear(sbuffer); /* store the tag, paramSize, and returnCode */ printf("TPM_Process: Ordinal returnCode %08x %u\n", returnCode, returnCode); rc = TPM_Sbuffer_StoreInitialResponse(sbuffer, TPM_TAG_RQU_COMMAND, returnCode); } /* call this to handle the TPM_FAIL causing the TPM going into failure mode */ if (rc == 0) { rc = TPM_Sbuffer_StoreFinalResponse(sbuffer, returnCode, targetInstance); } if (rc == 0) { rc = TPM_Sbuffer_AppendSBuffer(response, sbuffer); } } /* cleanup */ TPM_Sbuffer_Delete(&localBuffer); /* @1 */ return rc; } /* TPM_Process_Wrapped() is called recursively to process a wrapped command. 'command_size' is the actual size of the command stream. 'targetInstance' is an input indicating the TPM instance being called. 'transportInternal' not NULL indicates that this function was called recursively from TPM_ExecuteTransport For wrapped commands, this function cannot trust that command_size and the incoming paramSize in the command stream are consistent. Therefore, this function checks for consistency. The processor ensures that the response bytes are set according to the outgoing paramSize on return. Returns: 0 on success non-zero on a fatal error preventing the command from being processed. The response is invalid in this case. */ TPM_RESULT TPM_Process_Wrapped(TPM_STORE_BUFFER *response, unsigned char *command, /* complete command array */ uint32_t command_size, /* actual bytes in command */ tpm_state_t *targetInstance, /* global TPM state */ TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rc = 0; /* fatal error, no response */ TPM_RESULT returnCode = TPM_SUCCESS; /* non-fatal error, returned in response */ TPM_TAG tag = 0; uint32_t paramSize = 0; TPM_COMMAND_CODE ordinal = 0; tpm_process_function_t tpm_process_function = NULL; /* based on ordinal */ TPM_STORE_BUFFER ordinalResponse; /* response for this ordinal */ printf("TPM_Process_Wrapped:\n"); TPM_Sbuffer_Init(&ordinalResponse); /* freed @1 */ /* Set the tag, paramSize, and ordinal from the wrapped command stream */ /* If paramSize does not equal the command stream size, return TPM_BAD_PARAM_SIZE */ if ((rc == 0) && (returnCode == TPM_SUCCESS)) { returnCode = TPM_Process_GetCommandParams(&tag, ¶mSize, &ordinal, &command, &command_size); } /* preprocessing common to all ordinals */ if ((rc == 0) && (returnCode == TPM_SUCCESS)) { returnCode = TPM_Process_Preprocess(targetInstance, ordinal, transportInternal); } /* process the ordinal */ if ((rc == 0) && (returnCode == TPM_SUCCESS)) { /* get the processing function from the ordinal table */ TPM_OrdinalTable_GetProcessFunction(&tpm_process_function, tpm_ordinal_table, ordinal); /* call the processing function to execute the command */ returnCode = tpm_process_function(targetInstance, &ordinalResponse, tag, command_size, ordinal, command, transportInternal); } /* If the ordinal processing function returned without a fatal error, append its ordinalResponse to the output response buffer */ if ((rc == 0) && (returnCode == TPM_SUCCESS)) { returnCode = TPM_Sbuffer_AppendSBuffer(response, &ordinalResponse); } /* If: - an error in this function occurred before the ordinal was processed - the ordinal processing function returned a fatal error - an error occurred appending the ordinal response then use the return code of that failure as the final response. Failure here is fatal, since no error code can be returned. */ if ((rc == 0) && (returnCode != TPM_SUCCESS)) { rc = TPM_Sbuffer_StoreFinalResponse(response, returnCode, targetInstance); } /* cleanup */ TPM_Sbuffer_Delete(&ordinalResponse); /* @1 */ return rc; } /* TPM_Process_GetCommandParams() gets the standard 3 parameters from the command input stream The stream is adjusted to point past the parameters. The resulting paramSize is checked against the stream size for consistency. paramSize is returned for reference, but command_size reflects the remaining bytes in the stream. */ TPM_RESULT TPM_Process_GetCommandParams(TPM_TAG *tag, uint32_t *paramSize , TPM_COMMAND_CODE *ordinal, unsigned char **command, uint32_t *command_size) { TPM_RESULT rc = 0; printf(" TPM_Process_GetCommandParams:\n"); /* get tag */ if (rc == 0) { rc = TPM_Load16(tag, command, command_size); } /* get paramSize */ if (rc == 0) { rc = TPM_Load32(paramSize, command, command_size); } /* get ordinal */ if (rc == 0) { rc = TPM_Load32(ordinal, command, command_size); } /* check the paramSize against the command_size */ if (rc == 0) { if (*paramSize != *command_size + sizeof(TPM_TAG) + sizeof(uint32_t) + sizeof(TPM_COMMAND_CODE)) { printf("TPM_Process_GetCommandParams: Error, " "command size %lu not equal to paramSize %u\n", (unsigned long) (*command_size + sizeof(TPM_TAG) + sizeof(uint32_t) + sizeof(TPM_COMMAND_CODE)), *paramSize); rc = TPM_BAD_PARAM_SIZE; } else { printf(" TPM_Process_GetCommandParams: tag %04x paramSize %u ordinal %08x\n", *tag, *paramSize, *ordinal); } } return rc; } /* TPM_Process_GetResponseParams() gets the standard 3 parameters from the response output stream The stream is adjusted to point past the parameters. The resulting paramSize is checked against the stream size for consistency. paramSize is returned for reference, but response_size reflects the remaining bytes in the stream. */ TPM_RESULT TPM_Process_GetResponseParams(TPM_TAG *tag, uint32_t *paramSize , TPM_RESULT *returnCode, unsigned char **response, uint32_t *response_size) { TPM_RESULT rc = 0; printf(" TPM_Process_GetResponseParams:\n"); /* get tag */ if (rc == 0) { rc = TPM_Load16(tag, response, response_size); } /* get paramSize */ if (rc == 0) { rc = TPM_Load32(paramSize, response, response_size); } /* get returnCode */ if (rc == 0) { rc = TPM_Load32(returnCode, response, response_size); } /* check the paramSize against the response_size */ if (rc == 0) { if (*paramSize != (*response_size + sizeof(TPM_TAG) + sizeof(uint32_t) + sizeof(TPM_RESULT))) { printf("TPM_Process_GetResponseParams: Error, " "response size %lu not equal to paramSize %u\n", (unsigned long) (*response_size + sizeof(TPM_TAG) + sizeof(uint32_t) + sizeof(TPM_RESULT)), *paramSize); rc = TPM_BAD_PARAM_SIZE; } else { printf(" TPM_Process_GetResponseParams: tag %04x paramSize %u ordinal %08x\n", *tag, *paramSize, *returnCode); } } return rc; } /* TPM_CheckRequestTagnnn() is common code to verify the command tag */ TPM_RESULT TPM_CheckRequestTag210(TPM_TAG tpm_tag) { TPM_RESULT rc = 0; if ((tpm_tag != TPM_TAG_RQU_AUTH2_COMMAND) && (tpm_tag != TPM_TAG_RQU_AUTH1_COMMAND) && (tpm_tag != TPM_TAG_RQU_COMMAND)) { printf("TPM_CheckRequestTag210: Error, tag %04hx\n", tpm_tag); rc = TPM_BADTAG; } return rc; } TPM_RESULT TPM_CheckRequestTag21(TPM_TAG tpm_tag) { TPM_RESULT rc = 0; if ((tpm_tag != TPM_TAG_RQU_AUTH2_COMMAND) && (tpm_tag != TPM_TAG_RQU_AUTH1_COMMAND)) { printf("TPM_CheckRequestTag21: Error, tag %04hx\n", tpm_tag); rc = TPM_BADTAG; } return rc; } TPM_RESULT TPM_CheckRequestTag2(TPM_TAG tpm_tag) { TPM_RESULT rc = 0; if (tpm_tag != TPM_TAG_RQU_AUTH2_COMMAND) { printf("TPM_CheckRequestTag2: Error, tag %04hx\n", tpm_tag); rc = TPM_BADTAG; } return rc; } TPM_RESULT TPM_CheckRequestTag10(TPM_TAG tpm_tag) { TPM_RESULT rc = 0; if ((tpm_tag != TPM_TAG_RQU_AUTH1_COMMAND) && (tpm_tag != TPM_TAG_RQU_COMMAND)) { printf("TPM_CheckRequestTag10: Error, tag %04hx\n", tpm_tag); rc = TPM_BADTAG; } return rc; } TPM_RESULT TPM_CheckRequestTag1(TPM_TAG tpm_tag) { TPM_RESULT rc = 0; if (tpm_tag != TPM_TAG_RQU_AUTH1_COMMAND) { printf("TPM_CheckRequestTag1: Error, tag %04hx\n", tpm_tag); rc = TPM_BADTAG; } return rc; } TPM_RESULT TPM_CheckRequestTag0(TPM_TAG tpm_tag) { TPM_RESULT rc = 0; if (tpm_tag != TPM_TAG_RQU_COMMAND) { printf("TPM_CheckRequestTag0: Error, tag %04hx\n", tpm_tag); rc = TPM_BADTAG; } return rc; } TPM_RESULT TPM_Process_Unused(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; printf("TPM_Process_Unused:\n"); tpm_state = tpm_state; /* not used */ paramSize = paramSize; /* not used */ ordinal = ordinal; /* not used */ command = command; /* not used */ transportInternal = transportInternal; /* not used */ printf("TPM_Process_Unused: Ordinal returnCode %08x %u\n", TPM_BAD_ORDINAL, TPM_BAD_ORDINAL); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, TPM_BAD_ORDINAL); return rcf; } /* TPM_CheckState() should be called by all commands. It checks a set of flags specified by tpm_check_map to determine whether the command can execute in that state. Returns: 0 if the command can execute non-zero error code that should be returned as a response */ TPM_RESULT TPM_CheckState(tpm_state_t *tpm_state, TPM_TAG tag, uint32_t tpm_check_map) { TPM_RESULT rc = 0; printf(" TPM_CheckState: Check map %08x\n", tpm_check_map); /* check the dictionary attack lockout, only for authorized commands */ if (rc == 0) { if ((tpm_check_map & TPM_CHECK_NO_LOCKOUT) && (tag != TPM_TAG_RQU_COMMAND)) { rc = TPM_Authdata_CheckState(tpm_state); } } /* TPM_GetTestResult. This command can assist the TPM manufacturer in determining the cause of the self-test failure. iii. All other operations will return the error code TPM_FAILEDSELFTEST. */ if (rc == 0) { if (tpm_check_map & TPM_CHECK_NOT_SHUTDOWN) { if (tpm_state->testState == TPM_TEST_STATE_FAILURE) { printf("TPM_CheckState: Error, shutdown is TRUE\n"); rc = TPM_FAILEDSELFTEST; } } } /* TPM_Startup SHALL execute as normal, and is the only function that does not call TPM_CheckState(). All other commands SHALL return TPM_INVALID_POSTINIT */ if (rc == 0) { if (tpm_state->tpm_stany_flags.postInitialise) { printf("TPM_CheckState: Error, postInitialise is TRUE\n"); rc = TPM_INVALID_POSTINIT; } } /* For checking disabled and deactivated, the check is NOT done if it's one of the special NV commands (indicated by TPM_CHECK_NV_NOAUTH) and nvLocked is FALSE, indicating that the NV store does not require authorization */ /* For commands available only when enabled. */ if (rc == 0) { if ((tpm_check_map & TPM_CHECK_ENABLED) && !((tpm_check_map & TPM_CHECK_NV_NOAUTH) && !tpm_state->tpm_permanent_flags.nvLocked)) { if (tpm_state->tpm_permanent_flags.disable) { printf("TPM_CheckState: Error, disable is TRUE\n"); rc = TPM_DISABLED; } } } /* For commands only available when activated. */ if (rc == 0) { if ((tpm_check_map & TPM_CHECK_ACTIVATED) && !((tpm_check_map & TPM_CHECK_NV_NOAUTH) && !tpm_state->tpm_permanent_flags.nvLocked)) { if (tpm_state->tpm_stclear_flags.deactivated) { printf("TPM_CheckState: Error, deactivated is TRUE\n"); rc = TPM_DEACTIVATED; } } } /* For commands available only after an owner is installed. see Ordinals chart */ if (rc == 0) { if (tpm_check_map & TPM_CHECK_OWNER) { if (!tpm_state->tpm_permanent_data.ownerInstalled) { printf("TPM_CheckState: Error, ownerInstalled is FALSE\n"); rc = TPM_NOSRK; } } } return rc; } /* TPM_Process_Preprocess() handles check functions common to all ordinals 'transportPublic' not NULL indicates that this function was called recursively from TPM_ExecuteTransport */ TPM_RESULT TPM_Process_Preprocess(tpm_state_t *tpm_state, TPM_COMMAND_CODE ordinal, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rc = 0; /* fatal error, no response */ printf(" TPM_Process_Preprocess: Ordinal %08x\n", ordinal); /* Preprocess to check if command can be run in limited operation mode */ if (rc == 0) { if (tpm_state->testState == TPM_TEST_STATE_LIMITED) { /* 1. At startup, a TPM MUST self-test all internal functions that are necessary to do TPM_SHA1Start, TPM_SHA1Update, TPM_SHA1Complete, TPM_SHA1CompleteExtend, TPM_Extend, TPM_Startup, TPM_ContinueSelfTest, a subset of TPM_GetCapability, and TPM_GetTestResult.. */ if (!((ordinal == TPM_ORD_Startup) || (ordinal == TPM_ORD_SHA1Start) || (ordinal == TPM_ORD_SHA1Update) || (ordinal == TPM_ORD_SHA1Complete) || (ordinal == TPM_ORD_SHA1CompleteExtend) || (ordinal == TPM_ORD_Extend) || (ordinal == TPM_ORD_Startup) || (ordinal == TPM_ORD_ContinueSelfTest) || /* a subset of TPM_GetCapability does not require self-test. The ordinal itself decides whether to run TPM_ContinueSelfTest() */ (ordinal == TPM_ORD_GetCapability) || /* 3. The TPM MAY allow TPM_SelfTestFull to be used before completion of the actions of TPM_ContinueSelfTest. */ (ordinal == TPM_ORD_SelfTestFull) || (ordinal == TPM_ORD_GetTestResult) || /* 2. The TSC_PhysicalPresence and TSC_ResetEstablishmentBit commands do not operate on shielded-locations and have no requirement to be self-tested before any use. TPM's SHOULD test these functions before operation. */ (ordinal == TSC_ORD_PhysicalPresence) || (ordinal == TSC_ORD_ResetEstablishmentBit) )) { /* One of the optional actions. */ /* rc = TPM_NEEDS_SELFTEST; */ /* Alternatively, could run the actions of continue self-test */ rc = TPM_ContinueSelfTestCmd(tpm_state); } } } /* special pre-processing for SHA1 context */ if (rc == 0) { rc = TPM_Check_SHA1Context(tpm_state, ordinal, transportInternal); } /* Special pre-processing to invalidate the saved state if it exists. Omit this processing for TPM_Startup, since that function might restore the state first */ if (rc == 0) { if (tpm_state->tpm_stany_flags.stateSaved && !((ordinal == TPM_ORD_Startup) || (ordinal == TPM_ORD_Init))) { /* For any other ordinal, invalidate the saved state if it exists. */ rc = TPM_SaveState_NVDelete(tpm_state, TRUE); } } /* When an exclusive session is running, execution of any command other then TPM_ExecuteTransport or TPM_ReleaseTransportSigned targeting the exclusive session causes the abnormal invalidation of the exclusive transport session. */ if ((rc == 0) && (transportInternal == NULL)) { /* do test only for the outer ordinal */ if ((tpm_state->tpm_stany_flags.transportExclusive != 0) && /* active exclusive */ /* These two ordinals terminate the exclusive transport session if the transport handle is not the specified handle. So the check is deferred until the command is parsed for the transport handle. */ !((ordinal == TPM_ORD_ExecuteTransport) || (ordinal == TPM_ORD_ReleaseTransportSigned))) { rc = TPM_TransportSessions_TerminateHandle (tpm_state->tpm_stclear_data.transSessions, tpm_state->tpm_stany_flags.transportExclusive, &(tpm_state->tpm_stany_flags.transportExclusive)); } } /* call platform specific code to set the localityModifier */ if ((rc == 0) && (transportInternal == NULL)) { /* do only for the outer ordinal */ rc = TPM_IO_GetLocality(&(tpm_state->tpm_stany_flags.localityModifier), tpm_state->tpm_number); } return rc; } /* TPM_Check_SHA1Context() checks the current SHA1 context The TPM may not allow any other types of processing during the execution of a SHA-1 session. There is only one SHA-1 session active on a TPM. After the execution of SHA1Start, and prior to SHA1End, the receipt of any command other than SHA1Update will cause the invalidation of the SHA-1 session. 2. After receipt of TPM_SHA1Start, and prior to the receipt of TPM_SHA1Complete or TPM_SHA1CompleteExtend, receipt of any command other than TPM_SHA1Update invalidates the SHA-1 session. a. If the command received is TPM_ExecuteTransport, the SHA-1 session invalidation is based on the wrapped command, not the TPM_ExecuteTransport ordinal. b. A SHA-1 thread (start, update, complete) MUST take place either completely outside a transport session or completely within a single transport session. */ TPM_RESULT TPM_Check_SHA1Context(tpm_state_t *tpm_state, TPM_COMMAND_CODE ordinal, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rc = 0; if ((tpm_state->sha1_context != NULL) && /* if there was a SHA-1 context set up */ (ordinal != TPM_ORD_ExecuteTransport)) /* depends on the wrapped command */ { /* the non-SHA1 ordinals invalidate the SHA-1 session */ if ( ((ordinal != TPM_ORD_SHA1Update) && (ordinal != TPM_ORD_SHA1Complete) && (ordinal != TPM_ORD_SHA1CompleteExtend)) || /* invalidate if the SHA1 ordinal is within a transport session and the session was not set up within the same transport session. */ ((transportInternal != NULL) && (tpm_state->transportHandle != transportInternal->transHandle)) || /* invalidate if the SHA1 ordinal is not within a transport session and the session was set up with a transport session */ ((transportInternal == NULL) && (tpm_state->transportHandle != 0)) ) { printf("TPM_Check_SHA1Context: Invalidating SHA1 context\n"); TPM_SHA1Delete(&(tpm_state->sha1_context)); } } return rc; } /* TPM_GetInParamDigest() does common processing of input parameters. Common processing includes: - determining if the ordinal is being run within an encrypted transport session, since the inParamDigest does not have to be calculated for audit in that case. - retrieving the audit status. It is determinant of whether the input parameter digest should be calculated. - calculating the input parameter digest for HMAC authorization and/or auditing This function is called before authorization for several reasons. 1 - It makes ordinal processing code more uniform, since authorization sometimes occurs far into the actions. 2 - It is a minor optimization, since the resulting inParamDigest can be used twice in an auth-2 command, as well as extending the audit digest. */ TPM_RESULT TPM_GetInParamDigest(TPM_DIGEST inParamDigest, /* output */ TPM_BOOL *auditStatus, /* output */ TPM_BOOL *transportEncrypt, /* output */ tpm_state_t *tpm_state, TPM_TAG tag, TPM_COMMAND_CODE ordinal, unsigned char *inParamStart, unsigned char *inParamEnd, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rc = 0; /* this function return code */ TPM_COMMAND_CODE nOrdinal; /* ordinal in network byte order */ printf(" TPM_GetInParamDigest:\n"); if (rc == 0) { /* TRUE if called from encrypted transport session. This is currently only needed when auditing, but it's safer to always initialize it */ *transportEncrypt = (transportInternal != NULL) && (transportInternal->transPublic.transAttributes & TPM_TRANSPORT_ENCRYPT); printf(" TPM_GetInParamDigest: transportEncrypt %02x\n", *transportEncrypt); /* Determine if the ordinal should be audited. */ rc = TPM_OrdinalAuditStatus_GetAuditStatus(auditStatus, ordinal, &(tpm_state->tpm_permanent_data)); } /* If inParamDigest is needed for: 1 - for auditing (auditStatus == TRUE) and not called from an encrypted transport. Different parameters are audited if the ordinal is called through an encrypted transport session. 2 - for authorization (tag != auth-0) */ if (rc == 0) { if ((*auditStatus && !(*transportEncrypt)) || /* digest for auditing */ (tag != TPM_TAG_RQU_COMMAND)) { /* digest for authorization */ /* convert ordinal to network byte order */ nOrdinal = htonl(ordinal); /* a. Create inParamDigest - digest of inputs above the double line. NOTE: If there are no inputs other than the ordinal, inParamEnd - inParamStart will be 0, terminating the SHA1 vararg hash. It is important that the termination condition be the length and not the NULL pointer. */ rc = TPM_SHA1(inParamDigest, sizeof(TPM_COMMAND_CODE), &nOrdinal, /* 1S */ inParamEnd - inParamStart, inParamStart, /* 2S - ... */ 0, NULL); if (rc == 0) { TPM_PrintFour(" TPM_GetInParamDigest: inParamDigest", inParamDigest); } } } return rc; } /* TPM_GetOutParamDigest() does common processing of output parameters. It calculates the output parameter digest for HMAC generation and/or auditing if required. */ TPM_RESULT TPM_GetOutParamDigest(TPM_DIGEST outParamDigest, /* output */ TPM_BOOL auditStatus, /* input audit status */ TPM_BOOL transportEncrypt, /* wrapped in encrypt transport */ TPM_TAG tag, TPM_RESULT returnCode, TPM_COMMAND_CODE ordinal, /* command ordinal (hbo) */ unsigned char *outParamStart, /* starting point of param's */ uint32_t outParamLength) /* length of param's */ { TPM_RESULT rc = 0; TPM_RESULT nreturnCode; /* returnCode in nbo */ TPM_COMMAND_CODE nOrdinal; /* ordinal in network byte order */ printf(" TPM_GetOutParamDigest:\n"); if (rc == 0) { if ((auditStatus && !transportEncrypt) || (tag != TPM_TAG_RQU_COMMAND)) { nreturnCode = htonl(returnCode); nOrdinal = htonl(ordinal); /* a. Create outParamDigest - digest of outputs above the double line. NOTE: If there are no outputs other than the returnCode and ordinal, outParamLength will be 0, terminating the SHA1 vararg hash. It is important that the termination condition be the length and not the NULL pointer. */ rc = TPM_SHA1(outParamDigest, sizeof(TPM_RESULT), &nreturnCode, /* 1S */ sizeof(TPM_COMMAND_CODE), &nOrdinal, /* 2S */ outParamLength, outParamStart, /* 3S - ...*/ 0, NULL); if (rc == 0) { TPM_PrintFour(" TPM_GetOutParamDigest: outParamDigest", outParamDigest); } } } return rc; } /* TPM_ProcessAudit() rev 109 This function is called when command auditing is required. This function must be called after the output authorization, since it requires the (almost) final return code. */ TPM_RESULT TPM_ProcessAudit(tpm_state_t *tpm_state, TPM_BOOL transportEncrypt, /* wrapped in encrypt transport */ TPM_DIGEST inParamDigest, TPM_DIGEST outParamDigest, TPM_COMMAND_CODE ordinal) { TPM_RESULT rc = 0; /* audit return code */ TPM_BOOL isZero; TPM_RESULT nreturnCode; /* returnCode in nbo */ TPM_COMMAND_CODE nOrdinal; /* ordinal in network byte order */ TPM_DIGEST transportDigest; /* special case digest in encrypted transport */ printf(" TPM_ProcessAudit:\n"); /* The TPM will execute the ordinal and perform auditing in the following manner: */ /* 1. Execute command */ /* a. Execution implies the performance of the listed actions for the ordinal. */ /* 2. If the command will return TPM_SUCCESS */ /* a. If TPM_STANY_DATA -> auditDigest is all zeros */ if (rc == 0) { TPM_Digest_IsZero(&isZero, tpm_state->tpm_stclear_data.auditDigest); if (isZero) { /* i. Increment TPM_PERMANENT_DATA -> auditMonotonicCounter by 1 */ tpm_state->tpm_permanent_data.auditMonotonicCounter.counter++; printf(" TPM_ProcessAudit: Incrementing auditMonotonicCounter to %u\n", tpm_state->tpm_permanent_data.auditMonotonicCounter.counter); rc = TPM_PermanentAll_NVStore(tpm_state, TRUE, /* write NV */ 0); /* no roll back */ } } /* b. Create A1 a TPM_AUDIT_EVENT_IN structure */ /* i. Set A1 -> inputParms to the digest of the input parameters from the command */ /* (1) Digest value according to the HMAC digest rules of the "above the line" parameters (i.e. the first HMAC digest calculation). */ /* ii. Set A1 -> auditCount to TPM_PERMANENT_DATA -> auditMonotonicCounter */ /* c. Set TPM_STANY_DATA -> auditDigest to SHA-1 (TPM_STANY_DATA -> auditDigest || A1) */ if (rc == 0) { /* normal case, audit uses inParamDigest */ if (!transportEncrypt) { rc = TPM_AuditDigest_ExtendIn(tpm_state, inParamDigest); } /* 1. When the wrapped command requires auditing and the transport session specifies encryption, the TPM MUST perform the audit. However, when computing the audit digest: */ else { /* a. For input, only the ordinal is audited. */ if (rc == 0) { nOrdinal = htonl(ordinal); rc = TPM_SHA1(transportDigest, sizeof(TPM_COMMAND_CODE), &nOrdinal, 0, NULL); } if (rc == 0) { rc = TPM_AuditDigest_ExtendIn(tpm_state, transportDigest); } } } /* d. Create A2 a TPM_AUDIT_EVENT_OUT structure */ /* i. Set A2 -> outputParms to the digest of the output parameters from the command */ /* (1). Digest value according to the HMAC digest rules of the "above the line" parameters (i.e. the first HMAC digest calculation). */ /* ii. Set A2 -> auditCount to TPM_PERMANENT_DATA -> auditMonotonicCounter */ /* e. Set TPM_STANY_DATA -> auditDigest to SHA-1 (TPM_STANY_DATA -> auditDigest || A2) */ /* Audit Generation Corner cases 3.a. TPM_SaveState: Only the input parameters are audited, and the audit occurs before the state is saved. If an error occurs while or after the state is saved, the audit still occurs. */ if ((rc == 0) && (ordinal != TPM_ORD_SaveState)) { /* normal case, audit uses outParamDigest */ if (!transportEncrypt) { rc = TPM_AuditDigest_ExtendOut(tpm_state, outParamDigest); } /* 1. When the wrapped command requires auditing and the transport session specifies encryption, the TPM MUST perform the audit. However, when computing the audit digest: */ else { /* b. For output, only the ordinal and return code are audited. */ if (rc == 0) { nreturnCode = htonl(TPM_SUCCESS); /* only called when TPM_SUCCESS */ nOrdinal = htonl(ordinal); rc = TPM_SHA1(transportDigest, sizeof(TPM_RESULT), &nreturnCode, sizeof(TPM_COMMAND_CODE), &nOrdinal, 0, NULL); } if (rc == 0) { rc = TPM_AuditDigest_ExtendOut(tpm_state, transportDigest); } } } /* 1. When, in performing the audit process, the TPM has an internal failure (unable to write, SHA-1 failure etc.) the TPM MUST set the internal TPM state such that the TPM returns the TPM_FAILEDSELFTEST error on subsequent attempts to execute a command. */ /* 2. The return code for the command uses the following rules */ /* a. Command result success, audit success -> return TPM_SUCCESS */ /* b. Command result failure, no audit -> return command result failure */ /* c. Command result success, audit failure -> return TPM_AUDITFAIL_SUCCESSFUL */ /* 3. If the TPM is permanently nonrecoverable after an audit failure, then the TPM MUST always return TPM_FAILEDSELFTEST for every command other than TPM_GetTestResult. This state must persist regardless of power cycling, the execution of TPM_Init or any other actions. */ if (rc != 0) { rc = TPM_AUDITFAIL_SUCCESSFUL; tpm_state->testState = TPM_TEST_STATE_FAILURE; } return rc; } /* Processing Functions */ /* 7.1 TPM_GetCapability rev 99 This command returns current information regarding the TPM. The limitation on what can be returned in failure mode restricts the information a manufacturer may return when capArea indicates TPM_CAP_MFR. */ TPM_RESULT TPM_Process_GetCapability(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_TAG returnCode = 0; /* command return code */ /* input parameters */ TPM_CAPABILITY_AREA capArea; /* Partition of capabilities to be interrogated */ TPM_SIZED_BUFFER subCap; /* Further definition of information */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt = FALSE;/* wrapped in encrypted transport session */ uint16_t subCap16 = 0; /* the subCap as a uint16_t */ uint32_t subCap32 = 0; /* the subCap as a uint32_t */ TPM_STORE_BUFFER capabilityResponse; /* response */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_GetCapability: Ordinal Entry\n"); TPM_SizedBuffer_Init(&subCap); /* freed @1 */ TPM_Sbuffer_Init(&capabilityResponse); /* freed @2 */ /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get capArea parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&capArea, &command, ¶mSize); } /* get subCap parameter */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_GetCapability: capArea %08x\n", capArea); returnCode = TPM_SizedBuffer_Load(&subCap, &command, ¶mSize); } /* subCap is often a uint16_t or uint32_t, create them now */ if (returnCode == TPM_SUCCESS) { TPM_GetSubCapInt(&subCap16, &subCap32, &subCap); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ /* The shutdown test is delayed until after the subcap is calculated */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_NO_LOCKOUT); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_GetCapability: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* check state */ /* 1. The TPM validates the capArea and subCap indicators. If the information is available, the TPM creates the response field and fills in the actual information. */ /* 2. The structure document contains the list of caparea and subCap values */ if (returnCode == TPM_SUCCESS) { /* 3. If the TPM is in failure mode or limited operation mode, the TPM MUST return */ if ((tpm_state->testState == TPM_TEST_STATE_FAILURE) || (tpm_state->testState == TPM_TEST_STATE_LIMITED)) { /* a. TPM_CAP_VERSION */ /* b. TPM_CAP_VERSION_VAL */ /* c. TPM_CAP_MFR */ /* d. TPM_CAP_PROPERTY -> TPM_CAP_PROP_MANUFACTURER */ /* e. TPM_CAP_PROPERTY -> TPM_CAP_PROP_DURATION */ /* f. TPM_CAP_PROPERTY -> TPM_CAP_PROP_TIS_TIMEOUT */ /* g. The TPM MAY return any other capability. */ if ( !(capArea == TPM_CAP_VERSION) && !(capArea == TPM_CAP_VERSION_VAL) && !(capArea == TPM_CAP_MFR) && !((capArea == TPM_CAP_PROPERTY) && (subCap32 == TPM_CAP_PROP_MANUFACTURER)) && !((capArea == TPM_CAP_PROPERTY) && (subCap32 == TPM_CAP_PROP_DURATION)) && !((capArea == TPM_CAP_PROPERTY) && (subCap32 == TPM_CAP_PROP_TIS_TIMEOUT)) ) { if (tpm_state->testState == TPM_TEST_STATE_FAILURE) { printf("TPM_Process_GetCapability: Error, shutdown capArea %08x subCap %08x\n", capArea, subCap32); returnCode = TPM_FAILEDSELFTEST; } else { printf("TPM_Process_GetCapability: Limited operation, run self-test\n"); returnCode = TPM_ContinueSelfTestCmd(tpm_state); } } } } /* Processing */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_GetCapability: capArea %08x subCap32 subCap16 %08x %04x\n", capArea, subCap32, subCap16); returnCode = TPM_GetCapabilityCommon(&capabilityResponse, tpm_state, capArea, subCap16, subCap32, &subCap); } /* response */ if (rcf == 0) { printf("TPM_Process_GetCapability: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* store the capabilityResponse */ returnCode = TPM_Sbuffer_AppendAsSizedBuffer(response, &capabilityResponse); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* cleanup */ TPM_SizedBuffer_Delete(&subCap); /* @1 */ TPM_Sbuffer_Delete(&capabilityResponse); /* @2 */ return rcf; } /* TPM_GetSubCapInt() converts from a TPM_SIZED_BUFFER to either a uint16_t or uint32_t as applicable No return code is needed. If the size it not applicable, a 0 value is returned, which is (fortunately) always illegal for subCap integral values. */ void TPM_GetSubCapInt(uint16_t *subCap16, uint32_t *subCap32, TPM_SIZED_BUFFER *subCap) { *subCap16 = 0; /* default, means was not a uint16_t */ *subCap32 = 0; /* default, means was not a uint32_t */ if (subCap->size == sizeof(uint32_t)) { *subCap32 = htonl(*(uint32_t *)subCap->buffer); printf(" TPM_GetSubCapInt: subCap %08x\n", *subCap32); } else if (subCap->size == sizeof(uint16_t)) { *subCap16 = htons(*(uint16_t *)subCap->buffer); printf(" TPM_GetSubCapInt: subCap %04x\n", *subCap16); } } /* TPM_GetCapabilityCommon() is common code for getting a capability. It loads the result to 'capabilityResponse' A previously called TPM_GetSubCapInt() converts the subCap buffer into a subCap16 if the size is 2 or subCap32 if the size is 4. If the values are used, this function checks the size to ensure that the incoming subCap parameter was correct for the capArea. */ TPM_RESULT TPM_GetCapabilityCommon(TPM_STORE_BUFFER *capabilityResponse, tpm_state_t *tpm_state, TPM_CAPABILITY_AREA capArea, uint16_t subCap16, uint32_t subCap32, TPM_SIZED_BUFFER *subCap) { TPM_RESULT rc = 0; printf(" TPM_GetCapabilityCommon: capArea %08x\n", capArea); switch (capArea) { case TPM_CAP_ORD: if (subCap->size == sizeof(uint32_t)) { rc = TPM_GetCapability_CapOrd(capabilityResponse, subCap32); } else { printf("TPM_GetCapabilityCommon: Error, Bad subCap size %u\n", subCap->size); rc = TPM_BAD_MODE; } break; case TPM_CAP_ALG: if (subCap->size == sizeof(uint32_t)) { rc = TPM_GetCapability_CapAlg(capabilityResponse, subCap32); } else { printf("TPM_GetCapabilityCommon: Error, Bad subCap size %u\n", subCap->size); rc = TPM_BAD_MODE; } break; case TPM_CAP_PID: if (subCap->size == sizeof(uint16_t)) { rc = TPM_GetCapability_CapPid(capabilityResponse, subCap16); } else { printf("TPM_GetCapabilityCommon: Error, Bad subCap size %u\n", subCap->size); rc = TPM_BAD_MODE; } break; case TPM_CAP_FLAG: if (subCap->size == sizeof(uint32_t)) { rc = TPM_GetCapability_CapFlag(capabilityResponse, tpm_state, subCap32); } else { printf("TPM_GetCapabilityCommon: Error, Bad subCap size %u\n", subCap->size); rc = TPM_BAD_MODE; } break; case TPM_CAP_PROPERTY: if (subCap->size == sizeof(uint32_t)) { rc = TPM_GetCapability_CapProperty(capabilityResponse, tpm_state, subCap32); } else { printf("TPM_GetCapabilityCommon: Error, Bad subCap size %u\n", subCap->size); rc = TPM_BAD_MODE; } break; case TPM_CAP_VERSION: rc = TPM_GetCapability_CapVersion(capabilityResponse); break; case TPM_CAP_KEY_HANDLE: /* This is command is available for backwards compatibility. It is the same as TPM_CAP_HANDLE with a resource type of keys. */ rc = TPM_KeyHandleEntries_StoreHandles(capabilityResponse, tpm_state->tpm_key_handle_entries); break; case TPM_CAP_CHECK_LOADED: rc = TPM_GetCapability_CapCheckLoaded(capabilityResponse, tpm_state->tpm_key_handle_entries, subCap); break; case TPM_CAP_SYM_MODE: if (subCap->size == sizeof(uint32_t)) { rc = TPM_GetCapability_CapSymMode(capabilityResponse, subCap32); } else { printf("TPM_GetCapabilityCommon: Error, Bad subCap size %u\n", subCap->size); rc = TPM_BAD_MODE; } break; case TPM_CAP_KEY_STATUS: if (subCap->size == sizeof(uint32_t)) { rc = TPM_GetCapability_CapKeyStatus(capabilityResponse, tpm_state->tpm_key_handle_entries, subCap32); } else { printf("TPM_GetCapabilityCommon: Error, Bad subCap size %u\n", subCap->size); rc = TPM_BAD_MODE; } break; case TPM_CAP_NV_LIST: rc = TPM_NVIndexEntries_GetNVList(capabilityResponse, &(tpm_state->tpm_nv_index_entries)); break; case TPM_CAP_MFR: rc = TPM_GetCapability_CapMfr(capabilityResponse, tpm_state, subCap); break; case TPM_CAP_NV_INDEX: if (subCap->size == sizeof(uint32_t)) { rc = TPM_GetCapability_CapNVIndex(capabilityResponse, tpm_state, subCap32); } else { printf("TPM_GetCapabilityCommon: Error, Bad subCap size %u\n", subCap->size); rc = TPM_BAD_MODE; } break; case TPM_CAP_TRANS_ALG: if (subCap->size == sizeof(uint32_t)) { rc = TPM_GetCapability_CapTransAlg(capabilityResponse, subCap32); } else { printf("TPM_GetCapabilityCommon: Error, Bad subCap size %u\n", subCap->size); rc = TPM_BAD_MODE; } break; case TPM_CAP_HANDLE: if (subCap->size == sizeof(uint32_t)) { rc = TPM_GetCapability_CapHandle(capabilityResponse, tpm_state, subCap32); } else { printf("TPM_GetCapabilityCommon: Error, Bad subCap size %u\n", subCap->size); rc = TPM_BAD_MODE; } break; case TPM_CAP_TRANS_ES: if (subCap->size == sizeof(uint16_t)) { rc = TPM_GetCapability_CapTransEs(capabilityResponse, subCap16); } else { printf("TPM_GetCapabilityCommon: Error, Bad subCap size %u\n", subCap->size); rc = TPM_BAD_MODE; } break; case TPM_CAP_AUTH_ENCRYPT: if (subCap->size == sizeof(uint32_t)) { rc = TPM_GetCapability_CapAuthEncrypt(capabilityResponse, subCap32); } else { printf("TPM_GetCapabilityCommon: Error, Bad subCap size %u\n", subCap->size); rc = TPM_BAD_MODE; } break; case TPM_CAP_SELECT_SIZE: rc = TPM_GetCapability_CapSelectSize(capabilityResponse, subCap); break; #if (TPM_REVISION >= 103) /* added for rev 103 */ case TPM_CAP_DA_LOGIC: rc = TPM_GetCapability_CapDaLogic(capabilityResponse, subCap, tpm_state); break; #endif case TPM_CAP_VERSION_VAL: rc = TPM_GetCapability_CapVersionVal(capabilityResponse, &(tpm_state->tpm_permanent_data)); break; default: printf("TPM_GetCapabilityCommon: Error, unsupported capArea %08x", capArea); rc = TPM_BAD_MODE; break; } return rc; } /* Boolean value. TRUE indicates that the TPM supports the ordinal. FALSE indicates that the TPM does not support the ordinal. */ static TPM_RESULT TPM_GetCapability_CapOrd(TPM_STORE_BUFFER *capabilityResponse, uint32_t ordinal) { TPM_RESULT rc = 0; tpm_process_function_t tpm_process_function; TPM_BOOL supported; TPM_OrdinalTable_GetProcessFunction(&tpm_process_function, tpm_ordinal_table, ordinal); /* determine of the ordinal is supported */ if (tpm_process_function != TPM_Process_Unused) { supported = TRUE; } /* if the processing function is 'Unused', it's not supported */ else { supported = FALSE; } printf(" TPM_GetCapability_CapOrd: Ordinal %08x, result %02x\n", ordinal, supported); rc = TPM_Sbuffer_Append(capabilityResponse, &supported, sizeof(TPM_BOOL)); return rc; } /* algorithmID is TPM_ALG_XX: A value from TPM_ALGORITHM_ID Boolean value. TRUE means that the TPM supports the asymmetric algorithm for TPM_Sign, TPM_Seal, TPM_UnSeal and TPM_UnBind and related commands. FALSE indicates that the asymmetric algorithm is not supported for these types of commands. The TPM MAY return TRUE or FALSE for other than asymmetric algorithms that it supports. Unassigned and unsupported algorithm IDs return FALSE. */ static TPM_RESULT TPM_GetCapability_CapAlg(TPM_STORE_BUFFER *capabilityResponse, uint32_t algorithmID) { TPM_RESULT rc = 0; TPM_BOOL supported; printf(" TPM_GetCapability_CapAlg: algorithmID %08x\n", algorithmID); if (algorithmID == TPM_ALG_RSA) { supported = TRUE; } else { supported = FALSE; } printf(" TPM_GetCapability_CapAlg: Result %08x\n", supported); rc = TPM_Sbuffer_Append(capabilityResponse, &supported, sizeof(TPM_BOOL)); return rc; } /* Boolean value. TRUE indicates that the TPM supports the protocol, FALSE indicates that the TPM does not support the protocol. */ static TPM_RESULT TPM_GetCapability_CapPid(TPM_STORE_BUFFER *capabilityResponse, uint16_t protocolID) { TPM_RESULT rc = 0; TPM_BOOL supported; printf(" TPM_GetCapability_CapPid: protocolID %04hx\n", protocolID); switch (protocolID) { /* supported protocols */ case TPM_PID_OIAP: case TPM_PID_OSAP: case TPM_PID_ADIP: case TPM_PID_ADCP: case TPM_PID_DSAP: case TPM_PID_TRANSPORT: case TPM_PID_OWNER: supported = TRUE; break; /* unsupported protocols */ default: supported = FALSE; break; } printf(" TPM_GetCapability_CapPid: Result %08x\n", supported); rc = TPM_Sbuffer_Append(capabilityResponse, &supported, sizeof(TPM_BOOL)); return rc; } /* Either of the next two subcaps TPM_CAP_FLAG_PERMANENT Return the TPM_PERMANENT_FLAGS structure TPM_CAP_FLAG_VOLATILE Return the TPM_STCLEAR_FLAGS structure */ static TPM_RESULT TPM_GetCapability_CapFlag(TPM_STORE_BUFFER *capabilityResponse, tpm_state_t *tpm_state, uint32_t capFlag) { TPM_RESULT rc = 0; printf(" TPM_GetCapability_CapFlag: capFlag %08x\n", capFlag); switch (capFlag) { case TPM_CAP_FLAG_PERMANENT: printf(" TPM_GetCapability_CapFlag: TPM_CAP_FLAG_PERMANENT\n");; rc = TPM_PermanentFlags_StoreBytes(capabilityResponse, &(tpm_state->tpm_permanent_flags)); break; case TPM_CAP_FLAG_VOLATILE: printf(" TPM_GetCapability_CapFlag: TPM_CAP_FLAG_VOLATILE\n"); rc = TPM_StclearFlags_Store(capabilityResponse, &(tpm_state->tpm_stclear_flags)); break; default: printf("TPM_GetCapability_CapFlag: Error, illegal capFlag %08x\n", capFlag); rc = TPM_BAD_MODE; break; } return rc; } /* TPM_GetCapability_CapProperty() handles Subcap values for CAP_PROPERTY rev 100 */ static TPM_RESULT TPM_GetCapability_CapProperty(TPM_STORE_BUFFER *capabilityResponse, tpm_state_t *tpm_state, uint32_t capProperty) { TPM_RESULT rc = 0; uint32_t uint32; uint32_t uint32a; uint32_t dummy; /* to hold unused response parameter */ printf(" TPM_GetCapability_CapProperty: capProperty %08x\n", capProperty); switch (capProperty) { case TPM_CAP_PROP_PCR: /* Returns the number of PCR registers supported by the TPM */ printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_PCR %u\n", TPM_NUM_PCR); rc = TPM_Sbuffer_Append32(capabilityResponse, TPM_NUM_PCR); break; case TPM_CAP_PROP_DIR: /* Returns the number of DIR registers under control of the TPM owner supported by the TPM. */ printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_DIR %u\n", TPM_AUTHDIR_SIZE); rc = TPM_Sbuffer_Append32(capabilityResponse, TPM_AUTHDIR_SIZE); break; case TPM_CAP_PROP_MANUFACTURER: /* Returns the Identifier of the TPM manufacturer. */ printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_MANUFACTURER %.4s\n", TPM_MANUFACTURER); rc = TPM_Sbuffer_Append(capabilityResponse, (const unsigned char *)TPM_MANUFACTURER, 4); break; case TPM_CAP_PROP_KEYS: /* Returns the number of 2048-bit RSA keys that can be loaded. This MAY vary with time and circumstances. */ TPM_KeyHandleEntries_GetSpace(&uint32, tpm_state->tpm_key_handle_entries); printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_KEYS %u\n", uint32); rc = TPM_Sbuffer_Append32(capabilityResponse, uint32); break; case TPM_CAP_PROP_MIN_COUNTER: /* uint32_t. The minimum amount of time in 10ths of a second that must pass between invocations of incrementing the monotonic counter. */ printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_MIN_COUNTER\n"); rc = TPM_Sbuffer_Append32(capabilityResponse, 0); break; case TPM_CAP_PROP_AUTHSESS: /* The number of available authorization sessions. This MAY vary with time and circumstances. */ TPM_AuthSessions_GetSpace(&uint32, tpm_state->tpm_stclear_data.authSessions); printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_AUTHSESS space %u\n", uint32); rc = TPM_Sbuffer_Append32(capabilityResponse, uint32); break; case TPM_CAP_PROP_TRANSESS: /* The number of available transport sessions. This MAY vary with time and circumstances. */ TPM_TransportSessions_GetSpace(&uint32, tpm_state->tpm_stclear_data.transSessions); printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_TRANSESS space %u\n", uint32); rc = TPM_Sbuffer_Append32(capabilityResponse, uint32); break; case TPM_CAP_PROP_COUNTERS: /* The number of available monotonic counters. This MAY vary with time and circumstances. */ TPM_Counters_GetSpace(&uint32, tpm_state->tpm_permanent_data.monotonicCounter); printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_COUNTERS %u\n", uint32); rc = TPM_Sbuffer_Append32(capabilityResponse, uint32); break; case TPM_CAP_PROP_MAX_AUTHSESS: /* The maximum number of loaded authorization sessions the TPM supports. */ printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_MAX_AUTHSESS %u\n", TPM_MIN_AUTH_SESSIONS); rc = TPM_Sbuffer_Append32(capabilityResponse, TPM_MIN_AUTH_SESSIONS); break; case TPM_CAP_PROP_MAX_TRANSESS: /* The maximum number of loaded transport sessions the TPM supports. */ printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_MAX_TRANSESS %u\n", TPM_MIN_TRANS_SESSIONS); rc = TPM_Sbuffer_Append32(capabilityResponse, TPM_MIN_TRANS_SESSIONS); break; case TPM_CAP_PROP_MAX_COUNTERS: /* The maximum number of monotonic counters under control of TPM_CreateCounter */ printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_MAX_COUNTERS %u\n", TPM_MIN_COUNTERS); rc = TPM_Sbuffer_Append32(capabilityResponse, TPM_MIN_COUNTERS); break; case TPM_CAP_PROP_MAX_KEYS: /* The maximum number of 2048 RSA keys that the TPM can support. The number does not include the EK or SRK. */ printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_MAX_KEYS %u\n", TPM_KEY_HANDLES); rc = TPM_Sbuffer_Append32(capabilityResponse, TPM_KEY_HANDLES); break; case TPM_CAP_PROP_OWNER: /* A value of TRUE indicates that the TPM has successfully installed an owner. */ printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_OWNER %02x\n", tpm_state->tpm_permanent_data.ownerInstalled); rc = TPM_Sbuffer_Append(capabilityResponse, &(tpm_state->tpm_permanent_data.ownerInstalled), sizeof(TPM_BOOL)); break; case TPM_CAP_PROP_CONTEXT: /* The number of available saved session slots. This MAY vary with time and circumstances. */ TPM_ContextList_GetSpace(&uint32, &dummy, tpm_state->tpm_stclear_data.contextList); printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_CONTEXT %u\n", uint32); rc = TPM_Sbuffer_Append32(capabilityResponse, uint32); break; case TPM_CAP_PROP_MAX_CONTEXT: /* The maximum number of saved session slots. */ printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_MAX_CONTEXT %u\n", TPM_MIN_SESSION_LIST); rc = TPM_Sbuffer_Append32(capabilityResponse, TPM_MIN_SESSION_LIST); break; case TPM_CAP_PROP_FAMILYROWS: /* The number of rows in the family table */ printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_FAMILYROWS %u\n", TPM_NUM_FAMILY_TABLE_ENTRY_MIN); rc = TPM_Sbuffer_Append32(capabilityResponse, TPM_NUM_FAMILY_TABLE_ENTRY_MIN); break; case TPM_CAP_PROP_TIS_TIMEOUT: printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_TIS_TIMEOUT\n"); rc = TPM_GetCapability_CapPropTisTimeout(capabilityResponse); break; case TPM_CAP_PROP_STARTUP_EFFECT: /* The TPM_STARTUP_EFFECTS structure */ printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_STARTUP_EFFECT %08x\n", TPM_STARTUP_EFFECTS_VALUE); rc = TPM_Sbuffer_Append32(capabilityResponse, TPM_STARTUP_EFFECTS_VALUE); break; case TPM_CAP_PROP_DELEGATE_ROW: /* The size of the delegate table in rows. */ printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_DELEGATE_ENTRIES %u\n", TPM_NUM_DELEGATE_TABLE_ENTRY_MIN); rc = TPM_Sbuffer_Append32(capabilityResponse, TPM_NUM_DELEGATE_TABLE_ENTRY_MIN); break; case TPM_CAP_PROP_MAX_DAASESS: /* The maximum number of loaded DAA sessions (join or sign) that the TPM supports */ printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_DAA_MAX\n"); rc = TPM_Sbuffer_Append32(capabilityResponse, TPM_MIN_DAA_SESSIONS); break; case TPM_CAP_PROP_DAASESS: /* The number of available DAA sessions. This may vary with time and circumstances */ TPM_DaaSessions_GetSpace(&uint32, tpm_state->tpm_stclear_data.daaSessions); printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_SESSION_DAA space %u\n", uint32); rc = TPM_Sbuffer_Append32(capabilityResponse, uint32); break; case TPM_CAP_PROP_CONTEXT_DIST: /* The maximum distance between context count values. This MUST be at least 2^16-1. */ printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_CONTEXT_DIST\n"); rc = TPM_Sbuffer_Append32(capabilityResponse, 0xffffffff); break; case TPM_CAP_PROP_DAA_INTERRUPT: /* BOOL. A value of TRUE indicates that the TPM will accept ANY command while executing a DAA Join or Sign. A value of FALSE indicates that the TPM will invalidate the DAA Join or Sign upon the receipt of any command other than the next join/sign in the session or a TPM_SaveContext */ printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_DAA_INTERRUPT\n"); rc = TPM_Sbuffer_Append8(capabilityResponse, TRUE); break; case TPM_CAP_PROP_SESSIONS: /* UNIT32. The number of available authorization and transport sessions from the pool. This may vary with time and circumstances. */ TPM_AuthSessions_GetSpace(&uint32, tpm_state->tpm_stclear_data.authSessions); TPM_TransportSessions_GetSpace(&uint32a, tpm_state->tpm_stclear_data.transSessions); printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_SESSIONS %u + %u\n", uint32, uint32a); rc = TPM_Sbuffer_Append32(capabilityResponse, uint32 + uint32a); break; case TPM_CAP_PROP_MAX_SESSIONS: /* uint32_t. The maximum number of sessions the TPM supports. */ printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_MAX_SESSIONS\n"); rc = TPM_Sbuffer_Append32(capabilityResponse, TPM_MIN_AUTH_SESSIONS + TPM_MIN_TRANS_SESSIONS); break; case TPM_CAP_PROP_CMK_RESTRICTION: /* uint32_t TPM_Permanent_Data -> restrictDelegate */ printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_CMK_RESTRICTION %08x\n", tpm_state->tpm_permanent_data.restrictDelegate); rc = TPM_Sbuffer_Append32(capabilityResponse, tpm_state->tpm_permanent_data.restrictDelegate); break; case TPM_CAP_PROP_DURATION: printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_DURATION\n"); rc = TPM_GetCapability_CapPropDuration(capabilityResponse); break; case TPM_CAP_PROP_ACTIVE_COUNTER: /* TPM_COUNT_ID. The id of the current counter. 0xff..ff if no counter is active */ TPM_Counters_GetActiveCounter(&uint32, tpm_state->tpm_stclear_data.countID); /* The illegal value after releasing an active counter must be mapped back to the null value */ if (uint32 == TPM_COUNT_ID_ILLEGAL) { uint32 = TPM_COUNT_ID_NULL; } printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_ACTIVE_COUNTER %u\n", uint32); rc = TPM_Sbuffer_Append32(capabilityResponse, uint32); break; case TPM_CAP_PROP_MAX_NV_AVAILABLE: /* uint32_t. Deprecated. The maximum number of NV space that can be allocated, MAY vary with time and circumstances. This capability was not implemented consistently, and is replaced by TPM_NV_INDEX_TRIAL. */ rc = TPM_NVIndexEntries_GetFreeSpace(&uint32, &(tpm_state->tpm_nv_index_entries)); if (rc == 0) { printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_MAX_NV_AVAILABLE %u\n", uint32); rc = TPM_Sbuffer_Append32(capabilityResponse, uint32); } /* There should always be free space >= 0. If the call fails here, there is an internal error. */ else { printf(" TPM_GetCapability_CapProperty: Error (fatal) " "in TPM_CAP_PROP_MAX_NV_AVAILABLE\n"); rc = TPM_FAIL; } break; case TPM_CAP_PROP_INPUT_BUFFER: /* uint32_t. The size of the TPM input and output buffers in bytes. */ printf(" TPM_GetCapability_CapProperty: TPM_CAP_PROP_INPUT_BUFFER %u\n", TPM_BUFFER_MAX); rc = TPM_Sbuffer_Append32(capabilityResponse, TPM_BUFFER_MAX); break; default: printf("TPM_GetCapability_CapProperty: Error, illegal capProperty %08x\n", capProperty); rc = TPM_BAD_MODE; break; } return rc; } /* TPM_VERSION structure. The Major and Minor must indicate 1.1. The manufacturer information MUST indicate the firmware version of the TPM. Any software using this structure MUST be aware that when included in a structure the value MUST be 1.1.0.0, when reported by this command the manufacturer information MAY include firmware versions. The use of this value is deprecated, new software SHOULD use TPM_CAP_VERSION_VAL to obtain version information regarding the TPM. Return 0.0 for revision for 1.1 backward compatibility, since TPM_PERMANENT_DATA now holds the new type TPM_VERSION_BYTE. */ static TPM_RESULT TPM_GetCapability_CapVersion(TPM_STORE_BUFFER *capabilityResponse) { TPM_RESULT rc = 0; TPM_STRUCT_VER tpm_struct_ver; TPM_StructVer_Init(&tpm_struct_ver); printf(" TPM_GetCapability_CapVersion: %u.%u.%u.%u\n", tpm_struct_ver.major, tpm_struct_ver.minor, tpm_struct_ver.revMajor, tpm_struct_ver.revMinor); rc = TPM_StructVer_Store(capabilityResponse, &tpm_struct_ver); return rc; } /* A Boolean value. TRUE indicates that the TPM has enough memory available to load a key of the type specified by ALGORITHM. FALSE indicates that the TPM does not have enough memory. */ static TPM_RESULT TPM_GetCapability_CapCheckLoaded(TPM_STORE_BUFFER *capabilityResponse, const TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry, TPM_SIZED_BUFFER *subCap) { TPM_RESULT rc = 0; uint32_t stream_size; unsigned char *stream; TPM_KEY_PARMS keyParms; TPM_BOOL isSpace; uint32_t index; TPM_KeyParms_Init(&keyParms); /* freed @1 */ if (rc == 0) { /* make temporary copies so the subCap is not touched */ stream = subCap->buffer; stream_size = subCap->size; rc = TPM_KeyParms_Load(&keyParms, &stream, &stream_size); } if (rc == 0) { if (keyParms.algorithmID == TPM_ALG_RSA) { TPM_KeyHandleEntries_IsSpace(&isSpace, &index, tpm_key_handle_entry); } else { printf(" TPM_GetCapability_CapCheckLoaded: algorithmID %08x is not TPM_ALG_RSA %08x\n", keyParms.algorithmID, TPM_ALG_RSA); isSpace = FALSE; } } if (rc == 0) { printf(" TPM_GetCapability_CapCheckLoaded: Return %02x\n", isSpace); rc = TPM_Sbuffer_Append(capabilityResponse, &isSpace, sizeof(TPM_BOOL)); } TPM_KeyParms_Delete(&keyParms); /* @1 */ return rc; } /* (Deprecated) This indicates the mode of a symmetric encryption. Mode is Electronic CookBook (ECB) or some other such mechanism. */ static TPM_RESULT TPM_GetCapability_CapSymMode(TPM_STORE_BUFFER *capabilityResponse, TPM_SYM_MODE symMode) { TPM_RESULT rc = 0; symMode = symMode; /* not currently used */ printf(" TPM_GetCapability_CapSymMode: Return %02x\n", FALSE); rc = TPM_Sbuffer_Append8(capabilityResponse, FALSE); return rc; } /* Boolean value of ownerEvict. The handle MUST point to a valid key handle. */ static TPM_RESULT TPM_GetCapability_CapKeyStatus(TPM_STORE_BUFFER *capabilityResponse, TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entries, uint32_t tpm_key_handle) { TPM_RESULT rc = 0; TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry; /* corresponding to handle */ TPM_BOOL ownerEvict; printf(" TPM_GetCapability_CapKeyStatus: key handle %08x\n", tpm_key_handle); /* map from the handle to the TPM_KEY structure */ if (rc == 0) { rc = TPM_KeyHandleEntries_GetEntry(&tpm_key_handle_entry, tpm_key_handle_entries, tpm_key_handle); if (rc != 0) { printf("TPM_GetCapability_CapKeyStatus: Error, key handle %08x not found\n", tpm_key_handle); } } /* test the ownerEvict bit */ if (rc == 0) { ownerEvict = (tpm_key_handle_entry->keyControl & TPM_KEY_CONTROL_OWNER_EVICT) ? TRUE : FALSE;; printf(" TPM_GetCapability_CapKeyStatus: return %02x\n", ownerEvict); rc = TPM_Sbuffer_Append(capabilityResponse, &ownerEvict, sizeof(TPM_BOOL)); } return rc; } /* Manufacturer specific. The manufacturer may provide any additional information regarding the TPM and the TPM state but MUST not expose any sensitive information. */ static TPM_RESULT TPM_GetCapability_CapMfr(TPM_STORE_BUFFER *capabilityResponse, tpm_state_t *tpm_state, TPM_SIZED_BUFFER *subCap) { TPM_RESULT rc = 0; uint32_t subCap32; /* all of the subCaps are at least a uint32_t. Some have more data */ if (rc == 0) { if (subCap->size >= sizeof(uint32_t)) { subCap32 = htonl(*(uint32_t *)subCap->buffer); printf(" TPM_GetCapability_CapMfr: subCap %08x\n", subCap32); } else { printf("TPM_GetCapability_CapMfr: Error, subCap size %u < %lu\n", subCap->size, (unsigned long)sizeof(uint32_t)); rc = TPM_BAD_MODE; } } /* switch on the subCap and append the get capability response to the capabilityResponse buffer */ if (rc == 0) { switch(subCap32) { #ifdef TPM_POSIX case TPM_CAP_PROCESS_ID: if (subCap->size == sizeof(uint32_t)) { pid_t pid = getpid(); printf(" TPM_GetCapability_CapMfr: TPM_CAP_PROCESS_ID %u\n", (uint32_t)pid); rc = TPM_Sbuffer_Append32(capabilityResponse, (uint32_t)pid); } else { printf("TPM_GetCapability_CapMfr: Error, Bad subCap size %u\n", subCap->size); rc = TPM_BAD_MODE; } break; #endif default: capabilityResponse = capabilityResponse; /* not used */ tpm_state = tpm_state; /* not used */ printf("TPM_GetCapability_CapMfr: Error, unsupported subCap %08x\n", subCap32); rc = TPM_BAD_MODE; break; } } return rc; } /* Returns a TPM_NV_DATA_PUBLIC structure that indicates the values for the TPM_NV_INDEX */ static TPM_RESULT TPM_GetCapability_CapNVIndex(TPM_STORE_BUFFER *capabilityResponse, tpm_state_t *tpm_state, uint32_t nvIndex) { TPM_RESULT rc = 0; TPM_NV_DATA_PUBLIC *tpm_nv_data_public; printf(" TPM_GetCapability_CapNVIndex: nvIndex %08x\n", nvIndex); /* map from the nvIndex to the TPM_NV_DATA_PUBLIC structure */ if (rc == 0) { rc = TPM_NVIndexEntries_GetDataPublic(&tpm_nv_data_public, &(tpm_state->tpm_nv_index_entries), nvIndex); } /* serialize the structure */ if (rc == 0) { rc = TPM_NVDataPublic_Store(capabilityResponse, tpm_nv_data_public, FALSE); /* do not optimize digestAtRelease */ } return rc; } /* Returns a Boolean value. TRUE means that the TPM supports the algorithm for TPM_EstablishTransport, TPM_ExecuteTransport and TPM_ReleaseTransportSigned. FALSE indicates that for these three commands the algorithm is not supported." */ static TPM_RESULT TPM_GetCapability_CapTransAlg(TPM_STORE_BUFFER *capabilityResponse, TPM_ALGORITHM_ID algorithmID) { TPM_RESULT rc = 0; TPM_BOOL supported; printf(" TPM_GetCapability_CapTransAlg: algorithmID %08x\n", algorithmID); TPM_TransportPublic_CheckAlgId(&supported, algorithmID); printf(" TPM_GetCapability_CapTransAlg: Result %08x\n", supported); rc = TPM_Sbuffer_Append(capabilityResponse, &supported, sizeof(TPM_BOOL)); return rc; } /* Returns a TPM_KEY_HANDLE_LIST structure that enumerates all handles currently loaded in the TPM for the given resource type. TPM_KEY_HANDLE_LIST is the number of handles followed by a list of the handles. When describing keys the handle list only contains the number of handles that an external manager can operate with and does not include the EK or SRK. Legal resources are TPM_RT_KEY, TPM_RT_AUTH, TPM_RT_TRANS, TPM_RT_COUNTER TPM_RT_CONTEXT is valid and returns not a list of handles but a list of the context count values. */ static TPM_RESULT TPM_GetCapability_CapHandle(TPM_STORE_BUFFER *capabilityResponse, tpm_state_t *tpm_state, TPM_RESOURCE_TYPE resourceType) { TPM_RESULT rc = 0; printf(" TPM_GetCapability_CapHandle: resourceType %08x\n", resourceType); switch (resourceType) { case TPM_RT_KEY: printf(" TPM_GetCapability_CapHandle: TPM_RT_KEY\n"); rc = TPM_KeyHandleEntries_StoreHandles(capabilityResponse, tpm_state->tpm_key_handle_entries); break; case TPM_RT_AUTH: printf(" TPM_GetCapability_CapHandle: TPM_RT_AUTH\n"); rc = TPM_AuthSessions_StoreHandles(capabilityResponse, tpm_state->tpm_stclear_data.authSessions); break; case TPM_RT_TRANS: printf(" TPM_GetCapability_CapHandle: TPM_RT_TRANS\n"); rc = TPM_TransportSessions_StoreHandles(capabilityResponse, tpm_state->tpm_stclear_data.transSessions); break; case TPM_RT_CONTEXT: printf(" TPM_GetCapability_CapHandle: TPM_RT_CONTEXT\n"); rc = TPM_ContextList_StoreHandles(capabilityResponse, tpm_state->tpm_stclear_data.contextList); break; case TPM_RT_COUNTER: printf(" TPM_GetCapability_CapHandle: TPM_RT_COUNTER\n"); rc = TPM_Counters_StoreHandles(capabilityResponse, tpm_state->tpm_permanent_data.monotonicCounter); break; case TPM_RT_DAA_TPM: printf(" TPM_GetCapability_CapHandle: TPM_RT_DAA_TPM\n"); rc = TPM_DaaSessions_StoreHandles(capabilityResponse, tpm_state->tpm_stclear_data.daaSessions); break; default: printf("TPM_GetCapability_CapHandle: Error, illegal resource type %08x\n", resourceType); rc = TPM_BAD_PARAMETER; } return rc; } /* Returns Boolean value. TRUE means the TPM supports the encryption scheme in a transport session. */ static TPM_RESULT TPM_GetCapability_CapTransEs(TPM_STORE_BUFFER *capabilityResponse, TPM_ENC_SCHEME encScheme) { TPM_RESULT rc = 0; TPM_BOOL supported; printf(" TPM_GetCapability_CapTransEs: encScheme %04hx\n", encScheme); switch (encScheme) { /* supported protocols */ case TPM_ES_SYM_CTR: case TPM_ES_SYM_OFB: supported = TRUE; break; /* unsupported protocols */ case TPM_ES_RSAESPKCSv15: case TPM_ES_RSAESOAEP_SHA1_MGF1: default: supported = FALSE; break; } printf(" TPM_GetCapability_CapTransEs: Result %08x\n", supported); rc = TPM_Sbuffer_Append(capabilityResponse, &supported, sizeof(TPM_BOOL)); return rc; } /* Boolean value. TRUE indicates that the TPM supports the encryption algorithm in OSAP encryption of AuthData values */ static TPM_RESULT TPM_GetCapability_CapAuthEncrypt(TPM_STORE_BUFFER *capabilityResponse, TPM_ALGORITHM_ID algorithmID) { TPM_RESULT rc = 0; TPM_BOOL supported; printf(" TPM_GetCapability_CapAuthEncrypt: algorithmID %08x\n", algorithmID); switch (algorithmID) { case TPM_ALG_XOR: case TPM_ALG_AES128: /* supported protocols */ supported = TRUE; break; case TPM_ALG_RSA: case TPM_ALG_SHA: case TPM_ALG_HMAC: case TPM_ALG_MGF1: case TPM_ALG_AES192: case TPM_ALG_AES256: default: /* unsupported protocols */ supported = FALSE; break; } printf(" TPM_GetCapability_CapAuthEncrypt: Result %08x\n", supported); rc = TPM_Sbuffer_Append(capabilityResponse, &supported, sizeof(TPM_BOOL)); return rc; } /* Boolean value. TRUE indicates that the TPM supports the size for the given version. For instance a request could ask for version 1.1 size 2 and the TPM would indicate TRUE. For 1.1 size 3 the TPM would indicate FALSE. For 1.2 size 3 the TPM would indicate TRUE. */ static TPM_RESULT TPM_GetCapability_CapSelectSize(TPM_STORE_BUFFER *capabilityResponse, TPM_SIZED_BUFFER *subCap) { TPM_RESULT rc = 0; TPM_SELECT_SIZE tpm_select_size; unsigned char *stream; uint32_t stream_size; TPM_BOOL supported; printf(" TPM_GetCapability_CapSelectSize:\n"); TPM_SelectSize_Init(&tpm_select_size); /* no free required */ /* deserialize the subCap to the structure */ if (rc == 0) { stream = subCap->buffer; stream_size = subCap->size; rc = TPM_SelectSize_Load(&tpm_select_size, &stream , &stream_size); } if (rc == 0) { /* The TPM MUST return an error if sizeOfSelect is 0 */ printf(" TPM_GetCapability_CapSelectSize: subCap reqSize %u\n", tpm_select_size.reqSize); if ((tpm_select_size.reqSize > (TPM_NUM_PCR/CHAR_BIT)) || (tpm_select_size.reqSize == 0)) { supported = FALSE; } else { supported = TRUE; } } if (rc == 0) { printf(" TPM_GetCapability_CapSelectSize: Result %08x\n", supported); rc = TPM_Sbuffer_Append(capabilityResponse, &supported, sizeof(TPM_BOOL)); } return rc; } #if (TPM_REVISION >= 103) /* added for rev 103 */ /* TPM_GetCapability_CapDaLogic() rev 100 A TPM_DA_INFO or TPM_DA_INFO_LIMITED structure that returns data according to the selected entity type (e.g., TPM_ET_KEYHANDLE, TPM_ET_OWNER, TPM_ET_SRK, TPM_ET_COUNTER, TPM_ET_OPERATOR, etc.). If the implemented dictionary attack logic does not support different secret types, the entity type can be ignored. */ static TPM_RESULT TPM_GetCapability_CapDaLogic(TPM_STORE_BUFFER *capabilityResponse, TPM_SIZED_BUFFER *subCap, tpm_state_t *tpm_state) { TPM_RESULT rc = 0; TPM_DA_INFO_LIMITED tpm_da_info_limited; TPM_DA_INFO tpm_da_info; printf(" TPM_GetCapability_CapDaLogic:\n"); TPM_DaInfoLimited_Init(&tpm_da_info_limited); /* freed @1 */ TPM_DaInfo_Init(&tpm_da_info); /* freed @2 */ subCap = subCap; /* dictionary attack mitigation not per entity type in this implementation. */ /* if disableFullDALogicInfo is TRUE, the full dictionary attack TPM_GetCapability info is deactivated. The returned structure is TPM_DA_INFO_LIMITED. */ if (tpm_state->tpm_permanent_flags.disableFullDALogicInfo) { TPM_DaInfoLimited_Set(&tpm_da_info_limited, tpm_state); rc = TPM_DaInfoLimited_Store(capabilityResponse, &tpm_da_info_limited); } /* if disableFullDALogicInfo is FALSE, the full dictionary attack TPM_GetCapability info is activated. The returned structure is TPM_DA_INFO. */ else { TPM_DaInfo_Set(&tpm_da_info, tpm_state); rc = TPM_DaInfo_Store(capabilityResponse, &tpm_da_info); } TPM_DaInfoLimited_Delete(&tpm_da_info_limited); /* @1 */ TPM_DaInfo_Delete(&tpm_da_info); /* @2 */ return rc; } #endif /* Returns TPM_CAP_VERSION_INFO structure. The TPM fills in the structure and returns the information indicating what the TPM currently supports. */ static TPM_RESULT TPM_GetCapability_CapVersionVal(TPM_STORE_BUFFER *capabilityResponse, TPM_PERMANENT_DATA *tpm_permanent_data) { TPM_RESULT rc = 0; TPM_CAP_VERSION_INFO tpm_cap_version_info; printf(" TPM_GetCapability_CapVersionVal:\n"); TPM_CapVersionInfo_Set(&tpm_cap_version_info, tpm_permanent_data); /* freed @1 */ printf(" TPM_GetCapability_CapVersionVal: specLevel %04hx\n", tpm_cap_version_info.specLevel); printf(" TPM_GetCapability_CapVersionVal: errataRev %02x\n", tpm_cap_version_info.errataRev); printf(" TPM_GetCapability_CapVersionVal: revMajor %02x revMinor %02x\n", tpm_cap_version_info.version.revMajor, tpm_cap_version_info.version.revMinor); printf(" TPM_GetCapability_CapVersionVal: tpmVendorID %02x %02x %02x %02x\n", tpm_cap_version_info.tpmVendorID[0], tpm_cap_version_info.tpmVendorID[1], tpm_cap_version_info.tpmVendorID[2], tpm_cap_version_info.tpmVendorID[3]); rc = TPM_CapVersionInfo_Store(capabilityResponse, &tpm_cap_version_info); TPM_CapVersionInfo_Delete(&tpm_cap_version_info); /* @1 */ return rc; } /* Returns a 4 element array of uint32_t values each denoting the timeout value in microseconds for the following in this order: TIMEOUT_A, TIMEOUT_B, TIMEOUT_C, TIMEOUT_D Where these timeouts are to be used is determined by the platform specific TPM Interface Specification. */ static TPM_RESULT TPM_GetCapability_CapPropTisTimeout(TPM_STORE_BUFFER *capabilityResponse) { TPM_RESULT rc = 0; printf(" TPM_GetCapability_CapPropTisTimeout:\n"); if (rc == 0) { rc = TPM_Sbuffer_Append32(capabilityResponse, TPM_TIMEOUT_A); } if (rc == 0) { rc = TPM_Sbuffer_Append32(capabilityResponse, TPM_TIMEOUT_B); } if (rc == 0) { rc = TPM_Sbuffer_Append32(capabilityResponse, TPM_TIMEOUT_C); } if (rc == 0) { rc = TPM_Sbuffer_Append32(capabilityResponse, TPM_TIMEOUT_D); } return rc; } /* Returns a 3 element array of uint32_t values each denoting the duration value in microseconds of the duration of the three classes of commands: Small, Medium and Long in the following in this order: SMALL_DURATION, MEDIUM_DURATION, LONG_DURATION */ static TPM_RESULT TPM_GetCapability_CapPropDuration(TPM_STORE_BUFFER *capabilityResponse) { TPM_RESULT rc = 0; printf(" TPM_GetCapability_CapPropDuration:\n"); if (rc == 0) { rc = TPM_Sbuffer_Append32(capabilityResponse, TPM_SMALL_DURATION); } if (rc == 0) { rc = TPM_Sbuffer_Append32(capabilityResponse, TPM_MEDIUM_DURATION); } if (rc == 0) { rc = TPM_Sbuffer_Append32(capabilityResponse, TPM_LONG_DURATION); } return rc; } /* 7.3 TPM_GetCapabilityOwner rev 98 TPM_GetCapabilityOwner enables the TPM Owner to retrieve all the non-volatile flags and the volatile flags in a single operation. This command is deprecated, mandatory. The flags summarize many operational aspects of the TPM. The information represented by some flags is private to the TPM Owner. So, for simplicity, proof of ownership of the TPM must be presented to retrieve the set of flags. When necessary, the flags that are not private to the Owner can be deduced by Users via other (more specific) means. The normal TPM authentication mechanisms are sufficient to prove the integrity of the response. No additional integrity check is required. For 31>=N>=0 1. Bit-N of the TPM_PERMANENT_FLAGS structure is the Nth bit after the opening bracket in the definition of TPM_PERMANENT_FLAGS in the version of the specification indicated by the parameter "version". The bit immediately after the opening bracket is the 0th bit. 2. Bit-N of the TPM_STCLEAR_FLAGS structure is the Nth bit after the opening bracket in the definition of TPM_STCLEAR_FLAGS in the version of the specification indicated by the parameter "version". The bit immediately after the opening bracket is the 0th bit. 3. Bit-N of non_volatile_flags corresponds to the Nth bit in TPM_PERMANENT_FLAGS, and the lsb of non_volatile_flags corresponds to bit0 of TPM_PERMANENT_FLAGS 4. Bit-N of volatile_flags corresponds to the Nth bit in TPM_STCLEAR_FLAGS, and the lsb of volatile_flags corresponds to bit0 of TPM_STCLEAR_FLAGS */ TPM_RESULT TPM_Process_GetCapabilityOwner(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_AUTHHANDLE authHandle; /* The authorization session handle used for Owner authentication. */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization session */ TPM_AUTHDATA ownerAuth; /* The authorization session digest for inputs and owner authentication. HMAC key: ownerAuth. */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_AUTH_SESSION_DATA *auth_session_data; /* session data for authHandle */ TPM_SECRET *hmacKey; /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_VERSION version; /* A properly filled out version structure. */ uint32_t non_volatile_flags; /* The current state of the non-volatile flags. */ uint32_t volatile_flags; /* The current state of the volatile flags. */ printf("TPM_Process_GetCapabilityOwner: Ordinal Entry\n"); /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag1(tag); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, ownerAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_GetCapabilityOwner: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* 1. The TPM validates that the TPM Owner authorizes the command. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_OWNER, ordinal, NULL, &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ } if (returnCode == TPM_SUCCESS) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* owner HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, ownerAuth); /* Authorization digest for input */ } /* 2. The TPM creates the parameter non_volatile_flags by setting each bit to the same state as the corresponding bit in TPM_PERMANENT_FLAGS. Bits in non_volatile_flags for which there is no corresponding bit in TPM_PERMANENT_FLAGS are set to zero. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_PermanentFlags_StoreBitmap(&non_volatile_flags, &(tpm_state->tpm_permanent_flags)); } /* 3. The TPM creates the parameter volatile_flags by setting each bit to the same state as the corresponding bit in TPM_STCLEAR_FLAGS. Bits in volatile_flags for which there is no corresponding bit in TPM_STCLEAR_FLAGS are set to zero. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_StclearFlags_StoreBitmap(&volatile_flags, &(tpm_state->tpm_stclear_flags)); } /* 4. The TPM generates the parameter "version". */ if (returnCode == TPM_SUCCESS) { TPM_Version_Set(&version, &(tpm_state->tpm_permanent_data)); } /* 5. The TPM returns non_volatile_flags, volatile_flags and version to the caller. */ /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_GetCapabilityOwner: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* return the version */ returnCode = TPM_Version_Store(response, &version); } /* return the non_volatile_flags */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Sbuffer_Append32(response, non_volatile_flags); } /* return the volatile_flags */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Sbuffer_Append32(response, volatile_flags); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* owner HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ return rcf; } /* 29.1 TPM_GetCapabilitySigned rev 94 TPM_GetCapabilitySigned is almost the same as TPM_GetCapability. The differences are that the input includes a challenge (a nonce) and the response includes a digital signature to vouch for the source of the answer. If a caller itself requires proof, it is sufficient to use any signing key for which only the TPM and the caller have AuthData. If a caller requires proof for a third party, the signing key must be one whose signature is trusted by the third party. A TPM-identity key may be suitable. */ TPM_RESULT TPM_Process_GetCapabilitySigned(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_KEY_HANDLE keyHandle; /* The handle of a loaded key that can perform digital signatures. */ TPM_NONCE antiReplay; /* Nonce provided to allow caller to defend against replay of messages */ TPM_CAPABILITY_AREA capArea = 0; /* Partition of capabilities to be interrogated */ TPM_SIZED_BUFFER subCap; /* Further definition of information */ TPM_AUTHHANDLE authHandle; /* The authorization session handle used for keyHandle authorization */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization session handle */ TPM_AUTHDATA privAuth; /* The authorization session digest that authorizes the use of keyHandle. HMAC key: key.usageAuth */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt = FALSE;/* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_AUTH_SESSION_DATA *auth_session_data; /* session data for authHandle */ TPM_SECRET *hmacKey; TPM_KEY *sigKey = NULL; /* the key specified by keyHandle */ TPM_SECRET *keyUsageAuth; TPM_BOOL parentPCRStatus; uint16_t subCap16; /* the subCap as a uint16_t */ uint32_t subCap32; /* the subCap as a uint32_t */ TPM_STORE_BUFFER r1Response; /* capability response */ const unsigned char *r1_buffer; /* r1 serialization */ uint32_t r1_length; TPM_DIGEST s1; /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_VERSION version; /* A properly filled out version structure. */ TPM_SIZED_BUFFER resp; /* The capability response */ TPM_SIZED_BUFFER sig; /* The resulting digital signature. */ printf("TPM_Process_GetCapabilitySigned: Ordinal Entry\n"); TPM_SizedBuffer_Init(&subCap); /* freed @1 */ TPM_SizedBuffer_Init(&resp); /* freed @2 */ TPM_SizedBuffer_Init(&sig); /* freed @3 */ TPM_Sbuffer_Init(&r1Response); /* freed @4 */ /* get inputs */ /* get keyHandle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&keyHandle, &command, ¶mSize); } /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get antiReplay parameter */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_GetCapabilitySigned: keyHandle %08x\n", keyHandle); returnCode = TPM_Nonce_Load(antiReplay, &command, ¶mSize); } /* get capArea parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&capArea, &command, ¶mSize); } /* get get subCap parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_Load(&subCap, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag10(tag); } /* get the optional 'below the line' authorization parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, privAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_GetCapabilitySigned: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* get the key corresponding to the keyHandle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyHandleEntries_GetKey(&sigKey, &parentPCRStatus, tpm_state, keyHandle, FALSE, /* not r/o, used to sign */ FALSE, /* do not ignore PCRs */ FALSE); /* cannot use EK */ } /* 1. The TPM validates the authority to use keyHandle */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)) { if (sigKey->authDataUsage != TPM_AUTH_NEVER) { printf("TPM_Process_GetCapabilitySigned: Error, authorization required\n"); returnCode = TPM_AUTHFAIL; } } /* get keyHandle -> usageAuth */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_Key_GetUsageAuth(&keyUsageAuth, sigKey); } /* get the session data */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_KEYHANDLE, ordinal, sigKey, keyUsageAuth, /* OIAP */ sigKey->tpm_store_asymkey->pubDataDigest); /* OSAP */ } /* 1. The TPM MUST validate the authorization to use the key pointed to by keyHandle. */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, privAuth); /* Authorization digest for input */ } /* subCap is often a uint16_t or uint32_t, create them now */ if (returnCode == TPM_SUCCESS) { TPM_GetSubCapInt(&subCap16, &subCap32, &subCap); } /* 2. The TPM calls TPM_GetCapability passing the capArea and subCap fields and saving the resp field as R1 */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetCapabilityCommon(&r1Response, tpm_state, capArea, subCap16, subCap32, &subCap); } if (returnCode == TPM_SUCCESS) { /* get the capability r1 serialization */ TPM_Sbuffer_Get(&r1Response, &r1_buffer, &r1_length); printf("TPM_Process_GetCapabilitySigned: resp length %08x\n", r1_length); TPM_PrintFour("TPM_Process_GetCapabilitySigned: Hashing resp", r1_buffer); TPM_PrintFour("TPM_Process_GetCapabilitySigned: antiReplay", antiReplay); /* 3. The TPM creates S1 by taking a SHA1 hash of the concatenation (r1 || antiReplay). */ returnCode = TPM_SHA1(s1, r1_length, r1_buffer, TPM_NONCE_SIZE, antiReplay, 0, NULL); } /* 4. The TPM validates the authority to use keyHandle */ /* The key in keyHandle MUST have a KEYUSAGE value of type TPM_KEY_SIGNING or TPM_KEY_LEGACY or TPM_KEY_IDENTITY. */ if (returnCode == TPM_SUCCESS) { if ((sigKey->keyUsage != TPM_KEY_SIGNING) && ((sigKey->keyUsage) != TPM_KEY_IDENTITY) && ((sigKey->keyUsage) != TPM_KEY_LEGACY)) { printf("TPM_Process_GetCapabilitySigned: Error, keyUsage %04hx is invalid\n", sigKey->keyUsage); returnCode = TPM_INVALID_KEYUSAGE; } } /* 5. The TPM creates a digital signature of S1 using the key in keyHandle and returns the result in sig. */ if (returnCode == TPM_SUCCESS) { if (sigKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1) { printf("TPM_Process_GetCapabilitySigned: Error, inappropriate signature scheme %04x\n", sigKey->algorithmParms.sigScheme); returnCode = TPM_INAPPROPRIATE_SIG; } } if (returnCode == TPM_SUCCESS) { TPM_PrintFour("TPM_Process_GetCapabilitySigned: Signing s1", s1); returnCode = TPM_RSASignToSizedBuffer(&sig, /* signature */ s1, /* message */ TPM_DIGEST_SIZE, /* message size */ sigKey); /* signing key and parameters */ } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_GetCapabilitySigned: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* return the version */ TPM_Version_Set(&version, &(tpm_state->tpm_permanent_data)); returnCode = TPM_Version_Store(response, &version); } /* return the capability response size */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Sbuffer_Append32(response, r1_length); } /* return the capability response */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Sbuffer_Append(response, r1_buffer, r1_length); } /* return the signature */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_Store(response, &sig); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* owner HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ TPM_SizedBuffer_Delete(&subCap); /* @1 */ TPM_SizedBuffer_Delete(&resp); /* @2 */ TPM_SizedBuffer_Delete(&sig); /* @3 */ TPM_Sbuffer_Delete(&r1Response); /* @4 */ return rcf; } /* 7.2 TPM_SetCapability rev 96 This command sets values in the TPM */ TPM_RESULT TPM_Process_SetCapability(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_TAG returnCode = 0; /* command return code */ /* input parameters */ TPM_CAPABILITY_AREA capArea; /* Partition of capabilities to be set */ TPM_SIZED_BUFFER subCap; /* Further definition of information */ TPM_SIZED_BUFFER setValue; /* The value to set */ TPM_AUTHHANDLE authHandle; /* The authorization session handle used for owner authentication. */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization session handle */ TPM_AUTHDATA ownerAuth; /* Authorization. HMAC key: owner.usageAuth */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt = FALSE;/* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_AUTH_SESSION_DATA *auth_session_data; /* session data for authHandle */ TPM_SECRET *hmacKey; uint16_t subCap16; /* the subCap as a uint16_t */ uint32_t subCap32; /* the subCap as a uint32_t */ TPM_BOOL ownerAuthorized = FALSE; /* TRUE if owner authorization validated */ TPM_BOOL presenceAuthorized = FALSE; /* TRUE if physicalPresence validated */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_SetCapability: Ordinal Entry\n"); TPM_SizedBuffer_Init(&subCap); /* freed @1 */ TPM_SizedBuffer_Init(&setValue); /* freed @2 */ /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get capArea parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&capArea, &command, ¶mSize); } /* get subCap parameter */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_SetCapability: capArea %08x \n", capArea); returnCode = TPM_SizedBuffer_Load(&subCap, &command, ¶mSize); } /* get setValue parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_Load(&setValue , &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | TPM_CHECK_NO_LOCKOUT)); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag10(tag); } /* get the optional 'below the line' authorization parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { ownerAuthorized = TRUE; returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, ownerAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_SetCapability: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* 1. If tag = TPM_TAG_RQU_AUTH1_COMMAND, validate the command and parameters using ownerAuth, return TPM_AUTHFAIL on error */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_OWNER, ordinal, NULL, &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ } if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* owner HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, ownerAuth); /* Authorization digest for input */ } if (returnCode == TPM_SUCCESS) { returnCode = TPM_Global_GetPhysicalPresence(&presenceAuthorized, tpm_state); } /* 2. The TPM validates the capArea and subCap indicators, including the ability to set value based on any set restrictions */ /* 3. If the capArea and subCap indicators conform with one of the entries in the structure TPM_CAPABILITY_AREA (Values for TPM_SetCapability) */ /* a. The TPM sets the relevant flag/data to the value of setValue parameter. */ /* 4. Else */ /* a. Return the error code TPM_BAD_PARAMETER. */ if (returnCode == TPM_SUCCESS) { /* subCap is often a uint16_t or uint32_t, create them now */ TPM_GetSubCapInt(&subCap16, &subCap32, &subCap); returnCode = TPM_SetCapabilityCommon(tpm_state, ownerAuthorized, presenceAuthorized, capArea, subCap16, subCap32, &subCap, &setValue); } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_SetCapability: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* owner HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, terminate the session. */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ TPM_SizedBuffer_Delete(&subCap); /* @1 */ TPM_SizedBuffer_Delete(&setValue); /* @2 */ return rcf; } /* TPM_SetCapabilityCommon() is common code for setting a capability from setValue NOTE: This function assumes that the caller has validated either owner authorization or physical presence! */ TPM_RESULT TPM_SetCapabilityCommon(tpm_state_t *tpm_state, TPM_BOOL ownerAuthorized, TPM_BOOL presenceAuthorized, TPM_CAPABILITY_AREA capArea, uint16_t subCap16, uint32_t subCap32, TPM_SIZED_BUFFER *subCap, TPM_SIZED_BUFFER *setValue) { TPM_RESULT rc = 0; TPM_BOOL valueBool; uint32_t valueUint32 = 0; /* start with illegal value */ printf(" TPM_SetCapabilityCommon:\n"); subCap16 = subCap16; /* not used */ subCap = subCap; /* not used */ if (rc == 0) { if ((capArea == TPM_SET_PERM_FLAGS) || (capArea == TPM_SET_STCLEAR_FLAGS) || (capArea == TPM_SET_STANY_FLAGS)) { rc = TPM_SizedBuffer_GetBool(&valueBool, setValue); } else if (((capArea == TPM_SET_PERM_DATA) && (subCap32 != TPM_PD_DAAPROOF)) || (capArea == TPM_SET_STCLEAR_DATA)) { /* deferredPhysicalPresence */ rc = TPM_SizedBuffer_GetUint32(&valueUint32, setValue); } } if (rc == 0) { switch (capArea) { case TPM_SET_PERM_FLAGS: rc = TPM_SetCapability_CapPermFlags(tpm_state, ownerAuthorized, presenceAuthorized, subCap32, valueBool); break; case TPM_SET_PERM_DATA: rc = TPM_SetCapability_CapPermData(tpm_state, ownerAuthorized, presenceAuthorized, subCap32, valueUint32); break; case TPM_SET_STCLEAR_FLAGS: rc = TPM_SetCapability_CapStclearFlags(tpm_state, ownerAuthorized, presenceAuthorized, subCap32, valueBool); break; case TPM_SET_STCLEAR_DATA: rc = TPM_SetCapability_CapStclearData(tpm_state, ownerAuthorized, presenceAuthorized, subCap32, valueUint32); break; case TPM_SET_STANY_FLAGS: rc = TPM_SetCapability_CapStanyFlags(tpm_state, ownerAuthorized, presenceAuthorized, subCap32, valueBool); break; case TPM_SET_STANY_DATA: rc = TPM_SetCapability_CapStanyData(tpm_state, ownerAuthorized, presenceAuthorized, subCap32, setValue); break; case TPM_SET_VENDOR: rc = TPM_SetCapability_CapVendor(tpm_state, ownerAuthorized, presenceAuthorized, subCap32, setValue); break; default: printf("TPM_SetCapabilityCommon: Error, unsupported capArea %08x", capArea); rc = TPM_BAD_MODE; break; } } return rc; } /* TPM_SetCapability_Flag() tests if the values are not already equal. If they are not, 'flag' is set to 'value' and 'altered' is set TRUE. Otherwise 'altered' is returned unchanged. The 'altered' flag is used by the caller to determine if an NVRAM write is required. */ void TPM_SetCapability_Flag(TPM_BOOL *altered, TPM_BOOL *flag, TPM_BOOL value) { /* If the values are not already equal. Can't use != since there are many values for TRUE. */ if ((value && !*flag) || (!value && *flag)) { *altered = TRUE; *flag = value; } return; } /* TPM_SetCapability_CapPermFlags() rev 100 Sets TPM_PERMANENT_FLAGS values */ static TPM_RESULT TPM_SetCapability_CapPermFlags(tpm_state_t *tpm_state, TPM_BOOL ownerAuthorized, TPM_BOOL presenceAuthorized, uint32_t subCap32, TPM_BOOL valueBool) { TPM_RESULT rc = 0; TPM_BOOL altered = FALSE; /* TRUE if the structure has been changed */ printf(" TPM_SetCapability_CapPermFlags: valueBool %02x\n", valueBool); if (rc == 0) { switch (subCap32) { case TPM_PF_DISABLE: printf(" TPM_SetCapability_CapPermFlags: TPM_PF_DISABLE\n"); /* Owner authorization or physical presence TPM_OwnerSetDisable TPM_PhysicalEnable TPM_PhysicalDisable */ if (rc == 0) { if (!ownerAuthorized && !presenceAuthorized) { printf("TPM_SetCapability_CapPermFlags: Error, no authorization\n"); rc = TPM_AUTHFAIL; } } if (rc == 0) { TPM_SetCapability_Flag(&altered, &(tpm_state->tpm_permanent_flags.disable), valueBool); } break; case TPM_PF_OWNERSHIP: printf(" TPM_SetCapability_CapPermFlags: TPM_PF_OWNERSHIP\n"); /* No authorization. No ownerInstalled. Physical presence asserted Not available when TPM deactivated or disabled TPM_SetOwnerInstall */ if (rc == 0) { if (tpm_state->tpm_permanent_data.ownerInstalled) { printf("TPM_SetCapability_CapPermFlags: Error, owner installed\n"); rc = TPM_OWNER_SET; } } if (rc == 0) { if (!presenceAuthorized) { printf("TPM_SetCapability_CapPermFlags: Error, no physicalPresence\n"); rc = TPM_AUTHFAIL; } } if (rc == 0) { if (tpm_state->tpm_permanent_flags.disable) { printf("TPM_SetCapability_CapPermFlags: Error, disabled\n"); rc = TPM_DISABLED; } } if (rc == 0) { if (tpm_state->tpm_stclear_flags.deactivated) { printf("TPM_SetCapability_CapPermFlags: Error, deactivated\n"); rc = TPM_DEACTIVATED; } } if (rc == 0) { TPM_SetCapability_Flag(&altered, &(tpm_state->tpm_permanent_flags.ownership), valueBool); } break; case TPM_PF_DEACTIVATED: printf(" TPM_SetCapability_CapPermFlags: TPM_PF_DEACTIVATED\n"); /* No authorization, physical presence assertion Not available when TPM disabled TPM_PhysicalSetDeactivated */ if (rc == 0) { if (!presenceAuthorized) { printf("TPM_SetCapability_CapPermFlags: Error, no physicalPresence\n"); rc = TPM_AUTHFAIL; } } if (rc == 0) { if (tpm_state->tpm_permanent_flags.disable) { printf("TPM_SetCapability_CapPermFlags: Error, disabled\n"); rc = TPM_DISABLED; } } if (rc == 0) { TPM_SetCapability_Flag(&altered, &(tpm_state->tpm_permanent_flags.deactivated), valueBool); } break; case TPM_PF_READPUBEK: printf(" TPM_SetCapability_CapPermFlags: TPM_PF_READPUBEK\n"); /* Owner authorization Not available when TPM deactivated or disabled */ if (rc == 0) { if (!ownerAuthorized) { printf("TPM_SetCapability_CapPermFlags: Error, not owner authorized\n"); rc = TPM_AUTHFAIL; } } if (rc == 0) { if (tpm_state->tpm_permanent_flags.disable) { printf("TPM_SetCapability_CapPermFlags: Error, disabled\n"); rc = TPM_DISABLED; } } if (rc == 0) { if (tpm_state->tpm_stclear_flags.deactivated) { printf("TPM_SetCapability_CapPermFlags: Error, deactivated\n"); rc = TPM_DEACTIVATED; } } if (rc == 0) { TPM_SetCapability_Flag(&altered, &(tpm_state->tpm_permanent_flags.readPubek), valueBool); } if (rc == 0) { printf(" TPM_SetCapability_CapPermFlags : readPubek %02x\n", tpm_state->tpm_permanent_flags.readPubek); } break; case TPM_PF_DISABLEOWNERCLEAR: printf(" TPM_SetCapability_CapPermFlags: TPM_PF_DISABLEOWNERCLEAR\n"); /* Owner authorization. Can only set to TRUE, FALSE invalid value. After being set only ForceClear resets back to FALSE. Not available when TPM deactivated or disabled TPM_DisableOwnerClear */ if (rc == 0) { if (!ownerAuthorized) { printf("TPM_SetCapability_CapPermFlags: Error, not owner authorized\n"); rc = TPM_AUTHFAIL; } } if (rc == 0) { if (!valueBool) { printf("TPM_SetCapability_CapPermFlags: Error, cannot set FALSE\n"); rc = TPM_BAD_PARAMETER; } } if (rc == 0) { if (tpm_state->tpm_permanent_flags.disable) { printf("TPM_SetCapability_CapPermFlags: Error, disabled\n"); rc = TPM_DISABLED; } } if (rc == 0) { if (tpm_state->tpm_stclear_flags.deactivated) { printf("TPM_SetCapability_CapPermFlags: Error, deactivated\n"); rc = TPM_DEACTIVATED; } } if (rc == 0) { TPM_SetCapability_Flag(&altered, &(tpm_state->tpm_permanent_flags.disableOwnerClear), valueBool); } break; case TPM_PF_ALLOWMAINTENANCE: printf(" TPM_SetCapability_CapPermFlags: TPM_PF_ALLOWMAINTENANCE\n"); /* Owner authorization. Can only set to FALSE, TRUE invalid value. After being set only changing TPM owner resets back to TRUE Not available when TPM deactivated or disabled TPM_KillMaintenanceFeature */ if (rc == 0) { if (!ownerAuthorized) { printf("TPM_SetCapability_CapPermFlags: Error, not owner authorized\n"); rc = TPM_AUTHFAIL; } } if (rc == 0) { if (valueBool) { printf("TPM_SetCapability_CapPermFlags: Error, cannot set TRUE\n"); rc = TPM_BAD_PARAMETER; } } if (rc == 0) { if (tpm_state->tpm_permanent_flags.disable) { printf("TPM_SetCapability_CapPermFlags: Error, disabled\n"); rc = TPM_DISABLED; } } if (rc == 0) { if (tpm_state->tpm_stclear_flags.deactivated) { printf("TPM_SetCapability_CapPermFlags: Error, deactivated\n"); rc = TPM_DEACTIVATED; } } if (rc == 0) { TPM_SetCapability_Flag(&altered, &(tpm_state->tpm_permanent_flags.allowMaintenance), valueBool); } break; case TPM_PF_READSRKPUB: printf(" TPM_SetCapability_CapPermFlags: TPM_PF_READSRKPUB\n"); /* Owner Authorization Not available when TPM deactivated or disabled TPM_SetCapability */ if (rc == 0) { if (!ownerAuthorized) { printf("TPM_SetCapability_CapPermFlags: Error, not owner authorized\n"); rc = TPM_AUTHFAIL; } } if (rc == 0) { if (tpm_state->tpm_permanent_flags.disable) { printf("TPM_SetCapability_CapPermFlags: Error, disable is TRUE\n"); rc = TPM_DISABLED; } } if (rc == 0) { if (tpm_state->tpm_stclear_flags.deactivated) { printf("TPM_SetCapability_CapPermFlags: Error, deactivated is TRUE\n"); rc = TPM_DEACTIVATED; } } if (rc == 0) { TPM_SetCapability_Flag(&altered, &(tpm_state->tpm_permanent_flags.readSRKPub), valueBool); } break; case TPM_PF_TPMESTABLISHED: printf(" TPM_SetCapability_CapPermFlags: TPM_PF_TPMESTABLISHED\n"); /* Locality 3 or locality 4 Can only set to FALSE TPM_ResetEstablishmentBit */ if (rc == 0) { rc = TPM_Locality_Check(TPM_LOC_THREE | TPM_LOC_FOUR, /* BYTE bitmap */ tpm_state->tpm_stany_flags.localityModifier); } if (rc == 0) { if (valueBool) { printf("TPM_SetCapability_CapPermFlags: Error, can only set to FALSE\n"); rc = TPM_BAD_PARAMETER; } } if (rc == 0) { TPM_SetCapability_Flag(&altered, &(tpm_state->tpm_permanent_flags.tpmEstablished), valueBool); } break; #if (TPM_REVISION >= 103) /* added for rev 103 */ case TPM_PF_DISABLEFULLDALOGICINFO: /* Owner Authorization TPM_SetCapability */ printf(" TPM_SetCapability_CapPermFlags: TPM_PF_DISABLEFULLDALOGICINFO\n"); if (rc == 0) { if (!ownerAuthorized) { printf("TPM_SetCapability_CapPermFlags: Error, not owner authorized\n"); rc = TPM_AUTHFAIL; } } if (rc == 0) { TPM_SetCapability_Flag(&altered, &(tpm_state->tpm_permanent_flags.disableFullDALogicInfo), valueBool); } break; #endif case TPM_PF_PHYSICALPRESENCELIFETIMELOCK: case TPM_PF_PHYSICALPRESENCEHWENABLE: case TPM_PF_PHYSICALPRESENCECMDENABLE: case TPM_PF_CEKPUSED: case TPM_PF_TPMPOST: case TPM_PF_TPMPOSTLOCK: case TPM_PF_FIPS: case TPM_PF_OPERATOR: case TPM_PF_ENABLEREVOKEEK: case TPM_PF_NV_LOCKED: case TPM_PF_MAINTENANCEDONE: default: printf("TPM_SetCapability_CapPermFlags: Error, bad subCap32 %u\n", subCap32); rc = TPM_BAD_PARAMETER; } } rc = TPM_PermanentAll_NVStore(tpm_state, altered, rc); return rc; } /* TPM_SetCapability_CapPermData() rev 105 Sets TPM_PERMANENT_DATA values */ static TPM_RESULT TPM_SetCapability_CapPermData(tpm_state_t *tpm_state, TPM_BOOL ownerAuthorized, TPM_BOOL presenceAuthorized, uint32_t subCap32, uint32_t valueUint32) { TPM_RESULT rc = 0; TPM_BOOL writeAllNV = FALSE; /* TRUE if the structure has been changed */ printf(" TPM_SetCapability_CapPermData:\n"); presenceAuthorized = presenceAuthorized; /* not used */ if (rc == 0) { switch (subCap32) { case TPM_PD_RESTRICTDELEGATE: printf(" TPM_SetCapability_CapPermData: TPM_PD_RESTRICTDELEGATE\n"); /* Owner authorization. Not available when TPM deactivated or disabled */ /* TPM_CMK_SetRestrictions */ if (rc == 0) { if (!ownerAuthorized) { printf("TPM_SetCapability_CapPermData: Error, not owner authorized\n"); rc = TPM_AUTHFAIL; } } if (rc == 0) { if (tpm_state->tpm_permanent_flags.disable) { printf("TPM_SetCapability_CapPermData: Error, disabled\n"); rc = TPM_DISABLED; } } if (rc == 0) { if (tpm_state->tpm_stclear_flags.deactivated) { printf("TPM_SetCapability_CapPermData: Error, deactivated\n"); rc = TPM_DEACTIVATED; } } if (rc == 0) { if (tpm_state->tpm_permanent_data.restrictDelegate != valueUint32) { tpm_state->tpm_permanent_data.restrictDelegate = valueUint32; writeAllNV = TRUE; } } break; case TPM_PD_DAAPROOF: /* TPM_PD_DAAPROOF This capability has no value. When specified by TPM_SetCapability, a new daaProof, tpmDAASeed, and daaBlobKey are generated. */ rc = TPM_PermanentData_InitDaa(&(tpm_state->tpm_permanent_data)); writeAllNV = TRUE; break; case TPM_PD_REVMAJOR: case TPM_PD_REVMINOR: case TPM_PD_TPMPROOF: case TPM_PD_OWNERAUTH: case TPM_PD_OPERATORAUTH: case TPM_PD_MANUMAINTPUB: case TPM_PD_ENDORSEMENTKEY: case TPM_PD_SRK: case TPM_PD_DELEGATEKEY: case TPM_PD_CONTEXTKEY: case TPM_PD_AUDITMONOTONICCOUNTER: case TPM_PD_MONOTONICCOUNTER: case TPM_PD_PCRATTRIB: case TPM_PD_ORDINALAUDITSTATUS: case TPM_PD_AUTHDIR: case TPM_PD_RNGSTATE: case TPM_PD_FAMILYTABLE: case TPM_DELEGATETABLE: case TPM_PD_EKRESET: case TPM_PD_LASTFAMILYID: case TPM_PD_NOOWNERNVWRITE: case TPM_PD_TPMDAASEED: default: printf("TPM_SetCapability_CapPermData: Error, bad subCap32 %u\n", subCap32); rc = TPM_BAD_PARAMETER; } } rc = TPM_PermanentAll_NVStore(tpm_state, writeAllNV, rc); return rc; } /* TPM_SetCapability_CapStclearFlags() rev 85 Sets TPM_STCLEAR_FLAGS values */ static TPM_RESULT TPM_SetCapability_CapStclearFlags(tpm_state_t *tpm_state, TPM_BOOL ownerAuthorized, TPM_BOOL presenceAuthorized, uint32_t subCap32, TPM_BOOL valueBool) { TPM_RESULT rc = 0; printf(" TPM_SetCapability_CapStclearFlags: valueBool %02x\n", valueBool); ownerAuthorized = ownerAuthorized; /* not used */ presenceAuthorized = presenceAuthorized; /* not used */ if (rc == 0) { switch (subCap32) { case TPM_SF_DISABLEFORCECLEAR: printf(" TPM_SetCapability_CapStclearFlags: TPM_SF_DISABLEFORCECLEAR\n"); /* Not available when TPM deactivated or disabled */ /* TPM_DisableForceClear */ if (rc == 0) { if (tpm_state->tpm_permanent_flags.disable) { printf("TPM_SetCapability_CapStclearFlags: Error, disabled\n"); rc = TPM_DISABLED; } } if (rc == 0) { if (tpm_state->tpm_stclear_flags.deactivated) { printf("TPM_SetCapability_CapStclearFlags: Error, deactivated\n"); rc = TPM_DEACTIVATED; } } /* Can only set to TRUE */ if (rc == 0) { if (!valueBool) { printf("TPM_SetCapability_CapStclearFlags: Error, cannot set FALSE\n"); rc = TPM_BAD_PARAMETER; } } if (rc == 0) { tpm_state->tpm_stclear_flags.disableForceClear = TRUE; } break; case TPM_SF_DEACTIVATED: case TPM_SF_PHYSICALPRESENCE: case TPM_SF_PHYSICALPRESENCELOCK: case TPM_SF_BGLOBALLOCK: default: printf("TPM_SetCapability_CapStclearFlags: Error, bad subCap32 %u\n", subCap32); rc = TPM_BAD_PARAMETER; } } return rc; } /* TPM_SetCapability_CapStclearData() rev 100 Sets TPM_STCLEAR_DATA values */ static TPM_RESULT TPM_SetCapability_CapStclearData(tpm_state_t *tpm_state, TPM_BOOL ownerAuthorized, TPM_BOOL presenceAuthorized, uint32_t subCap32, uint32_t valueUint32) { TPM_RESULT rc = 0; #if (TPM_REVISION < 103) /* added for rev 103 */ tpm_state = tpm_state; /* to quiet the compiler */ presenceAuthorized = presenceAuthorized; valueUint32 = valueUint32; #endif printf(" TPM_SetCapability_CapStclearData:\n"); ownerAuthorized = ownerAuthorized; /* not used */ if (rc == 0) { switch (subCap32) { #if (TPM_REVISION >= 103) /* added for rev 103 */ case TPM_SD_DEFERREDPHYSICALPRESENCE: printf(" TPM_SetCapability_CapStclearData: TPM_SD_DEFERREDPHYSICALPRESENCE\n"); /* Can only set to TRUE if PhysicalPresence is asserted. Can set to FALSE at any time. */ /* 1. If physical presence is not asserted */ /* a. If TPM_SetCapability -> setValue has a bit set that is not already set in TPM_STCLEAR_DATA -> deferredPhysicalPresence, return TPM_BAD_PRESENCE. */ if (rc == 0) { if (!presenceAuthorized) { if (~(tpm_state->tpm_stclear_data.deferredPhysicalPresence) & valueUint32) { printf("TPM_SetCapability_CapStclearData: " "Error, no physicalPresence and deferredPhysicalPresence %08x\n", tpm_state->tpm_stclear_data.deferredPhysicalPresence); rc = TPM_BAD_PRESENCE; } } } /* 2.Set TPM_STCLEAR_DATA -> deferredPhysicalPresence to TPM_SetCapability -> setValue. */ if (rc == 0) { printf(" TPM_SetCapability_CapStclearData: deferredPhysicalPresence now %08x\n", valueUint32); tpm_state->tpm_stclear_data.deferredPhysicalPresence = valueUint32; } break; #endif case TPM_SD_CONTEXTNONCEKEY: case TPM_SD_COUNTID: case TPM_SD_OWNERREFERENCE: case TPM_SD_DISABLERESETLOCK: case TPM_SD_PCR: default: printf("TPM_SetCapability_CapStclearData: Error, bad subCap32 %u\n", subCap32); rc = TPM_BAD_PARAMETER; } } return rc; } /* TPM_SetCapability_CapStanyFlags() rev 85 Sets TPM_STANY_FLAGS values */ static TPM_RESULT TPM_SetCapability_CapStanyFlags(tpm_state_t *tpm_state, TPM_BOOL ownerAuthorized, TPM_BOOL presenceAuthorized, uint32_t subCap32, TPM_BOOL valueBool) { TPM_RESULT rc = 0; printf(" TPM_SetCapability_CapStanyFlags:\n"); ownerAuthorized = ownerAuthorized; /* not used */ presenceAuthorized = presenceAuthorized; /* not used */ if (rc == 0) { switch (subCap32) { case TPM_AF_TOSPRESENT: printf(" TPM_SetCapability_CapStanyFlags: TPM_AF_TOSPRESENT\n"); /* locality 3 or 4 */ /* Not available when TPM deactivated or disabled */ if (rc == 0) { rc = TPM_Locality_Check(TPM_LOC_THREE | TPM_LOC_FOUR, tpm_state->tpm_stany_flags.localityModifier); } if (rc == 0) { if (tpm_state->tpm_permanent_flags.disable) { printf("TPM_SetCapability_CapStanyFlags: Error, disabled\n"); rc = TPM_DISABLED; } } if (rc == 0) { if (tpm_state->tpm_stclear_flags.deactivated) { printf("TPM_SetCapability_CapStanyFlags: Error, deactivated\n"); rc = TPM_DEACTIVATED; } } /* can only be set to FALSE */ if (rc == 0) { if (valueBool) { printf("TPM_SetCapability_CapStanyFlags: Error, cannot set TRUE\n"); rc = TPM_BAD_PARAMETER; } } if (rc == 0) { tpm_state->tpm_stany_flags.TOSPresent = FALSE; } break; case TPM_AF_POSTINITIALISE: case TPM_AF_LOCALITYMODIFIER: case TPM_AF_TRANSPORTEXCLUSIVE: default: printf("TPM_SetCapability_CapStanyFlags: Error, bad subCap32 %u\n", subCap32); rc = TPM_BAD_PARAMETER; } } return rc; } /* TPM_SetCapability_CapStanyData() rev 85 Sets TPM_STANY_DATA values */ static TPM_RESULT TPM_SetCapability_CapStanyData(tpm_state_t *tpm_state, TPM_BOOL ownerAuthorized, TPM_BOOL presenceAuthorized, uint32_t subCap32, TPM_SIZED_BUFFER *setValue) { TPM_RESULT rc = 0; printf(" TPM_SetCapability_CapStanyData:\n"); tpm_state = tpm_state; /* not used */ ownerAuthorized = ownerAuthorized; /* not used */ presenceAuthorized = presenceAuthorized; /* not used */ setValue = setValue; /* not used */ if (rc == 0) { switch (subCap32) { case TPM_AD_CONTEXTNONCESESSION: case TPM_AD_AUDITDIGEST: case TPM_AD_CURRENTTICKS: case TPM_AD_CONTEXTCOUNT: case TPM_AD_CONTEXTLIST: case TPM_AD_SESSIONS: default: printf("TPM_SetCapability_CapStanyData: Error, bad subCap32 %u\n", subCap32); rc = TPM_BAD_PARAMETER; } } return rc; } /* These are subCaps to TPM_SetCapability -> TPM_SET_VENDOR capArea, the vendor specific area. */ static TPM_RESULT TPM_SetCapability_CapVendor(tpm_state_t *tpm_state, TPM_BOOL ownerAuthorized, TPM_BOOL presenceAuthorized, uint32_t subCap32, TPM_SIZED_BUFFER *setValue) { TPM_RESULT rc = 0; printf(" TPM_SetCapability_CapVendor:\n"); ownerAuthorized = ownerAuthorized; /* not used */ presenceAuthorized = presenceAuthorized; /* not used */ setValue = setValue; /* make temporary copies so the setValue is not touched */ if (rc == 0) { switch(subCap32) { default: printf("TPM_SetCapability_CapVendor: Error, unsupported subCap %08x\n", subCap32); tpm_state = tpm_state; /* not used */ rc = TPM_BAD_PARAMETER; break; } } return rc; } libtpms-0.9.3/src/tpm12/tpm_process.h000066400000000000000000000366261421143571500174560ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM Command Processor */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_process.h 4120 2010-10-26 22:00:40Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_PROCESS_H #define TPM_PROCESS_H #include /* Commented out. This is not a standard header. If needed for a particular platform, replace but also add comments and ifdef. */ /* #include */ #include "tpm_global.h" #include "tpm_store.h" /* TPM_CAP_VERSION_INFO */ void TPM_CapVersionInfo_Init(TPM_CAP_VERSION_INFO *tpm_cap_version_info); TPM_RESULT TPM_CapVersionInfo_Load(TPM_CAP_VERSION_INFO *tpm_cap_version_info, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_CapVersionInfo_Store(TPM_STORE_BUFFER *sbuffer, const TPM_CAP_VERSION_INFO *tpm_cap_version_info); void TPM_CapVersionInfo_Delete(TPM_CAP_VERSION_INFO *tpm_cap_version_info); void TPM_CapVersionInfo_Set(TPM_CAP_VERSION_INFO *tpm_cap_version_info, TPM_PERMANENT_DATA *tpm_permanent_data); /* Capability Common Code */ void TPM_SetCapability_Flag(TPM_BOOL *altered, TPM_BOOL *flag, TPM_BOOL value); void TPM_GetSubCapInt(uint16_t *subCap16, uint32_t *subCap32, TPM_SIZED_BUFFER *subCap); TPM_RESULT TPM_GetCapabilityCommon(TPM_STORE_BUFFER *capabilityResponse, tpm_state_t *tpm_state, TPM_CAPABILITY_AREA capArea, uint16_t subCap16, uint32_t subCap32, TPM_SIZED_BUFFER *subCap); TPM_RESULT TPM_SetCapabilityCommon(tpm_state_t *tpm_state, TPM_BOOL ownerAuthorized, TPM_BOOL presenceAuthorized, TPM_CAPABILITY_AREA capArea, uint16_t subCap16, uint32_t subCap32, TPM_SIZED_BUFFER *subCap, TPM_SIZED_BUFFER *setValue); /* Processing Functions */ TPM_RESULT TPM_ProcessA(unsigned char **response, uint32_t *response_size, uint32_t *response_total, unsigned char *command, uint32_t command_size); TPM_RESULT TPM_Process(TPM_STORE_BUFFER *response, unsigned char *command, uint32_t command_size); TPM_RESULT TPM_Process_Wrapped(TPM_STORE_BUFFER *response, unsigned char *command, uint32_t command_size, tpm_state_t *targetInstance, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_GetCommandParams(TPM_TAG *tag, uint32_t *paramSize , TPM_COMMAND_CODE *ordinal, unsigned char **command, uint32_t *command_size); TPM_RESULT TPM_Process_GetResponseParams(TPM_TAG *tag, uint32_t *paramSize , TPM_RESULT *returnCode, unsigned char **response, uint32_t *response_size); TPM_RESULT TPM_Process_Unused(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_GetCapability(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_GetCapabilityOwner(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_GetCapabilitySigned(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_SetCapability(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); /* Processing Utilities */ /* tag checking */ TPM_RESULT TPM_CheckRequestTag210(TPM_TAG tpm_tag); TPM_RESULT TPM_CheckRequestTag21 (TPM_TAG tpm_tag); TPM_RESULT TPM_CheckRequestTag2 (TPM_TAG tpm_tag); TPM_RESULT TPM_CheckRequestTag10 (TPM_TAG tpm_tag); TPM_RESULT TPM_CheckRequestTag1 (TPM_TAG tpm_tag); TPM_RESULT TPM_CheckRequestTag0 (TPM_TAG tpm_tag); /* TPM state checking */ TPM_RESULT TPM_CheckState(tpm_state_t *tpm_state, TPM_TAG tag, uint32_t tpm_check_map); TPM_RESULT TPM_Process_Preprocess(tpm_state_t *tpm_state, TPM_COMMAND_CODE ordinal, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Check_SHA1Context(tpm_state_t *tpm_state, TPM_COMMAND_CODE ordinal, TPM_TRANSPORT_INTERNAL *transportInternal); /* ordinal processing */ /* Prototype for all ordinal processing functions tpm_state: the entire TPM instance non-volatile and volatile state response: the buffer to hold the ordinal response tag: the command tag paramSize: bytes left after the tag, paramSize, and ordinal ordinal: the ordinal being called (could be hard coded, but eliminates cut/paste errors) command: the remainder of the command packet transportInternal: if not NULL, indicates that this function was called recursively from TPM_ExecuteTransport */ typedef TPM_RESULT (*tpm_process_function_t)(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); typedef struct tdTPM_ORDINAL_TABLE { TPM_COMMAND_CODE ordinal; tpm_process_function_t process_function_v11; /* processing function for TPM 1.1 */ tpm_process_function_t process_function_v12; /* processing function for TPM 1.2 */ TPM_BOOL auditable; /* FALSE for functions never audited */ TPM_BOOL auditDefault; /* TRUE if auditing is enabled by default */ uint16_t ownerPermissionBlock; /* 0:unused, 1:per1 2:per2 */ uint32_t ownerPermissionPosition; /* owner permission bit position */ uint16_t keyPermissionBlock; /* 0:unused, 1:per1 2:per2 */ uint32_t keyPermissionPosition; /* key permission bit position */ uint32_t inputHandleSize; /* bytes of input handles (or other bytes not to be encrypted or transport audited) */ uint32_t keyHandles; /* number of input key handles */ uint32_t outputHandleSize; /* bytes of output handles (or other bytes not to be encrypted or transport audited */ TPM_BOOL transportWrappable; /* can be wrapped in transport session */ TPM_BOOL instanceWrappable; /* ordinal can be wrapped and called by a parent instance */ TPM_BOOL hardwareWrappable; /* ordinal can be wrapped and call the hardware TPM instance */ } TPM_ORDINAL_TABLE; TPM_RESULT TPM_OrdinalTable_GetEntry(TPM_ORDINAL_TABLE **entry, TPM_ORDINAL_TABLE *ordinalTable, TPM_COMMAND_CODE ordinal); void TPM_OrdinalTable_GetProcessFunction(tpm_process_function_t *tpm_process_function, TPM_ORDINAL_TABLE *ordinalTable, TPM_COMMAND_CODE ordinal); void TPM_OrdinalTable_GetAuditable(TPM_BOOL *auditable, TPM_COMMAND_CODE ordinal); void TPM_OrdinalTable_GetAuditDefault(TPM_BOOL *auditDefault, TPM_COMMAND_CODE ordinal); TPM_RESULT TPM_OrdinalTable_GetOwnerPermission(uint16_t *ownerPermissionBlock, uint32_t *ownerPermissionPosition, TPM_COMMAND_CODE ordinal); TPM_RESULT TPM_OrdinalTable_GetKeyPermission(uint16_t *keyPermissionBlock, uint32_t *keyPermissionPosition, TPM_COMMAND_CODE ordinal); TPM_RESULT TPM_OrdinalTable_ParseWrappedCmd(uint32_t *datawStart, uint32_t *datawLen, uint32_t *keyHandles, uint32_t *keyHandle1Index, uint32_t *keyHandle2Index, TPM_COMMAND_CODE *ordinal, TPM_BOOL *transportWrappable, TPM_SIZED_BUFFER *wrappedCmd); TPM_RESULT TPM_OrdinalTable_ParseWrappedRsp(uint32_t *datawStart, uint32_t *datawLen, TPM_RESULT *rcw, TPM_COMMAND_CODE ordinal, const unsigned char *wrappedRspStream, uint32_t wrappedRspStreamSize); TPM_RESULT TPM_GetInParamDigest(TPM_DIGEST inParamDigest, TPM_BOOL *auditStatus, TPM_BOOL *transportEncrypt, tpm_state_t *tpm_state, TPM_TAG tag, TPM_COMMAND_CODE ordinal, unsigned char *inParamStart, unsigned char *inParamEnd, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_GetOutParamDigest(TPM_DIGEST outParamDigest, TPM_BOOL auditStatus, TPM_BOOL transportEncrypt, TPM_TAG tag, TPM_RESULT returnCode, TPM_COMMAND_CODE ordinal, unsigned char *outParamStart, uint32_t outParamLength); TPM_RESULT TPM_ProcessAudit(tpm_state_t *tpm_state, TPM_BOOL transportEncrypt, TPM_DIGEST inParamDigest, TPM_DIGEST outParamDigest, TPM_COMMAND_CODE ordinal); /* defines for TPM_CheckState check map */ #define TPM_CHECK_NOT_SHUTDOWN 0x00000001 #define TPM_CHECK_ENABLED 0x00000004 #define TPM_CHECK_ACTIVATED 0x00000008 #define TPM_CHECK_OWNER 0x00000010 #define TPM_CHECK_NO_LOCKOUT 0x00000020 #define TPM_CHECK_NV_NOAUTH 0x00000040 /* default conditions to check */ #define TPM_CHECK_ALL 0x0000003f /* all state */ #define TPM_CHECK_ALLOW_NO_OWNER 0x0000002f /* all state but owner installed */ #endif libtpms-0.9.3/src/tpm12/tpm_secret.c000066400000000000000000000124351421143571500172500ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Secret Data Handler */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_secret.c 4071 2010-04-29 19:26:45Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include #include #include "tpm_crypto.h" #include "tpm_debug.h" #include "tpm_error.h" #include "tpm_store.h" #include "tpm_secret.h" void TPM_Secret_Init(TPM_SECRET tpm_secret) { printf(" TPM_Secret_Init:\n"); memset(tpm_secret, 0, TPM_SECRET_SIZE); return; } /* TPM_Secret_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes After use, call TPM_Secret_Delete() to free memory */ TPM_RESULT TPM_Secret_Load(TPM_SECRET tpm_secret, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_Secret_Load:\n"); rc = TPM_Loadn(tpm_secret, TPM_SECRET_SIZE, stream, stream_size); return rc; } /* TPM_Secret_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes After use, call TPM_Sbuffer_Delete() to free memory */ TPM_RESULT TPM_Secret_Store(TPM_STORE_BUFFER *sbuffer, const TPM_SECRET tpm_secret) { TPM_RESULT rc = 0; printf(" TPM_Secret_Store:\n"); rc = TPM_Sbuffer_Append(sbuffer, tpm_secret, TPM_SECRET_SIZE); return rc; } /* TPM_Secret_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the secret sets pointers to NULL calls TPM_Secret_Init to set members back to default values The secret itself is not freed returns 0 or error codes */ void TPM_Secret_Delete(TPM_SECRET tpm_secret) { printf(" TPM_Secret_Delete:\n"); if (tpm_secret != NULL) { TPM_Secret_Init(tpm_secret); } return; } /* TPM_Secret_Copy() copies the source to the destination */ void TPM_Secret_Copy(TPM_SECRET destination, const TPM_SECRET source) { printf(" TPM_Secret_Copy:\n"); memcpy(destination, source, TPM_SECRET_SIZE); return; } /* TPM_Secret_Compare() compares the source to the destination. Returns TPM_AUTHFAIL if the nonces are not equal */ TPM_RESULT TPM_Secret_Compare(TPM_SECRET expect, const TPM_SECRET actual) { TPM_RESULT rc = 0; printf(" TPM_Secret_Compare:\n"); rc = memcmp(expect, actual, TPM_SECRET_SIZE); if (rc != 0) { printf("TPM_Secret_Compare: Error comparing secret\n"); rc = TPM_AUTHFAIL; } return rc; } /* TPM_Secret_Generate() generates a new TPM_SECRET from the random number generator */ TPM_RESULT TPM_Secret_Generate(TPM_SECRET tpm_secret) { TPM_RESULT rc = 0; printf(" TPM_Secret_Generate:\n"); rc = TPM_Random(tpm_secret, TPM_SECRET_SIZE); return rc; } /* TPM_Secret_XOR() XOR's the source and the destination, and returns the result on output. */ void TPM_Secret_XOR(TPM_SECRET output, TPM_SECRET input1, TPM_SECRET input2) { size_t i; printf(" TPM_Secret_XOR:\n"); for (i = 0 ; i < TPM_SECRET_SIZE ; i++) { output[i] = input1[i] ^ input2[i]; } return; } libtpms-0.9.3/src/tpm12/tpm_secret.h000066400000000000000000000062071421143571500172550ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Secret Data Handler */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_secret.h 4071 2010-04-29 19:26:45Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_SECRET_H #define TPM_SECRET_H #include "tpm_store.h" #include "tpm_structures.h" #include "tpm_types.h" void TPM_Secret_Init(TPM_SECRET tpm_secret); TPM_RESULT TPM_Secret_Load(TPM_SECRET tpm_secret, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_Secret_Store(TPM_STORE_BUFFER *sbuffer, const TPM_SECRET tpm_secret); void TPM_Secret_Delete(TPM_SECRET tpm_secret); void TPM_Secret_Copy(TPM_SECRET destination, const TPM_SECRET source); TPM_RESULT TPM_Secret_Compare(TPM_SECRET expect, const TPM_SECRET actual); TPM_RESULT TPM_Secret_Generate(TPM_SECRET tpm_secret); void TPM_Secret_XOR(TPM_SECRET output, TPM_SECRET input1, TPM_SECRET input2); #endif libtpms-0.9.3/src/tpm12/tpm_session.c000066400000000000000000006412631421143571500174550ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Session Handler */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_session.c 4584 2011-06-22 15:49:41Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include #include #include #include "tpm_auth.h" #include "tpm_counter.h" #include "tpm_crypto.h" #include "tpm_cryptoh.h" #include "tpm_daa.h" #include "tpm_debug.h" #include "tpm_delegate.h" #include "tpm_digest.h" #include "tpm_error.h" #include "tpm_init.h" #include "tpm_io.h" #include "tpm_key.h" #include "tpm_nonce.h" #include "tpm_nvram.h" #include "tpm_pcr.h" #include "tpm_process.h" #include "tpm_permanent.h" #include "tpm_secret.h" #include "tpm_transport.h" #include "tpm_types.h" #include "tpm_session.h" /* local function prototypes */ static TPM_RESULT TPM_OSAPDelegate(TPM_DIGEST **entityDigest, TPM_SECRET **authData, TPM_AUTH_SESSION_DATA *authSession, tpm_state_t *tpm_state, uint32_t delegateRowIndex); static TPM_RESULT TPM_LoadContext_CheckKeyLoaded(tpm_state_t *tpm_state, TPM_HANDLE entityHandle, TPM_DIGEST entityDigest); static TPM_RESULT TPM_LoadContext_CheckKeyLoadedByDigest(tpm_state_t *tpm_state, TPM_DIGEST entityDigest); static TPM_RESULT TPM_LoadContext_CheckOwnerLoaded(tpm_state_t *tpm_state, TPM_DIGEST entityDigest); static TPM_RESULT TPM_LoadContext_CheckSrkLoaded(tpm_state_t *tpm_state, TPM_DIGEST entityDigest); static TPM_RESULT TPM_LoadContext_CheckCounterLoaded(tpm_state_t *tpm_state, TPM_HANDLE entityHandle, TPM_DIGEST entityDigest); static TPM_RESULT TPM_LoadContext_CheckNvLoaded(tpm_state_t *tpm_state, TPM_HANDLE entityHandle, TPM_DIGEST entityDigest); /* TPM_AUTH_SESSION_DATA (one element of the array) */ /* TPM_AuthSessionData_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_AuthSessionData_Init(TPM_AUTH_SESSION_DATA *tpm_auth_session_data) { printf(" TPM_AuthSessionData_Init:\n"); tpm_auth_session_data->handle = 0; tpm_auth_session_data->protocolID = 0; tpm_auth_session_data->entityTypeByte = 0; tpm_auth_session_data->adipEncScheme = 0; TPM_Nonce_Init(tpm_auth_session_data->nonceEven); TPM_Secret_Init(tpm_auth_session_data->sharedSecret); TPM_Digest_Init(tpm_auth_session_data->entityDigest); TPM_DelegatePublic_Init(&(tpm_auth_session_data->pub)); tpm_auth_session_data->valid = FALSE; return; } /* TPM_AuthSessionData_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_AuthSessionData_Init() After use, call TPM_AuthSessionData_Delete() to free memory */ TPM_RESULT TPM_AuthSessionData_Load(TPM_AUTH_SESSION_DATA *tpm_auth_session_data, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_AuthSessionData_Load:\n"); /* load handle */ if (rc == 0) { rc = TPM_Load32(&(tpm_auth_session_data->handle), stream, stream_size); } /* load protocolID */ if (rc == 0) { rc = TPM_Load16(&(tpm_auth_session_data->protocolID), stream, stream_size); } /* load entityTypeByte */ if (rc == 0) { rc = TPM_Loadn(&(tpm_auth_session_data->entityTypeByte), sizeof(BYTE), stream, stream_size); } /* load adipEncScheme */ if (rc == 0) { rc = TPM_Loadn(&(tpm_auth_session_data->adipEncScheme), sizeof(BYTE), stream, stream_size); } /* load nonceEven */ if (rc == 0) { rc = TPM_Nonce_Load(tpm_auth_session_data->nonceEven, stream, stream_size); } /* load sharedSecret */ if (rc == 0) { rc = TPM_Nonce_Load(tpm_auth_session_data->sharedSecret, stream, stream_size); } /* load entityDigest */ if (rc == 0) { rc = TPM_Digest_Load(tpm_auth_session_data->entityDigest, stream, stream_size); } /* load pub */ if (rc == 0) { rc = TPM_DelegatePublic_Load(&(tpm_auth_session_data->pub), stream, stream_size); } /* set valid */ if (rc == 0) { tpm_auth_session_data->valid = TRUE; } return rc; } /* TPM_AuthSessionData_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_AuthSessionData_Store(TPM_STORE_BUFFER *sbuffer, const TPM_AUTH_SESSION_DATA *tpm_auth_session_data) { TPM_RESULT rc = 0; printf(" TPM_AuthSessionData_Store:\n"); /* store handle */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_auth_session_data->handle); } /* store protocolID */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, tpm_auth_session_data->protocolID); } /* store entityTypeByte */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_auth_session_data->entityTypeByte), sizeof(BYTE)); } /* store adipEncScheme */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_auth_session_data->adipEncScheme), sizeof(BYTE)); } /* store nonceEven */ if (rc == 0) { rc = TPM_Nonce_Store(sbuffer, tpm_auth_session_data->nonceEven); } /* store sharedSecret */ if (rc == 0) { rc = TPM_Nonce_Store(sbuffer, tpm_auth_session_data->sharedSecret); } /* store entityDigest */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_auth_session_data->entityDigest); } /* store pub */ if (rc == 0) { rc = TPM_DelegatePublic_Store(sbuffer, &(tpm_auth_session_data->pub)); } return rc; } /* TPM_AuthSessionData_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_AuthSessionData_Init to set members back to default values The object itself is not freed */ void TPM_AuthSessionData_Delete(TPM_AUTH_SESSION_DATA *tpm_auth_session_data) { printf(" TPM_AuthSessionData_Delete:\n"); if (tpm_auth_session_data != NULL) { TPM_DelegatePublic_Delete(&(tpm_auth_session_data->pub)); TPM_AuthSessionData_Init(tpm_auth_session_data); } return; } /* TPM_AuthSessionData_Copy() copies the source to the destination. The source handle is ignored, since it might already be used. */ void TPM_AuthSessionData_Copy(TPM_AUTH_SESSION_DATA *dest_auth_session_data, TPM_HANDLE tpm_handle, TPM_AUTH_SESSION_DATA *src_auth_session_data) { dest_auth_session_data->handle = tpm_handle; dest_auth_session_data->protocolID = src_auth_session_data->protocolID; dest_auth_session_data->entityTypeByte = src_auth_session_data->entityTypeByte; dest_auth_session_data-> adipEncScheme = src_auth_session_data->adipEncScheme; TPM_Nonce_Copy(dest_auth_session_data->nonceEven, src_auth_session_data->nonceEven); TPM_Secret_Copy(dest_auth_session_data->sharedSecret, src_auth_session_data->sharedSecret); TPM_Digest_Copy(dest_auth_session_data->entityDigest, src_auth_session_data->entityDigest); TPM_DelegatePublic_Copy(&(dest_auth_session_data->pub), &(src_auth_session_data->pub)); dest_auth_session_data->valid= src_auth_session_data->valid; } /* TPM_AuthSessionData_GetDelegatePublic() */ TPM_RESULT TPM_AuthSessionData_GetDelegatePublic(TPM_DELEGATE_PUBLIC **delegatePublic, TPM_AUTH_SESSION_DATA *auth_session_data) { TPM_RESULT rc = 0; printf(" TPM_AuthSessionData_GetDelegatePublic:\n"); if (rc == 0) { *delegatePublic = &(auth_session_data->pub); } return rc; } /* TPM_AuthSessionData_CheckEncScheme() checks that the encryption scheme specified by TPM_ENTITY_TYPE is supported by the TPM (by TPM_AuthSessionData_Decrypt) */ TPM_RESULT TPM_AuthSessionData_CheckEncScheme(TPM_ADIP_ENC_SCHEME adipEncScheme, TPM_BOOL FIPS) { TPM_RESULT rc = 0; printf(" TPM_AuthSessionData_CheckEncScheme: adipEncScheme %02x\n", adipEncScheme); switch (adipEncScheme) { case TPM_ET_XOR: /* i.If TPM_PERMANENT_FLAGS -> FIPS is TRUE */ /* (1) All encrypted authorizations MUST use a symmetric key encryption scheme. */ if (FIPS) { rc = TPM_INAPPROPRIATE_ENC; } break; case TPM_ET_AES128_CTR: break; default: printf("TPM_AuthSessionData_CheckEncScheme: Error, unsupported adipEncScheme\n"); rc = TPM_INAPPROPRIATE_ENC; break; } return rc; } /* TPM_AuthSessionData_Decrypt() decrypts the encAuth secret using the algorithm indicated in the OSAP or DSAP session If 'odd' is FALSE, one decrypt of encAuthEven to a1Even. If 'odd' is TRUE, a second decrypt of encAuthOdd to a1Odd is also performed. */ TPM_RESULT TPM_AuthSessionData_Decrypt(TPM_DIGEST a1Even, TPM_DIGEST a1Odd, TPM_ENCAUTH encAuthEven, TPM_AUTH_SESSION_DATA *tpm_auth_session_data, TPM_NONCE nonceOdd, TPM_ENCAUTH encAuthOdd, TPM_BOOL odd) { TPM_RESULT rc = 0; TPM_DIGEST x1Even; TPM_DIGEST x2Odd; printf(" TPM_AuthSessionData_Decrypt:\n"); /* sanity check - the session must be OSAP or DSAP */ if (rc == 0) { if ((tpm_auth_session_data->protocolID != TPM_PID_OSAP) && (tpm_auth_session_data->protocolID != TPM_PID_DSAP)) { printf("TPM_AuthSessionData_Decrypt: Error, protocolID should be OSAP, is %04hx\n", tpm_auth_session_data->protocolID); rc = TPM_BAD_MODE; } } if (rc == 0) { /* algorithm indicated in the OSAP session */ switch(tpm_auth_session_data->adipEncScheme) { case TPM_ET_XOR: /* 4. If the entity type indicates XOR encryption for the AuthData secret */ /* a.Create X1 the SHA-1 of the concatenation of (authHandle -> sharedSecret || authLastNonceEven). */ if (rc == 0) { rc = TPM_SHA1(x1Even, TPM_SECRET_SIZE, tpm_auth_session_data->sharedSecret, TPM_NONCE_SIZE, tpm_auth_session_data->nonceEven, 0, NULL); } /* b. Create the decrypted AuthData the XOR of X1 and the encrypted AuthData. */ if (rc == 0) { TPM_Digest_XOR(a1Even, encAuthEven, x1Even); } /* c. If the command ordinal contains a second AuthData2 secret (e.g. TPM_CreateWrapKey) */ /* i. Create X2 the SHA-1 of the concatenation of (authHandle -> sharedSecret || nonceOdd). */ if ((rc == 0) && (odd)) { rc = TPM_SHA1(x2Odd, TPM_SECRET_SIZE, tpm_auth_session_data->sharedSecret, TPM_NONCE_SIZE, nonceOdd, 0, NULL); } /* ii. Create the decrypted AuthData2 the XOR of X2 and the encrypted AuthData2. */ if ((rc == 0) && (odd)) { TPM_Digest_XOR(a1Odd, encAuthOdd, x2Odd); } break; #ifdef TPM_AES /* if AES is supported */ case TPM_ET_AES128_CTR: /* 5. If the entity type indicates symmetric key encryption */ /* a. The key for the encryption algorithm is the first bytes of the OSAP shared secret. */ /* i. E.g., For AES128, the key is the first 16 bytes of the OSAP shared secret. */ /* ii. There is no support for AES keys greater than 128 bits. */ /* b. If the entity type indicates CTR mode */ /* i. The initial counter value for AuthData is the first bytes of authLastNonceEven. */ /* (1) E.g., For AES128, the initial counter value is the first 16 bytes of authLastNonceEven. */ /* b. Create the decrypted AuthData from the encrypted AuthData. */ if (rc == 0) { rc = TPM_SymmetricKeyData_CtrCrypt(a1Even, /* output data */ encAuthEven, /* input data */ TPM_AUTHDATA_SIZE, /* data size */ tpm_auth_session_data->sharedSecret, /* key */ TPM_SECRET_SIZE, tpm_auth_session_data->nonceEven, /* CTR */ TPM_NONCE_SIZE); } /* ii. If the command ordinal contains a second AuthData2 secret (e.g. TPM_CreateWrapKey) */ /* (1) The initial counter value for AuthData2 is the first bytes of nonceOdd. */ /* ii. Create the decrypted AuthData2 from the the encrypted AuthData2. */ if ((rc == 0) && (odd)) { rc = TPM_SymmetricKeyData_CtrCrypt(a1Odd, /* output data */ encAuthOdd, /* input data */ TPM_AUTHDATA_SIZE, /* data size */ tpm_auth_session_data->sharedSecret, /* key */ TPM_SECRET_SIZE, nonceOdd, /* CTR */ TPM_NONCE_SIZE); } /* iii. Additional counter values as required are generated by incrementing the entire counter value as a big endian number. */ break; #endif /* TPM_AES */ default: printf("TPM_AuthSessionData_Decrypt: Error, entityType %02x not supported\n", tpm_auth_session_data->adipEncScheme); rc = TPM_INAPPROPRIATE_ENC; break; } } return rc; } /* TPM_AUTH_SESSION_DATA (the entire array) */ void TPM_AuthSessions_Init(TPM_AUTH_SESSION_DATA *authSessions) { size_t i; printf(" TPM_AuthSessions_Init:\n"); for (i = 0 ; i < TPM_MIN_AUTH_SESSIONS ; i++) { TPM_AuthSessionData_Init(&(authSessions[i])); } return; } /* TPM_AuthSessions_Load() reads a count of the number of stored sessions and then loads those sessions. deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_AuthSessions_Init() */ TPM_RESULT TPM_AuthSessions_Load(TPM_AUTH_SESSION_DATA *authSessions, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; size_t i; uint32_t activeCount; printf(" TPM_AuthSessions_Load:\n"); /* load active count */ if (rc == 0) { rc = TPM_Load32(&activeCount, stream, stream_size); } /* load authorization sessions */ if (rc == 0) { if (activeCount > TPM_MIN_AUTH_SESSIONS) { printf("TPM_AuthSessions_Load: Error (fatal) %u sessions, %u slots\n", activeCount, TPM_MIN_AUTH_SESSIONS); rc = TPM_FAIL; } } if (rc == 0) { printf(" TPM_AuthSessions_Load: Loading %u sessions\n", activeCount); } for (i = 0 ; (rc == 0) && (i < activeCount) ; i++) { rc = TPM_AuthSessionData_Load(&(authSessions[i]), stream, stream_size); } return rc; } /* TPM_AuthSessions_Store() stores a count of the active sessions, followed by the sessions. serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_AuthSessions_Store(TPM_STORE_BUFFER *sbuffer, TPM_AUTH_SESSION_DATA *authSessions) { TPM_RESULT rc = 0; size_t i; uint32_t space; /* free authorization session slots */ uint32_t activeCount; /* used authorization session slots */ /* store active count */ if (rc == 0) { TPM_AuthSessions_GetSpace(&space, authSessions); activeCount = TPM_MIN_AUTH_SESSIONS - space; printf(" TPM_AuthSessions_Store: Storing %u sessions\n", activeCount); rc = TPM_Sbuffer_Append32(sbuffer, activeCount); } /* store auth sessions */ for (i = 0 ; (rc == 0) && (i < TPM_MIN_AUTH_SESSIONS) ; i++) { if ((authSessions[i]).valid) { /* if the session is active */ printf(" TPM_AuthSessions_Store: Storing %08x\n", authSessions[i].handle); rc = TPM_AuthSessionData_Store(sbuffer, &(authSessions[i])); } } return rc; } /* TPM_AuthSessions_Delete() terminates all sessions */ void TPM_AuthSessions_Delete(TPM_AUTH_SESSION_DATA *authSessions) { size_t i; printf(" TPM_AuthSessions_Delete:\n"); for (i = 0 ; i < TPM_MIN_AUTH_SESSIONS ; i++) { TPM_AuthSessionData_Delete(&(authSessions[i])); } return; } /* TPM_AuthSessions_IsSpace() returns 'isSpace' TRUE if an entry is available, FALSE if not. If TRUE, 'index' holds the first free position. */ void TPM_AuthSessions_IsSpace(TPM_BOOL *isSpace, uint32_t *index, TPM_AUTH_SESSION_DATA *authSessions) { printf(" TPM_AuthSessions_IsSpace:\n"); for (*index = 0, *isSpace = FALSE ; *index < TPM_MIN_AUTH_SESSIONS ; (*index)++) { if (!((authSessions[*index]).valid)) { printf(" TPM_AuthSessions_IsSpace: Found space at %u\n", *index); *isSpace = TRUE; break; } } return; } void TPM_AuthSessions_Trace(TPM_AUTH_SESSION_DATA *authSessions) { size_t i; for (i = 0 ; i < TPM_MIN_AUTH_SESSIONS ; i++) { if ((authSessions[i]).valid) { printf(" TPM_AuthSessions_Trace: %lu handle %08x\n", (unsigned long)i, authSessions[i].handle); } } return; } /* TPM_AuthSessions_GetSpace() returns the number of unused authHandle's. */ void TPM_AuthSessions_GetSpace(uint32_t *space, TPM_AUTH_SESSION_DATA *authSessions) { uint32_t i; printf(" TPM_AuthSessions_GetSpace:\n"); for (*space = 0 , i = 0 ; i < TPM_MIN_AUTH_SESSIONS ; i++) { if (!((authSessions[i]).valid)) { (*space)++; } } return; } /* TPM_AuthSessions_StoreHandles() stores - the number of loaded sessions - a list of session handles */ TPM_RESULT TPM_AuthSessions_StoreHandles(TPM_STORE_BUFFER *sbuffer, TPM_AUTH_SESSION_DATA *authSessions) { TPM_RESULT rc = 0; uint16_t i; uint32_t space; printf(" TPM_AuthSessions_StoreHandles:\n"); /* get the number of loaded handles */ if (rc == 0) { TPM_AuthSessions_GetSpace(&space, authSessions); /* store loaded handle count. Cast safe because of TPM_MIN_AUTH_SESSIONS value */ rc = TPM_Sbuffer_Append16(sbuffer, (uint16_t)(TPM_MIN_AUTH_SESSIONS - space)); } for (i = 0 ; (rc == 0) && (i < TPM_MIN_AUTH_SESSIONS) ; i++) { if ((authSessions[i]).valid) { /* if the index is loaded */ rc = TPM_Sbuffer_Append32(sbuffer, (authSessions[i]).handle); /* store it */ } } return rc; } /* TPM_AuthSessions_GetNewHandle() checks for space in the authorization sessions table. If there is space, it returns a TPM_AUTH_SESSION_DATA entry in 'tpm_auth_session_data' and its handle in 'authHandle'. The entry is marked 'valid'. If *authHandle non-zero, the suggested value is tried first. Returns TPM_RESOURCES if there is no space in the sessions table. */ TPM_RESULT TPM_AuthSessions_GetNewHandle(TPM_AUTH_SESSION_DATA **tpm_auth_session_data, TPM_AUTHHANDLE *authHandle, TPM_AUTH_SESSION_DATA *authSessions) { TPM_RESULT rc = 0; uint32_t index; TPM_BOOL isSpace; printf(" TPM_AuthSessions_GetNewHandle:\n"); /* is there an empty entry, get the location index */ if (rc == 0) { TPM_AuthSessions_IsSpace(&isSpace, &index, authSessions); if (!isSpace) { printf("TPM_AuthSessions_GetNewHandle: Error, no space in authSessions table\n"); TPM_AuthSessions_Trace(authSessions); rc = TPM_RESOURCES; } } if (rc == 0) { rc = TPM_Handle_GenerateHandle(authHandle, /* I/O */ authSessions, /* handle array */ FALSE, /* keepHandle */ FALSE, /* isKeyHandle */ (TPM_GETENTRY_FUNCTION_T)TPM_AuthSessions_GetEntry); } if (rc == 0) { printf(" TPM_AuthSessions_GetNewHandle: Assigned handle %08x\n", *authHandle); *tpm_auth_session_data = &(authSessions[index]); /* assign the handle */ (*tpm_auth_session_data)->handle = *authHandle; (*tpm_auth_session_data)->valid = TRUE; } return rc; } /* TPM_AuthSessions_GetEntry() searches all entries for the entry matching the handle, and returns the TPM_AUTH_SESSION_DATA entry associated with the handle. Returns 0 for success TPM_INVALID_AUTHHANDLE if the handle is not found */ TPM_RESULT TPM_AuthSessions_GetEntry(TPM_AUTH_SESSION_DATA **tpm_auth_session_data, /* session for authHandle */ TPM_AUTH_SESSION_DATA *authSessions, /* points to first session */ TPM_AUTHHANDLE authHandle) /* input */ { TPM_RESULT rc = 0; size_t i; TPM_BOOL found; printf(" TPM_AuthSessions_GetEntry: authHandle %08x\n", authHandle); for (i = 0, found = FALSE ; (i < TPM_MIN_AUTH_SESSIONS) && !found ; i++) { if ((authSessions[i].valid) && (authSessions[i].handle == authHandle)) { /* found */ found = TRUE; *tpm_auth_session_data = &(authSessions[i]); } } if (!found) { printf(" TPM_AuthSessions_GetEntry: session handle %08x not found\n", authHandle); rc = TPM_INVALID_AUTHHANDLE; } return rc; } /* TPM_AuthSessions_AddEntry() adds an TPM_AUTH_SESSION_DATA object to the list. If *tpm_handle == 0, a value is assigned. If *tpm_handle != 0, that value is used if it it not currently in use. The handle is returned in tpm_handle. */ TPM_RESULT TPM_AuthSessions_AddEntry(TPM_HANDLE *tpm_handle, /* i/o */ TPM_BOOL keepHandle, /* input */ TPM_AUTH_SESSION_DATA *authSessions, /* input */ TPM_AUTH_SESSION_DATA *tpm_auth_session_data) /* input */ { TPM_RESULT rc = 0; uint32_t index; TPM_BOOL isSpace; printf(" TPM_AuthSessions_AddEntry: handle %08x, keepHandle %u\n", *tpm_handle, keepHandle); /* check for valid TPM_AUTH_SESSION_DATA */ if (rc == 0) { if (tpm_auth_session_data == NULL) { /* NOTE: should never occur */ printf("TPM_AuthSessions_AddEntry: Error (fatal), NULL TPM_AUTH_SESSION_DATA\n"); rc = TPM_FAIL; } } /* is there an empty entry, get the location index */ if (rc == 0) { TPM_AuthSessions_IsSpace(&isSpace, &index, authSessions); if (!isSpace) { printf("TPM_AuthSessions_AddEntry: Error, session entries full\n"); TPM_AuthSessions_Trace(authSessions); rc = TPM_RESOURCES; } } if (rc == 0) { rc = TPM_Handle_GenerateHandle(tpm_handle, /* I/O */ authSessions, /* handle array */ keepHandle, /* keepHandle */ FALSE, /* isKeyHandle */ (TPM_GETENTRY_FUNCTION_T)TPM_AuthSessions_GetEntry); } if (rc == 0) { TPM_AuthSessionData_Copy(&(authSessions[index]), *tpm_handle, tpm_auth_session_data); authSessions[index].valid = TRUE; printf(" TPM_AuthSessions_AddEntry: Index %u handle %08x\n", index, authSessions[index].handle); } return rc; } /* TPM_AuthSessions_GetData() checks that authHandle indexes a valid TPM_AUTH_SESSION_DATA object. If so, a pointer to the object is returned in tpm_auth_session_data. If required protocolID is either TPM_PID_OIAP or TPM_PID_OSAP, the object is checked for that type. TPM_PID_OSAP will accept DSAP as well. If it is TPM_PID_NONE, either is accepted. Any other value is unsupported. If the session protocolID is OIAP, the input entityAuth is echoed back as the HMAC key. entityDigest is ignored and may be NULL. If the session protocolID is OSAP or DSAP, the function must check that the entity used to set up the session is the same as the entity specified in the processing command. It does that by comparing the entityDigest to that saved during setup of the OSAP session. The shared secret is returned as the HMAC key. entityAuth is ignored and may be NULL. If the session protocolID is DSAP, the TPM_DELEGATE_PUBLIC saved during the TPM_DSAP session setup is checked for permission and PCR's. The entityType (TPM_ET_KEYHANDLE or TPM_ET_OWNER) is checked against the TPM_DELEGATE_PUBLIC -> TPM_DELEGATIONS delegateType. Then the bit map is fetched from the ordinals table and verified against the per1 or per 2 values. The pcrInfo is checked against the current PCR values. The saved entityDigest depends upon the entity type: TPM_ET_KEYHANDLE: pubDataDigest TPM_ET_OWNER: ownerAuth TPM_ET_SRK: TPM_KEY -> key_digest TPM_ET_COUNTER: TPM_COUNTER_VALUE -> digest TPM_ET_NV: TPM_NV_DATA_SENSITIVE -> digest */ TPM_RESULT TPM_AuthSessions_GetData(TPM_AUTH_SESSION_DATA **tpm_auth_session_data, /* session for authHandle */ TPM_SECRET **hmacKey, /* output */ tpm_state_t *tpm_state, /* input */ TPM_AUTHHANDLE authHandle, /* input */ TPM_PROTOCOL_ID protocolID, /* input: required protocol */ TPM_ENT_TYPE entityType, /* input: entity type */ TPM_COMMAND_CODE ordinal, /* input: for delegation */ TPM_KEY *tpmKey, /* input, for delegate restrictions */ TPM_SECRET *entityAuth, /* input OIAP hmac key */ TPM_DIGEST entityDigest) /* input OSAP session setup auth */ { TPM_RESULT rc = 0; TPM_DELEGATE_TABLE_ROW *delegateTableRow; printf(" TPM_AuthSessions_GetData: authHandle %08x\n", authHandle); if (rc == 0) { rc = TPM_AuthSessions_GetEntry(tpm_auth_session_data, tpm_state->tpm_stclear_data.authSessions, authHandle); if (rc != 0) { printf("TPM_AuthSessions_GetData: Error, authHandle %08x not found\n", authHandle); } } /* If a specific protocol is required, check that the handle points to the correct session type */ if (rc == 0) { switch (protocolID) { /* what protocol is required */ case TPM_PID_NONE: /* accept any protocol */ break; case TPM_PID_OIAP: if ((*tpm_auth_session_data)->protocolID != TPM_PID_OIAP) { printf("TPM_AuthSessions_GetData: Error, " "session protocolID should be OIAP, is %04hx\n", (*tpm_auth_session_data)->protocolID); rc = TPM_BAD_MODE; } break; case TPM_PID_OSAP: /* Any ordinal requiring OSAP should also accept DSAP */ if (((*tpm_auth_session_data)->protocolID != TPM_PID_OSAP) && ((*tpm_auth_session_data)->protocolID != TPM_PID_DSAP)) { printf("TPM_AuthSessions_GetData: Error, " "session protocolID should be OSAP or DSAP, is %04hx\n", (*tpm_auth_session_data)->protocolID); rc = TPM_BAD_MODE; } break; default: /* should not occur */ printf("TPM_AuthSessions_GetData: Error, required protocolID %04hx unsupported\n", protocolID); rc = TPM_BAD_MODE; break; } } /* if the entity is owner auth, verify that an owner is installed */ if (rc == 0) { if (entityType == TPM_ET_OWNER) { if (!tpm_state->tpm_permanent_data.ownerInstalled) { printf("TPM_AuthSessions_GetData: Error, no owner installed\n"); rc = TPM_AUTHFAIL; } } } /* session protocol specific processing */ if (rc == 0) { switch ((*tpm_auth_session_data)->protocolID) { case TPM_PID_OIAP: /* a. If the command using the OIAP session requires owner authorization */ /* i. If TPM_STCLEAR_DATA -> ownerReference is TPM_KH_OWNER, the secret AuthData is TPM_PERMANENT_DATA -> ownerAuth */ /* ii. If TPM_STCLEAR_DATA -> ownerReference is pointing to a delegate row */ if ((entityType == TPM_ET_OWNER) && (tpm_state->tpm_stclear_data.ownerReference != TPM_KH_OWNER)) { printf(" TPM_AuthSessions_GetData: Delegating to row %u\n", tpm_state->tpm_stclear_data.ownerReference); /* (1) Set R1 a row index to TPM_STCLEAR_DATA -> ownerReference */ /* (2) Set D1 a TPM_DELEGATE_TABLE_ROW to TPM_PERMANENT_DATA -> delegateTable -> delRow[R1] */ if (rc == 0) { rc = TPM_DelegateTable_GetValidRow (&delegateTableRow, &(tpm_state->tpm_permanent_data.delegateTable), tpm_state->tpm_stclear_data.ownerReference); } /* (4) Validate the TPM_DELEGATE_PUBLIC D1 -> pub based on the command ordinal */ /* (a) Validate D1 -> pub -> permissions based on the command ordinal */ /* (b) Validate D1 -> pub -> pcrInfo based on the PCR values */ if (rc == 0) { rc = TPM_Delegations_CheckPermission(tpm_state, &(delegateTableRow->pub), entityType, ordinal); } /* (3) Set the secret AuthData to D1 -> authValue */ if (rc == 0) { *hmacKey = &(delegateTableRow->authValue); } } /* not owner or owner but not delegated */ else { /* the hmac key is the input authorization secret */ *hmacKey = entityAuth; } break; case TPM_PID_OSAP: case TPM_PID_DSAP: /* the first part of DSAP is the same as OSAP */ /* ensure that the OSAP shared secret is that derived from the entity using OSAP */ if (rc == 0) { rc = TPM_Digest_Compare(entityDigest, (*tpm_auth_session_data)->entityDigest); } /* extra processing for DSAP sessions */ if ((*tpm_auth_session_data)->protocolID == TPM_PID_DSAP) { /* check that delegation is allowed for the ordinal */ if (rc == 0) { rc = TPM_Delegations_CheckPermission(tpm_state, &((*tpm_auth_session_data)->pub), entityType, /* required for ordinal */ ordinal); } /* check restrictions on delegation of a certified migration key */ if ((rc == 0) && (entityType == TPM_ET_KEYHANDLE)) { rc = TPM_Key_CheckRestrictDelegate (tpmKey, tpm_state->tpm_permanent_data.restrictDelegate); } } /* the HMAC key is the shared secret calculated during OSAP setup */ if (rc == 0) { *hmacKey = &((*tpm_auth_session_data)->sharedSecret); } break; default: /* should not occur */ printf("TPM_AuthSessions_GetData: session protocolID %04hx unsupported\n", (*tpm_auth_session_data)->protocolID); rc = TPM_AUTHFAIL; break; } } return rc; } /* TPM_AuthSessions_TerminateHandle() terminates the session associated with 'authHandle'. */ TPM_RESULT TPM_AuthSessions_TerminateHandle(TPM_AUTH_SESSION_DATA *authSessions, TPM_AUTHHANDLE authHandle) { TPM_RESULT rc = 0; TPM_AUTH_SESSION_DATA *tpm_auth_session_data; printf(" TPM_AuthSessions_TerminateHandle: Handle %08x\n", authHandle); /* get the TPM_AUTH_SESSION_DATA associated with the TPM_AUTHHANDLE */ if (rc == 0) { rc = TPM_AuthSessions_GetEntry(&tpm_auth_session_data, authSessions, authHandle); } /* invalidate the valid handle */ if (rc == 0) { TPM_AuthSessionData_Delete(tpm_auth_session_data); } return rc; } /* TPM_AuthSessions_TerminateEntity() terminates all OSAP and DSAP sessions connected to the entityType. If the session associated with authHandle is terminated, continueAuthSession is set to FALSE for the ordinal response. If the entityDigest is NULL, all sessions are terminated. If entityDigest is not NULL, only those with a matching entityDigest are terminated. */ void TPM_AuthSessions_TerminateEntity(TPM_BOOL *continueAuthSession, TPM_AUTHHANDLE authHandle, TPM_AUTH_SESSION_DATA *authSessions, TPM_ENT_TYPE entityType, TPM_DIGEST *entityDigest) { uint32_t i; TPM_BOOL terminate; TPM_RESULT match; printf(" TPM_AuthSessions_TerminateEntity: entityType %04x\n", entityType); for (i = 0 ; i < TPM_MIN_AUTH_SESSIONS ; i++) { terminate = FALSE; if ((authSessions[i].valid) && /* if the entry is valid */ ((authSessions[i].protocolID == TPM_PID_OSAP) || /* if it's OSAP or DSAP */ (authSessions[i].protocolID == TPM_PID_DSAP)) && (authSessions[i].entityTypeByte == entityType)) { /* connected to entity type */ /* if entityDigest is NULL, terminate all matching entityType */ if (entityDigest == NULL) { terminate = TRUE; } /* if entityDigest is not NULL, terminate only those matching entityDigest */ else { match = TPM_Digest_Compare(*entityDigest, authSessions[i].entityDigest); if (match == 0) { terminate = TRUE; } } } if (terminate) { printf(" TPM_AuthSessions_TerminateEntity: Terminating handle %08x\n", authSessions[i].handle); /* if terminating the ordinal's session */ if (authSessions[i].handle == authHandle) { *continueAuthSession = FALSE; /* for the ordinal response */ } TPM_AuthSessionData_Delete(&authSessions[i]); } } return; } /* TPM_AuthSessions_TerminatexSAP terminates all OSAP and DSAP sessions If the session associated with authHandle is terminated, continueAuthSession is set to FALSE for the ordinal response. It is safe to call this function during ordinal processing provided a copy of the shared secret is first saved for the response HMAC calculation. The evenNonce is newly created for the response. The oddNonce and continueAuthSession are command inputs, not part of the session data structure. */ void TPM_AuthSessions_TerminatexSAP(TPM_BOOL *continueAuthSession, TPM_AUTHHANDLE authHandle, TPM_AUTH_SESSION_DATA *authSessions) { uint32_t i; printf(" TPM_AuthSessions_TerminatexSAP:\n"); for (i = 0 ; i < TPM_MIN_AUTH_SESSIONS ; i++) { if ((authSessions[i].protocolID == TPM_PID_OSAP) || (authSessions[i]. protocolID == TPM_PID_DSAP)) { /* if terminating the ordinal's session */ if (authSessions[i].handle == authHandle) { *continueAuthSession = FALSE; /* for the ordinal response */ } printf(" TPM_AuthSessions_TerminatexSAP: Terminating handle %08x\n", authSessions[i].handle); TPM_AuthSessionData_Delete(&authSessions[i]); } } return; } /* Context List Methods to manipulate the TPM_STANY_DATA->contextList[TPM_MAX_SESSION_LIST] array */ /* TPM_ContextList_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_ContextList_Init(uint32_t *contextList) { size_t i; printf(" TPM_ContextList_Init:\n"); for (i = 0 ; i < TPM_MIN_SESSION_LIST ; i++) { contextList[i] = 0; } return; } /* TPM_ContextList_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_ContextList_Init() */ TPM_RESULT TPM_ContextList_Load(uint32_t *contextList, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; size_t i; printf(" TPM_ContextList_Load:\n"); for (i = 0 ; (rc == 0) && (i < TPM_MIN_SESSION_LIST) ; i++) { rc = TPM_Load32(&(contextList[i]), stream, stream_size); } return rc; } /* TPM_ContextList_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_ContextList_Store(TPM_STORE_BUFFER *sbuffer, const uint32_t *contextList) { TPM_RESULT rc = 0; size_t i; printf(" TPM_ContextList_Store: Storing %u contexts\n", TPM_MIN_SESSION_LIST); for (i = 0 ; (rc == 0) && (i < TPM_MIN_SESSION_LIST) ; i++) { rc = TPM_Sbuffer_Append32(sbuffer, contextList[i]); } return rc; } /* TPM_ContextList_GetSpace() returns 'space', the number of unused context list entries. If 'space' is non-zero, 'entry' points to the first unused index. */ void TPM_ContextList_GetSpace(uint32_t *space, uint32_t *entry, const uint32_t *contextList) { uint32_t i; printf(" TPM_ContextList_GetSpace:\n"); for (*space = 0 , i = 0 ; i < TPM_MIN_SESSION_LIST ; i++) { if (contextList[i] == 0) { /* zero values are free space */ if (*space == 0) { *entry = i; /* point to the first non-zero entry */ } (*space)++; } } return; } /* TPM_ContextList_GetEntry() gets the entry index corresponding to the value */ TPM_RESULT TPM_ContextList_GetEntry(uint32_t *entry, const uint32_t *contextList, uint32_t value) { TPM_RESULT rc = 0; printf(" TPM_ContextList_GetEntry:\n"); if (rc == 0) { if (value == 0) { printf("TPM_ContextList_GetEntry: Error, value %d never found\n", value); rc = TPM_BADCONTEXT; } } if (rc == 0) { for (*entry = 0 ; *entry < TPM_MIN_SESSION_LIST ; (*entry)++) { if (contextList[*entry] == value) { break; } } if (*entry == TPM_MIN_SESSION_LIST) { printf("TPM_ContextList_GetEntry: Error, value %d not found\n", value); rc = TPM_BADCONTEXT; } } return rc; } /* TPM_ContextList_StoreHandles() stores - the number of loaded context entries - a list of context handles */ TPM_RESULT TPM_ContextList_StoreHandles(TPM_STORE_BUFFER *sbuffer, const uint32_t *contextList) { TPM_RESULT rc = 0; uint16_t i; uint16_t loaded; printf(" TPM_ContextList_StoreHandles:\n"); if (rc == 0) { loaded = 0; /* count the number of loaded handles */ for (i = 0 ; i < TPM_MIN_SESSION_LIST ; i++) { if (contextList[i] != 0) { loaded++; } } /* store 'loaded' handle count */ rc = TPM_Sbuffer_Append16(sbuffer, loaded); } for (i = 0 ; (rc == 0) && (i < TPM_MIN_SESSION_LIST ) ; i++) { if (contextList[i] != 0) { /* if the index is loaded */ rc = TPM_Sbuffer_Append32(sbuffer, contextList[i]); /* store it */ } } return rc; } /* TPM_CONTEXT_BLOB */ /* TPM_ContextBlob_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_ContextBlob_Init(TPM_CONTEXT_BLOB *tpm_context_blob) { printf(" TPM_ContextBlob_Init:\n"); tpm_context_blob->resourceType = 0; tpm_context_blob->handle = 0; memset(tpm_context_blob->label, 0, TPM_CONTEXT_LABEL_SIZE); tpm_context_blob->contextCount = 0; TPM_Digest_Init(tpm_context_blob->integrityDigest); TPM_SizedBuffer_Init(&(tpm_context_blob->additionalData)); TPM_SizedBuffer_Init(&(tpm_context_blob->sensitiveData)); return; } /* TPM_ContextBlob_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_ContextBlob_Init() After use, call TPM_ContextBlob_Delete() to free memory */ TPM_RESULT TPM_ContextBlob_Load(TPM_CONTEXT_BLOB *tpm_context_blob, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_ContextBlob_Load:\n"); /* check tag */ if (rc == 0) { rc = TPM_CheckTag(TPM_TAG_CONTEXTBLOB, stream, stream_size); } /* load resourceType */ if (rc == 0) { rc = TPM_Load32(&(tpm_context_blob->resourceType), stream, stream_size); } /* load handle */ if (rc == 0) { rc = TPM_Load32(&(tpm_context_blob->handle), stream, stream_size); } /* load label */ if (rc == 0) { rc = TPM_Loadn(tpm_context_blob->label, TPM_CONTEXT_LABEL_SIZE, stream, stream_size); } /* load contextCount */ if (rc == 0) { rc = TPM_Load32(&(tpm_context_blob->contextCount), stream, stream_size); } /* load integrityDigest */ if (rc == 0) { rc = TPM_Digest_Load(tpm_context_blob->integrityDigest, stream, stream_size); } /* load additionalData */ if (rc == 0) { rc = TPM_SizedBuffer_Load(&(tpm_context_blob->additionalData), stream, stream_size); } /* load sensitiveData */ if (rc == 0) { rc = TPM_SizedBuffer_Load(&(tpm_context_blob->sensitiveData), stream, stream_size); } return rc; } /* TPM_ContextBlob_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_ContextBlob_Store(TPM_STORE_BUFFER *sbuffer, const TPM_CONTEXT_BLOB *tpm_context_blob) { TPM_RESULT rc = 0; printf(" TPM_ContextBlob_Store:\n"); /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_CONTEXTBLOB); } /* store resourceType */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_context_blob->resourceType); } /* store handle */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_context_blob->handle); } /* store label */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, tpm_context_blob->label, TPM_CONTEXT_LABEL_SIZE); } /* store contextCount */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_context_blob->contextCount); } /* store integrityDigest */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_context_blob->integrityDigest); } /* store additionalData */ if (rc == 0) { rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_context_blob->additionalData)); } /* store sensitiveData */ if (rc == 0) { rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_context_blob->sensitiveData)); } return rc; } /* TPM_ContextBlob_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_ContextBlob_Init to set members back to default values The object itself is not freed */ void TPM_ContextBlob_Delete(TPM_CONTEXT_BLOB *tpm_context_blob) { printf(" TPM_ContextBlob_Delete:\n"); if (tpm_context_blob != NULL) { TPM_SizedBuffer_Delete(&(tpm_context_blob->additionalData)); TPM_SizedBuffer_Delete(&(tpm_context_blob->sensitiveData)); TPM_ContextBlob_Init(tpm_context_blob); } return; } /* TPM_CONTEXT_SENSITIVE */ /* TPM_ContextSensitive_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_ContextSensitive_Init(TPM_CONTEXT_SENSITIVE *tpm_context_sensitive) { printf(" TPM_ContextSensitive_Init:\n"); TPM_Nonce_Init(tpm_context_sensitive->contextNonce); TPM_SizedBuffer_Init(&(tpm_context_sensitive->internalData)); return; } /* TPM_ContextSensitive_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_ContextSensitive_Init() After use, call TPM_ContextSensitive_Delete() to free memory */ TPM_RESULT TPM_ContextSensitive_Load(TPM_CONTEXT_SENSITIVE *tpm_context_sensitive, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_ContextSensitive_Load:\n"); /* check tag */ if (rc == 0) { rc = TPM_CheckTag(TPM_TAG_CONTEXT_SENSITIVE, stream, stream_size); } /* load contextNonce */ if (rc == 0) { rc = TPM_Nonce_Load(tpm_context_sensitive->contextNonce, stream, stream_size); } /* load internalData */ if (rc == 0) { rc = TPM_SizedBuffer_Load(&(tpm_context_sensitive->internalData), stream, stream_size); } return rc; } /* TPM_ContextSensitive_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_ContextSensitive_Store(TPM_STORE_BUFFER *sbuffer, const TPM_CONTEXT_SENSITIVE *tpm_context_sensitive) { TPM_RESULT rc = 0; printf(" TPM_ContextSensitive_Store:\n"); /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_CONTEXT_SENSITIVE); } /* store contextNonce */ if (rc == 0) { rc = TPM_Nonce_Store(sbuffer, tpm_context_sensitive->contextNonce); } /* store internalData */ if (rc == 0) { rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_context_sensitive->internalData)); } return rc; } /* TPM_ContextSensitive_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_ContextSensitive_Init to set members back to default values The object itself is not freed */ void TPM_ContextSensitive_Delete(TPM_CONTEXT_SENSITIVE *tpm_context_sensitive) { printf(" TPM_ContextSensitive_Delete:\n"); if (tpm_context_sensitive != NULL) { TPM_SizedBuffer_Delete(&(tpm_context_sensitive->internalData)); TPM_ContextSensitive_Init(tpm_context_sensitive); } return; } /* Processing Functions */ /* 18.1 TPM_OIAP rev 87 */ TPM_RESULT TPM_Process_OIAP(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_AUTH_SESSION_DATA *authSession; /* the empty structure to be filled */ TPM_BOOL got_handle = FALSE; /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_AUTHHANDLE authHandle = 0; /* 0, no suggested value */ printf("TPM_Process_OIAP: Ordinal Entry\n"); /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | TPM_CHECK_NO_LOCKOUT)); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_OIAP: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ /* 1. The TPM_OIAP command allows the creation of an authorization session handle and the tracking of the handle by the TPM. The TPM generates the handle and nonce. */ /* 2. The TPM has an internal limit as to the number of handles that may be open at one time, so the request for a new handle may fail if there is insufficient space available. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetNewHandle(&authSession, &authHandle, tpm_state->tpm_stclear_data.authSessions); } /* 3. Internally the TPM will do the following: */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_OIAP: Using authHandle %08x\n", authHandle); got_handle = TRUE; /* a. TPM allocates space to save handle, protocol identification, both nonces and any other information the TPM needs to manage the session. */ authSession->protocolID = TPM_PID_OIAP; /* b. TPM generates authHandle and nonceEven, returns these to caller */ returnCode = TPM_Nonce_Generate(authSession->nonceEven); } /* 4. On each subsequent use of the OIAP session the TPM MUST generate a new nonceEven value. */ /* 5. When TPM_OIAP is wrapped in an encrypted transport session no input or output parameters encrypted */ /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_OIAP: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; /* append authHandle */ returnCode = TPM_Sbuffer_Append32(response, authHandle); } /* append nonceEven */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Nonce_Store(response, authSession->nonceEven); } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if the handle is not being returned, it should be terminated */ if (((returnCode != 0) || (rcf != 0)) && got_handle) { TPM_AuthSessionData_Delete(authSession); } return rcf; } /* 18.2 TPM_OSAP rev 98 The TPM_OSAP command creates the authorization handle, the shared secret and generates nonceEven and nonceEvenOSAP. 1 The TPM_OSAP command allows the creation of an authorization handle and the tracking of the handle by the TPM. The TPM generates the handle, nonceEven and nonceEvenOSAP. 2. The TPM has an internal limit on the number of handles that may be open at one time, so the request for a new handle may fail if there is insufficient space available. 3. The TPM_OSAP allows the binding of an authorization to a specific entity. This allows the caller to continue to send in authorization data for each command but not have to request the information or cache the actual authorization data. 4. When TPM_OSAP is wrapped in an encrypted transport session, no input or output parameters are encrypted 5. If the owner pointer is pointing to a delegate row, the TPM internally MUST treat the OSAP session as a DSAP session 6. TPM_ET_SRK or TPM_ET_KEYHANDLE with a value of TPM_KH_SRK MUST specify the SRK. 7. If the entity is tied to PCR values, the PCR's are not validated during the TPM_OSAP ordinal session creation. The PCR's are validated when the OSAP session is used. */ TPM_RESULT TPM_Process_OSAP(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_ENTITY_TYPE entityType; /* The type of entity in use */ uint32_t entityValue = 0; /* The selection value based on entityType, e.g. a keyHandle # */ TPM_NONCE nonceOddOSAP; /* The nonce generated by the caller associated with the shared secret. */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_AUTH_SESSION_DATA *authSession; /* the empty structure to be filled */ TPM_BOOL got_handle = FALSE; TPM_SECRET *authData; /* usageAuth for the entity */ TPM_DIGEST *entityDigest = NULL; /* digest of the entity establishing the OSAP session, initialize to silence compiler */ TPM_KEY *authKey; /* key to authorize */ TPM_BOOL parentPCRStatus; TPM_COUNTER_VALUE *counterValue; /* associated with entityValue */ TPM_NV_DATA_SENSITIVE *tpm_nv_data_sensitive; /* associated with entityValue */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_AUTHHANDLE authHandle = 0; /* Handle that TPM creates that points to the authorization state. */ TPM_NONCE nonceEvenOSAP; /* Nonce generated by TPM and associated with shared secret. */ printf("TPM_Process_OSAP: Ordinal Entry\n"); /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* get entityType */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load16(&entityType, &command, ¶mSize); } /* get entityValue */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_OSAP: entityType %04hx\n", entityType); returnCode = TPM_Load32(&entityValue, &command, ¶mSize); } /* get nonceOddOSAP */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_OSAP: entityValue %08x\n", entityValue); returnCode = TPM_Nonce_Load(nonceOddOSAP, &command, ¶mSize); } /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | TPM_CHECK_OWNER | TPM_CHECK_NO_LOCKOUT)); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_OSAP: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ /* 1. The TPM creates S1 a storage area that keeps track of the information associated with the authorization. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetNewHandle(&authSession, &authHandle, tpm_state->tpm_stclear_data.authSessions); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_OSAP: Using authHandle %08x\n", authHandle); got_handle = TRUE; /* 2. S1 MUST track the following information: */ /* a. Protocol identification */ authSession->protocolID = TPM_PID_OSAP; /* save protocol identification */ authSession->entityTypeByte = entityType & 0x00ff; /* save entity type LSB */ /* b. nonceEven */ /* i. Initialized to the next value from the TPM RNG */ TPM_Nonce_Generate(authSession->nonceEven); /* c. shared secret NOTE: determined below */ /* d. ADIP encryption scheme from TPM_ENTITY_TYPE entityType */ authSession->adipEncScheme = (entityType >> 8) & 0x00ff; /* save entity type MSB */ /* e. Any other internal TPM state the TPM needs to manage the session */ /* 3. The TPM MUST create and MAY track the following information */ /* a. nonceEvenOSAP */ /* i. Initialized to the next value from the TPM RNG */ TPM_Nonce_Generate(nonceEvenOSAP); /* 4. HMAC, shared secret NOTE: determined below */ /* 5. Check if the ADIP encryption scheme specified by entityType is supported, if not return TPM_INAPPROPRIATE_ENC. */ returnCode = TPM_AuthSessionData_CheckEncScheme(authSession->adipEncScheme, tpm_state->tpm_permanent_flags.FIPS); } if (returnCode == TPM_SUCCESS) { switch (authSession->entityTypeByte) { case TPM_ET_KEYHANDLE: /* 6. If entityType = TPM_ET_KEYHANDLE */ /* a. The entity to authorize is a key held in the TPM. entityValue contains the keyHandle that holds the key. */ /* b. If entityValue is TPM_KH_OPERATOR return TPM_BAD_HANDLE */ if (returnCode == TPM_SUCCESS) { if (entityValue == TPM_KH_OPERATOR) { printf("TPM_Process_OSAP: Error, " "entityType TPM_ET_KEYHANDLE entityValue TPM_KH_OPERATOR\n"); returnCode = TPM_BAD_HANDLE; } } /* look up and get the TPM_KEY authorization data */ if (returnCode == TPM_SUCCESS) { /* get the TPM_KEY, entityValue is the handle */ printf("TPM_Process_OSAP: entityType TPM_ET_KEYHANDLE entityValue %08x\n", entityValue); /* TPM_KeyHandleEntries_GetKey() does the mapping from TPM_KH_SRK to the SRK */ returnCode = TPM_KeyHandleEntries_GetKey(&authKey, &parentPCRStatus, tpm_state, entityValue, TRUE, /* read only */ TRUE, /* ignore PCRs */ FALSE); /* cannot use EK */ } if (returnCode == TPM_SUCCESS) { /* get the entityDigest for the key */ entityDigest = &(authKey->tpm_store_asymkey->pubDataDigest); /* get the usageAuth for the key */ returnCode = TPM_Key_GetUsageAuth(&authData, authKey); } break; case TPM_ET_OWNER: /* 7. else if entityType = TPM_ET_OWNER */ /* a. This value indicates that the entity is the TPM owner. entityValue is ignored. */ /* b. The HMAC key is the secret pointed to by ownerReference (owner secret or delegated secret) */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_OSAP: entityType TPM_ET_OWNER, ownerReference %08x\n", tpm_state->tpm_stclear_data.ownerReference); /* verify that an owner is installed */ if (!tpm_state->tpm_permanent_data.ownerInstalled) { printf("TPM_Process_OSAP: Error, no owner\n"); returnCode = TPM_BAD_PARAMETER; } } if (returnCode == TPM_SUCCESS) { /* owner reference is owner, use the owner authorization data */ if (tpm_state->tpm_stclear_data.ownerReference == TPM_KH_OWNER) { entityDigest = &(tpm_state->tpm_permanent_data.ownerAuth); authData = &(tpm_state->tpm_permanent_data.ownerAuth); } /* Description 5. If the owner pointer is pointing to a delegate row, the TPM internally MUST treat the OSAP session as a DSAP session */ else { returnCode = TPM_OSAPDelegate(&entityDigest, &authData, authSession, tpm_state, tpm_state->tpm_stclear_data.ownerReference); } } break; case TPM_ET_SRK: /* 8. else if entityType = TPM_ET_SRK */ /* a. The entity to authorize is the SRK. entityValue is ignored. */ printf("TPM_Process_OSAP: entityType TPM_ET_SRK\n"); entityDigest = &(tpm_state->tpm_permanent_data.srk.tpm_store_asymkey->pubDataDigest); returnCode = TPM_Key_GetUsageAuth(&authData, &(tpm_state->tpm_permanent_data.srk)); break; case TPM_ET_COUNTER: /* 9. else if entityType = TPM_ET_COUNTER */ /* a. The entity is a monotonic counter, entityValue contains the counter handle */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_OSAP: entityType TPM_ET_COUNTER entityValue %08x\n", entityValue); returnCode = TPM_Counters_GetCounterValue(&counterValue, tpm_state->tpm_permanent_data.monotonicCounter, entityValue); } if (returnCode == TPM_SUCCESS) { /* get the entityDigest for the counter */ entityDigest = &(counterValue->digest); /* get the authData for the counter */ authData = &(counterValue->authData); } break; case TPM_ET_NV: /* 10. else if entityType = TPM_ET_NV a. The entity is a NV index, entityValue contains the NV index */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_OSAP: entityType TPM_ET_NV\n"); returnCode = TPM_NVIndexEntries_GetEntry(&tpm_nv_data_sensitive, &(tpm_state->tpm_nv_index_entries), entityValue); } if (returnCode == TPM_SUCCESS) { /* get the entityDigest for the NV data */ entityDigest = &(tpm_nv_data_sensitive->digest); /* get the authData for the NV data */ authData = &(tpm_nv_data_sensitive->authValue); } break; default: /* 11. else return TPM_INVALID_PARAMETER */ printf("TPM_Process_OSAP: Error, unknown entityType %04x\n", entityType); returnCode = TPM_BAD_PARAMETER; break; } } /* 2.c. shared secret */ /* 4. The TPM calculates the shared secret using an HMAC calculation. The key for the HMAC calculation is the secret AuthData assigned to the key handle identified by entityValue. The input to the HMAC calculation is the concatenation of nonces nonceEvenOSAP and nonceOddOSAP. The output of the HMAC calculation is the shared secret which is saved in the authorization area associated with authHandle */ if (returnCode == TPM_SUCCESS) { TPM_Digest_Copy(authSession->entityDigest, *entityDigest); TPM_PrintFour("TPM_Process_OSAP: entityDigest", *entityDigest); TPM_PrintFour("TPM_Process_OSAP: authData", *authData); TPM_PrintFour("TPM_Process_OSAP: nonceEvenOSAP", nonceEvenOSAP); TPM_PrintFour("TPM_Process_OSAP: nonceOddOSAP", nonceOddOSAP); returnCode = TPM_HMAC_Generate(authSession->sharedSecret, *authData, /* HMAC key */ TPM_NONCE_SIZE, nonceEvenOSAP, TPM_NONCE_SIZE, nonceOddOSAP, 0, NULL); } if (returnCode == TPM_SUCCESS) { TPM_PrintFour("TPM_Process_OSAP: sharedSecret", authSession->sharedSecret); } /* 12. On each subsequent use of the OSAP session the TPM MUST generate a new nonce value. NOTE: Done as the response is generated. */ /* 13. The TPM MUST ensure that OSAP shared secret is only available while the OSAP session is valid. */ /* 14. The session MUST terminate upon any of the following conditions: a. The command that uses the session returns an error NOTE Done by command b. The resource is evicted from the TPM or otherwise invalidated NOTE Done by evict or flush c. The session is used in any command for which the shared secret is used to encrypt an input parameter (TPM_ENCAUTH) NOTE Done by the command d. The TPM Owner is cleared NOTE Done by owner clear e. TPM_ChangeAuthOwner is executed and this session is attached to the owner authorization NOTE Done by TPM_ChangeAuthOwner f. The session explicitly terminated with continueAuth, TPM_Reset or TPM_FlushSpecific NOTE Done by the ordinal processing g. All OSAP sessions associated with the delegation table MUST be invalidated when any of the following commands execute: i. TPM_Delegate_Manage ii. TPM_Delegate_CreateOwnerDelegation with Increment==TRUE iii. TPM_Delegate_LoadOwnerDelegation NOTE Done by the ordinal processing */ /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_OSAP: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; /* append authHandle */ returnCode = TPM_Sbuffer_Append32(response, authHandle); } /* append nonceEven */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Nonce_Store(response, authSession->nonceEven); } /* append nonceEvenOSAP */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Nonce_Store(response, nonceEvenOSAP); } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if the handle is not being returned, it should be terminated */ if (((returnCode != 0) || (rcf != 0)) && got_handle) { TPM_AuthSessionData_Delete(authSession); } /* cleanup */ return rcf; } /* 18.3 TPM_DSAP rev 106 The TPM_DSAP command creates the authorization session handle using a delegated AuthData value passed into the command as an encrypted blob or from the internal delegation table. It can be used to start an authorization session for a user key or the owner. As in TPM_OSAP, it generates a shared secret and generates nonceEven and nonceEvenOSAP. 1. The TPM_DSAP command allows the creation of an authorization session handle and the tracking of the handle by the TPM. The TPM generates the handle, nonceEven and nonceEvenOSAP. 2. The TPM has an internal limit on the number of handles that may be open at one time, so the request for a new handle may fail if there is insufficient space available. 3. The TPM_DSAP allows the binding of a delegated authorization to a specific entity. This allows the caller to continue to send in AuthData for each command but not have to request the information or cache the actual AuthData. 4. On each subsequent use of the DSAP session the TPM MUST generate a new nonce value and check if the ordinal to be executed has delegation to execute. The TPM MUST ensure that the DSAP shared secret is only available while the DSAP session is valid. 5. When TPM_DSAP is wrapped in an encrypted transport session a. For input the only parameter encrypted or logged is entityValue b. For output no parameters are encrypted or logged 6. The DSAP session MUST terminate under any of the following conditions a. The command that uses the session returns an error b. If attached to a key, when the key is evicted from the TPM or otherwise invalidated c. The session is used in any command for which the shared secret is used to encrypt an input parameter (TPM_ENCAUTH) d. The TPM Owner is cleared e. TPM_ChangeAuthOwner is executed and this session is attached to the owner authorization f. The session explicitly terminated with continueAuth, TPM_Reset or TPM_FlushSpecific g. All DSAP sessions MUST be invalidated when any of the following commands execute: i. TPM_Delegate_CreateOwnerDelegation (1) When Increment is TRUE ii. TPM_Delegate_LoadOwnerDelegation iii. TPM_Delegate_Manage NOTE Done by the ordinal processing entityType = TPM_ET_DEL_OWNER_BLOB The entityValue parameter contains a delegation blob structure. entityType = TPM_ET_DEL_ROW The entityValue parameter contains a row number in the nv Delegation table which should be used for the AuthData value. */ TPM_RESULT TPM_Process_DSAP(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_ENTITY_TYPE entityType; /* The type of delegation information to use */ TPM_KEY_HANDLE keyHandle = 0; /* Key for which delegated authority corresponds, or 0 if delegated owner activity. Only relevant if entityValue equals TPM_DELEGATE_USEKEY_BLOB */ TPM_NONCE nonceOddDSAP; /* The nonce generated by the caller associated with the shared secret. */ TPM_SIZED_BUFFER entityValue; /* TPM_DELEGATE_KEY_BLOB or TPM_DELEGATE_OWNER_BLOB or index. MUST not be empty. If entityType is TPM_ET_DEL_ROW then entityValue is a TPM_DELEGATE_INDEX */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_AUTH_SESSION_DATA *authSession; /* the empty structure to be filled */ unsigned char *stream; /* temp input stream */ uint32_t stream_size; TPM_DELEGATE_OWNER_BLOB b1DelegateOwnerBlob; TPM_DELEGATE_KEY_BLOB k1DelegateKeyBlob; TPM_KEY *delKey; /* key corresponding to keyHandle */ TPM_BOOL parentPCRStatus; TPM_DELEGATE_SENSITIVE s1DelegateSensitive; uint32_t delegateRowIndex; TPM_DELEGATE_TABLE_ROW *d1DelegateTableRow; TPM_SECRET *a1AuthValue = NULL; TPM_FAMILY_TABLE_ENTRY *familyRow; /* family table row containing familyID */ TPM_BOOL got_handle = FALSE; /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_AUTHHANDLE authHandle = 0; /* Handle that TPM creates that points to the authorization state. */ TPM_NONCE nonceEvenDSAP; /* Nonce generated by TPM and associated with shared secret. */ printf("TPM_Process_DSAP: Ordinal Entry\n"); TPM_SizedBuffer_Init(&entityValue); /* freed @1 */ TPM_DelegateOwnerBlob_Init(&b1DelegateOwnerBlob); /* freed @2 */ TPM_DelegateKeyBlob_Init(&k1DelegateKeyBlob); /* freed @3 */ TPM_DelegateSensitive_Init(&s1DelegateSensitive); /* freed @4 */ /* get inputs */ /* get entityType */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load16(&entityType, &command, ¶mSize); } /* get keyHandle */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_DSAP: entityType %04hx\n", entityType); returnCode = TPM_Load32(&keyHandle, &command, ¶mSize); } /* get nonceOddDSAP */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_DSAP: keyHandle %08x\n", keyHandle); returnCode = TPM_Nonce_Load(nonceOddDSAP, &command, ¶mSize); } /* save the starting point of inParam's for authorization and auditing */ inParamStart = command + sizeof(uint32_t); /* audit entityValue but not entityValueSize */ /* get entityValue */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_Load(&entityValue, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | TPM_CHECK_OWNER | TPM_CHECK_NO_LOCKOUT)); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_DSAP: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ if (returnCode == TPM_SUCCESS) { /* use a temporary copy so the original values are not moved */ stream = entityValue.buffer; stream_size = entityValue.size; switch (entityType & 0x00ff) { /* entity type LSB is the actual entity type */ case TPM_ET_DEL_OWNER_BLOB: /* 1. If entityType == TPM_ET_DEL_OWNER_BLOB */ /* a. Map entityValue to B1 a TPM_DELEGATE_OWNER_BLOB */ /* b. Validate that B1 is a valid TPM_DELEGATE_OWNER_BLOB, return TPM_WRONG_ENTITYTYPE on error */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_DelegateOwnerBlob_Load(&b1DelegateOwnerBlob, &stream, &stream_size); if (returnCode != TPM_SUCCESS) { returnCode = TPM_WRONG_ENTITYTYPE; } } /* c. Locate B1 -> pub -> familyID in the TPM_FAMILY_TABLE and set familyRow to indicate row, return TPM_BADINDEX if not found */ /* d. Set FR to TPM_FAMILY_TABLE.famTableRow[familyRow] */ /* e. If FR -> flags TPM_FAMFLAG_ENABLED is FALSE, return TPM_DISABLED_CMD */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_FamilyTable_GetEnabledEntry(&familyRow, &(tpm_state->tpm_permanent_data.familyTable), b1DelegateOwnerBlob.pub.familyID); } /* f. Verify that B1->verificationCount equals FR -> verificationCount. */ if (returnCode == TPM_SUCCESS) { if (b1DelegateOwnerBlob.pub.verificationCount != familyRow->verificationCount) { printf("TPM_Process_DSAP: Error, verificationCount mismatch %u %u\n", b1DelegateOwnerBlob.pub.verificationCount, familyRow->verificationCount); returnCode = TPM_FAMILYCOUNT; } } /* g. Validate the integrity of the blob */ /* i. Copy B1 -> integrityDigest to H2 */ /* ii. Set B1 -> integrityDigest to NULL */ /* iii. Create H3 the HMAC of B1 using tpmProof as the secret */ /* iv. Compare H2 to H3 return TPM_AUTHFAIL on mismatch */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_HMAC_CheckStructure (tpm_state->tpm_permanent_data.tpmProof, /* key */ &b1DelegateOwnerBlob, /* structure */ b1DelegateOwnerBlob.integrityDigest, /* expected */ (TPM_STORE_FUNCTION_T)TPM_DelegateOwnerBlob_Store,/* store function */ TPM_AUTHFAIL); /* error code */ } /* h. Create S1 a TPM_DELEGATE_SENSITIVE by decrypting B1 -> sensitiveArea using TPM_DELEGATE_KEY */ /* i. Validate S1 values */ /* i. S1 -> tag is TPM_TAG_DELEGATE_SENSITIVE */ /* ii. Return TPM_BAD_DELEGATE on error */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_DelegateSensitive_DecryptEncData (&s1DelegateSensitive, /* decrypted data */ &(b1DelegateOwnerBlob.sensitiveArea), tpm_state->tpm_permanent_data.delegateKey); } /* j. Set A1 to S1 -> authValue */ if (returnCode == TPM_SUCCESS) { a1AuthValue = &(s1DelegateSensitive.authValue); } break; case TPM_ET_DEL_ROW: /* 2. Else if entityType == TPM_ET_DEL_ROW */ /* a. Verify that entityValue points to a valid row in the delegation table. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&delegateRowIndex, &stream, &stream_size); } /* b. Set D1 to the delegation information in the row. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_DelegateTable_GetValidRow(&d1DelegateTableRow, &(tpm_state->tpm_permanent_data.delegateTable), delegateRowIndex); } if (returnCode == TPM_SUCCESS) { /* c. Set A1 to D1->authValue. */ a1AuthValue = &d1DelegateTableRow->authValue; /* d. Locate D1 -> familyID in the TPM_FAMILY_TABLE and set familyRow to indicate that row, return TPM_BADINDEX if not found */ /* e. Set FR to TPM_FAMILY_TABLE.FamTableRow[familyRow] */ /* f. If FR -> flags TPM_FAMFLAG_ENABLED is FALSE, return TPM_DISABLED_CMD */ returnCode = TPM_FamilyTable_GetEnabledEntry(&familyRow, &(tpm_state->tpm_permanent_data.familyTable), d1DelegateTableRow->pub.familyID); } /* g. Verify that D1->verificationCount equals FR -> verificationCount. */ if (returnCode == TPM_SUCCESS) { if (d1DelegateTableRow->pub.verificationCount != familyRow->verificationCount) { printf("TPM_Process_DSAP: Error, verificationCount mismatch %u %u\n", d1DelegateTableRow->pub.verificationCount, familyRow->verificationCount); returnCode = TPM_FAMILYCOUNT; } } break; case TPM_ET_DEL_KEY_BLOB: /* 3. Else if entityType == TPM_ET_DEL_KEY_BLOB */ /* a. Map entityValue to K1 a TPM_DELEGATE_KEY_BLOB */ /* b. Validate that K1 is a valid TPM_DELEGATE_KEY_BLOB, return TPM_WRONG_ENTITYTYPE on error */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_DelegateKeyBlob_Load(&k1DelegateKeyBlob, &stream, &stream_size); if (returnCode != TPM_SUCCESS) { returnCode = TPM_WRONG_ENTITYTYPE; } } /* c. Locate K1 -> pub -> familyID in the TPM_FAMILY_TABLE and set familyRow to indicate that row, return TPM_BADINDEX if not found */ /* d. Set FR to TPM_FAMILY_TABLE.FamTableRow[familyRow] */ /* e. If FR -> flags TPM_FAMFLAG_ENABLED is FALSE, return TPM_DISABLED_CMD */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_FamilyTable_GetEnabledEntry(&familyRow, &(tpm_state->tpm_permanent_data.familyTable), k1DelegateKeyBlob.pub.familyID); } /* f. Verify that K1 -> pub -> verificationCount equals FR -> verificationCount. */ if (returnCode == TPM_SUCCESS) { if (k1DelegateKeyBlob.pub.verificationCount != familyRow->verificationCount) { printf("TPM_Process_DSAP: Error, verificationCount mismatch %u %u\n", k1DelegateKeyBlob.pub.verificationCount, familyRow->verificationCount); returnCode = TPM_FAMILYCOUNT; } } /* g. Validate the integrity of the blob */ /* i. Copy K1 -> integrityDigest to H2 */ /* ii. Set K1 -> integrityDigest to NULL */ /* iii. Create H3 the HMAC of K1 using tpmProof as the secret */ /* iv. Compare H2 to H3 return TPM_AUTHFAIL on mismatch */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_HMAC_CheckStructure (tpm_state->tpm_permanent_data.tpmProof, /* key */ &k1DelegateKeyBlob, /* structure */ k1DelegateKeyBlob.integrityDigest, /* expected */ (TPM_STORE_FUNCTION_T)TPM_DelegateKeyBlob_Store, /* store function */ TPM_AUTHFAIL); /* error code */ } /* h. Validate that K1 -> pubKeyDigest identifies keyHandle, return TPM_KEYNOTFOUND on error */ /* get the TPM_KEY corresponding to keyHandle */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyHandleEntries_GetKey(&delKey, &parentPCRStatus, tpm_state, keyHandle, TRUE, /* read only */ TRUE, /* ignore PCRs at setup */ FALSE); /* cannot use EK */ } if (returnCode == TPM_SUCCESS) { returnCode = TPM_SHA1_CheckStructure(k1DelegateKeyBlob.pubKeyDigest, &(delKey->pubKey), (TPM_STORE_FUNCTION_T)TPM_SizedBuffer_Store, TPM_KEYNOTFOUND); } /* i. Create S1 a TPM_DELEGATE_SENSITIVE by decrypting K1 -> sensitiveArea using TPM_DELEGATE_KEY */ /* j. Validate S1 values */ /* i. S1 -> tag is TPM_TAG_DELEGATE_SENSITIVE */ /* ii. Return TPM_BAD_DELEGATE on error */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_DelegateSensitive_DecryptEncData (&s1DelegateSensitive, /* decrypted data */ &(k1DelegateKeyBlob.sensitiveArea), tpm_state->tpm_permanent_data.delegateKey); } /* k. Set A1 to S1 -> authValue */ if (returnCode == TPM_SUCCESS) { a1AuthValue = &(s1DelegateSensitive.authValue); } break; default: /* 4. Else return TPM_BAD_PARAMETER */ printf("TPM_Process_DSAP: Error, bad entityType %04hx\n", entityType); returnCode = TPM_BAD_PARAMETER; } } /* 5. Generate a new authorization session handle and reserve space to save protocol identification, shared secret, pcrInfo, both nonces, ADIP encryption scheme, delegated permission bits and any other information the TPM needs to manage the session. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetNewHandle(&authSession, &authHandle, tpm_state->tpm_stclear_data.authSessions); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_DSAP: Using authHandle %08x\n", authHandle); got_handle = TRUE; /* save protocol identification */ authSession->protocolID = TPM_PID_DSAP; /* save the ADIP encryption scheme */ authSession->adipEncScheme = (entityType >> 8) & 0x00ff; /* NOTE: added: Check if the ADIP encryption scheme specified by entityType is supported, if not return TPM_INAPPROPRIATE_ENC. */ returnCode = TPM_AuthSessionData_CheckEncScheme(authSession->adipEncScheme, tpm_state->tpm_permanent_flags.FIPS); } if (returnCode == TPM_SUCCESS) { if (entityType == TPM_ET_DEL_KEY_BLOB) { /* map the entity type to a key */ authSession->entityTypeByte = TPM_ET_KEYHANDLE; /* Save the entityDigest for comparison during use. */ TPM_Digest_Copy(authSession->entityDigest, delKey->tpm_store_asymkey->pubDataDigest); /* Save the TPM_DELEGATE_PUBLIC to check the permissions and pcrInfo at DSAP session use. */ returnCode =TPM_DelegatePublic_Copy(&(authSession->pub), &(k1DelegateKeyBlob.pub)); } else { /* owner or blob or delegate row are both owner auth */ authSession->entityTypeByte = TPM_ET_OWNER; /* Save the entityDigest for comparison during use. */ TPM_Digest_Copy(authSession->entityDigest, tpm_state->tpm_permanent_data.ownerAuth); /* Save the TPM_DELEGATE_PUBLIC to check the permissions and pcrInfo at DSAP session use. */ if (entityType == TPM_ET_DEL_OWNER_BLOB) { returnCode = TPM_DelegatePublic_Copy(&(authSession->pub), &(b1DelegateOwnerBlob.pub)); } else { /* TPM_ET_DEL_ROW */ returnCode = TPM_DelegatePublic_Copy(&(authSession->pub), &(d1DelegateTableRow->pub)); } } /* 6. Read two new values from the RNG to generate nonceEven and nonceEvenOSAP. */ TPM_Nonce_Generate(authSession->nonceEven); TPM_Nonce_Generate(nonceEvenDSAP); } /* 7. The TPM calculates the shared secret using an HMAC calculation. The key for the HMAC calculation is A1. The input to the HMAC calculation is the concatenation of nonces nonceEvenOSAP and nonceOddOSAP. The output of the HMAC calculation is the shared secret which is saved in the authorization area associated with authHandle. */ if (returnCode == TPM_SUCCESS) { TPM_PrintFour("TPM_Process_DSAP: authData", *a1AuthValue); TPM_PrintFour("TPM_Process_DSAP: nonceEvenOSAP", nonceEvenDSAP); TPM_PrintFour("TPM_Process_DSAP: nonceOddOSAP", nonceOddDSAP); returnCode = TPM_HMAC_Generate(authSession->sharedSecret, *a1AuthValue, /* HMAC key */ TPM_NONCE_SIZE, nonceEvenDSAP, TPM_NONCE_SIZE, nonceOddDSAP, 0, NULL); } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_DSAP: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; /* append authHandle */ returnCode = TPM_Sbuffer_Append32(response, authHandle); } /* append nonceEven */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Nonce_Store(response, authSession->nonceEven); } /* append nonceEvenDSAP */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Nonce_Store(response, nonceEvenDSAP); } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if the handle is not being returned, it should be terminated */ if (((returnCode != 0) || (rcf != 0)) && got_handle) { TPM_AuthSessionData_Delete(authSession); } /* cleanup */ TPM_SizedBuffer_Delete(&entityValue); /* @1 */ TPM_DelegateOwnerBlob_Delete(&b1DelegateOwnerBlob); /* @2 */ TPM_DelegateKeyBlob_Delete(&k1DelegateKeyBlob); /* @3 */ TPM_DelegateSensitive_Delete(&s1DelegateSensitive); /* @4 */ return rcf; } /* TPM_DSAPDelegate() implements the actions common to TPM_DSAP and TPM_OSAP with ownerReference pointing to a delegate row. 'entityDigest' and 'authData' are returned, as they are used by common code. authSession. protocolID is changed to DSAP. the TPM_DELEGATE_PUBLIC blob is copied to the OSAP/DSAP session structure. */ static TPM_RESULT TPM_OSAPDelegate(TPM_DIGEST **entityDigest, TPM_SECRET **authData, TPM_AUTH_SESSION_DATA *authSession, tpm_state_t *tpm_state, uint32_t delegateRowIndex) { TPM_RESULT rc = 0; TPM_DELEGATE_TABLE_ROW *d1DelegateTableRow; TPM_FAMILY_TABLE_ENTRY *familyRow; /* family table row containing familyID */ printf("TPM_DSAPCommon: Index %u\n", delegateRowIndex); /* 2. Else if entityType == TPM_ET_DEL_ROW */ /* a. Verify that entityValue points to a valid row in the delegation table. */ /* b. Set d1 to the delegation information in the row. */ if (rc == TPM_SUCCESS) { rc = TPM_DelegateTable_GetValidRow(&d1DelegateTableRow, &(tpm_state->tpm_permanent_data.delegateTable), delegateRowIndex); } if (rc == TPM_SUCCESS) { /* d. Locate D1 -> familyID in the TPM_FAMILY_TABLE and set familyRow to indicate that row, return TPM_BADINDEX if not found */ /* e. Set FR to TPM_FAMILY_TABLE.FamTableRow[familyRow] */ /* f. If FR -> flags TPM_FAMFLAG_ENABLED is FALSE, return TPM_DISABLED_CMD */ rc = TPM_FamilyTable_GetEnabledEntry(&familyRow, &(tpm_state->tpm_permanent_data.familyTable), d1DelegateTableRow->pub.familyID); } /* g. Verify that d1->verificationCount equals FR -> verificationCount. */ if (rc == TPM_SUCCESS) { if (d1DelegateTableRow->pub.verificationCount != familyRow->verificationCount) { printf("TPM_DSAPCommon: Error, verificationCount mismatch %u %u\n", d1DelegateTableRow->pub.verificationCount, familyRow->verificationCount); rc = TPM_FAMILYCOUNT; } } if (rc == TPM_SUCCESS) { /* c. Set a1 to d1->authValue. */ *authData = &d1DelegateTableRow->authValue; /* use owner delegate authorization value */ /* indicate later that the entity is the 'owner'. Use the real owner auth because the ordinal doesn't know about the delegation */ *entityDigest = &(tpm_state->tpm_permanent_data.ownerAuth); authSession->protocolID = TPM_PID_DSAP; /* change from OSAP to DSAP */ /* Save the TPM_DELEGATE_PUBLIC to check the permissions and pcrInfo at DSAP session use. */ rc = TPM_DelegatePublic_Copy(&(authSession->pub), &(d1DelegateTableRow->pub)); } return rc; } /* 18.4 TPM_SetOwnerPointer rev 109 This command will set a reference to which secret the TPM will use when executing an owner secret related OIAP or OSAP session. This command should only be used to provide an owner delegation function for legacy code that does not itself support delegation. Normally, TPM_STCLEAR_DATA->ownerReference points to TPM_KH_OWNER, indicating that OIAP and OSAP sessions should use the owner authorization. This command allows ownerReference to point to an index in the delegation table, indicating that OIAP and OSAP sessions should use the delegation authorization. In use, a TSS supporting delegation would create and load the owner delegation and set the owner pointer to that delegation. From then on, a legacy TSS application would use its OIAP and OSAP sessions with the delegated owner authorization. Since this command is not authorized, the ownerReference is open to DoS attacks. Applications can attempt to recover from a failing owner authorization by resetting ownerReference to an appropriate value. This command intentionally does not clear OSAP sessions. A TPM 1.1 application gets the benefit of owner delegation, while the original owner can use a pre-existing OSAP session with the actual owner authorization. */ TPM_RESULT TPM_Process_SetOwnerPointer(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_ENTITY_TYPE entityType; /* The type of entity in use */ uint32_t entityValue = 0; /* The selection value based on entityType */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_STCLEAR_DATA *v1StClearData; TPM_DELEGATE_TABLE_ROW *b1DelegateTableRow; /* delegate row indicated by entityValue */ TPM_FAMILY_TABLE_ENTRY *familyRow; /* family table row containing familyID */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_SetOwnerPointer: Ordinal Entry\n"); /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get entityType */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load16(&entityType, &command, ¶mSize); } /* get entityValue */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_SetOwnerPointer: entityType %04hx\n", entityType); returnCode = TPM_Load32(&entityValue, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_SetOwnerPointer: entityValue %08x\n", entityValue); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_SetOwnerPointer: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ /* 1. Map TPM_STCLEAR_DATA to V1 */ if (returnCode == TPM_SUCCESS) { v1StClearData = &(tpm_state->tpm_stclear_data); /* 2. If entityType = TPM_ET_DEL_ROW */ if (entityType == TPM_ET_DEL_ROW) { /* a. This value indicates that the entity is a delegate row. entityValue is a delegate index in the delegation table. */ /* b. Validate that entityValue points to a legal row within the delegate table stored within the TPM. If not return TPM_BADINDEX */ /* i. Set D1 to the delegation information in the row. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_DelegateTable_GetValidRow(&b1DelegateTableRow, &(tpm_state->tpm_permanent_data.delegateTable), entityValue); } /* c. Locate D1 -> familyID in the TPM_FAMILY_TABLE and set familyRow to indicate that row, return TPM_BADINDEX if not found. */ /* d. Set FR to TPM_FAMILY_TABLE.famTableRow[familyRow] */ /* e. If FR -> flags TPM_FAMFLAG_ENABLED is FALSE, return TPM_DISABLED_CMD */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_FamilyTable_GetEnabledEntry(&familyRow, &(tpm_state->tpm_permanent_data.familyTable), b1DelegateTableRow->pub.familyID); } /* f. Verify that B1->verificationCount equals FR -> verificationCount. */ if (returnCode == TPM_SUCCESS) { if (b1DelegateTableRow->pub.verificationCount != familyRow->verificationCount) { printf("TPM_Process_SetOwnerPointer: Error, " "verificationCount mismatch %u %u\n", b1DelegateTableRow->pub.verificationCount, familyRow->verificationCount); returnCode = TPM_FAMILYCOUNT; } } /* g. The TPM sets V1-> ownerReference to entityValue */ /* h. Return TPM_SUCCESS */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_SetOwnerPointer: Setting ownerReference to %08x\n", entityValue); v1StClearData->ownerReference = entityValue; } } /* 3. else if entityType = TPM_ET_OWNER */ else if (entityType == TPM_ET_OWNER) { /* a. This value indicates that the entity is the TPM owner. entityValue is ignored. */ /* b. The TPM sets V1-> ownerReference to TPM_KH_OWNER */ /* c. Return TPM_SUCCESS */ printf("TPM_Process_SetOwnerPointer: Setting ownerReference to %08x\n", TPM_KH_OWNER); v1StClearData->ownerReference = TPM_KH_OWNER; } /* 4. Return TPM_BAD_PARAMETER */ else { printf("TPM_Process_SetOwnerPointer: Error, bad entityType\n"); returnCode = TPM_BAD_PARAMETER; } } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_SetOwnerPointer: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* cleanup */ return rcf; } /* 27.1.2 TPM_Terminate_Handle rev 87 This allows the TPM manager to clear out information in a session handle. The TPM may maintain the authorization session even though a key attached to it has been unloaded or the authorization session itself has been unloaded in some way. When a command is executed that requires this session, it is the responsibility of the external software to load both the entity and the authorization session information prior to command execution. The TPM SHALL terminate the session and destroy all data associated with the session indicated. */ TPM_RESULT TPM_Process_TerminateHandle(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_AUTHHANDLE authHandle; /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_TerminateHandle: Ordinal Entry\n"); /* get inputs */ /* get handle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&authHandle, &command, ¶mSize); } /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | TPM_CHECK_NO_LOCKOUT)); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_TerminateHandle: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ /* terminate the handle */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_TerminateHandle: Using authHandle %08x\n", authHandle); returnCode = TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_TerminateHandle: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } return rcf; } /* 22.1 TPM_FlushSpecific rev 104 TPM_FlushSpecific flushes from the TPM a specific handle. TPM_FlushSpecific releases the resources associated with the given handle. */ TPM_RESULT TPM_Process_FlushSpecific(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_HANDLE handle; /* The handle of the item to flush */ TPM_RESOURCE_TYPE resourceType = 0; /* The type of resource that is being flushed */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ uint32_t r1Resource; /* the context resource being flushed */ TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry; /* key table entry for the handle */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_FlushSpecific: Ordinal Entry\n"); /* get inputs */ /* get handle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&handle, &command, ¶mSize); } /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get resourceType parameter */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_FlushSpecific: Handle %08x\n", handle); returnCode = TPM_Load32(&resourceType, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | TPM_CHECK_NO_LOCKOUT)); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_FlushSpecific: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ if (returnCode == TPM_SUCCESS) { switch (resourceType) { case TPM_RT_CONTEXT: /* 1. If resourceType is TPM_RT_CONTEXT */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_FlushSpecific: Flushing context count %08x\n", handle); /* a. The handle for a context is not a handle but the "context count" value. The TPM uses the "context count" value to locate the proper contextList entry and sets R1 to the contextList entry */ returnCode = TPM_ContextList_GetEntry(&r1Resource, /* index into contextList[] */ tpm_state->tpm_stclear_data.contextList, handle); /* 7. Validate that R1 determined by resourceType and handle points to a valid allocated resource. Return TPM_BAD_PARAMETER on error. */ if (returnCode != TPM_SUCCESS) { printf("TPM_Process_FlushSpecific: Error, context count %08x not found\n", handle); returnCode = TPM_BAD_PARAMETER; } } /* 8. Invalidate R1 and all internal resources allocated to R1 */ /* a. Resources include authorization sessions */ if (returnCode == TPM_SUCCESS) { /* setting the entry to 0 prevents the session from being reloaded. */ tpm_state->tpm_stclear_data.contextList[r1Resource] = 0; } break; case TPM_RT_KEY: /* 2. Else if resourceType is TPM_RT_KEY */ /* a. Set R1 to the key pointed to by handle */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_FlushSpecific: Flushing key handle %08x\n", handle); returnCode = TPM_KeyHandleEntries_GetEntry(&tpm_key_handle_entry, tpm_state->tpm_key_handle_entries, handle); /* 7. Validate that R1 determined by resourceType and handle points to a valid allocated resource. Return TPM_BAD_PARAMETER on error. */ if (returnCode != TPM_SUCCESS) { printf("TPM_Process_FlushSpecific: Error, key handle %08x not found\n", handle); returnCode = TPM_BAD_PARAMETER; } } /* b. If R1 -> ownerEvict is TRUE return TPM_KEY_OWNER_CONTROL */ if (returnCode == TPM_SUCCESS) { if (tpm_key_handle_entry->keyControl & TPM_KEY_CONTROL_OWNER_EVICT) { printf("TPM_Process_FlushSpecific: Error, keyHandle specifies owner evict\n"); returnCode = TPM_KEY_OWNER_CONTROL; } } /* 8. Invalidate R1 and all internal resources allocated to R1 */ /* a. Resources include authorization sessions */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyHandleEntry_FlushSpecific(tpm_state, tpm_key_handle_entry); } break; case TPM_RT_AUTH: /* NOTE replaces deprecated TPM_Terminate_Handle */ /* 3. Else if resourceType is TPM_RT_AUTH */ /* a. Set R1 to the authorization session pointed to by handle */ /* 7. Validate that R1 determined by resourceType and handle points to a valid allocated resource. Return TPM_BAD_PARAMETER on error. */ /* 8. Invalidate R1 and all internal resources allocated to R1 */ /* a. Resources include authorization sessions */ printf("TPM_Process_FlushSpecific: Flushing authorization session handle %08x\n", handle); returnCode = TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, handle); break; case TPM_RT_TRANS: /* 4. Else if resourceType is TPM_RT_TRANS */ /* a. Set R1 to the transport session pointed to by handle */ /* 7. Validate that R1 determined by resourceType and handle points to a valid allocated resource. Return TPM_BAD_PARAMETER on error. */ /* 8. Invalidate R1 and all internal resources allocated to R1 */ /* a. Resources include authorization sessions */ printf("TPM_Process_FlushSpecific: Flushing transport session handle %08x\n", handle); returnCode = TPM_TransportSessions_TerminateHandle (tpm_state->tpm_stclear_data.transSessions, handle, &(tpm_state->tpm_stany_flags.transportExclusive)); break; case TPM_RT_DAA_TPM: /* 5. Else if resourceType is TPM_RT_DAA_TPM */ /* a. Set R1 to the DAA session pointed to by handle */ /* 7. Validate that R1 determined by resourceType and handle points to a valid allocated resource. Return TPM_BAD_PARAMETER on error. */ /* 8. Invalidate R1 and all internal resources allocated to R1 */ /* a. Resources include authorization sessions */ printf("TPM_Process_FlushSpecific: Flushing DAA session handle %08x\n", handle); returnCode = TPM_DaaSessions_TerminateHandle(tpm_state->tpm_stclear_data.daaSessions, handle); break; default: /* 6. Else return TPM_INVALID_RESOURCE */ printf("TPM_Process_FlushSpecific: Error, invalid resourceType %08x\n", resourceType); returnCode = TPM_INVALID_RESOURCE; break; } } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_FlushSpecific: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } return rcf; } /* 21.2 TPM_SaveContext rev 107 SaveContext saves a loaded resource outside the TPM. After successful execution of the command the TPM automatically releases the internal memory for sessions but leaves keys in place. The caller of the function uses the label field to add additional sequencing, anti-replay or other items to the blob. The information does not need to be confidential but needs to be part of the blob integrity. */ TPM_RESULT TPM_Process_SaveContext(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_HANDLE handle; /* Handle of the resource being saved. */ TPM_RESOURCE_TYPE resourceType = 0; /* The type of resource that is being saved */ BYTE label[TPM_CONTEXT_LABEL_SIZE]; /* Label for identification purposes */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_STORE_BUFFER b1_sbuffer; /* serialization of b1 */ TPM_STCLEAR_DATA *v1StClearData = NULL; TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry; /* key table entry for the handle */ TPM_AUTH_SESSION_DATA *tpm_auth_session_data = NULL; /* session table entry for the handle */ TPM_TRANSPORT_INTERNAL *tpm_transport_internal; /* transport table entry for the handle */ TPM_DAA_SESSION_DATA *tpm_daa_session_data; /* daa session table entry for the handle */ TPM_NONCE *n1ContextNonce = NULL; TPM_SYMMETRIC_KEY_TOKEN k1ContextKey = NULL; TPM_STORE_BUFFER r1ContextSensitive; /* serialization of sensitive data clear text */ TPM_CONTEXT_SENSITIVE c1ContextSensitive; TPM_CONTEXT_BLOB b1ContextBlob; TPM_STORE_BUFFER c1_sbuffer; /* serialization of c1ContextSensitive */ uint32_t contextIndex = 0; /* free index in context list */ uint32_t space; /* free space in context list */ TPM_BOOL isZero; /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_SaveContext: Ordinal Entry\n"); TPM_Sbuffer_Init(&b1_sbuffer); /* freed @1 */ TPM_Sbuffer_Init(&r1ContextSensitive); /* freed @2 */ TPM_ContextBlob_Init(&b1ContextBlob); /* freed @3 */ TPM_ContextSensitive_Init(&c1ContextSensitive); /* freed @4 */ TPM_Sbuffer_Init(&c1_sbuffer); /* freed @6 */ /* get inputs */ /* get handle */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&handle, &command, ¶mSize); } /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get resourceType */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_SaveContext: handle %08x\n", handle); returnCode = TPM_Load32(&resourceType, &command, ¶mSize); } /* get label */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_SaveContext: resourceType %08x\n", resourceType); returnCode = TPM_Loadn(label, TPM_CONTEXT_LABEL_SIZE, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { TPM_PrintFour("TPM_Process_SaveContext: label", label); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_SaveContext: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ /* 1. Map V1 to TPM_STANY_DATA NOTE MAY be TPM_STCLEAR_DATA */ if (returnCode == TPM_SUCCESS) { v1StClearData = &(tpm_state->tpm_stclear_data); } /* 2. Validate that handle points to resource that matches resourceType, return TPM_INVALID_RESOURCE on error */ /* 3. Validate that resourceType is a resource from the following list if not return TPM_INVALID_RESOURCE */ if (returnCode == TPM_SUCCESS) { switch (resourceType) { case TPM_RT_KEY: /* a. TPM_RT_KEY */ printf("TPM_Process_SaveContext: Resource is key handle %08x\n", handle); /* check if the key handle is valid */ returnCode = TPM_KeyHandleEntries_GetEntry(&tpm_key_handle_entry, tpm_state->tpm_key_handle_entries, handle); break; case TPM_RT_AUTH: /* b. TPM_RT_AUTH */ printf("TPM_Process_SaveContext: Resource is session handle %08x\n", handle); returnCode = TPM_AuthSessions_GetEntry(&tpm_auth_session_data, v1StClearData->authSessions, handle); break; case TPM_RT_TRANS: /* c. TPM_RT_TRANS */ printf("TPM_Process_SaveContext: Resource is transport handle %08x\n", handle); returnCode = TPM_TransportSessions_GetEntry(&tpm_transport_internal, v1StClearData->transSessions, handle); break; case TPM_RT_DAA_TPM: /* d. TPM_RT_DAA_TPM */ printf("TPM_Process_SaveContext: Resource is DAA handle %08x\n", handle); returnCode = TPM_DaaSessions_GetEntry(&tpm_daa_session_data, v1StClearData->daaSessions, handle); break; default: printf("TPM_Process_SaveContext: Error, invalid resourceType %08x\n", resourceType); returnCode = TPM_INVALID_RESOURCE; break; } if (returnCode != 0) { printf("TPM_Process_SaveContext: Error, handle %08x not found\n", handle); returnCode = TPM_INVALID_RESOURCE; } } /* 4. Locate the correct nonce */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_SaveContext: Locating nonce\n"); /* a. If resourceType is TPM_RT_KEY */ if (resourceType == TPM_RT_KEY) { if (returnCode == TPM_SUCCESS) { /* i. If TPM_STCLEAR_DATA -> contextNonceKey is NULLS */ TPM_Nonce_IsZero(&isZero, tpm_state->tpm_stclear_data.contextNonceKey); if (isZero) { /* (1) Set TPM_STCLEAR_DATA -> contextNonceKey to the next value from the TPM RNG */ returnCode = TPM_Nonce_Generate(tpm_state->tpm_stclear_data.contextNonceKey); } } if (returnCode == TPM_SUCCESS) { /* ii. Map N1 to TPM_STCLEAR_DATA -> contextNonceKey */ n1ContextNonce = &(tpm_state->tpm_stclear_data.contextNonceKey); /* iii. If the key has TPM_KEY_CONTROL_OWNER_EVICT set then return TPM_OWNER_CONTROL */ if (tpm_key_handle_entry->keyControl & TPM_KEY_CONTROL_OWNER_EVICT) { printf("TPM_Process_SaveContext: Error, key under owner control\n"); returnCode = TPM_OWNER_CONTROL; } } } /* b. Else (resource not TPM_RT_KEY) */ else { if (returnCode == TPM_SUCCESS) { /* i. If V1 -> contextNonceSession is NULLS */ TPM_Nonce_IsZero(&isZero, v1StClearData->contextNonceSession); if (isZero) { /* (1) Set V1 -> contextNonceSession to the next value from the TPM RNG */ returnCode = TPM_Nonce_Generate(v1StClearData->contextNonceSession); } } /* ii. Map N1 to V1 -> contextNonceSession */ if (returnCode == TPM_SUCCESS) { n1ContextNonce = &(v1StClearData->contextNonceSession); } } } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_SaveContext: Building sensitive data\n"); /* 5. Set K1 to TPM_PERMANENT_DATA -> contextKey */ k1ContextKey = tpm_state->tpm_permanent_data.contextKey; /* 6. Create R1 by putting the sensitive part of the resource pointed to by handle into a structure. The structure is a TPM manufacturer option. The TPM MUST ensure that ALL sensitive information of the resource is included in R1. */ /* NOTE Since the contextKey is a symmetric key, the entire resource is put into the sensitiveData */ switch (resourceType) { case TPM_RT_KEY: returnCode = TPM_KeyHandleEntry_Store(&r1ContextSensitive, tpm_key_handle_entry); break; case TPM_RT_AUTH: returnCode = TPM_AuthSessionData_Store(&r1ContextSensitive, tpm_auth_session_data); break; case TPM_RT_TRANS: returnCode = TPM_TransportInternal_Store(&r1ContextSensitive, tpm_transport_internal); break; case TPM_RT_DAA_TPM: returnCode = TPM_DaaSessionData_Store(&r1ContextSensitive, tpm_daa_session_data); break; default: printf("TPM_Process_SaveContext: Error, invalid resourceType %08x", resourceType); returnCode = TPM_INVALID_RESOURCE; break; } } /* 7. Create C1 a TPM_CONTEXT_SENSITIVE structure */ /* NOTE Done at TPM_ContextSensitive_Init() */ /* a. C1 forms the inner encrypted wrapper for the blob. All saved context blobs MUST include a TPM_CONTEXT_SENSITIVE structure and the TPM_CONTEXT_SENSITIVE structure MUST be encrypted. */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_SaveContext: Building TPM_CONTEXT_SENSITIVE\n"); /* b. Set C1 -> contextNonce to N1 */ TPM_Nonce_Copy(c1ContextSensitive.contextNonce, *n1ContextNonce); /* c. Set C1 -> internalData to R1 */ returnCode = TPM_SizedBuffer_SetFromStore(&(c1ContextSensitive.internalData), &r1ContextSensitive); } /* 8. Create B1 a TPM_CONTEXT_BLOB */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_SaveContext: Building TPM_CONTEXT_BLOB\n"); /* a. Set B1 -> tag to TPM_TAG_CONTEXTBLOB */ /* NOTE Done at TPM_ContextBlob_Init() */ /* b. Set B1 -> resourceType to resourceType */ b1ContextBlob.resourceType = resourceType; /* c. Set B1 -> handle to handle */ b1ContextBlob.handle = handle; /* d. Set B1 -> integrityDigest to NULL */ /* NOTE Done at TPM_ContextBlob_Init() */ /* e. Set B1 -> label to label */ memcpy(b1ContextBlob.label, label, TPM_CONTEXT_LABEL_SIZE); } /* f. Set B1 -> additionalData to information determined by the TPM manufacturer. This data will help the TPM to reload and reset context. This area MUST NOT hold any data that is sensitive (symmetric IV are fine, prime factors of an RSA key are not). */ /* i. For OSAP sessions, and for DSAP sessions attached to keys, the hash of the entity MUST be included in additionalData */ /* NOTE Included in TPM_AUTH_SESSION_DATA. This is implementation defined, and the manufacturer can put everything in sensitive data. */ /* g. Set B1 -> additionalSize to the size of additionalData */ /* NOTE Initialized by TPM_ContextBlob_Init() */ /* h. Set B1 -> sensitiveSize to the size of C1 */ /* i. Set B1 -> sensitiveData to C1 */ /* serialize C1 */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_ContextSensitive_Store(&c1_sbuffer, &c1ContextSensitive); } /* Here the clear text goes into TPM_CONTEXT_BLOB->sensitiveData */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_SetFromStore(&(b1ContextBlob.sensitiveData), &c1_sbuffer); } if (returnCode == TPM_SUCCESS) { /* 9. If resourceType is TPM_RT_KEY */ if (resourceType == TPM_RT_KEY) { /* a. Set B1 -> contextCount to 0 */ b1ContextBlob.contextCount = 0; } /* 10. Else */ else { printf("TPM_Process_SaveContext: Processing session context count\n"); if (returnCode == TPM_SUCCESS) { /* a. If V1 -> contextCount > 2^32-2 then */ if (v1StClearData->contextCount > 0xfffffffe) { /* i. Return with TPM_TOOMANYCONTEXTS */ printf("TPM_Process_SaveContext: Error, too many contexts\n"); returnCode = TPM_TOOMANYCONTEXTS; } } /* b. Else */ if (returnCode == TPM_SUCCESS) { /* i. Validate that the TPM can still manage the new count value */ /* (1) If the distance between the oldest saved context and the contextCount is too large return TPM_CONTEXT_GAP */ /* Since contextCount is uint32_t, this is not applicable here. From email: Does the TPM have the ability to keep track of the context delta. It is possible to keep track of things with just a byte or so internally, if this is done a gap of greater than 2^16 or so might be too large, hence the context gap message */ } /* ii. Find contextIndex such that V1 -> contextList[contextIndex] equals 0. If not found exit with TPM_NOCONTEXTSPACE */ if (returnCode == TPM_SUCCESS) { TPM_ContextList_GetSpace(&space, &contextIndex, v1StClearData->contextList); if (space == 0) { printf("TPM_Process_SaveContext: Error, no space in context list\n"); returnCode = TPM_NOCONTEXTSPACE; } } if (returnCode == TPM_SUCCESS) { /* iii. Increment V1 -> contextCount by 1 */ v1StClearData->contextCount++; /* iv. Set V1-> contextList[contextIndex] to V1 -> contextCount */ v1StClearData->contextList[contextIndex] = v1StClearData->contextCount; /* v. Set B1 -> contextCount to V1 -> contextCount */ b1ContextBlob.contextCount = v1StClearData->contextCount; } /* c. The TPM MUST invalidate all information regarding the resource except for information needed for reloading */ if (returnCode == TPM_SUCCESS) { switch (resourceType) { case TPM_RT_AUTH: returnCode = TPM_AuthSessions_TerminateHandle(v1StClearData->authSessions, handle); break; case TPM_RT_TRANS: returnCode = TPM_TransportSessions_TerminateHandle (v1StClearData->transSessions, handle, &(tpm_state->tpm_stany_flags.transportExclusive)); break; case TPM_RT_DAA_TPM: returnCode = TPM_DaaSessions_TerminateHandle(v1StClearData->daaSessions, handle); break; default: printf("TPM_Process_SaveContext: Error, invalid resourceType %08x", resourceType); returnCode = TPM_INVALID_RESOURCE; break; } } } } /* 11. Calculate B1 -> integrityDigest the HMAC of B1 using TPM_PERMANENT_DATA -> tpmProof as the secret. NOTE It is calculated on the cleartext data */ if (returnCode == TPM_SUCCESS) { /* This is a bit circular. It's safe since the TPM_CONTEXT_BLOB is serialized before the HMAC is generated. The result is put back into the structure. */ printf("TPM_Process_SaveContext: Digesting TPM_CONTEXT_BLOB\n"); returnCode = TPM_HMAC_GenerateStructure (b1ContextBlob.integrityDigest, /* HMAC */ tpm_state->tpm_permanent_data.tpmProof, /* HMAC key */ &b1ContextBlob, /* structure */ (TPM_STORE_FUNCTION_T)TPM_ContextBlob_Store); /* store function */ } /* 12. Create E1 by encrypting C1 using K1 as the key */ /* a. Set B1 -> sensitiveSize to the size of E1 */ /* b. Set B1 -> sensitiveData to E1 */ if (returnCode == TPM_SUCCESS) { /* The cleartext went into sensitiveData for the integrityDigest calculation. Free it now, before the encrypted data is stored there. */ TPM_SizedBuffer_Delete(&(b1ContextBlob.sensitiveData)); returnCode = TPM_SymmetricKeyData_EncryptSbuffer(&(b1ContextBlob.sensitiveData), &c1_sbuffer, k1ContextKey); } /* 13. Set contextSize to the size of B1 */ /* 14. Return B1 in contextBlob */ /* Since the redundant size parameter must be returned, the TPM_CONTEXT_BLOB is serialized first. Later, rather than the usual _Store to the response, the already serialized buffer is stored. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_ContextBlob_Store(&b1_sbuffer, &b1ContextBlob); } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_SaveContext: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* return contextSize and contextBlob */ returnCode = TPM_Sbuffer_AppendAsSizedBuffer(response, &b1_sbuffer); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* cleanup */ TPM_Sbuffer_Delete(&b1_sbuffer); /* @1 */ TPM_Sbuffer_Delete(&r1ContextSensitive); /* @2 */ TPM_ContextBlob_Delete(&b1ContextBlob); /* @3 */ TPM_ContextSensitive_Delete(&c1ContextSensitive); /* @4 */ TPM_Sbuffer_Delete(&c1_sbuffer); /* @6 */ return rcf; } /* 21.3 TPM_LoadContext rev 107 TPM_LoadContext loads into the TPM a previously saved context. The command returns the handle. */ TPM_RESULT TPM_Process_LoadContext(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_HANDLE entityHandle; /* The handle the TPM MUST use to locate the entity ties to the OSAP/DSAP session */ TPM_BOOL keepHandle; /* Indication if the handle MUST be preserved */ uint32_t contextSize; /* The size of the following context blob */ TPM_CONTEXT_BLOB b1ContextBlob; /* The context blob */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL key_added = FALSE; /* key has been added to handle list */ TPM_BOOL auth_session_added = FALSE; TPM_BOOL trans_session_added = FALSE; TPM_BOOL daa_session_added = FALSE; TPM_STCLEAR_DATA *v1StClearData = NULL; unsigned char *m1Decrypt; /* decrypted sensitive data */ uint32_t m1_length; /* actual data in m1 */ unsigned char *stream; uint32_t stream_size; TPM_CONTEXT_SENSITIVE c1ContextSensitive; TPM_KEY_HANDLE_ENTRY tpm_key_handle_entry; TPM_AUTH_SESSION_DATA tpm_auth_session_data; /* loaded authorization session */ TPM_TRANSPORT_INTERNAL tpm_transport_internal; /* loaded transport session */ TPM_DAA_SESSION_DATA tpm_daa_session_data; /* loaded daa session */ TPM_DIGEST entityDigest; /* digest of the entity corresponding to entityHandle */ uint32_t contextIndex; /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_LoadContext: Ordinal Entry\n"); TPM_ContextBlob_Init(&b1ContextBlob); /* freed @1 */ TPM_KeyHandleEntry_Init(&tpm_key_handle_entry); /* no free */ m1Decrypt = NULL; /* freed @2 */ TPM_ContextSensitive_Init(&c1ContextSensitive); /* freed @3 */ TPM_AuthSessionData_Init(&tpm_auth_session_data); /* freed @4 */ TPM_TransportInternal_Init(&tpm_transport_internal); /* freed @5 */ TPM_DaaSessionData_Init(&tpm_daa_session_data); /* freed @6 */ /* get inputs */ /* get parameter entityHandle */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&entityHandle, &command, ¶mSize); } /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get keepHandle parameter */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_LoadContext: entityHandle %08x\n", entityHandle); returnCode = TPM_LoadBool(&keepHandle, &command, ¶mSize); } /* get contextSize parameter (redundant, not used) */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_LoadContext: keepHandle %02x\n", keepHandle); returnCode = TPM_Load32(&contextSize, &command, ¶mSize); } /* get contextBlob parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_ContextBlob_Load(&b1ContextBlob, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_LoadContext: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ /* 1. Map contextBlob to B1, a TPM_CONTEXT_BLOB structure */ /* NOTE Done by TPM_ContextBlob_Load() */ if (returnCode == TPM_SUCCESS) { /* 2. Map V1 to TPM_STANY_DATA NOTE MAY be TPM_STCLEAR_DATA */ v1StClearData = &(tpm_state->tpm_stclear_data); /* 3. Create M1 by decrypting B1 -> sensitiveData using TPM_PERMANENT_DATA -> contextKey */ printf("TPM_Process_LoadContext: Decrypting sensitiveData\n"); returnCode = TPM_SymmetricKeyData_Decrypt(&m1Decrypt, /* decrypted data */ &m1_length, /* length decrypted data */ b1ContextBlob.sensitiveData.buffer, /* encrypt */ b1ContextBlob.sensitiveData.size, tpm_state->tpm_permanent_data.contextKey); } /* 4. Create C1 and R1 by splitting M1 into a TPM_CONTEXT_SENSITIVE structure and internal resource data */ /* NOTE R1 is manufacturer specific data that might be part of the blob. This implementation does not use R1 */ if (returnCode == TPM_SUCCESS) { stream = m1Decrypt; stream_size = m1_length; returnCode = TPM_ContextSensitive_Load(&c1ContextSensitive, &stream, &stream_size); } /* Parse the TPM_CONTEXT_SENSITIVE -> internalData depending on the resource type */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_LoadContext: Parsing TPM_CONTEXT_SENSITIVE -> internalData\n"); stream = c1ContextSensitive.internalData.buffer; stream_size = c1ContextSensitive.internalData.size; switch (b1ContextBlob.resourceType) { case TPM_RT_KEY: printf("TPM_Process_LoadContext: Loading TPM_KEY_HANDLE_ENTRY\n"); returnCode = TPM_KeyHandleEntry_Load(&tpm_key_handle_entry, &stream, &stream_size); break; case TPM_RT_AUTH: printf("TPM_Process_LoadContext: Loading TPM_AUTH_SESSION_DATA\n"); returnCode = TPM_AuthSessionData_Load(&tpm_auth_session_data, &stream, &stream_size); printf("TPM_Process_LoadContext: protocolID %02x entityTypeByte %02x\n", tpm_auth_session_data.protocolID, tpm_auth_session_data.entityTypeByte); break; case TPM_RT_TRANS: printf("TPM_Process_LoadContext: Loading TPM_TRANSPORT_INTERNAL\n"); returnCode = TPM_TransportInternal_Load(&tpm_transport_internal, &stream, &stream_size); break; case TPM_RT_DAA_TPM: printf("TPM_Process_LoadContext: Loading TPM_DAA_SESSION_DATA\n"); returnCode = TPM_DaaSessionData_Load(&tpm_daa_session_data, &stream, &stream_size); printf("TPM_Process_LoadContext: stage %u\n", tpm_daa_session_data.DAA_session.DAA_stage); break; default: printf("TPM_Process_LoadContext: Error, invalid resourceType %08x", b1ContextBlob.resourceType); returnCode = TPM_INVALID_RESOURCE; break; } } /* 5. Check contextNonce */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_LoadContext: Checking contextNonce\n"); /* a. If B1 -> resourceType is NOT TPM_RT_KEY */ if (b1ContextBlob.resourceType != TPM_RT_KEY) { /* i. If C1 -> contextNonce does not equal V1 -> contextNonceSession return TPM_BADCONTEXT */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Nonce_Compare(v1StClearData->contextNonceSession, c1ContextSensitive.contextNonce); if (returnCode != TPM_SUCCESS) { printf("TPM_Process_LoadContext: Error comparing non-key contextNonce\n"); returnCode = TPM_BADCONTEXT; } } /* ii. Validate that the resource pointed to by the context is loaded (i.e. for OSAP the key referenced is loaded and DSAP connected to the key) return TPM_RESOURCEMISSING */ /* (1) For OSAP sessions and for DSAP sessions attached to keys, the TPM MUST validate that the hash of the entity matches the entity held by the TPM */ /* (2) For OSAP and DSAP sessions referring to a key, verify that entityHandle identifies the key linked to this OSAP/DSAP session, if not return TPM_BAD_HANDLE. */ if ((returnCode == TPM_SUCCESS) && (b1ContextBlob.resourceType == TPM_RT_AUTH)) { if ((tpm_auth_session_data.protocolID == TPM_PID_OSAP) || (tpm_auth_session_data.protocolID == TPM_PID_DSAP)) { /* check that the entity is loaded, and get the entity's digest */ switch (tpm_auth_session_data.entityTypeByte) { case TPM_ET_KEYHANDLE: returnCode = TPM_LoadContext_CheckKeyLoaded(tpm_state, entityHandle, entityDigest); break; case TPM_ET_OWNER: returnCode = TPM_LoadContext_CheckOwnerLoaded(tpm_state, entityDigest); break; case TPM_ET_SRK: returnCode = TPM_LoadContext_CheckSrkLoaded(tpm_state, entityDigest); break; case TPM_ET_COUNTER: returnCode = TPM_LoadContext_CheckCounterLoaded(tpm_state, entityHandle, entityDigest); break; case TPM_ET_NV: returnCode = TPM_LoadContext_CheckNvLoaded(tpm_state, entityHandle, entityDigest); break; default: printf("TPM_Process_LoadContext: Error, invalid session entityType %02x\n", tpm_auth_session_data.entityTypeByte); returnCode = TPM_WRONG_ENTITYTYPE; break; } if (returnCode == TPM_SUCCESS) { returnCode= TPM_Digest_Compare(entityDigest, tpm_auth_session_data.entityDigest); if (returnCode != TPM_SUCCESS) { printf("TPM_Process_LoadContext: Error, " "OSAP or DSAP entityDigest mismatch\n"); returnCode = TPM_RESOURCEMISSING; } } } } } /* b. Else (TPM_RT_KEY) */ else { /* i. If C1 -> internalData -> parentPCRStatus is FALSE and C1 -> internalData -> isVolatile is FALSE */ /* NOTE parentPCRStatus and keyFlags are not security sensitive data, could be in additionalData */ /* (1) Ignore C1 -> contextNonce */ if (returnCode == TPM_SUCCESS) { if (tpm_key_handle_entry.parentPCRStatus || (tpm_key_handle_entry.key->keyFlags & TPM_ISVOLATILE)) { /* ii. else */ /* (1) If C1 -> contextNonce does not equal TPM_STCLEAR_DATA -> contextNonceKey return TPM_BADCONTEXT */ returnCode = TPM_Nonce_Compare(v1StClearData->contextNonceKey, c1ContextSensitive.contextNonce); if (returnCode != 0) { printf("TPM_Process_LoadContext: Error comparing contextNonceKey\n"); returnCode = TPM_BADCONTEXT; } } } } } /* 6. Validate the structure */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_LoadContext: Checking integrityDigest\n"); /* a. Set H1 to B1 -> integrityDigest */ /* NOTE Done by TPM_HMAC_CheckStructure() */ /* b. Set B1 -> integrityDigest to all zeros */ /* NOTE Done by TPM_HMAC_CheckStructure() */ /* c. Copy M1 to B1 -> sensitiveData (integrityDigest HMAC uses cleartext) */ returnCode = TPM_SizedBuffer_Set(&(b1ContextBlob.sensitiveData), m1_length, m1Decrypt); } /* d. Create H2 the HMAC of B1 using TPM_PERMANENT_DATA -> tpmProof as the HMAC key */ /* e. If H2 does not equal H1 return TPM_BADCONTEXT */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_HMAC_CheckStructure (tpm_state->tpm_permanent_data.tpmProof, /* key */ &b1ContextBlob, /* structure */ b1ContextBlob.integrityDigest, /* expected */ (TPM_STORE_FUNCTION_T)TPM_ContextBlob_Store, /* store function */ TPM_BADCONTEXT); /* error code */ } /* 9. If B1 -> resourceType is NOT TPM_RT_KEY */ if ((returnCode == TPM_SUCCESS) && (b1ContextBlob.resourceType != TPM_RT_KEY)) { printf("TPM_Process_LoadContext: Checking contextCount\n"); /* a. Find contextIndex such that V1 -> contextList[contextIndex] equals B1 -> TPM_CONTEXT_BLOB -> contextCount */ /* b. If not found then return TPM_BADCONTEXT */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_ContextList_GetEntry(&contextIndex, v1StClearData->contextList, b1ContextBlob.contextCount); } /* c. Set V1 -> contextList[contextIndex] to 0 */ if (returnCode == TPM_SUCCESS) { v1StClearData->contextList[contextIndex] = 0; } } /* 10. Process B1 to return the resource back into TPM use */ /* restore the entity, try to keep the handle as 'handle' */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_LoadContext: Adding entry to table\n"); switch (b1ContextBlob.resourceType) { case TPM_RT_KEY: returnCode = TPM_KeyHandleEntries_AddEntry(&(b1ContextBlob.handle), keepHandle, tpm_state->tpm_key_handle_entries, &tpm_key_handle_entry); key_added = TRUE; break; case TPM_RT_AUTH: returnCode = TPM_AuthSessions_AddEntry(&(b1ContextBlob.handle), /* input/output */ keepHandle, v1StClearData->authSessions, &tpm_auth_session_data); auth_session_added = TRUE; break; case TPM_RT_TRANS: returnCode = TPM_TransportSessions_AddEntry(&(b1ContextBlob.handle), /* input/output */ keepHandle, v1StClearData->transSessions, &tpm_transport_internal); trans_session_added = TRUE; break; case TPM_RT_DAA_TPM: returnCode = TPM_DaaSessions_AddEntry(&(b1ContextBlob.handle), /* input/output */ keepHandle, v1StClearData->daaSessions, &tpm_daa_session_data); daa_session_added = TRUE; break; default: printf("TPM_Process_LoadContext: Error, invalid resourceType %08x\n", b1ContextBlob.resourceType); returnCode = TPM_INVALID_RESOURCE; break; } } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_LoadContext: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* return handle */ returnCode = TPM_Sbuffer_Append32(response, b1ContextBlob.handle); /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* cleanup */ /* if there was a failure, roll back */ if ((rcf != 0) || (returnCode != TPM_SUCCESS)) { TPM_Key_Delete(tpm_key_handle_entry.key); /* free on error */ free(tpm_key_handle_entry.key); /* free on error */ if (key_added) { /* if there was a failure and inKey was stored in the handle list, free the handle. Ignore errors, since only one error code can be returned. */ TPM_KeyHandleEntries_DeleteHandle(tpm_state->tpm_key_handle_entries, b1ContextBlob.handle); } if (auth_session_added) { TPM_AuthSessions_TerminateHandle(v1StClearData->authSessions, b1ContextBlob.handle); } if (trans_session_added) { TPM_TransportSessions_TerminateHandle(v1StClearData->transSessions, b1ContextBlob.handle, &(tpm_state->tpm_stany_flags.transportExclusive)); } if (daa_session_added) { TPM_DaaSessions_TerminateHandle(v1StClearData->daaSessions, b1ContextBlob.handle); } } TPM_ContextBlob_Delete(&b1ContextBlob); /* @1 */ free(m1Decrypt); /* @2 */ TPM_ContextSensitive_Delete(&c1ContextSensitive); /* @3 */ TPM_AuthSessionData_Delete(&tpm_auth_session_data); /* @4 */ TPM_TransportInternal_Delete(&tpm_transport_internal); /* @5 */ TPM_DaaSessionData_Delete(&tpm_daa_session_data); /* @6 */ return rcf; } /* TPM_LoadContext_CheckKeyLoaded() validates that the key associated with a loading authorization context is loaded. It returns the key pubDataDigest for comparison with the digest of the loading context. */ static TPM_RESULT TPM_LoadContext_CheckKeyLoaded(tpm_state_t *tpm_state, TPM_HANDLE entityHandle, TPM_DIGEST entityDigest) { TPM_RESULT rc = 0; TPM_KEY_HANDLE_ENTRY *key_handle_entry; printf("TPM_LoadContext_CheckKeyLoaded: handle %08x\n", entityHandle); /* get the key associated with entityHandle */ /* special case, SRK is not in the key handle list */ if (entityHandle == TPM_KH_SRK) { if (tpm_state->tpm_permanent_data.ownerInstalled) { TPM_Digest_Copy(entityDigest, tpm_state->tpm_permanent_data.srk.tpm_store_asymkey->pubDataDigest); } else { printf("TPM_LoadContext_CheckKeyLoaded: Error, ownerInstalled is FALSE\n"); rc = TPM_NOSRK; } } /* normal case, key is in the key handle list */ else { rc = TPM_KeyHandleEntries_GetEntry(&key_handle_entry, tpm_state->tpm_key_handle_entries, entityHandle); if (rc == 0) { TPM_Digest_Copy(entityDigest, key_handle_entry->key->tpm_store_asymkey->pubDataDigest); } else { printf("TPM_LoadContext_CheckKeyLoaded: Error, key handle %08x not found\n", entityHandle); rc = TPM_BAD_HANDLE; } } return rc; } /* TPM_LoadContext_CheckKeyLoadedByDigest() validates that the key associated with a loading authorization context is loaded. It compares the key the pubDataDigest to the digest of the loading context. */ static TPM_RESULT TPM_LoadContext_CheckKeyLoadedByDigest(tpm_state_t *tpm_state, TPM_DIGEST entityDigest) { TPM_RESULT rc = TPM_RETRY; /* any non-zero value will do */ size_t start; size_t current; TPM_KEY_HANDLE_ENTRY *key_handle_entry; printf("TPM_LoadContext_CheckKeyLoadedByDigest:\n"); /* get the key associated with entityDigest */ start = 0; /* iterate through all keys in the key handle table */ while ((rc != 0) && /* a match sets rc to 0, terminates loop */ /* returns TPM_RETRY when at the end of the table, terminates loop */ (TPM_KeyHandleEntries_GetNextEntry(&key_handle_entry, ¤t, tpm_state->tpm_key_handle_entries, start)) == 0) { start = current + 1; rc = TPM_Digest_Compare(entityDigest, key_handle_entry->key->tpm_store_asymkey->pubDataDigest); } /* if that failed, check the SRK */ if (rc != 0) { if (tpm_state->tpm_permanent_data.ownerInstalled) { rc = TPM_Digest_Compare (entityDigest, tpm_state->tpm_permanent_data.srk.tpm_store_asymkey->pubDataDigest); } } if (rc != 0) { printf("TPM_LoadContext_CheckKeyLoadedByDigest: " "Error, OSAP or DSAP entityDigest mismatch\n"); rc = TPM_RESOURCEMISSING; } return rc; } /* TPM_LoadContext_CheckOwnerLoaded() validates that the owner is loaded. It returns the owner authorization for comparison with the digest of the loading context. */ static TPM_RESULT TPM_LoadContext_CheckOwnerLoaded(tpm_state_t *tpm_state, TPM_DIGEST entityDigest) { TPM_RESULT rc = 0; printf("TPM_LoadContext_CheckOwnerLoaded:\n"); /* verify that an owner is installed */ if (rc == 0) { if (!tpm_state->tpm_permanent_data.ownerInstalled) { printf("TPM_LoadContext_CheckOwnerLoaded: Error, no owner\n"); rc = TPM_RESOURCEMISSING; } } if (rc == 0) { TPM_Digest_Copy(entityDigest, tpm_state->tpm_permanent_data.ownerAuth); } return rc; } /* TPM_LoadContext_CheckSrkLoaded() validates that the SRK is loaded. It returns the SRK pubDataDigest for comparison with the digest of the loading context. */ static TPM_RESULT TPM_LoadContext_CheckSrkLoaded(tpm_state_t *tpm_state, TPM_DIGEST entityDigest) { TPM_RESULT rc = 0; printf("TPM_LoadContext_CheckSrkLoaded:\n"); /* verify that an owner is installed */ if (rc == 0) { if (!tpm_state->tpm_permanent_data.ownerInstalled) { printf("TPM_LoadContext_CheckSrkLoaded: Error, no SRK\n"); rc = TPM_RESOURCEMISSING; } } if (rc == 0) { TPM_Digest_Copy(entityDigest, tpm_state->tpm_permanent_data.srk.tpm_store_asymkey->pubDataDigest); } return rc; } /* TPM_LoadContext_CheckCounterLoaded() validates that the counter associated with a loading authorization context is loaded. It returns the counter authorization for comparison with the digest of the loading context. */ static TPM_RESULT TPM_LoadContext_CheckCounterLoaded(tpm_state_t *tpm_state, TPM_HANDLE entityHandle, TPM_DIGEST entityDigest) { TPM_RESULT rc = 0; TPM_COUNTER_VALUE *counterValue; /* associated with entityHandle */ printf("TPM_LoadContext_CheckCounterLoaded: handle %08x\n", entityHandle); if (rc == 0) { rc = TPM_Counters_GetCounterValue(&counterValue, tpm_state->tpm_permanent_data.monotonicCounter, entityHandle); if (rc != 0) { printf("TPM_LoadContext_CheckCounterLoaded: Error, no counter\n"); rc = TPM_RESOURCEMISSING; } } if (rc == 0) { TPM_Digest_Copy(entityDigest, counterValue->digest); } return rc; } /* TPM_LoadContext_CheckNvLoaded() validates that the NV space associated with a loading authorization context exists. */ static TPM_RESULT TPM_LoadContext_CheckNvLoaded(tpm_state_t *tpm_state, TPM_HANDLE entityHandle, TPM_DIGEST entityDigest) { TPM_RESULT rc = 0; TPM_NV_DATA_SENSITIVE *tpm_nv_data_sensitive; /* associated with entityValue */ printf(" TPM_LoadContext_CheckNvLoaded: handle %08x\n", entityHandle); if (rc == 0) { rc = TPM_NVIndexEntries_GetEntry(&tpm_nv_data_sensitive, &(tpm_state->tpm_nv_index_entries), entityHandle); if (rc != 0) { printf("TPM_LoadContext_CheckNvLoaded: Error, no NV at index %08x\n", entityHandle); rc = TPM_RESOURCEMISSING; } } if (rc == 0) { TPM_Digest_Copy(entityDigest, tpm_nv_data_sensitive->digest); } return rc; } /* 21.1 TPM_KeyControlOwner rev 116 This command controls some attributes of keys that are stored within the TPM key cache. 1. Set an internal bit within the key cache that controls some attribute of a loaded key. 2.When a key is set to ownerEvict, the key handle value remains the same as long as the key remains ownerEvict. The key handle value persists through TPM_Startup. OwnerEvict: If this bit is set to true, this key remains in the TPM non-volatile storage through all TPM_Startup events. The only way to evict this key is for the TPM Owner to execute this command again, setting the owner control bit to false and then executing TPM_FlushSpecific. The key handle does not reference an authorized entity and is not validated. The check for two remaining key slots ensures that users can load the two keys required to execute many commands. Since only the owner can flush owner evict keys, non-owner commands could be blocked if this test was not performed. */ TPM_RESULT TPM_Process_KeyControlOwner(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_KEY_HANDLE keyHandle; /* The handle of a loaded key. */ TPM_PUBKEY pubKey; /* The public key associated with the loaded key */ TPM_KEY_CONTROL bitName = 0; /* The name of the bit to be modified */ TPM_BOOL bitValue = FALSE; /* The value to set the bit to */ TPM_AUTHHANDLE authHandle; /* The authorization session handle used for owner authentication. */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization session handle */ TPM_AUTHDATA ownerAuth; /* HMAC authorization: key ownerAuth */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ TPM_SECRET *hmacKey; TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry; /* entry for keyHandle */ TPM_BOOL isSpace; TPM_BOOL oldOwnerEvict; /* original owner evict state */ uint16_t ownerEvictCount; /* current number of owner evict keys */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_KeyControlOwner: Ordinal Entry\n"); TPM_Pubkey_Init(&pubKey); /* freed @1 */ /* get inputs */ /* get keyHandle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&keyHandle, &command, ¶mSize); } /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get pubKey parameter */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_KeyControlOwner: keyHandle %08x\n", keyHandle); returnCode = TPM_Pubkey_Load(&pubKey, &command, ¶mSize); } /* get bitName parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&bitName, &command, ¶mSize); } /* get bitValue parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load8(&bitValue, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_KeyControlOwner: bitName %08x bitValue %02x\n", bitName, bitValue); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag1(tag); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, ownerAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_KeyControlOwner: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* 1. Validate the AuthData using the owner authentication value, on error return TPM_AUTHFAIL */ /* get the session data */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_OWNER, ordinal, NULL, &(tpm_state->tpm_permanent_data.ownerAuth), /* OIAP */ tpm_state->tpm_permanent_data.ownerAuth); /* OSAP */ } if (returnCode == TPM_SUCCESS) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* owner HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, ownerAuth); /* Authorization digest for input */ } /* 2. Validate that keyHandle refers to a loaded key, return TPM_INVALID_KEYHANDLE on error. */ /* get the key corresponding to the keyHandle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyHandleEntries_GetEntry(&tpm_key_handle_entry, tpm_state->tpm_key_handle_entries, keyHandle); if (returnCode != TPM_SUCCESS) { printf("TPM_Process_KeyControlOwner: Error, key handle not loaded\n"); returnCode = TPM_INVALID_KEYHANDLE; } } /* If the keyUsage field of the key indicated by keyHandle does not have the value TPM_KEY_SIGNING, TPM_KEY_STORAGE, TPM_KEY_IDENTITY, TPM_KEY_BIND, or TPM_KEY_LEGACY, the TPM must return the error code TPM_INVALID_KEYUSAGE. */ if (returnCode == TPM_SUCCESS) { if ((tpm_key_handle_entry->key->keyUsage != TPM_KEY_SIGNING) && (tpm_key_handle_entry->key->keyUsage != TPM_KEY_STORAGE) && (tpm_key_handle_entry->key->keyUsage != TPM_KEY_IDENTITY) && (tpm_key_handle_entry->key->keyUsage != TPM_KEY_BIND) && (tpm_key_handle_entry->key->keyUsage != TPM_KEY_LEGACY)) { printf("TPM_Process_KeyControlOwner: Error, invalid key keyUsage %04hx\n", tpm_key_handle_entry->key->keyUsage); returnCode = TPM_INVALID_KEYUSAGE; } } /* 3. Validate that pubKey matches the key held by the TPM pointed to by keyHandle, return TPM_BAD_PARAMETER on mismatch */ /* a. This check is added so that virtualization of the keyHandle does not result in attacks, as the keyHandle is not associated with an authorization value */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Key_ComparePubkey(tpm_key_handle_entry->key, &pubKey); if (returnCode != TPM_SUCCESS) { printf("TPM_Process_KeyControlOwner: Error comparing pubKey\n"); returnCode = TPM_BAD_PARAMETER; } } /* 4. Validate that bitName is valid, return TPM_BAD_MODE on error. NOTE Valid means a legal TPM_KEY_CONTROL value */ if (returnCode == TPM_SUCCESS) { switch(bitName) { /* 5. If bitName == TPM_KEY_CONTROL_OWNER_EVICT */ case TPM_KEY_CONTROL_OWNER_EVICT: /* save the old value to determine if NVRAM update is necessary */ oldOwnerEvict = tpm_key_handle_entry->keyControl & TPM_KEY_CONTROL_OWNER_EVICT; /* a. If bitValue == TRUE */ if (bitValue) { printf("TPM_Process_KeyControlOwner: setting key owner evict\n"); if (!oldOwnerEvict) { /* if the key is not owner evict */ /* i. Verify that after this operation at least two key slots will be present within the TPM that can store any type of key both of which do NOT have the OwnerEvict bit set, on error return TPM_NOSPACE */ if (returnCode == TPM_SUCCESS) { TPM_KeyHandleEntries_IsEvictSpace(&isSpace, tpm_state->tpm_key_handle_entries, 2); /* minSpace */ if (!isSpace) { printf("TPM_Process_KeyControlOwner: Error, " "Need 2 non-evict slots\n"); returnCode = TPM_NOSPACE; } } /* ii. Verify that for this key handle, parentPCRStatus is FALSE and isVolatile is FALSE. Return TPM_BAD_PARAMETER on error. */ if (returnCode == TPM_SUCCESS) { if (tpm_key_handle_entry->parentPCRStatus || tpm_key_handle_entry->key->keyFlags & TPM_ISVOLATILE) { printf("TPM_Process_KeyControlOwner: Error, " "parentPCRStatus or Volatile\n"); returnCode = TPM_BAD_PARAMETER; } } /* check the current number of occupied owner evict key slots */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyHandleEntries_OwnerEvictGetCount (&ownerEvictCount, tpm_state->tpm_key_handle_entries); } /* check that the number of owner evict key slots will not be exceeded */ if (returnCode == TPM_SUCCESS) { if (ownerEvictCount == TPM_OWNER_EVICT_KEY_HANDLES) { printf("TPM_Process_KeyControlOwner: Error, " "no evict space, only %u evict slots\n", TPM_OWNER_EVICT_KEY_HANDLES); returnCode = TPM_NOSPACE; } } /* iii. Set ownerEvict within the internal key storage structure to TRUE. */ if (returnCode == TPM_SUCCESS) { tpm_key_handle_entry->keyControl |= TPM_KEY_CONTROL_OWNER_EVICT; } /* if the old value was FALSE, write the entry to NVRAM */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_PermanentAll_NVStore(tpm_state, TRUE, /* write NV */ 0); /* no roll back */ } } else { /* if the key is already owner evict, nothing to do */ printf("TPM_Process_KeyControlOwner: key is already owner evict\n"); } } /* b. Else if bitValue == FALSE */ else { if (oldOwnerEvict) { /* if the key is currently owner evict */ printf("TPM_Process_KeyControlOwner: setting key not owner evict\n"); /* i. Set ownerEvict within the internal key storage structure to FALSE. */ if (returnCode == TPM_SUCCESS) { tpm_key_handle_entry->keyControl &= ~TPM_KEY_CONTROL_OWNER_EVICT; } /* if the old value was TRUE, delete the entry from NVRAM */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_PermanentAll_NVStore(tpm_state, TRUE, /* write NV */ 0); /* no roll back */ } } else { /* if the key is already not owner evict, nothing to do */ printf("TPM_Process_KeyControlOwner: key is already not owner evict\n"); } } break; default: printf("TPM_Process_KeyControlOwner: Invalid bitName %08x\n", bitName); returnCode = TPM_BAD_MODE; break; } } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_KeyControlOwner: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* owner HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ TPM_Pubkey_Delete(&pubKey); /* @1 */ return rcf; } /* 27.2 Context management The 1.1 context commands were written for specific resource types. The 1.2 commands are generic for all resource types. So the Savexxx commands are replaced by TPM_SaveContext and the LoadXXX commands by TPM_LoadContext. */ /* 27.2.1 TPM_SaveKeyContext rev 87 SaveKeyContext saves a loaded key outside the TPM. After creation of the key context blob the TPM automatically releases the internal memory used by that key. The format of the key context blob is specific to a TPM. */ TPM_RESULT TPM_Process_SaveKeyContext(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_KEY_HANDLE keyHandle; /* The key which will be kept outside the TPM */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry; /* key table entry for the key handle */ TPM_BOOL isZero; /* contextNonceKey not set yet */ TPM_CONTEXT_SENSITIVE contextSensitive; TPM_STORE_BUFFER contextSensitive_sbuffer; /* serialization of contextSensitive */ TPM_CONTEXT_BLOB contextBlob; TPM_STORE_BUFFER contextBlob_sbuffer; /* serialization of contextBlob */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_SaveKeyContext: Ordinal Entry\n"); TPM_ContextSensitive_Init(&contextSensitive); /* freed @1 */ TPM_Sbuffer_Init(&contextSensitive_sbuffer); /* freed @2 */ TPM_ContextBlob_Init(&contextBlob); /* freed @3 */ TPM_Sbuffer_Init(&contextBlob_sbuffer); /* freed @4 */ /* get inputs */ /* get keyHandle */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&keyHandle, &command, ¶mSize); } /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_SaveKeyContext: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ /* 1. This command allows saving a loaded key outside the TPM. After creation of the KeyContextBlob, the TPM automatically releases the internal memory used by that key. The format of the key context blob is specific to a TPM. 2. A TPM protected capability belonging to the TPM that created a key context blob MUST be the only entity that can interpret the contents of that blob. If a cryptographic technique is used for this purpose, the level of security provided by that technique SHALL be at least as secure as a 2048 bit RSA algorithm. Any secrets (such as keys) used in such a cryptographic technique MUST be generated using the TPM's random number generator. Any symmetric key MUST be used within the power-on session during which it was created, only. 3. A key context blob SHALL enable verification of the integrity of the contents of the blob by a TPM protected capability. 4. A key context blob SHALL enable verification of the session validity of the contents of the blob by a TPM protected capability. The method SHALL ensure that all key context blobs are rendered invalid if power to the TPM is interrupted. */ /* check if the key handle is valid */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_SaveKeyContext: Handle %08x\n", keyHandle); returnCode = TPM_KeyHandleEntries_GetEntry(&tpm_key_handle_entry, tpm_state->tpm_key_handle_entries, keyHandle); } /* use the contextNonceKey to invalidate a blob at power up */ if (returnCode == TPM_SUCCESS) { /* If TPM_STCLEAR_DATA -> contextNonceKey is NULLS */ TPM_Nonce_IsZero(&isZero, tpm_state->tpm_stclear_data.contextNonceKey); if (isZero) { /* Set TPM_STCLEAR_DATA -> contextNonceKey to the next value from the TPM RNG */ returnCode = TPM_Nonce_Generate(tpm_state->tpm_stclear_data.contextNonceKey); } } /* Create internalData by putting the sensitive part of the resource pointed to by handle into a structure. The structure is a TPM manufacturer option. The TPM MUST ensure that ALL sensitive information of the resource is included in internalData. For a key, the sensitive part is the TPM_STORE_ASYMKEY */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_SaveKeyContext: Building TPM_CONTEXT_SENSITIVE\n"); returnCode = TPM_SizedBuffer_SetStructure(&(contextSensitive.internalData), tpm_key_handle_entry, (TPM_STORE_FUNCTION_T)TPM_KeyHandleEntry_Store); } if (returnCode == TPM_SUCCESS) { /* TPM_CONTEXT_SENSITIVE -> contextNonce */ TPM_Nonce_Copy(contextSensitive.contextNonce, tpm_state->tpm_stclear_data.contextNonceKey); /* TPM_CONTEXT_BLOB -> resourceType, handle, integrityDigest */ printf("TPM_Process_SaveKeyContext: Building TPM_CONTEXT_BLOB\n"); contextBlob.resourceType = TPM_RT_KEY; contextBlob.handle = keyHandle; contextBlob.contextCount = 0; } /* TPM_CONTEXT_BLOB -> sensitiveData */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_ContextSensitive_Store(&contextSensitive_sbuffer, &contextSensitive); } /* Here the clear text goes into TPM_CONTEXT_BLOB->sensitiveData */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_SetFromStore(&(contextBlob.sensitiveData), &contextSensitive_sbuffer); } /* Calculate TPM_CONTEXT_BLOB -> integrityDigest, the HMAC of TPM_CONTEXT_BLOB using TPM_PERMANENT_DATA -> tpmProof as the secret */ if (returnCode == TPM_SUCCESS) { /* This is a bit circular. It's safe since the TPM_CONTEXT_BLOB is serialized before the HMAC is generated. The result is put back into the structure. */ printf("TPM_Process_SaveKeyContext: Digesting TPM_CONTEXT_BLOB\n"); returnCode = TPM_HMAC_GenerateStructure (contextBlob.integrityDigest, /* HMAC */ tpm_state->tpm_permanent_data.tpmProof, /* HMAC key */ &contextBlob, /* structure */ (TPM_STORE_FUNCTION_T)TPM_ContextBlob_Store); /* store function */ } /* encrypt TPM_CONTEXT_SENSITIVE using as TPM_PERMANENT_DATA -> contextKey the key. Store the result in TPM_CONTEXT_BLOB -> sensitiveData */ if (returnCode == TPM_SUCCESS) { /* The cleartext went into sensitiveData for the integrityDigest calculation. Free it now, before the encrypted data is stored there. */ TPM_SizedBuffer_Delete(&(contextBlob.sensitiveData)); printf("TPM_Process_SaveKeyContext: Encrypting TPM_CONTEXT_SENSITIVE\n"); returnCode = TPM_SymmetricKeyData_EncryptSbuffer(&(contextBlob.sensitiveData), &contextSensitive_sbuffer, tpm_state->tpm_permanent_data.contextKey); } /* serialize TPM_CONTEXT_BLOB */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_ContextBlob_Store(&contextBlob_sbuffer, &contextBlob); } /* invalidate the key handle and delete the key */ if (returnCode == TPM_SUCCESS) { /* free the key resources, free the key itself, and remove entry from the key handle entries list */ TPM_KeyHandleEntry_Delete(tpm_key_handle_entry); } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_SaveKeyContext: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* return keyContextSize and keyContextBlob */ returnCode = TPM_Sbuffer_AppendAsSizedBuffer(response, &contextBlob_sbuffer); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* cleanup */ TPM_ContextSensitive_Delete(&contextSensitive); /* @1 */ TPM_Sbuffer_Delete(&contextSensitive_sbuffer); /* @2 */ TPM_ContextBlob_Delete(&contextBlob); /* @3 */ TPM_Sbuffer_Delete(&contextBlob_sbuffer); /* @4 */ return rcf; } /* 27.2.2 TPM_LoadKeyContext rev 87 LoadKeyContext loads a key context blob into the TPM previously retrieved by a SaveKeyContext call. After successful completion the handle returned by this command can be used to access the key. */ TPM_RESULT TPM_Process_LoadKeyContext(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ uint32_t keyContextSize; /* The size of the following key context blob */ TPM_CONTEXT_BLOB keyContextBlob; /* The key context blob */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ unsigned char *stream; uint32_t stream_size; unsigned char *contextSensitiveBuffer; /* decrypted sensitive data */ uint32_t contextSensitiveBuffer_length; /* actual data in contextSensitiveBuffer */ TPM_CONTEXT_SENSITIVE contextSensitive; TPM_KEY_HANDLE_ENTRY *used_key_handle_entry; TPM_KEY_HANDLE_ENTRY tpm_key_handle_entry; TPM_RESULT getRc; /* is the handle value free */ TPM_BOOL isSpace; uint32_t index; /* free space index */ TPM_BOOL key_added = FALSE; /* key has been added to handle list */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_KEY_HANDLE keyHandle; /* The handle assigned to the key after it has been successfully loaded. */ printf("TPM_Process_LoadKeyContext: Ordinal Entry\n"); TPM_ContextBlob_Init(&keyContextBlob); /* freed @1 */ contextSensitiveBuffer = NULL; /* freed @2 */ TPM_ContextSensitive_Init(&contextSensitive); /* freed @3 */ TPM_KeyHandleEntry_Init(&tpm_key_handle_entry); /* no free */ /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get keyContextSize parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&keyContextSize, &command, ¶mSize); } /* get keyContextBlob parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_ContextBlob_Load(&keyContextBlob, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_LoadKeyContext: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ /* 1. This command allows loading a key context blob into the TPM previously retrieved by a TPM_SaveKeyContext call. After successful completion the handle returned by this command can be used to access the key. 2. The contents of a key context blob SHALL be discarded unless the contents have passed an integrity test. This test SHALL (statistically) prove that the contents of the blob are the same as when the blob was created. 3. The contents of a key context blob SHALL be discarded unless the contents have passed a session validity test. This test SHALL (statistically) prove that the blob was created by this TPM during this power-on session. */ if (returnCode == TPM_SUCCESS) { if (keyContextBlob.resourceType != TPM_RT_KEY) { printf("TPM_Process_LoadKeyContext: Error, resourceType %08x should be TPM_RT_KEY\n", keyContextBlob.resourceType); returnCode =TPM_BAD_PARAMETER; } } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_LoadKeyContext: Decrypting TPM_CONTEXT_SENSITIVE stream\n"); returnCode = TPM_SymmetricKeyData_Decrypt(&contextSensitiveBuffer, /* decrypted data */ &contextSensitiveBuffer_length, /* length decrypted data */ keyContextBlob.sensitiveData.buffer, /* encrypted */ keyContextBlob.sensitiveData.size, tpm_state->tpm_permanent_data.contextKey); } /* deserialize TPM_CONTEXT_SENSITIVE */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_LoadKeyContext: Creating TPM_CONTEXT_SENSITIVE\n"); stream = contextSensitiveBuffer; stream_size = contextSensitiveBuffer_length; returnCode = TPM_ContextSensitive_Load(&contextSensitive, &stream, &stream_size); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_LoadKeyContext: Loading TPM_KEY_HANDLE_ENTRY from internalData\n"); stream = contextSensitive.internalData.buffer; stream_size = contextSensitive.internalData.size; returnCode = TPM_KeyHandleEntry_Load(&tpm_key_handle_entry, &stream, &stream_size); } /* check contextNonce */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_LoadKeyContext: Checking TPM_CONTEXT_SENSITIVE -> contextNonce\n"); returnCode = TPM_Nonce_Compare(tpm_state->tpm_stclear_data.contextNonceKey, contextSensitive.contextNonce); if (returnCode != TPM_SUCCESS) { printf("TPM_Process_LoadKeyContext: Error comparing contextNonceKey\n"); returnCode = TPM_BADCONTEXT; } } /* Move decrypted data back to keyContextBlob for integrityDigest check. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_Set(&(keyContextBlob.sensitiveData), contextSensitiveBuffer_length, contextSensitiveBuffer); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_LoadKeyContext: Checking integrityDigest\n"); /* make a copy of integrityDigest, because it needs to be 0 for the HMAC calculation */ /* NOTE Done by TPM_HMAC_CheckStructure() */ /* b. Set B1 -> integrityDigest to NULL */ /* NOTE Done by TPM_HMAC_CheckStructure() */ /* verify the integrityDigest HMAC of TPM_CONTEXT_BLOB using TPM_PERMANENT_DATA -> tpmProof as the HMAC key */ returnCode = TPM_HMAC_CheckStructure (tpm_state->tpm_permanent_data.tpmProof, /* key */ &keyContextBlob, /* structure */ keyContextBlob.integrityDigest, /* expected */ (TPM_STORE_FUNCTION_T)TPM_ContextBlob_Store, /* store function */ TPM_BADCONTEXT); /* error code */ } /* try to use the saved handle value when possible */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_LoadKeyContext: Checking if suggested handle %08x is free\n", keyContextBlob.handle); /* check if the key handle is free */ getRc = TPM_KeyHandleEntries_GetEntry(&used_key_handle_entry, tpm_state->tpm_key_handle_entries, keyContextBlob.handle); /* GetEntry TPM_SUCCESS means the handle is already used */ if (getRc == TPM_SUCCESS) { keyHandle = 0; /* no suggested handle */ } /* not success means that the handle value is not currently used */ else { keyHandle = keyContextBlob.handle; } } /* check that there is space in the key handle entries */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_LoadKeyContext: Checking for table space\n"); TPM_KeyHandleEntries_IsSpace(&isSpace, &index, tpm_state->tpm_key_handle_entries); /* if there is no space, return error */ if (!isSpace) { printf("TPM_Process_LoadKeyContext: Error, no room in table\n"); returnCode = TPM_RESOURCES; } } /* restore the entity, try to keep the handle as 'handle' */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_LoadKeyContext: Adding entry to table\n"); returnCode = TPM_KeyHandleEntries_AddEntry(&keyHandle, FALSE, /* keep handle */ tpm_state->tpm_key_handle_entries, &tpm_key_handle_entry); key_added = TRUE; } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_LoadKeyContext: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* return keyHandle */ returnCode = TPM_Sbuffer_Append32(response, keyHandle); /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* cleanup */ TPM_ContextBlob_Delete(&keyContextBlob); /* @1 */ free(contextSensitiveBuffer); /* @2 */ TPM_ContextSensitive_Delete(&contextSensitive); /* @3 */ /* if there was a failure, roll back */ if ((rcf != 0) || (returnCode != TPM_SUCCESS)) { TPM_Key_Delete(tpm_key_handle_entry.key); /* @5 */ free(tpm_key_handle_entry.key); /* @5 */ if (key_added) { /* if there was a failure and a key was stored in the handle list, free the handle. Ignore errors, since only one error code can be returned. */ TPM_KeyHandleEntries_DeleteHandle(tpm_state->tpm_key_handle_entries, keyHandle); } } return rcf; } /* 27.2.3 TPM_SaveAuthContext rev 87 SaveAuthContext saves a loaded authorization session outside the TPM. After creation of the authorization context blob, the TPM automatically releases the internal memory used by that session. The format of the authorization context blob is specific to a TPM. */ TPM_RESULT TPM_Process_SaveAuthContext(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_AUTHHANDLE authHandle; /* Authorization session which will be kept outside the TPM */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_AUTH_SESSION_DATA *tpm_auth_session_data; /* session table entry for the handle */ TPM_BOOL isZero; /* contextNonceSession not set yet */ TPM_STCLEAR_DATA *v1StClearData = NULL; uint32_t contextIndex = 0; /* free index in context list */ uint32_t space; /* free space in context list */ TPM_CONTEXT_SENSITIVE contextSensitive; TPM_STORE_BUFFER contextSensitive_sbuffer; /* serialization of contextSensitive */ TPM_CONTEXT_BLOB contextBlob; TPM_STORE_BUFFER contextBlob_sbuffer; /* serialization of contextBlob */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_SaveAuthContext: Ordinal Entry\n"); TPM_ContextSensitive_Init(&contextSensitive); /* freed @1 */ TPM_Sbuffer_Init(&contextSensitive_sbuffer); /* freed @2 */ TPM_ContextBlob_Init(&contextBlob); /* freed @3 */ TPM_Sbuffer_Init(&contextBlob_sbuffer); /* freed @4 */ /* get inputs */ /* get authHandle */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&authHandle, &command, ¶mSize); } /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; if (returnCode == TPM_SUCCESS) { printf("TPM_Process_SaveAuthContext: authHandle %08x\n", authHandle); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_SaveAuthContext: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ /* This command allows saving a loaded authorization session outside the TPM. After creation of the authContextBlob, the TPM automatically releases the internal memory used by that session. The format of the authorization context blob is specific to a TPM. A TPM protected capability belonging to the TPM that created an authorization context blob MUST be the only entity that can interpret the contents of that blob. If a cryptographic technique is used for this purpose, the level of security provided by that technique SHALL be at least as secure as a 2048 bit RSA algorithm. Any secrets (such as keys) used in such a cryptographic technique MUST be generated using the TPM's random number generator. Any symmetric key MUST be used within the power-on session during which it was created, only. An authorization context blob SHALL enable verification of the integrity of the contents of the blob by a TPM protected capability. An authorization context blob SHALL enable verification of the session validity of the contents of the blob by a TPM protected capability. The method SHALL ensure that all authorization context blobs are rendered invalid if power to the TPM is interrupted. */ /* 1. Map V1 to TPM_STANY_DATA NOTE MAY be TPM_STCLEAR_DATA */ if (returnCode == TPM_SUCCESS) { v1StClearData = &(tpm_state->tpm_stclear_data); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_SaveAuthContext: Handle %08x\n", authHandle); returnCode = TPM_AuthSessions_GetEntry(&tpm_auth_session_data, v1StClearData->authSessions, authHandle); } if (returnCode == TPM_SUCCESS) { /* If TPM_STANY_DATA -> contextNonceSession is NULLS */ TPM_Nonce_IsZero(&isZero, v1StClearData->contextNonceSession); if (isZero) { /* Set TPM_STANY_DATA -> contextNonceSession to the next value from the TPM RNG */ returnCode = TPM_Nonce_Generate(v1StClearData->contextNonceSession); } } /* Create internalData by putting the sensitive part of the resource pointed to by handle into a structure. The structure is a TPM manufacturer option. The TPM MUST ensure that ALL sensitive information of the resource is included in internalData. For a session, the entire structure can fit in the sensitive part. */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_SaveAuthContext: Building TPM_CONTEXT_SENSITIVE\n"); returnCode = TPM_SizedBuffer_SetStructure(&(contextSensitive.internalData), tpm_auth_session_data, (TPM_STORE_FUNCTION_T)TPM_AuthSessionData_Store); } if (returnCode == TPM_SUCCESS) { } if (returnCode == TPM_SUCCESS) { /* TPM_CONTEXT_SENSITIVE -> contextNonce */ TPM_Nonce_Copy(contextSensitive.contextNonce, v1StClearData->contextNonceSession); /* TPM_CONTEXT_BLOB -> resourceType, handle, integrityDigest */ printf("TPM_Process_SaveAuthContext: Building TPM_CONTEXT_BLOB\n"); contextBlob.resourceType = TPM_RT_AUTH; contextBlob.handle = authHandle; TPM_Digest_Init(contextBlob.integrityDigest); } /* TPM_CONTEXT_BLOB -> sensitiveData */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_ContextSensitive_Store(&contextSensitive_sbuffer, &contextSensitive); } /* Here the clear text goes into TPM_CONTEXT_BLOB->sensitiveData */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_SetFromStore(&(contextBlob.sensitiveData), &contextSensitive_sbuffer); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_SaveAuthContext: Processing session context count\n"); /* a. If V1 -> contextCount > 2^32-2 then */ if (v1StClearData->contextCount > 0xfffffffe) { /* i. Return with TPM_TOOMANYCONTEXTS */ printf("TPM_Process_SaveAuthContext: Error, too many contexts\n"); returnCode = TPM_TOOMANYCONTEXTS; } } /* b. Else */ if (returnCode == TPM_SUCCESS) { /* i. Increment V1 -> contextCount by 1 */ v1StClearData->contextCount++; /* ii. Validate that the TPM can still manage the new count value */ /* (1) If the distance between the oldest saved context and the contextCount is too large return TPM_CONTEXT_GAP */ /* Since contextCount is uint32_t, this is not applicable here. From email: Does the TPM have the ability to keep track of the context delta. It is possible to keep track of things with just a byte or so internally, if this is done a gap of greater than 2^16 or so might be too large, hence the context gap message */ } /* iii. Find contextIndex such that V1 -> contextList[contextIndex] equals 0. If not found exit with TPM_NOCONTEXTSPACE */ if (returnCode == TPM_SUCCESS) { TPM_ContextList_GetSpace(&space, &contextIndex, v1StClearData->contextList); if (space == 0) { printf("TPM_Process_SaveAuthContext: Error, no space in context list\n"); returnCode = TPM_NOCONTEXTSPACE; } } if (returnCode == TPM_SUCCESS) { /* iv. Set V1-> contextList[contextIndex] to V1 -> contextCount */ v1StClearData->contextList[contextIndex] = v1StClearData->contextCount; /* v. Set B1 -> contextCount to V1 -> contextCount */ contextBlob.contextCount = v1StClearData->contextCount; } /* c. The TPM MUST invalidate all information regarding the resource except for information needed for reloading */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_TerminateHandle(v1StClearData->authSessions, authHandle); } /* Calculate TPM_CONTEXT_BLOB -> integrityDigest, the HMAC of TPM_CONTEXT_BLOB using TPM_PERMANENT_DATA -> tpmProof as the secret */ if (returnCode == TPM_SUCCESS) { /* This is a bit circular. It's safe since the TPM_CONTEXT_BLOB is serialized before the HMAC is generated. The result is put back into the structure. */ printf("TPM_Process_SaveAuthContext: Digesting TPM_CONTEXT_BLOB\n"); returnCode = TPM_HMAC_GenerateStructure (contextBlob.integrityDigest, /* HMAC */ tpm_state->tpm_permanent_data.tpmProof, /* HMAC key */ &contextBlob, /* structure */ (TPM_STORE_FUNCTION_T)TPM_ContextBlob_Store); /* store function */ } /* encrypt TPM_CONTEXT_SENSITIVE using as TPM_PERMANENT_DATA -> contextKey the key. Store the result in TPM_CONTEXT_BLOB -> sensitiveData */ if (returnCode == TPM_SUCCESS) { /* The cleartext went into sensitiveData for the integrityDigest calculation. Free it now, before the encrypted data is stored there. */ TPM_SizedBuffer_Delete(&(contextBlob.sensitiveData)); printf("TPM_Process_SaveAuthContext: Encrypting TPM_CONTEXT_SENSITIVE\n"); returnCode = TPM_SymmetricKeyData_EncryptSbuffer(&(contextBlob.sensitiveData), &contextSensitive_sbuffer, tpm_state->tpm_permanent_data.contextKey); } /* serialize TPM_CONTEXT_BLOB */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_ContextBlob_Store(&contextBlob_sbuffer, &contextBlob); } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_SaveAuthContext: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* return authContextSize and authContextBlob */ returnCode = TPM_Sbuffer_AppendAsSizedBuffer(response, &contextBlob_sbuffer); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* cleanup */ TPM_ContextSensitive_Delete(&contextSensitive); /* @1 */ TPM_Sbuffer_Delete(&contextSensitive_sbuffer); /* @2 */ TPM_ContextBlob_Delete(&contextBlob); /* @3 */ TPM_Sbuffer_Delete(&contextBlob_sbuffer); /* @4 */ return rcf; } /* 27.2.4 TPM_LoadAuthContext rev 106 LoadAuthContext loads an authorization context blob into the TPM previously retrieved by a SaveAuthContext call. After successful completion, the handle returned by this command can be used to access the authorization session. */ TPM_RESULT TPM_Process_LoadAuthContext(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ uint32_t authContextSize; /* The size of the following auth context blob */ TPM_CONTEXT_BLOB authContextBlob; /* The auth context blob */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ unsigned char *stream; uint32_t stream_size; unsigned char *contextSensitiveBuffer; /* decrypted sensitive data */ uint32_t contextSensitiveBuffer_length; /* actual data in contextSensitiveBuffer */ TPM_CONTEXT_SENSITIVE contextSensitive; TPM_AUTH_SESSION_DATA tpm_auth_session_data; TPM_AUTH_SESSION_DATA *used_auth_session_data; TPM_RESULT getRc; /* is the handle value free */ TPM_BOOL isSpace; uint32_t index; /* free space index */ TPM_BOOL auth_session_added = FALSE; /* session key has been added to handle list */ TPM_STCLEAR_DATA *v1StClearData = NULL; uint32_t contextIndex; TPM_DIGEST entityDigest; /* digest of the entity used to set up the OSAP or DSAP session */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_KEY_HANDLE authHandle; /* The handle assigned to the authorization session after it has been successfully loaded. */ printf("TPM_Process_LoadAuthContext: Ordinal Entry\n"); TPM_ContextBlob_Init(&authContextBlob); /* freed @1 */ contextSensitiveBuffer = NULL; /* freed @2 */ TPM_ContextSensitive_Init(&contextSensitive); /* freed @3 */ TPM_AuthSessionData_Init(&tpm_auth_session_data); /* freed @4 */ /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get authContextSize parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&authContextSize, &command, ¶mSize); } /* get authContextBlob parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_ContextBlob_Load(&authContextBlob, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_LoadAuthContext: handle %08x\n", authContextBlob.handle); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_LoadAuthContext: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ /* This command allows loading an authorization context blob into the TPM previously retrieved by a TPM_SaveAuthContext call. After successful completion, the handle returned by this command can be used to access the authorization session. The contents of an authorization context blob SHALL be discarded unless the contents have passed an integrity test. This test SHALL (statistically) prove that the contents of the blob are the same as when the blob was created. The contents of an authorization context blob SHALL be discarded unless the contents have passed a session validity test. This test SHALL (statistically) prove that the blob was created by this TPM during this power-on session. For an OSAP authorization context blob referring to a key, verify that the key linked to this session is resident in the TPM. */ if (returnCode == TPM_SUCCESS) { /* 2. Map V1 to TPM_STANY_DATA NOTE MAY be TPM_STCLEAR_DATA */ v1StClearData = &(tpm_state->tpm_stclear_data); if (authContextBlob.resourceType != TPM_RT_AUTH) { printf("TPM_Process_LoadAuthContext: Error, resourceType %08x should be TPM_RT_AUTH\n", authContextBlob.resourceType); returnCode = TPM_BAD_PARAMETER; } } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_LoadAuthContext: Decrypting TPM_CONTEXT_SENSITIVE stream\n"); returnCode = TPM_SymmetricKeyData_Decrypt(&contextSensitiveBuffer, /* decrypted data */ &contextSensitiveBuffer_length, /* length decrypted data */ authContextBlob.sensitiveData.buffer, /* encrypted */ authContextBlob.sensitiveData.size, tpm_state->tpm_permanent_data.contextKey); } /* deserialize TPM_CONTEXT_SENSITIVE */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_LoadAuthContext: Creating TPM_CONTEXT_SENSITIVE\n"); stream = contextSensitiveBuffer; stream_size = contextSensitiveBuffer_length; returnCode = TPM_ContextSensitive_Load(&contextSensitive, &stream, &stream_size); } /* Parse the TPM_CONTEXT_SENSITIVE -> internalData to TPM_AUTH_SESSION_DATA */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_LoadAuthContext: Loading TPM_AUTH_SESSION_DATA from internalData\n"); stream = contextSensitive.internalData.buffer; stream_size = contextSensitive.internalData.size; returnCode = TPM_AuthSessionData_Load(&tpm_auth_session_data, &stream, &stream_size); } /* check contextNonce */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_LoadAuthContext: protocolID %04x entityTypeByte %02x\n", tpm_auth_session_data.protocolID, tpm_auth_session_data.entityTypeByte); printf("TPM_Process_LoadAuthContext: Checking TPM_CONTEXT_SENSITIVE -> contextNonce\n"); returnCode = TPM_Nonce_Compare(v1StClearData->contextNonceSession, contextSensitive.contextNonce); if (returnCode != TPM_SUCCESS) { printf("TPM_Process_LoadAuthContext: Error comparing contextNonceSession\n"); returnCode = TPM_BADCONTEXT; } } if (returnCode == TPM_SUCCESS) { if ((tpm_auth_session_data.protocolID == TPM_PID_OSAP) || (tpm_auth_session_data.protocolID == TPM_PID_DSAP)) { /* check that the entity is loaded, and that the entity's digest equals that of the OSAP or DSAP session */ switch (tpm_auth_session_data.entityTypeByte) { case TPM_ET_OWNER: printf("TPM_Process_LoadAuthContext: Owner OSAP/DSAP session\n"); /* check for owner */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_LoadContext_CheckOwnerLoaded(tpm_state, entityDigest); } /* compare entity digest */ if (returnCode == TPM_SUCCESS) { returnCode= TPM_Digest_Compare(entityDigest, tpm_auth_session_data.entityDigest); if (returnCode != TPM_SUCCESS) { printf("TPM_Process_LoadAuthContext: " "Error, OSAP or DSAP entityDigest mismatch\n"); returnCode = TPM_RESOURCEMISSING; } } break; case TPM_ET_SRK: printf("TPM_Process_LoadAuthContext: SRK OSAP/DSAP session\n"); /* check for SRK */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_LoadContext_CheckSrkLoaded(tpm_state, entityDigest); } /* compare entity digest */ if (returnCode == TPM_SUCCESS) { returnCode= TPM_Digest_Compare(entityDigest, tpm_auth_session_data.entityDigest); if (returnCode != TPM_SUCCESS) { printf("TPM_Process_LoadAuthContext: " "Error, OSAP or DSAP entityDigest mismatch\n"); returnCode = TPM_RESOURCEMISSING; } } break; case TPM_ET_KEYHANDLE: printf("TPM_Process_LoadAuthContext: Key OSAP/DSAP session\n"); /* for keys */ returnCode = TPM_LoadContext_CheckKeyLoadedByDigest(tpm_state, tpm_auth_session_data.entityDigest); break; case TPM_ET_COUNTER: printf("TPM_Process_LoadAuthContext: Counter OSAP/DSAP session\n"); #if 0 /* TPM_LoadAuthContext is a deprecated 1.1 command, where there was no counter */ returnCode = TPM_LoadContext_CheckCounterLoaded(tpm_state, entityHandle, entityDigest); #endif break; case TPM_ET_NV: printf("TPM_Process_LoadAuthContext: NV OSAP/DSAP session\n"); #if 0 /* TPM_LoadAuthContext is a deprecated 1.1 command, where there was no NV space */ returnCode = TPM_LoadContext_CheckNvLoaded(tpm_state, entityHandle, entityDigest); #endif break; default: printf("TPM_Process_LoadAuthContext: Error, invalid session entityType %02x\n", tpm_auth_session_data.entityTypeByte); returnCode = TPM_WRONG_ENTITYTYPE; break; } } } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_LoadAuthContext: Checking integrityDigest\n"); /* b. Set B1 -> integrityDigest to NULL */ /* NOTE Done by TPM_HMAC_CheckStructure() */ /* c. Copy M1 to B1 -> sensitiveData (integrityDigest HMAC uses cleartext) */ returnCode = TPM_SizedBuffer_Set(&(authContextBlob.sensitiveData), contextSensitiveBuffer_length, contextSensitiveBuffer); /* verify the integrityDigest HMAC of TPM_CONTEXT_BLOB using TPM_PERMANENT_DATA -> tpmProof as the HMAC key */ returnCode = TPM_HMAC_CheckStructure (tpm_state->tpm_permanent_data.tpmProof, /* key */ &authContextBlob, /* structure */ authContextBlob.integrityDigest, /* expected */ (TPM_STORE_FUNCTION_T)TPM_ContextBlob_Store, /* store function */ TPM_BADCONTEXT); /* error code */ } /* try to use the saved handle value when possible */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_LoadAuthContext: Checking if suggested handle %08x is free\n", authContextBlob.handle); /* check if the auth handle is free */ getRc = TPM_AuthSessions_GetEntry(&used_auth_session_data, tpm_state->tpm_stclear_data.authSessions, authContextBlob.handle); /* GetEntry TPM_SUCCESS means the handle is already used */ if (getRc == TPM_SUCCESS) { authHandle = 0; /* no suggested handle */ } /* not success means that the handle value is not currently used */ else { authHandle = authContextBlob.handle; } } /* check that there is space in the authorization handle entries */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_LoadAuthContext: Checking for table space\n"); TPM_AuthSessions_IsSpace(&isSpace, &index, tpm_state->tpm_stclear_data.authSessions); /* if there is no space, return error */ if (!isSpace) { printf("TPM_Process_LoadAuthContext: Error, no room in table\n"); TPM_AuthSessions_Trace(tpm_state->tpm_stclear_data.authSessions); returnCode = TPM_RESOURCES; } } /* a. Find contextIndex such that V1 -> contextList[contextIndex] equals B1 -> TPM_CONTEXT_BLOB -> contextCount */ /* b. If not found then return TPM_BADCONTEXT */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_LoadAuthContext: Checking contextCount\n"); returnCode = TPM_ContextList_GetEntry(&contextIndex, v1StClearData->contextList, authContextBlob.contextCount); } /* c. Set V1 -> contextList[contextIndex] to 0 */ if (returnCode == TPM_SUCCESS) { v1StClearData->contextList[contextIndex] = 0; } /* restore the entity, try to keep the handle as 'handle' */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_AddEntry(&authHandle, /* input/output */ FALSE, /* keepHandle */ v1StClearData->authSessions, &tpm_auth_session_data); auth_session_added = TRUE; } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_LoadAuthContext: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* return authHandle */ returnCode = TPM_Sbuffer_Append32(response, authHandle); /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* cleanup */ TPM_ContextBlob_Delete(&authContextBlob); /* @1 */ free(contextSensitiveBuffer); /* @2 */ TPM_ContextSensitive_Delete(&contextSensitive); /* @3 */ TPM_AuthSessionData_Delete(&tpm_auth_session_data); /* @4 */ /* if there was a failure, roll back */ if ((rcf != 0) || (returnCode != TPM_SUCCESS)) { if (auth_session_added) { TPM_AuthSessionData_Delete(&tpm_auth_session_data); } } return rcf; } libtpms-0.9.3/src/tpm12/tpm_session.h000066400000000000000000000346071421143571500174600ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM Sessions Handler */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_session.h 4526 2011-03-24 21:14:42Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_SESSION_H #define TPM_SESSION_H #include "tpm_global.h" #include "tpm_store.h" #include "tpm_types.h" /* TPM_AUTH_SESSION_DATA (the entire array) */ void TPM_AuthSessions_Init(TPM_AUTH_SESSION_DATA *authSessions); TPM_RESULT TPM_AuthSessions_Load(TPM_AUTH_SESSION_DATA *authSessions, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_AuthSessions_Store(TPM_STORE_BUFFER *sbuffer, TPM_AUTH_SESSION_DATA *authSessions); void TPM_AuthSessions_Delete(TPM_AUTH_SESSION_DATA *authSessions); void TPM_AuthSessions_IsSpace(TPM_BOOL *isSpace, uint32_t *index, TPM_AUTH_SESSION_DATA *authSessions); void TPM_AuthSessions_Trace(TPM_AUTH_SESSION_DATA *authSessions); void TPM_AuthSessions_GetSpace(uint32_t *space, TPM_AUTH_SESSION_DATA *authSessions); TPM_RESULT TPM_AuthSessions_StoreHandles(TPM_STORE_BUFFER *sbuffer, TPM_AUTH_SESSION_DATA *authSessions); TPM_RESULT TPM_AuthSessions_GetNewHandle(TPM_AUTH_SESSION_DATA **tpm_auth_session_data, TPM_AUTHHANDLE *authHandle, TPM_AUTH_SESSION_DATA *authSessions); TPM_RESULT TPM_AuthSessions_GetEntry(TPM_AUTH_SESSION_DATA **tpm_auth_session_data, TPM_AUTH_SESSION_DATA *authSessions, TPM_AUTHHANDLE authHandle); TPM_RESULT TPM_AuthSessions_AddEntry(TPM_HANDLE *tpm_handle, TPM_BOOL keepHandle, TPM_AUTH_SESSION_DATA *authSessions, TPM_AUTH_SESSION_DATA *tpm_auth_session_data); TPM_RESULT TPM_AuthSessions_GetData(TPM_AUTH_SESSION_DATA **tpm_auth_session_data, TPM_SECRET **hmacKey, tpm_state_t *tpm_state, TPM_AUTHHANDLE authHandle, TPM_PROTOCOL_ID protocolID, TPM_ENT_TYPE entityType, TPM_COMMAND_CODE ordinal, TPM_KEY *tpmKey, TPM_SECRET *entityAuth, TPM_DIGEST entityDigest); TPM_RESULT TPM_AuthSessions_TerminateHandle(TPM_AUTH_SESSION_DATA *authSessions, TPM_AUTHHANDLE authHandle); void TPM_AuthSessions_TerminateEntity(TPM_BOOL *continueAuthSession, TPM_AUTHHANDLE authHandle, TPM_AUTH_SESSION_DATA *authSessions, TPM_ENT_TYPE entityType, TPM_DIGEST *entityDigest); void TPM_AuthSessions_TerminatexSAP(TPM_BOOL *continueAuthSession, TPM_AUTHHANDLE authHandle, TPM_AUTH_SESSION_DATA *authSessions); /* TPM_AUTH_SESSION_DATA (one element of the array) */ void TPM_AuthSessionData_Init(TPM_AUTH_SESSION_DATA *tpm_auth_session_data); TPM_RESULT TPM_AuthSessionData_Load(TPM_AUTH_SESSION_DATA *tpm_auth_session_data, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_AuthSessionData_Store(TPM_STORE_BUFFER *sbuffer, const TPM_AUTH_SESSION_DATA *tpm_auth_session_data); void TPM_AuthSessionData_Delete(TPM_AUTH_SESSION_DATA *tpm_auth_session_data); void TPM_AuthSessionData_Copy(TPM_AUTH_SESSION_DATA *dest_auth_session_data, TPM_HANDLE tpm_handle, TPM_AUTH_SESSION_DATA *src_auth_session_data); TPM_RESULT TPM_AuthSessionData_GetDelegatePublic(TPM_DELEGATE_PUBLIC **delegatePublic, TPM_AUTH_SESSION_DATA *auth_session_data); TPM_RESULT TPM_AuthSessionData_CheckEncScheme(TPM_ADIP_ENC_SCHEME adipEncScheme, TPM_BOOL FIPS); TPM_RESULT TPM_AuthSessionData_Decrypt(TPM_DIGEST a1Even, TPM_DIGEST a1Odd, TPM_ENCAUTH encAuthEven, TPM_AUTH_SESSION_DATA *tpm_auth_session_data, TPM_NONCE nonceOdd, TPM_ENCAUTH encAuthOdd, TPM_BOOL odd); /* Context List */ void TPM_ContextList_Init(uint32_t *contextList); TPM_RESULT TPM_ContextList_Load(uint32_t *contextList, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_ContextList_Store(TPM_STORE_BUFFER *sbuffer, const uint32_t *contextList); TPM_RESULT TPM_ContextList_StoreHandles(TPM_STORE_BUFFER *sbuffer, const uint32_t *contextList); void TPM_ContextList_GetSpace(uint32_t *space, uint32_t *entry, const uint32_t *contextList); TPM_RESULT TPM_ContextList_GetEntry(uint32_t *entry, const uint32_t *contextList, uint32_t value); /* TPM_CONTEXT_BLOB */ void TPM_ContextBlob_Init(TPM_CONTEXT_BLOB *tpm_context_blob); TPM_RESULT TPM_ContextBlob_Load(TPM_CONTEXT_BLOB *tpm_context_blob, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_ContextBlob_Store(TPM_STORE_BUFFER *sbuffer, const TPM_CONTEXT_BLOB *tpm_context_blob); void TPM_ContextBlob_Delete(TPM_CONTEXT_BLOB *tpm_context_blob); /* TPM_CONTEXT_SENSITIVE */ void TPM_ContextSensitive_Init(TPM_CONTEXT_SENSITIVE *tpm_context_sensitive); TPM_RESULT TPM_ContextSensitive_Load(TPM_CONTEXT_SENSITIVE *tpm_context_sensitive, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_ContextSensitive_Store(TPM_STORE_BUFFER *sbuffer, const TPM_CONTEXT_SENSITIVE *tpm_context_sensitive); void TPM_ContextSensitive_Delete(TPM_CONTEXT_SENSITIVE *tpm_context_sensitive); /* Processing Functions */ TPM_RESULT TPM_Process_OIAP(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_OSAP(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_DSAP(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_SetOwnerPointer(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_TerminateHandle(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_FlushSpecific(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_SaveContext(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_LoadContext(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_KeyControlOwner(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_SaveKeyContext(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_LoadKeyContext(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_SaveAuthContext(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_LoadAuthContext(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); #endif libtpms-0.9.3/src/tpm12/tpm_sizedbuffer.c000066400000000000000000000307221421143571500202720ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM Sized Buffer Handler */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_sizedbuffer.c 4071 2010-04-29 19:26:45Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include #include #include #include "tpm_cryptoh.h" #include "tpm_debug.h" #include "tpm_error.h" #include "tpm_memory.h" #include "tpm_process.h" #include "tpm_types.h" #include "tpm_sizedbuffer.h" void TPM_SizedBuffer_Init(TPM_SIZED_BUFFER *tpm_sized_buffer) { tpm_sized_buffer->size = 0; tpm_sized_buffer->buffer = NULL; return; } /* TPM_SizedBuffer_Load() allocates and sets a sized buffer from a stream. A sized buffer structure has two members: - 4 bytes size - pointer to array of 'size' This structure is typically a cast from a subset of a larger TPM structure. Two members - a 4 bytes size followed by a 4 bytes pointer to the data is a common TPM structure idiom. This function correctly handles a 'size' of 0. Call TPM_SizedBuffer_Init() before first use Call TPM_SizedBuffer_Delete() after use */ TPM_RESULT TPM_SizedBuffer_Load(TPM_SIZED_BUFFER *tpm_sized_buffer, /* result */ unsigned char **stream, /* pointer to next parameter */ uint32_t *stream_size) /* stream size left */ { TPM_RESULT rc = 0; printf(" TPM_SizedBuffer_Load:\n"); if (rc == 0) { rc = TPM_Load32(&(tpm_sized_buffer->size), stream, stream_size); } /* if the size is not 0 */ if ((rc == 0) && (tpm_sized_buffer->size > 0)) { /* allocate memory for the buffer */ if (rc == 0) { rc = TPM_Malloc(&(tpm_sized_buffer->buffer), tpm_sized_buffer->size); } /* copy the buffer */ if (rc == 0) { rc = TPM_Loadn(tpm_sized_buffer->buffer, tpm_sized_buffer->size, stream, stream_size); } } return rc; } /* TPM_SizedBuffer_Set() reallocs a sized buffer and copies 'size' bytes of 'data' into it. If the sized buffer already has data, the buffer is realloc'ed. This function correctly handles a 'size' of 0. Call TPM_SizedBuffer_Delete() to free the buffer */ TPM_RESULT TPM_SizedBuffer_Set(TPM_SIZED_BUFFER *tpm_sized_buffer, uint32_t size, const unsigned char *data) { TPM_RESULT rc = 0; printf(" TPM_SizedBuffer_Set:\n"); /* allocate memory for the buffer, and copy the buffer */ if (rc == 0) { if (size > 0) { rc = TPM_Realloc(&(tpm_sized_buffer->buffer), size); if (rc == 0) { tpm_sized_buffer->size = size; memcpy(tpm_sized_buffer->buffer, data, size); } } /* if size is zero */ else { TPM_SizedBuffer_Delete(tpm_sized_buffer); } } return rc; } /* TPM_SizedBuffer_SetFromStore() reallocs a sized buffer and copies 'sbuffer" data into it. This function correctly handles an 'sbuffer' of 0 length. */ TPM_RESULT TPM_SizedBuffer_SetFromStore(TPM_SIZED_BUFFER *tpm_sized_buffer, TPM_STORE_BUFFER *sbuffer) { TPM_RESULT rc = 0; const unsigned char *data; uint32_t size; if (rc == 0) { /* get the stream and its size from the TPM_STORE_BUFFER */ TPM_Sbuffer_Get(sbuffer, &data, &size); rc = TPM_SizedBuffer_Set(tpm_sized_buffer, size, data); } return rc; } /* TPM_SizedBuffer_SetStructure() serializes the structure 'tpmStructure' using the function 'storeFunction', storing the result in a TPM_SIZED_BUFFER. */ TPM_RESULT TPM_SizedBuffer_SetStructure(TPM_SIZED_BUFFER *tpm_sized_buffer, void *tpmStructure, TPM_STORE_FUNCTION_T storeFunction) { TPM_RESULT rc = 0; TPM_STORE_BUFFER sbuffer; /* serialized tpmStructure */ printf(" TPM_SizedBuffer_SetStructure:\n"); TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ /* serialize the structure */ if (rc == 0) { if (tpmStructure != NULL) { rc = storeFunction(&sbuffer, tpmStructure); } } /* copy to TPM_SIZED_BUFFER */ if (rc == 0) { rc = TPM_SizedBuffer_SetFromStore(tpm_sized_buffer, &sbuffer); } TPM_Sbuffer_Delete(&sbuffer); /* @1 */ return rc; } TPM_RESULT TPM_SizedBuffer_Copy(TPM_SIZED_BUFFER *tpm_sized_buffer_dest, TPM_SIZED_BUFFER *tpm_sized_buffer_src) { TPM_RESULT rc = 0; rc = TPM_SizedBuffer_Set(tpm_sized_buffer_dest, tpm_sized_buffer_src->size, tpm_sized_buffer_src->buffer); return rc; } /* TPM_SizedBuffer_Store() serializes a TPM_SIZED_BUFFER into a TPM_STORE_BUFFER */ TPM_RESULT TPM_SizedBuffer_Store(TPM_STORE_BUFFER *sbuffer, const TPM_SIZED_BUFFER *tpm_sized_buffer) { TPM_RESULT rc = 0; printf(" TPM_SizedBuffer_Store:\n"); /* append the size */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_sized_buffer->size); } /* append the data */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, tpm_sized_buffer->buffer, tpm_sized_buffer->size); } return rc; } void TPM_SizedBuffer_Delete(TPM_SIZED_BUFFER *tpm_sized_buffer) { printf(" TPM_SizedBuffer_Delete:\n"); if (tpm_sized_buffer != NULL) { free(tpm_sized_buffer->buffer); TPM_SizedBuffer_Init(tpm_sized_buffer); } return; } /* TPM_SizedBuffer_Allocate() allocates 'size' bytes of memory and sets the TPM_SIZED_BUFFER members. The buffer data is not initialized. */ TPM_RESULT TPM_SizedBuffer_Allocate(TPM_SIZED_BUFFER *tpm_sized_buffer, uint32_t size) { TPM_RESULT rc = 0; printf(" TPM_SizedBuffer_Allocate: Size %u\n", size); tpm_sized_buffer->size = size; rc = TPM_Malloc(&(tpm_sized_buffer->buffer), size); return rc; } /* TPM_SizedBuffer_GetBool() converts from a TPM_SIZED_BUFFER to a TPM_BOOL. If the size does not indicate a TPM_BOOL, an error is returned. */ TPM_RESULT TPM_SizedBuffer_GetBool(TPM_BOOL *tpm_bool, TPM_SIZED_BUFFER *tpm_sized_buffer) { TPM_RESULT rc = 0; if (tpm_sized_buffer->size == sizeof(TPM_BOOL)) { *tpm_bool = *(TPM_BOOL *)tpm_sized_buffer->buffer; printf(" TPM_SizedBuffer_GetBool: bool %02x\n", *tpm_bool); } else { printf("TPM_SizedBuffer_GetBool: Error, buffer size %08x is not a BOOL\n", tpm_sized_buffer->size); rc = TPM_BAD_PARAMETER; } return rc; } /* TPM_SizedBuffer_GetUint32() converts from a TPM_SIZED_BUFFER to a uint32_t. If the size does not indicate a uint32_t, an error is returned. */ TPM_RESULT TPM_SizedBuffer_GetUint32(uint32_t *uint32, TPM_SIZED_BUFFER *tpm_sized_buffer) { TPM_RESULT rc = 0; unsigned char *stream; uint32_t stream_size; if (rc == 0) { if (tpm_sized_buffer->size != sizeof(uint32_t)) { printf("TPM_GetUint32: Error, buffer size %08x is not a uint32_t\n", tpm_sized_buffer->size); rc = TPM_BAD_PARAMETER; } } if (rc == 0) { stream = tpm_sized_buffer->buffer; stream_size = tpm_sized_buffer->size; rc = TPM_Load32(uint32, &stream, &stream_size); } return rc; } /* TPM_SizedBuffer_Append32() appends a uint32_t to a TPM_SIZED_BUFFER */ TPM_RESULT TPM_SizedBuffer_Append32(TPM_SIZED_BUFFER *tpm_sized_buffer, uint32_t uint32) { TPM_RESULT rc = 0; printf(" TPM_SizedBuffer_Append32: Current size %u uint32 %08x\n", tpm_sized_buffer->size, uint32); /* allocate space for another uint32_t */ if (rc == 0) { rc = TPM_Realloc(&(tpm_sized_buffer->buffer), tpm_sized_buffer->size + sizeof(uint32_t)); } if (rc == 0) { uint32_t ndata = htonl(uint32); /* convert to network byte order */ memcpy(tpm_sized_buffer->buffer + tpm_sized_buffer->size, /* append at end */ (char *)&ndata, /* cast safe after conversion */ sizeof(uint32_t)); tpm_sized_buffer->size += sizeof(uint32_t); } return rc; } /* TPM_SizedBuffer_Remove32() removes the uint32_t with value from a TPM_SIZED_BUFFER */ TPM_RESULT TPM_SizedBuffer_Remove32(TPM_SIZED_BUFFER *tpm_sized_buffer, uint32_t uint32) { TPM_RESULT rc = 0; unsigned char *stream; uint32_t stream_size; uint32_t bufferValue; TPM_BOOL found = FALSE; unsigned char *from; unsigned char *to; printf(" TPM_SizedBuffer_Remove32: Current size %u uint32 %08x\n", tpm_sized_buffer->size, uint32); stream = tpm_sized_buffer->buffer; stream_size = tpm_sized_buffer->size; /* search for the uint32 */ while ((rc == 0) && (stream_size != 0) && !found) { /* get the next value */ if (rc == 0) { rc = TPM_Load32(&bufferValue, &stream, &stream_size); } /* if the value is the one to be removed */ if (rc == 0) { if (bufferValue == uint32) { found = TRUE; /* shift the reset of the buffer down by a uint32_t */ for (from = stream, to = (stream - sizeof(uint32_t)) ; /* go to the end of the buffer */ from < (tpm_sized_buffer->buffer + tpm_sized_buffer->size) ; from++, to++) { *to = *from; } /* adjust the size */ tpm_sized_buffer->size -= sizeof(uint32_t); } } } if (!found) { printf("TPM_SizedBuffer_Remove32: Error, value not found\n"); rc = TPM_BAD_HANDLE; } return rc; } /* TPM_SizedBuffer_Zero() overwrites all data in the buffer with zeros */ void TPM_SizedBuffer_Zero(TPM_SIZED_BUFFER *tpm_sized_buffer) { printf(" TPM_SizedBuffer_Zero:\n"); if (tpm_sized_buffer->buffer != NULL) { memset(tpm_sized_buffer->buffer, 0, tpm_sized_buffer->size); } return; } libtpms-0.9.3/src/tpm12/tpm_sizedbuffer.h000066400000000000000000000104011421143571500202670ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM Sized Buffer Handler */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_sizedbuffer.h 4071 2010-04-29 19:26:45Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_SIZEDBUFFER_H #define TPM_SIZEDBUFFER_H #include "tpm_digest.h" #include "tpm_store.h" void TPM_SizedBuffer_Init(TPM_SIZED_BUFFER *tpm_sized_buffer); TPM_RESULT TPM_SizedBuffer_Load(TPM_SIZED_BUFFER *tpm_sized_buffer, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_SizedBuffer_Store(TPM_STORE_BUFFER *sbuffer, const TPM_SIZED_BUFFER *tpm_sized_buffer); TPM_RESULT TPM_SizedBuffer_Set(TPM_SIZED_BUFFER *tpm_sized_buffer, uint32_t size, const unsigned char *data); TPM_RESULT TPM_SizedBuffer_SetFromStore(TPM_SIZED_BUFFER *tpm_sized_buffer, TPM_STORE_BUFFER *sbuffer); TPM_RESULT TPM_SizedBuffer_SetStructure(TPM_SIZED_BUFFER *tpm_sized_buffer, void *tpmStructure, TPM_STORE_FUNCTION_T storeFunction); TPM_RESULT TPM_SizedBuffer_Copy(TPM_SIZED_BUFFER *tpm_sized_buffer_dest, TPM_SIZED_BUFFER *tpm_sized_buffer_src); void TPM_SizedBuffer_Delete(TPM_SIZED_BUFFER *tpm_sized_buffer); TPM_RESULT TPM_SizedBuffer_Allocate(TPM_SIZED_BUFFER *tpm_sized_buffer, uint32_t size); TPM_RESULT TPM_SizedBuffer_GetBool(TPM_BOOL *tpm_bool, TPM_SIZED_BUFFER *tpm_sized_buffer); TPM_RESULT TPM_SizedBuffer_GetUint32(uint32_t *uint32, TPM_SIZED_BUFFER *tpm_sized_buffer); TPM_RESULT TPM_SizedBuffer_Append32(TPM_SIZED_BUFFER *tpm_sized_buffer, uint32_t uint32); TPM_RESULT TPM_SizedBuffer_Remove32(TPM_SIZED_BUFFER *tpm_sized_buffer, uint32_t uint32); void TPM_SizedBuffer_Zero(TPM_SIZED_BUFFER *tpm_sized_buffer); #endif libtpms-0.9.3/src/tpm12/tpm_startup.c000066400000000000000000001451521421143571500174700ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM Admin Startup and State */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_startup.c 4533 2011-03-30 19:50:41Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include #include #include "tpm_debug.h" #include "tpm_error.h" #include "tpm_constants.h" #include "tpm_commands.h" #include "tpm_crypto.h" #include "tpm_cryptoh.h" #include "tpm_debug.h" #include "tpm_error.h" #include "tpm_digest.h" #include "tpm_init.h" #include "tpm_key.h" #include "tpm_nonce.h" #include "tpm_nvfile.h" #include "tpm_nvfilename.h" #include "tpm_nvram.h" #include "tpm_pcr.h" #include "tpm_process.h" #include "tpm_session.h" #include "tpm_startup.h" /* Save State */ /* TPM_SaveState_Load() restores the TPM state from a stream created by TPM_SaveState_Store() The two functions must be kept in sync. */ TPM_RESULT TPM_SaveState_Load(tpm_state_t *tpm_state, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; unsigned char *stream_start = *stream; /* copy for integrity check */ uint32_t stream_size_start = *stream_size; printf(" TPM_SaveState_Load:\n"); if (rc == 0) { printf(" TPM_SaveState_Load: Loading PCR's\n"); } /* 1. Store PCR contents except for */ /* a. If the PCR attribute pcrReset is TRUE */ /* b. Any platform identified debug PCR */ /* NOTE Done by TPM_StclearData_Load() */ /* 2. The auditDigest MUST be handled according to the audit requirements as reported by TPM_GetCapability */ /* NOTE Moved to TPM_STCLEAR_DATA */ /* 3. All values in TPM_STCLEAR_DATA MUST be preserved */ if (rc == 0) { rc = TPM_StclearData_Load(&(tpm_state->tpm_stclear_data), stream, stream_size, tpm_state->tpm_permanent_data.pcrAttrib); } /* 4. All values in TPM_STCLEAR_FLAGS MUST be preserved */ if (rc == 0) { rc = TPM_StclearFlags_Load(&(tpm_state->tpm_stclear_flags), stream, stream_size); } /* 5. The contents of any key that is currently loaded SHOULD be preserved if the key's parentPCRStatus indicator is TRUE. */ /* 6. The contents of any key that has TPM_KEY_CONTROL_OWNER_EVICT set MUST be preserved */ /* 7. The contents of any key that is currently loaded MAY be preserved as reported by TPM_GetCapability */ if (rc == 0) { rc = TPM_KeyHandleEntries_Load(tpm_state, stream, stream_size); } /* 8. The contents of sessions (authorization, transport etc.) MAY be preserved as reported by TPM_GetCapability */ /* NOTE Done at TPM_StclearData_Load() */ /* load the NV volatile flags */ if (rc == 0) { rc = TPM_NVIndexEntries_LoadVolatile(&(tpm_state->tpm_nv_index_entries), stream, stream_size); } /* sanity check the stream size */ if (rc == 0) { if (*stream_size != TPM_DIGEST_SIZE) { printf("TPM_SaveState_Load: Error (fatal) stream size %u not %u\n", *stream_size, TPM_DIGEST_SIZE); rc = TPM_FAIL; } } /* check the integrity digest */ if (rc == 0) { printf(" TPM_SaveState_Load: Checking integrity digest\n"); rc = TPM_SHA1_Check(*stream, /* currently points to integrity digest */ stream_size_start - TPM_DIGEST_SIZE, stream_start, 0, NULL); } /* remove the integrity digest from the stream */ if (rc == 0) { *stream_size -= TPM_DIGEST_SIZE; } return rc; } /* TPM_SaveState_Store() stores the TPM state to a stream that can be restored through TPM_SaveState_Load(). The two functions must be kept in sync. */ TPM_RESULT TPM_SaveState_Store(TPM_STORE_BUFFER *sbuffer, tpm_state_t *tpm_state) { TPM_RESULT rc = 0; const unsigned char *buffer; /* elements of sbuffer */ uint32_t length; TPM_DIGEST tpm_digest; printf(" TPM_SaveState_Store:\n"); if (rc == 0) { printf(" TPM_SaveState_Store: Storing PCR's\n"); } /* NOTE: Actions from TPM_SaveState */ /* 1. Store TPM_STCLEAR_DATA -> PCR contents except for */ /* a. If the PCR attribute pcrReset is TRUE */ /* b. Any platform identified debug PCR */ /* NOTE Done by TPM_StclearData_Store() */ /* 2. The auditDigest MUST be handled according to the audit requirements as reported by TPM_GetCapability */ /* NOTE Moved to TPM_STCLEAR_DATA */ /* a. If the ordinalAuditStatus is TRUE for the TPM_SaveState ordinal and the auditDigest is being stored in the saved state, the saved auditDigest MUST include the TPM_SaveState input parameters and MUST NOT include the output parameters. */ /* NOTE Done naturally because this function is called between input and output audit. */ /* 3. All values in TPM_STCLEAR_DATA MUST be preserved */ if (rc == 0) { rc = TPM_StclearData_Store(sbuffer, &(tpm_state->tpm_stclear_data), tpm_state->tpm_permanent_data.pcrAttrib); } /* 4. All values in TPM_STCLEAR_FLAGS MUST be preserved */ if (rc == 0) { rc = TPM_StclearFlags_Store(sbuffer, &(tpm_state->tpm_stclear_flags)); } /* 5. The contents of any key that is currently loaded SHOULD be preserved if the key's parentPCRStatus indicator is TRUE. */ /* 6. The contents of any key that has TPM_KEY_CONTROL_OWNER_EVICT set MUST be preserved */ /* 7. The contents of any key that is currently loaded MAY be preserved as reported by TPM_GetCapability */ /* NOTE This implementation saves all keys. Owner evict keys are not saved in the state blob, as they are already saved in the file system */ if (rc == 0) { rc = TPM_KeyHandleEntries_Store(sbuffer, tpm_state); } /* 8. The contents of sessions (authorization, transport etc.) MAY be preserved as reported by TPM_GetCapability */ /* NOTE Done by TPM_StclearData_Store() */ /* store the NV volatile flags */ if (rc == 0) { rc = TPM_NVIndexEntries_StoreVolatile(sbuffer, &(tpm_state->tpm_nv_index_entries)); } if (rc == 0) { /* get the current serialized buffer and its length */ TPM_Sbuffer_Get(sbuffer, &buffer, &length); /* generate the integrity digest */ rc = TPM_SHA1(tpm_digest, length, buffer, 0, NULL); } /* append the integrity digest to the stream */ if (rc == 0) { printf(" TPM_SaveState_Store: Appending integrity digest\n"); rc = TPM_Sbuffer_Append(sbuffer, tpm_digest, TPM_DIGEST_SIZE); } return rc; } /* TPM_SaveState_IsSaveKey() determines which keys are saved as part of the saved state. According to Ryan, all keys must be saved for this to be of use. */ void TPM_SaveState_IsSaveKey(TPM_BOOL *save, TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry) { *save = FALSE; /* 5. The contents of any key that is currently loaded SHOULD be preserved if the key's parentPCRStatus indicator is TRUE. */ /* 6. The contents of any key that has TPM_KEY_CONTROL_OWNER_EVICT set MUST be preserved */ /* 7. The contents of any key that is currently loaded MAY be preserved as reported by TPM_GetCapability */ /* NOTE Owner evict keys are not saved in the state blob, as they are already saved in the file system */ if (!(tpm_key_handle_entry->keyControl & TPM_KEY_CONTROL_OWNER_EVICT)) { *save = TRUE; } else { *save = FALSE; } if (*save) { printf(" TPM_SaveState_IsSaveKey: Save key handle %08x\n", tpm_key_handle_entry->handle); } return; } /* TPM_SaveState_NVLoad() deserializes the saved state data from the NV file TPM_SAVESTATE_NAME 0 on success. Returns TPM_RETRY on non-existent file TPM_FAIL on failure to load (fatal), since it should never occur */ TPM_RESULT TPM_SaveState_NVLoad(tpm_state_t *tpm_state) { TPM_RESULT rc = 0; unsigned char *stream = NULL; unsigned char *stream_start = NULL; uint32_t stream_size; printf(" TPM_SaveState_NVLoad:\n"); if (rc == 0) { /* load from NVRAM. Returns TPM_RETRY on non-existent file. */ rc = TPM_NVRAM_LoadData(&stream, /* freed @1 */ &stream_size, tpm_state->tpm_number, TPM_SAVESTATE_NAME); } /* deserialize from stream */ if (rc == 0) { stream_start = stream; /* save starting point for free() */ rc = TPM_SaveState_Load(tpm_state, &stream, &stream_size); if (rc != 0) { printf("TPM_SaveState_NVLoad: Error (fatal) loading deserializing saved state\n"); rc = TPM_FAIL; } } free(stream_start); /* @1 */ return rc; } /* TPM_SaveState_NVStore() serializes saved state data and stores it in the NV file TPM_SAVESTATE_NAME */ TPM_RESULT TPM_SaveState_NVStore(tpm_state_t *tpm_state) { TPM_RESULT rc = 0; TPM_STORE_BUFFER sbuffer; /* safe buffer for storing binary data */ const unsigned char *buffer; uint32_t length; printf(" TPM_SaveState_NVStore:\n"); TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ /* serialize relevant data from tpm_state to be written to NV */ if (rc == 0) { rc = TPM_SaveState_Store(&sbuffer, tpm_state); /* get the serialized buffer and its length */ TPM_Sbuffer_Get(&sbuffer, &buffer, &length); } /* validate the length of the stream */ if (rc == 0) { printf(" TPM_SaveState_NVStore: Require %u bytes\n", length); if (length > TPM_MAX_SAVESTATE_SPACE) { printf("TPM_SaveState_NVStore: Error, No space, need %u max %u\n", length, TPM_MAX_SAVESTATE_SPACE); rc = TPM_NOSPACE; } } if (rc == 0) { /* store the buffer in NVRAM */ rc = TPM_NVRAM_StoreData(buffer, length, tpm_state->tpm_number, TPM_SAVESTATE_NAME); tpm_state->tpm_stany_flags.stateSaved = TRUE; /* mark the state as stored */ } TPM_Sbuffer_Delete(&sbuffer); /* @1 */ return rc; } /* TPM_SaveState_NVDelete() deletes the NV file If mustExist is TRUE, returns an error if the file does not exist. If mustExist is FALSE, returns success if the file does not exist. */ TPM_RESULT TPM_SaveState_NVDelete(tpm_state_t *tpm_state, TPM_BOOL mustExist) { TPM_RESULT rc = 0; printf(" TPM_SaveState_NVDelete:\n"); if (rc == 0) { /* remove the saved state */ rc = TPM_NVRAM_DeleteName(tpm_state->tpm_number, TPM_SAVESTATE_NAME, mustExist); tpm_state->tpm_stany_flags.stateSaved = FALSE; /* mark the state as deleted */ } return rc; } /* Volatile state includes all the tpm_state structure volatile members. It is a superset of Saved state, used when the entire TPM state must be saved and restored */ /* TPM_VolatileAll_Load() restores the TPM state from a stream created by TPM_VolatileAll_Store() The two functions must be kept in sync. */ TPM_RESULT TPM_VolatileAll_Load(tpm_state_t *tpm_state, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; TPM_PCR_ATTRIBUTES pcrAttrib[TPM_NUM_PCR]; size_t i; unsigned char *stream_start = *stream; /* copy for integrity check */ uint32_t stream_size_start = *stream_size; printf(" TPM_VolatileAll_Load:\n"); /* check format tag */ /* In the future, if multiple formats are supported, this check will be replaced by a 'switch' on the tag */ if (rc == 0) { rc = TPM_CheckTag(TPM_TAG_VSTATE_V1, stream, stream_size); } /* compiled in TPM parameters */ if (rc == 0) { rc = TPM_Parameters_Load(stream, stream_size); } /* V1 is the TCG standard returned by the getcap. It's unlikely that this will change */ if (rc == 0) { rc = TPM_CheckTag(TPM_TAG_STCLEAR_FLAGS_V1, stream, stream_size); } /* TPM_STCLEAR_FLAGS */ if (rc == 0) { rc = TPM_StclearFlags_Load(&(tpm_state->tpm_stclear_flags), stream, stream_size); } /* TPM_STANY_FLAGS */ if (rc == 0) { rc = TPM_StanyFlags_Load(&(tpm_state->tpm_stany_flags), stream, stream_size); } /* TPM_STCLEAR_DATA */ /* normally, resettable PCRs are not restored. "All" means to restore everything */ for (i = 0 ; (rc == 0) && (i < TPM_NUM_PCR) ; i++) { pcrAttrib[i].pcrReset = FALSE; } /* TPM_STCLEAR_DATA */ if (rc == 0) { rc = TPM_StclearData_Load(&(tpm_state->tpm_stclear_data), stream, stream_size, (TPM_PCR_ATTRIBUTES *)&pcrAttrib); } /* TPM_STANY_DATA */ if (rc == 0) { rc = TPM_StanyData_Load(&(tpm_state->tpm_stany_data), stream, stream_size); } /* TPM_KEY_HANDLE_ENTRY */ if (rc == 0) { rc = TPM_KeyHandleEntries_Load(tpm_state, stream, stream_size); } /* Context for SHA1 functions */ if (rc == 0) { printf(" TPM_VolatileAll_Load: Loading SHA ordinal context\n"); rc = TPM_Sha1Context_Load(&(tpm_state->sha1_context), stream, stream_size); } /* Context for TIS SHA1 functions */ if (rc == 0) { printf(" TPM_VolatileAll_Load: Loading TIS context\n"); rc = TPM_Sha1Context_Load(&(tpm_state->sha1_context_tis), stream, stream_size); } /* TPM_TRANSHANDLE */ if (rc == 0) { rc = TPM_Load32(&(tpm_state->transportHandle), stream, stream_size); } /* testState */ if (rc == 0) { rc = TPM_Load32(&(tpm_state->testState), stream, stream_size); } /* load the NV volatile flags */ if (rc == 0) { rc = TPM_NVIndexEntries_LoadVolatile(&(tpm_state->tpm_nv_index_entries), stream, stream_size); } /* sanity check the stream size */ if (rc == 0) { if (*stream_size != TPM_DIGEST_SIZE) { printf("TPM_VolatileAll_Load: Error (fatal) stream size %u not %u\n", *stream_size, TPM_DIGEST_SIZE); rc = TPM_FAIL; } } /* check the integrity digest */ if (rc == 0) { printf(" TPM_VolatileAll_Load: Checking integrity digest\n"); rc = TPM_SHA1_Check(*stream, /* currently points to integrity digest */ stream_size_start - TPM_DIGEST_SIZE, stream_start, 0, NULL); } /* remove the integrity digest from the stream */ if (rc == 0) { *stream_size -= TPM_DIGEST_SIZE; } return rc; } /* TPM_VolatileAll_Store() stores the TPM state to a stream that can be restored through TPM_VolatileAll_Load(). The two functions must be kept in sync. */ TPM_RESULT TPM_VolatileAll_Store(TPM_STORE_BUFFER *sbuffer, tpm_state_t *tpm_state) { TPM_RESULT rc = 0; TPM_PCR_ATTRIBUTES pcrAttrib[TPM_NUM_PCR]; size_t i; const unsigned char *buffer; /* elements of sbuffer */ uint32_t length; TPM_DIGEST tpm_digest; printf(" TPM_VolatileAll_Store:\n"); /* overall format tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_VSTATE_V1); } /* compiled in TPM parameters */ if (rc == 0) { rc = TPM_Parameters_Store(sbuffer); } /* V1 is the TCG standard returned by the getcap. It's unlikely that this will change */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_STCLEAR_FLAGS_V1); } /* TPM_STCLEAR_FLAGS */ if (rc == 0) { rc = TPM_StclearFlags_Store(sbuffer, &(tpm_state->tpm_stclear_flags)); } /* TPM_STANY_FLAGS */ if (rc == 0) { rc = TPM_StanyFlags_Store(sbuffer, &(tpm_state->tpm_stany_flags)); } /* TPM_STCLEAR_DATA */ /* normally, resettable PCRs are not restored. "All" means to restore everything */ for (i = 0 ; (rc == 0) && (i < TPM_NUM_PCR) ; i++) { pcrAttrib[i].pcrReset = FALSE; } /* TPM_STCLEAR_DATA */ if (rc == 0) { rc = TPM_StclearData_Store(sbuffer, &(tpm_state->tpm_stclear_data), (TPM_PCR_ATTRIBUTES *)&pcrAttrib); } /* TPM_STANY_DATA */ if (rc == 0) { rc = TPM_StanyData_Store(sbuffer, &(tpm_state->tpm_stany_data)); } /* TPM_KEY_HANDLE_ENTRY */ if (rc == 0) { rc = TPM_KeyHandleEntries_Store(sbuffer, tpm_state); } /* Context for SHA1 functions */ if (rc == 0) { printf(" TPM_VolatileAll_Store: Storing SHA ordinal context\n"); rc = TPM_Sha1Context_Store(sbuffer, tpm_state->sha1_context); } /* Context for TIS SHA1 functions */ if (rc == 0) { printf(" TPM_VolatileAll_Store: Storing TIS context\n"); rc = TPM_Sha1Context_Store(sbuffer, tpm_state->sha1_context_tis); } /* TPM_TRANSHANDLE */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_state->transportHandle); } /* testState */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_state->testState); } /* store the NV volatile flags */ if (rc == 0) { rc = TPM_NVIndexEntries_StoreVolatile(sbuffer, &(tpm_state->tpm_nv_index_entries)); } if (rc == 0) { /* get the current serialized buffer and its length */ TPM_Sbuffer_Get(sbuffer, &buffer, &length); /* generate the integrity digest */ rc = TPM_SHA1(tpm_digest, length, buffer, 0, NULL); } /* append the integrity digest to the stream */ if (rc == 0) { printf(" TPM_VolatileAll_Store: Appending integrity digest\n"); rc = TPM_Sbuffer_Append(sbuffer, tpm_digest, TPM_DIGEST_SIZE); } return rc; } /* TPM_VolatileAll_NVLoad() deserializes the entire volatile state data from the NV file TPM_VOLATILESTATE_NAME. If the file does not exist (a normal startup), returns success. 0 on success or non-existent file TPM_FAIL on failure to load (fatal), since it should never occur */ TPM_RESULT TPM_VolatileAll_NVLoad(tpm_state_t *tpm_state) { TPM_RESULT rc = 0; TPM_BOOL done = FALSE; unsigned char *stream = NULL; unsigned char *stream_start = NULL; uint32_t stream_size; printf(" TPM_VolatileAll_NVLoad:\n"); if (rc == 0) { /* load from NVRAM. Returns TPM_RETRY on non-existent file. */ rc = TPM_NVRAM_LoadData(&stream, /* freed @1 */ &stream_size, tpm_state->tpm_number, TPM_VOLATILESTATE_NAME); /* if the file does not exist, leave the volatile state initial values */ if (rc == TPM_RETRY) { done = TRUE; rc = 0; } else if (rc != 0) { printf("TPM_VolatileAll_NVLoad: Error (fatal) loading %s\n", TPM_VOLATILESTATE_NAME); rc = TPM_FAIL; } } /* deserialize from stream */ if ((rc == 0) && !done) { stream_start = stream; /* save starting point for free() */ rc = TPM_VolatileAll_Load(tpm_state, &stream, &stream_size); if (rc != 0) { printf("TPM_VolatileAll_NVLoad: Error (fatal) loading deserializing state\n"); rc = TPM_FAIL; } } if (rc != 0) { printf(" TPM_VolatileAll_NVLoad: Set testState to %u \n", TPM_TEST_STATE_FAILURE); tpm_state->testState = TPM_TEST_STATE_FAILURE; } free(stream_start); /* @1 */ return rc; } /* TPM_VolatileAll_NVStore() serializes the entire volatile state data and stores it in the NV file TPM_VOLATILESTATE_NAME */ TPM_RESULT TPM_VolatileAll_NVStore(tpm_state_t *tpm_state) { TPM_RESULT rc = 0; TPM_STORE_BUFFER sbuffer; /* safe buffer for storing binary data */ const unsigned char *buffer; uint32_t length; printf(" TPM_VolatileAll_NVStore:\n"); TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ /* serialize relevant data from tpm_state to be written to NV */ if (rc == 0) { rc = TPM_VolatileAll_Store(&sbuffer, tpm_state); /* get the serialized buffer and its length */ TPM_Sbuffer_Get(&sbuffer, &buffer, &length); } /* validate the length of the stream */ if (rc == 0) { printf(" TPM_VolatileAll_NVStore: Require %u bytes\n", length); if (length > TPM_MAX_VOLATILESTATE_SPACE) { printf("TPM_VolatileAll_NVStore: Error, No space, need %u max %u\n", length, TPM_MAX_VOLATILESTATE_SPACE); rc = TPM_NOSPACE; } } if (rc == 0) { /* store the buffer in NVRAM */ rc = TPM_NVRAM_StoreData(buffer, length, tpm_state->tpm_number, TPM_VOLATILESTATE_NAME); } TPM_Sbuffer_Delete(&sbuffer); /* @1 */ return rc; } /* Compiled in TPM Parameters */ TPM_RESULT TPM_Parameters_Load(unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_Parameters_Load:\n"); if (rc == 0) { rc = TPM_CheckTag(TPM_TAG_TPM_PARAMETERS_V1, stream, stream_size); } if (rc == 0) { rc = TPM_Parameters_Check8(TPM_MAJOR, "TPM_MAJOR", stream, stream_size); } if (rc == 0) { rc = TPM_Parameters_Check8(TPM_MINOR, "TPM_MINOR", stream, stream_size); } if (rc == 0) { rc = TPM_Parameters_Check16(TPM_PCCLIENT, "TPM_PCCLIENT", stream, stream_size); } if (rc == 0) { rc = TPM_Parameters_Check16(TPM_NUM_PCR, "TPM_NUM_PCR", stream, stream_size); } if (rc == 0) { rc = TPM_Parameters_Check16(TPM_RSA_KEY_LENGTH_MAX, "TPM_RSA_KEY_LENGTH_MAX", stream, stream_size); } if (rc == 0) { rc = TPM_Parameters_Check16(TPM_KEY_HANDLES, "TPM_KEY_HANDLES", stream, stream_size); } if (rc == 0) { rc = TPM_Parameters_Check16(TPM_OWNER_EVICT_KEY_HANDLES, "TPM_OWNER_EVICT_KEY_HANDLES", stream, stream_size); } if (rc == 0) { rc = TPM_Parameters_Check16(TPM_NUM_FAMILY_TABLE_ENTRY_MIN, "TPM_NUM_FAMILY_TABLE_ENTRY_MIN", stream, stream_size); } if (rc == 0) { rc = TPM_Parameters_Check16(TPM_NUM_DELEGATE_TABLE_ENTRY_MIN, "TPM_NUM_DELEGATE_TABLE_ENTRY_MIN", stream, stream_size); } if (rc == 0) { rc = TPM_Parameters_Check16(TPM_MIN_AUTH_SESSIONS, "TPM_MIN_AUTH_SESSIONS", stream, stream_size); } if (rc == 0) { rc = TPM_Parameters_Check16(TPM_MIN_TRANS_SESSIONS, "TPM_MIN_TRANS_SESSIONS", stream, stream_size); } if (rc == 0) { rc = TPM_Parameters_Check16(TPM_MIN_DAA_SESSIONS, "TPM_MIN_DAA_SESSIONS", stream, stream_size); } if (rc == 0) { rc = TPM_Parameters_Check16(TPM_MIN_COUNTERS, "TPM_MIN_COUNTERS", stream, stream_size); } if (rc == 0) { rc = TPM_Parameters_Check16(TPM_MIN_SESSION_LIST, "TPM_MIN_SESSION_LIST", stream, stream_size); } if (rc == 0) { rc = TPM_Parameters_Check32(TPM_MAX_NV_SPACE, "TPM_MAX_NV_SPACE", stream, stream_size); } return rc; } TPM_RESULT TPM_Parameters_Check8(uint8_t expected, const char *parameter, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; uint8_t tmp8; if (rc == 0) { rc = TPM_Load8(&tmp8, stream, stream_size); if (tmp8 != expected) { printf("TPM_Parameters_Check8: Error (fatal) %s received %u expect %u\n", parameter, tmp8, expected); rc = TPM_FAIL; } } return rc; } TPM_RESULT TPM_Parameters_Check16(uint16_t expected, const char *parameter, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; uint16_t tmp16; if (rc == 0) { rc = TPM_Load16(&tmp16, stream, stream_size); if (tmp16 != expected) { printf("TPM_Parameters_Check16: Error (fatal) %s received %u expect %u\n", parameter, tmp16, expected); rc = TPM_FAIL; } } return rc; } TPM_RESULT TPM_Parameters_Check32(uint32_t expected, const char *parameter, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; uint32_t tmp32; if (rc == 0) { rc = TPM_Load32(&tmp32, stream, stream_size); if (tmp32 != expected) { printf("TPM_Parameters_Check32: Error (fatal) %s received %u expect %u\n", parameter, tmp32, expected); rc = TPM_FAIL; } } return rc; } TPM_RESULT TPM_Parameters_Store(TPM_STORE_BUFFER *sbuffer) { TPM_RESULT rc = 0; printf(" TPM_Parameters_Store:\n"); if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_TPM_PARAMETERS_V1); } if (rc == 0) { rc = TPM_Sbuffer_Append8(sbuffer, TPM_MAJOR); } if (rc == 0) { rc = TPM_Sbuffer_Append8(sbuffer, TPM_MINOR); } if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_PCCLIENT); } if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_NUM_PCR); } if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_RSA_KEY_LENGTH_MAX); } if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_KEY_HANDLES); } if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_OWNER_EVICT_KEY_HANDLES); } if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_NUM_FAMILY_TABLE_ENTRY_MIN); } if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_NUM_DELEGATE_TABLE_ENTRY_MIN); } if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_MIN_AUTH_SESSIONS); } if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_MIN_TRANS_SESSIONS); } if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_MIN_DAA_SESSIONS); } if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_MIN_COUNTERS); } if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_MIN_SESSION_LIST); } if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, TPM_MAX_NV_SPACE); } return rc; } /* 27.5 TPM_Reset rev 105 Releases all resources associated with existing authorization sessions. This is useful if a TSS driver has lost track of the state in the TPM. This is a deprecated command in V1.2. This command in 1.1 only referenced authorization sessions and is not upgraded to affect any other TPM entity in 1.2 */ TPM_RESULT TPM_Process_Reset(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_Reset: Ordinal Entry\n"); /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | TPM_CHECK_NO_LOCKOUT)); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_Reset: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ /* 1. The TPM invalidates all resources allocated to authorization sessions as per version 1.1 extant in the TPM */ /* a. This includes structures created by TPM_SaveAuthContext and TPM_SaveKeyContext */ /* b.The TPM MUST invalidate OSAP sessions */ /* c.The TPM MAY invalidate DSAP sessions */ /* d. The TPM MUST NOT invalidate structures created by TPM_SaveContext */ if (returnCode == TPM_SUCCESS) { TPM_StclearData_AuthSessionDelete(&(tpm_state->tpm_stclear_data)); } /* 2. The TPM does not reset any PCR or DIR values. */ /* 3. The TPM does not reset any flags in the TPM_STCLEAR_FLAGS structure. */ /* 4. The TPM does not reset or invalidate any keys */ /* response */ if (rcf == 0) { printf("TPM_Process_Reset: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* cleanup */ return rcf; } /* 3.2 TPM_Startup rev 101 TPM_Startup is always preceded by TPM_Init, which is the physical indication (a system-wide reset) that TPM initialization is necessary. There are many events on a platform that can cause a reset and the response to these events can require different operations to occur on the TPM. The mere reset indication does not contain sufficient information to inform the TPM as to what type of reset is occurring. Additional information known by the platform initialization code needs transmitting to the TPM. The TPM_Startup command provides the mechanism to transmit the information. The TPM can startup in three different modes: A "clear" start where all variables go back to their default or non-volatile set state A "save" start where the TPM recovers appropriate information and restores various values based on a prior TPM_SaveState. This recovery requires an invocation of TPM_Init to be successful. A failing "save" start must shut down the TPM. The CRTM cannot leave the TPM in a state where an untrusted upper software layer could issue a "clear" and then extend PCR's and thus mimic the CRTM. A "deactivated" start where the TPM turns itself off and requires another TPM_Init before the TPM will execute in a fully operational state. The TPM can startup in three different modes: */ TPM_RESULT TPM_Process_Startup(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ TPM_RESULT returnCode1 = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_STARTUP_TYPE startupType; /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_Startup: Ordinal Entry\n"); /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get startupType parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load16(&startupType, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_Startup: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* TPM_CheckState() can check for the normal case where postInitialise TRUE is an error. This is the only command where FALSE is the error. */ if (returnCode == TPM_SUCCESS) { /* 1. If TPM_STANY_FLAGS -> postInitialise is FALSE, */ if (!(tpm_state->tpm_stany_flags.postInitialise)) { /* a. Then the TPM MUST return TPM_INVALID_POSTINIT, and exit this capability */ printf("TPM_Process_Startup: Error, postInitialise is FALSE\n"); returnCode = TPM_INVALID_POSTINIT; } } if (returnCode == TPM_SUCCESS) { /* 1. If the TPM is in failure mode */ if (tpm_state->testState == TPM_TEST_STATE_FAILURE) { /* a. TPM_STANY_FLAGS -> postInitialize is still set to FALSE */ tpm_state->tpm_stany_flags.postInitialise = FALSE; printf("TPM_Process_Startup: Error, shutdown is TRUE\n"); /* b. The TPM returns TPM_FAILEDSELFTEST */ returnCode = TPM_FAILEDSELFTEST; } } /* Processing */ if (returnCode == TPM_SUCCESS) { switch (startupType) { case TPM_ST_CLEAR: /* The TPM is starting up from a clean state */ returnCode = TPM_Startup_Clear(tpm_state); break; case TPM_ST_STATE: /* The TPM is starting up from a saved state */ returnCode = TPM_Startup_State(tpm_state); break; case TPM_ST_DEACTIVATED: /* The TPM is to startup and set the deactivated flag to TRUE */ returnCode = TPM_Startup_Deactivated(tpm_state); break; default: returnCode = TPM_BAD_PARAMETER; break; } } /* TPM_STANY_FLAGS MUST reset on TPM_Startup(any) */ if (returnCode == TPM_SUCCESS) { TPM_StanyFlags_Init(&(tpm_state->tpm_stany_flags)); } /* 5. The TPM MUST ensure that state associated with TPM_SaveState is invalidated */ returnCode1 = TPM_SaveState_NVDelete(tpm_state, FALSE); /* Ignore errors if the state does not exist. */ if (returnCode == TPM_SUCCESS) { /* previous error takes precedence */ returnCode = returnCode1; } /* 6. The TPM MUST set TPM_STANY_FLAGS -> postInitialise to FALSE */ tpm_state->tpm_stany_flags.postInitialise = FALSE; /* response */ if (rcf == 0) { printf("TPM_Process_Startup: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } return rcf; } /* 3.2 TPM_Startup(TPM_ST_CLEAR) rev 99 */ TPM_RESULT TPM_Startup_Clear(tpm_state_t *tpm_state) { TPM_RESULT returnCode = TPM_SUCCESS; printf("TPM_Startup_Clear:\n"); /* 2. If stType = TPM_ST_CLEAR */ if (returnCode == TPM_SUCCESS) { /* a. Ensure that sessions associated with resources TPM_RT_CONTEXT, TPM_RT_AUTH, TPM_RT_DAA_TPM, and TPM_RT_TRANS are invalidated */ /* NOTE TPM_RT_CONTEXT - contextNonceKey cleared by TPM_Global_Init() -> TPM_StanyData_Init() contextNonceSession cleared by TPM_Global_Init() -> TPM_StanyData_Init() */ /* NOTE TPM_RT_AUTH - TPM_AuthSessions_Init() called by TPM_Global_Init() -> TPM_StanyData_Init() */ /* TPM_RT_TRANS - TPM_TransportSessions_Init() called by TPM_Global_Init() -> TPM_StanyData_Init()*/ /* TPM_RT_DAA_TPM - TPM_DaaSessions_Init() called by TPM_Global_Init() -> TPM_StanyData_Init()*/ /* b. Reset PCR values to each correct default value */ /* i. pcrReset is FALSE, set to 0x00..00 */ /* ii. pcrReset is TRUE, set to 0xFF..FF */ /* NOTE done by TPM_MainInit() -> TPM_Global_Init() */ /* c. Set the following TPM_STCLEAR_FLAGS to their default state i. PhysicalPresence ii. PhysicalPresenceLock iii. disableForceClear */ /* NOTE Done by TPM_Global_Init() -> TPM_StclearFlags_Init() */ /* d. The TPM MAY initialize auditDigest to all zeros i. If not initialized to all zeros the TPM SHALL ensure that auditDigest contains a valid value ii. If initialization fails the TPM SHALL set auditDigest to all zeros and SHALL set the internal TPM state so that the TPM returns TPM_FAILEDSELFTEST to all subsequent commands. */ /* NOTE Done by TPM_Global_Init() ->TPM_StanyData_Init() */ /* e. The TPM SHALL set TPM_STCLEAR_FLAGS -> deactivated to the same state as TPM_PERMANENT_FLAGS -> deactivated */ tpm_state->tpm_stclear_flags.deactivated = tpm_state->tpm_permanent_flags.deactivated; /* f. The TPM MUST set the TPM_STANY_DATA fields to: */ /* i. TPM_STANY_DATA->contextNonceSession is set to all zeros */ /* ii. TPM_STANY_DATA->contextCount is set to 0 */ /* iii. TPM_STANY_DATA->contextList is set to 0 */ /* NOTE Done by TPM_Global_Init() ->TPM_StanyData_Init() */ /* g. The TPM MUST set TPM_STCLEAR_DATA fields to: */ /* i. Invalidate contextNonceKey */ /* ii. countID to zero */ /* iii. OwnerReference to TPM_KH_OWNER */ /* NOTE Done by TPM_Global_Init() -> TPM_StclearData_Init() */ /* h. The TPM MUST set the following TPM_STCLEAR_FLAGS to */ /* i. bGlobalLock to FALSE */ /* NOTE Done by TPM_Global_Init() -> TPM_StclearFlags_Init() */ /* i. Determine which keys should remain in the TPM */ /* i. For each key that has a valid preserved value in the TPM */ /* (1) if parentPCRStatus is TRUE then call TPM_FlushSpecific(keyHandle) */ /* (2) if isVolatile is TRUE then call TPM_FlushSpecific(keyHandle) */ /* NOTE Since TPM_Global_Init() calls TPM_KeyHandleEntries_Init(), there are no keys remaining. Since this TPM implementation loads keys into volatile memory, not NVRAM, no keys are preserved at ST_CLEAR. */ /* ii. Keys under control of the OwnerEvict flag MUST stay resident in the TPM */ /* NOTE Done by TPM_PermanentAll_NVLoad() */ /* bReadSTClear and bWriteSTClear are volatile, in that they are set FALSE at TPM_Startup(ST_Clear) */ TPM_NVIndexEntries_StClear(&(tpm_state->tpm_nv_index_entries)); } return returnCode; } /* 3.2 TPM_Startup(TPM_ST_STATE) rev 100 */ TPM_RESULT TPM_Startup_State(tpm_state_t *tpm_state) { TPM_RESULT returnCode = TPM_SUCCESS; printf("TPM_Startup_State:\n"); if (returnCode == TPM_SUCCESS) { /* a. If the TPM has no state to restore the TPM MUST set the internal state such that it returns TPM_FAILEDSELFTEST to all subsequent commands */ /* b. The TPM MAY determine for each session type (authorization, transport, DAA, ...) to release or maintain the session information. The TPM reports how it manages sessions in the TPM_GetCapability command. */ /* c. The TPM SHALL take all necessary actions to ensure that all PCRs contain valid preserved values. If the TPM is unable to successfully complete these actions, it SHALL enter the TPM failure mode. */ /* i. For resettable PCR the TPM MUST set the value of TPM_STCLEAR_DATA -> PCR[] to the resettable PCR default value. The TPM MUST NOT restore a resettable PCR to a preserved value */ /* d. The TPM MAY initialize auditDigest to all zeros */ /* i. Otherwise, the TPM SHALL take all actions necessary to ensure that auditDigest contains a valid value. If the TPM is unable to successfully complete these actions, the TPM SHALL initialize auditDigest to all zeros and SHALL set the internal state such that the TPM returns TPM_FAILEDSELFTEST to all subsequent commands. */ /* e. The TPM MUST restore the following flags to their preserved states: */ /* i. All values in TPM_STCLEAR_FLAGS */ /* ii. All values in TPM_STCLEAR_DATA */ /* f. The TPM MUST restore all keys that have a valid preserved value */ /* NOTE Owner evict keys are loaded at TPM_PermanentAll_NVLoad() */ returnCode = TPM_SaveState_NVLoad(tpm_state); /* returns TPM_RETRY on non-existent file */ } /* g. The TPM resumes normal operation. If the TPM is unable to resume normal operation, it SHALL enter the TPM failure mode. */ if (returnCode != TPM_SUCCESS) { printf("TPM_Startup_State: Error restoring state\n"); returnCode = TPM_FAILEDSELFTEST; printf(" TPM_Startup_State: Set testState to %u \n", TPM_TEST_STATE_FAILURE); tpm_state->testState = TPM_TEST_STATE_FAILURE; } return returnCode; } /* 3.2 TPM_Startup(TPM_ST_DEACTIVATED) rev 97 */ TPM_RESULT TPM_Startup_Deactivated(tpm_state_t *tpm_state) { TPM_RESULT returnCode = TPM_SUCCESS; printf("TPM_Startup_Deactivated:\n"); if (returnCode == TPM_SUCCESS) { /* a. Invalidate sessions */ /* i. Ensure that all resources associated with saved and active sessions are invalidated */ /* NOTE Done at TPM_MainInit() */ /* b. The TPM MUST set TPM_STCLEAR_FLAGS -> deactivated to TRUE */ tpm_state->tpm_stclear_flags.deactivated = TRUE; } return returnCode; } #if 0 /* TPM_Startup_Any() rev 96 Handles Actions common to all TPM_Startup options. */ TPM_RESULT TPM_Startup_Any(tpm_state_t *tpm_state) { TPM_RESULT returnCode = TPM_SUCCESS; printf("TPM_Startup_Any:\n"); /* TPM_STANY_FLAGS MUST reset on TPM_Startup(any) */ TPM_StanyFlags_Init(&(tpm_state->tpm_stany_flags)); /* 5. The TPM MUST ensure that state associated with TPM_SaveState is invalidated */ returnCode = TPM_SaveState_NVDelete(tpm_state, FALSE); /* Ignore errors if the state does not exist. */ /* 6. The TPM MUST set TPM_STANY_FLAGS -> postInitialise to FALSE */ tpm_state->tpm_stany_flags.postInitialise = FALSE; return returnCode; } #endif /* 3.3 TPM_SaveState rev 111 This warns a TPM to save some state information. If the relevant shielded storage is non-volatile, this command need have no effect. If the relevant shielded storage is volatile and the TPM alone is unable to detect the loss of external power in time to move data to non-volatile memory, this command should be presented before the TPM enters a low or no power state. Resettable PCRs are tied to platform state that does not survive a sleep state. If the PCRs did not reset, they would falsely indicate that the platform state was already present when it came out of sleep. Since some setup is required first, there would be a gap where PCRs indicated the wrong state. Therefore, the PCRs must be recreated. */ TPM_RESULT TPM_Process_SaveState(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_SaveState: Ordinal Entry\n"); /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, (TPM_CHECK_NOT_SHUTDOWN | TPM_CHECK_NO_LOCKOUT)); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_SaveState: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ /* 1. Preserved values MUST be non-volatile. */ /* 2. If data is never stored in a volatile medium, that data MAY be used as preserved data. In such cases, no explicit action may be required to preserve that data. */ /* 3. If an explicit action is required to preserve data, it MUST be possible for the TPM to determine whether preserved data is valid. */ /* 4. If the parameter mirrored by a preserved value is altered, all preserved values MUST be declared invalid. */ if (returnCode == TPM_SUCCESS) { /* Determine if TPM_SaveState was called from within a transport session. The TPM MAY save transport sessions as part of the saved state. Since this TPM implements that option, there's no point in saving the state, because it would be immediately invalidated during the transport response. Return an error to indicate that the state was not saved. */ if (transportInternal != NULL) { printf("TPM_Process_SaveState: Error, called from transport session\n"); returnCode = TPM_NO_WRAP_TRANSPORT; } } /* Audit Generation Corner cases 3.a. TPM_SaveState: Only the input parameters are audited, and the audit occurs before the state is saved. If an error occurs while or after the state is saved, the audit still occurs. */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* 5. The TPM MAY declare all preserved value is invalid in response to any command other that TPM_Init. */ /* NOTE Done by TPM_GetInParamDigest(), which is called by all ordinals */ /* 1. Store TPM_STCLEAR_DATA -> PCR contents except for */ /* a. If the PCR attribute pcrReset is TRUE */ /* b. Any platform identified debug PCR */ /* 2. The auditDigest MUST be handled according to the audit requirements as reported by TPM_GetCapability */ /* a. If the ordinalAuditStatus is TRUE for the TPM_SaveState ordinal and the auditDigest is being stored in the saved state, the saved auditDigest MUST include the TPM_SaveState input parameters and MUST NOT include the output parameters. */ /* 3. All values in TPM_STCLEAR_DATA MUST be preserved */ /* 4. All values in TPM_STCLEAR_FLAGS MUST be preserved */ /* 5. The contents of any key that is currently loaded SHOULD be preserved if the key's parentPCRStatus indicator is TRUE. */ /* 6. The contents of any key that has TPM_KEY_CONTROL_OWNER_EVICT set MUST be preserved */ /* 7. The contents of any key that is currently loaded MAY be preserved */ /* 8. The contents of sessions (authorization, transport, DAA etc.) MAY be preserved as reported by TPM_GetCapability */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SaveState_NVStore(tpm_state); } /* store the state in NVRAM */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_SaveState: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* Special case, no output parameter audit */ /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* cleanup */ return rcf; } libtpms-0.9.3/src/tpm12/tpm_startup.h000066400000000000000000000127711421143571500174750ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM Admin Startup and State */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_startup.h 4526 2011-03-24 21:14:42Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_STARTUP_H #define TPM_STARTUP_H #include "tpm_global.h" #include "tpm_store.h" #include "tpm_types.h" /* Startup */ TPM_RESULT TPM_Startup_Clear(tpm_state_t *tpm_state); TPM_RESULT TPM_Startup_State(tpm_state_t *tpm_state); TPM_RESULT TPM_Startup_Deactivated(tpm_state_t *tpm_state); #if 0 TPM_RESULT TPM_Startup_Any(tpm_state_t *tpm_state); #endif /* Save State */ TPM_RESULT TPM_SaveState_Load(tpm_state_t *tpm_state, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_SaveState_Store(TPM_STORE_BUFFER *sbuffer, tpm_state_t *tpm_state); TPM_RESULT TPM_SaveState_NVLoad(tpm_state_t *tpm_state); TPM_RESULT TPM_SaveState_NVStore(tpm_state_t *tpm_state); TPM_RESULT TPM_SaveState_NVDelete(tpm_state_t *tpm_state, TPM_BOOL mustExist); void TPM_SaveState_IsSaveKey(TPM_BOOL *save, TPM_KEY_HANDLE_ENTRY *tpm_key_handle_entry); /* Volatile State */ TPM_RESULT TPM_VolatileAll_Load(tpm_state_t *tpm_state, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_VolatileAll_Store(TPM_STORE_BUFFER *sbuffer, tpm_state_t *tpm_state); TPM_RESULT TPM_VolatileAll_NVLoad(tpm_state_t *tpm_state); TPM_RESULT TPM_VolatileAll_NVStore(tpm_state_t *tpm_state); /* Compiled in TPM Parameters */ TPM_RESULT TPM_Parameters_Load(unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_Parameters_Store(TPM_STORE_BUFFER *sbuffer); TPM_RESULT TPM_Parameters_Check8(uint8_t expected, const char *parameter, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_Parameters_Check16(uint16_t expected, const char *parameter, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_Parameters_Check32(uint32_t expected, const char *parameter, unsigned char **stream, uint32_t *stream_size); /* Processing Functions */ TPM_RESULT TPM_Process_Reset(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_Startup(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_SaveState(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); #endif libtpms-0.9.3/src/tpm12/tpm_storage.c000066400000000000000000004136651421143571500174410ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Storage Functions */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_storage.c 4442 2011-02-14 20:20:01Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include #include #include #include "tpm_auth.h" #include "tpm_cryptoh.h" #include "tpm_crypto.h" #include "tpm_debug.h" #include "tpm_digest.h" #include "tpm_error.h" #include "tpm_io.h" #include "tpm_key.h" #include "tpm_memory.h" #include "tpm_nonce.h" #include "tpm_pcr.h" #include "tpm_process.h" #include "tpm_secret.h" #include "tpm_structures.h" #include "tpm_ver.h" #include "tpm_storage.h" /* local function prototypes */ static TPM_RESULT TPM_SealCryptCommon(BYTE **o1, TPM_ADIP_ENC_SCHEME adipEncScheme, TPM_SIZED_BUFFER *inData, TPM_AUTH_SESSION_DATA *auth_session_data, TPM_NONCE nonceOdd); static TPM_RESULT TPM_LoadKeyCommon(TPM_KEY_HANDLE *inKeyHandle, TPM_BOOL *key_added, TPM_SECRET **hmacKey, TPM_AUTH_SESSION_DATA **auth_session_data, tpm_state_t *tpm_state, TPM_TAG tag, TPM_COMMAND_CODE ordinal, TPM_KEY_HANDLE parentHandle, TPM_KEY *inKey, TPM_DIGEST inParamDigest, TPM_AUTHHANDLE authHandle, TPM_NONCE nonceOdd, TPM_BOOL continueAuthSession, TPM_AUTHDATA parentAuth); /* TPM_BOUND_DATA */ /* TPM_BoundData_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_BoundData_Init(TPM_BOUND_DATA *tpm_bound_data) { printf(" TPM_BoundData_Init:\n"); TPM_StructVer_Init(&(tpm_bound_data->ver)); tpm_bound_data->payload = TPM_PT_BIND; tpm_bound_data->payloadDataSize = 0; tpm_bound_data->payloadData = NULL; return; } /* TPM_BoundData_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_BoundData_Init() After use, call TPM_BoundData_Delete() to free memory */ TPM_RESULT TPM_BoundData_Load(TPM_BOUND_DATA *tpm_bound_data, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_BoundData_Load:\n"); if (rc == 0) { rc = TPM_StructVer_Load(&(tpm_bound_data->ver), stream, stream_size); } /* check ver immediately to ease debugging */ if (rc == 0) { rc = TPM_StructVer_CheckVer(&(tpm_bound_data->ver)); } if (rc == 0) { rc = TPM_Load8(&(tpm_bound_data->payload), stream, stream_size); } if ((rc == 0) && (*stream_size > 0)){ /* There is no payloadData size in the serialized data. Assume it consumes the rest of the stream */ tpm_bound_data->payloadDataSize = *stream_size; rc = TPM_Malloc(&(tpm_bound_data->payloadData), tpm_bound_data->payloadDataSize); } if ((rc == 0) && (*stream_size > 0)){ memcpy(tpm_bound_data->payloadData, *stream, tpm_bound_data->payloadDataSize); *stream += tpm_bound_data->payloadDataSize; *stream_size -= tpm_bound_data->payloadDataSize; } return rc; } #if 0 /* TPM_BoundData_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes This structure serialization assumes that the payloadDataSize member indicates the size of payloadData. */ TPM_RESULT TPM_BoundData_Store(TPM_STORE_BUFFER *sbuffer, const TPM_BOUND_DATA *tpm_bound_data) { TPM_RESULT rc = 0; printf(" TPM_BoundData_Store:\n"); if (rc == 0) { rc = TPM_StructVer_Store(sbuffer, &(tpm_bound_data->ver)); } if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_bound_data->payload), sizeof(TPM_PAYLOAD_TYPE)); } if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, tpm_bound_data->payloadData, tpm_bound_data->payloadDataSize); } return rc; } #endif /* TPM_BoundData_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the bound_data sets pointers to NULL calls TPM_BoundData_Init to set members back to default values The bound_data itself is not freed */ void TPM_BoundData_Delete(TPM_BOUND_DATA *tpm_bound_data) { printf(" TPM_BoundData_Delete:\n"); if (tpm_bound_data != NULL) { free(tpm_bound_data->payloadData); TPM_BoundData_Init(tpm_bound_data); } return; } /* TPM_SEALED_DATA */ /* TPM_SealedData_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_SealedData_Init(TPM_SEALED_DATA *tpm_sealed_data) { printf(" TPM_SealedData_Init:\n"); tpm_sealed_data->payload = TPM_PT_SEAL; TPM_Secret_Init(tpm_sealed_data->authData); TPM_Secret_Init(tpm_sealed_data->tpmProof); TPM_Digest_Init(tpm_sealed_data->storedDigest); TPM_SizedBuffer_Init(&(tpm_sealed_data->data)); return; } /* TPM_SealedData_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_SealedData_Init() After use, call TPM_SealedData_Delete() to free memory */ TPM_RESULT TPM_SealedData_Load(TPM_SEALED_DATA *tpm_sealed_data, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_SealedData_Load:\n"); /* load payload */ if (rc == 0) { rc = TPM_Load8(&(tpm_sealed_data->payload), stream, stream_size); } /* load authData */ if (rc == 0) { rc = TPM_Secret_Load(tpm_sealed_data->authData, stream, stream_size); } /* load tpmProof */ if (rc == 0) { rc = TPM_Secret_Load(tpm_sealed_data->tpmProof, stream, stream_size); } /* load storedDigest */ if (rc == 0) { rc = TPM_Digest_Load(tpm_sealed_data->storedDigest, stream, stream_size); } /* load dataSize and data */ if (rc == 0) { rc = TPM_SizedBuffer_Load(&(tpm_sealed_data->data), stream, stream_size); } return rc; } /* TPM_SealedData_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_SealedData_Store(TPM_STORE_BUFFER *sbuffer, const TPM_SEALED_DATA *tpm_sealed_data) { TPM_RESULT rc = 0; printf(" TPM_SealedData_Store:\n"); /* store payload */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_sealed_data->payload), sizeof(TPM_PAYLOAD_TYPE)); } /* store authData */ if (rc == 0) { rc = TPM_Secret_Store(sbuffer, tpm_sealed_data->authData); } /* store tpmProof */ if (rc == 0) { rc = TPM_Secret_Store(sbuffer, tpm_sealed_data->tpmProof); } /* store storedDigest */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_sealed_data->storedDigest); } /* store dataSize and data */ if (rc == 0) { rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_sealed_data->data)); } return rc; } /* TPM_SealedData_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_SealedData_Init to set members back to default values The object itself is not freed */ void TPM_SealedData_Delete(TPM_SEALED_DATA *tpm_sealed_data) { printf(" TPM_SealedData_Delete:\n"); if (tpm_sealed_data != NULL) { TPM_SizedBuffer_Delete(&(tpm_sealed_data->data)); TPM_SealedData_Init(tpm_sealed_data); } return; } /* TPM_SealedData_GenerateEncData() generates an enc_data structure by serializing the TPM_SEALED_DATA structure and encrypting the result using the public key. */ TPM_RESULT TPM_SealedData_GenerateEncData(TPM_SIZED_BUFFER *enc_data, const TPM_SEALED_DATA *tpm_sealed_data, TPM_KEY *tpm_key) { TPM_RESULT rc = 0; TPM_STORE_BUFFER sbuffer; /* TPM_SEALED_DATA serialization */ printf(" TPM_SealedData_GenerateEncData\n"); TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ /* serialize the TPM_SEALED_DATA */ if (rc == 0) { rc = TPM_SealedData_Store(&sbuffer, tpm_sealed_data); } /* encrypt the TPM_SEALED_DATA serialization buffer with the public key, and place the result in the encData members */ if (rc == 0) { rc = TPM_RSAPublicEncryptSbuffer_Key(enc_data, &sbuffer, tpm_key); } TPM_Sbuffer_Delete(&sbuffer); /* @1 */ return rc; } /* TPM_SealedData_DecryptEncData() decrypts the enc_data using the private key. The result is deserialized and stored in the TPM_SEALED_DATA structure. */ TPM_RESULT TPM_SealedData_DecryptEncData(TPM_SEALED_DATA *tpm_sealed_data, /* result */ TPM_SIZED_BUFFER *enc_data, /* encrypted input */ TPM_KEY *tpm_key) /* key for decrypting */ { TPM_RESULT rc = 0; unsigned char *decryptData = NULL; /* freed @1 */ uint32_t decryptDataLength = 0; /* actual valid data */ unsigned char *stream; uint32_t stream_size; printf(" TPM_SealedData_DecryptEncData:\n"); /* allocate space for the decrypted data */ if (rc == 0) { rc = TPM_RSAPrivateDecryptMalloc(&decryptData, /* decrypted data */ &decryptDataLength, /* actual size of decrypted data */ enc_data->buffer, /* encrypted data */ enc_data->size, /* encrypted data size */ tpm_key); } /* load the TPM_SEALED_DATA structure from the decrypted data stream */ if (rc == 0) { /* use temporary variables, because TPM_SealedData_Load() moves the stream */ stream = decryptData; stream_size = decryptDataLength; rc = TPM_SealedData_Load(tpm_sealed_data, &stream, &stream_size); } free(decryptData); /* @1 */ return rc; } /* TPM_STORED_DATA */ /* TPM_StoredData_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_StoredData_Init(TPM_STORED_DATA *tpm_stored_data, unsigned int version) { printf(" TPM_StoredData_Init: v%u\n", version); if (version == 1) { TPM_StructVer_Init(&(tpm_stored_data->ver)); } else { ((TPM_STORED_DATA12 *)tpm_stored_data)->tag = TPM_TAG_STORED_DATA12; ((TPM_STORED_DATA12 *)tpm_stored_data)->et = 0x0000; } TPM_SizedBuffer_Init(&(tpm_stored_data->sealInfo)); TPM_SizedBuffer_Init(&(tpm_stored_data->encData)); tpm_stored_data->tpm_seal_info = NULL; return; } /* TPM_StoredData_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_StoredData_Init() After use, call TPM_StoredData_Delete() to free memory This function handles both TPM_STORED_DATA and TPM_STORED_DATA12 and returns the 'version'. */ TPM_RESULT TPM_StoredData_Load(TPM_STORED_DATA *tpm_stored_data, unsigned int *version, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; /* Peek at the first byte to guess the version number. The data is verified later. TPM_STORED_DATA is 01,01,00,00 TPM_STORED_DATA12 is 00,16,00,00 */ if ((rc == 0) && (*stream_size > 0)) { if (**stream == 0x01) { *version = 1; } else { *version = 2; } printf(" TPM_StoredData_Load: v%u\n", *version); } /* 1.1 load ver */ if ((rc == 0) && (*version == 1)) { rc = TPM_StructVer_Load(&(tpm_stored_data->ver), stream, stream_size); } /* 1.2 load tag */ if ((rc == 0) && (*version != 1)) { rc = TPM_Load16(&(((TPM_STORED_DATA12 *)tpm_stored_data)->tag), stream, stream_size); } /* 1.2 load et */ if ((rc == 0) && (*version != 1)) { rc = TPM_Load16(&(((TPM_STORED_DATA12 *)tpm_stored_data)->et), stream, stream_size); } /* check the TPM_STORED_DATA structure version */ if ((rc == 0) && (*version == 1)) { rc = TPM_StructVer_CheckVer(&(tpm_stored_data->ver)); } /* check the TPM_STORED_DATA12 structure tag */ if ((rc == 0) && (*version != 1)) { rc = TPM_StoredData_CheckTag((TPM_STORED_DATA12 *)tpm_stored_data); } /* load sealInfoSize and sealInfo */ if (rc == 0) { rc = TPM_SizedBuffer_Load(&(tpm_stored_data->sealInfo), stream, stream_size); } /* load the TPM_PCR_INFO or TPM_PCR_INFO_LONG cache */ if (rc == 0) { if (*version == 1) { rc = TPM_PCRInfo_CreateFromBuffer(&(tpm_stored_data->tpm_seal_info), &(tpm_stored_data->sealInfo)); } else { rc = TPM_PCRInfoLong_CreateFromBuffer (&(((TPM_STORED_DATA12 *)tpm_stored_data)->tpm_seal_info_long), &(tpm_stored_data->sealInfo)); } } /* load encDataSize and encData */ if (rc == 0) { rc = TPM_SizedBuffer_Load(&(tpm_stored_data->encData), stream, stream_size); } return rc; } /* TPM_StoredData_StoreClearData() serializes a TPM_STORED_DATA structure, excluding encData, appending results to 'sbuffer'. Before serializing, it serializes tpm_seal_info to sealInfoSize and sealInfo. This function handles both TPM_STORED_DATA and TPM_STORED_DATA12. serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_StoredData_StoreClearData(TPM_STORE_BUFFER *sbuffer, TPM_STORED_DATA *tpm_stored_data, unsigned int version) { TPM_RESULT rc = 0; printf(" TPM_StoredData_StoreClearData: v%u\n", version); /* 1.1 store ver */ if ((rc == 0) && (version == 1)) { rc = TPM_StructVer_Store(sbuffer, &(tpm_stored_data->ver)); } /* 1.2 store tag */ if ((rc == 0) && (version != 1)) { rc = TPM_Sbuffer_Append16(sbuffer, ((TPM_STORED_DATA12 *)tpm_stored_data)->tag); } /* 1.2 store et */ if ((rc == 0) && (version != 1)) { rc = TPM_Sbuffer_Append16(sbuffer, ((TPM_STORED_DATA12 *)tpm_stored_data)->et); } /* store sealInfoSize and sealInfo */ if (rc == 0) { /* copy cache to sealInfoSize and sealInfo */ if (version == 1) { rc = TPM_SizedBuffer_SetStructure(&(tpm_stored_data->sealInfo), tpm_stored_data->tpm_seal_info, (TPM_STORE_FUNCTION_T)TPM_PCRInfo_Store); } else { rc = TPM_SizedBuffer_SetStructure(&(tpm_stored_data->sealInfo), tpm_stored_data->tpm_seal_info, (TPM_STORE_FUNCTION_T)TPM_PCRInfoLong_Store); } } /* copy sealInfoSize and sealInfo to sbuffer */ if (rc == 0) { rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_stored_data->sealInfo)); } return rc; } /* TPM_StoredData_Store() Before serializing, it serializes tpm_seal_info to sealInfoSize and sealInfo. serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_StoredData_Store(TPM_STORE_BUFFER *sbuffer, TPM_STORED_DATA *tpm_stored_data, unsigned int version) { TPM_RESULT rc = 0; printf(" TPM_StoredData_Store: v%u\n", version); if (rc == 0) { rc = TPM_StoredData_StoreClearData(sbuffer, tpm_stored_data, version); } /* store encDataSize and encData */ if (rc == 0) { rc = TPM_SizedBuffer_Store(sbuffer, &(tpm_stored_data->encData)); } return rc; } /* TPM_StoredData_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_StoredData_Init to set members back to default values The object itself is not freed */ void TPM_StoredData_Delete(TPM_STORED_DATA *tpm_stored_data, unsigned int version) { printf(" TPM_StoredData_Delete: v%u\n", version); if (tpm_stored_data != NULL) { TPM_SizedBuffer_Delete(&(tpm_stored_data->sealInfo)); TPM_SizedBuffer_Delete(&(tpm_stored_data->encData)); if (version == 1) { TPM_PCRInfo_Delete(tpm_stored_data->tpm_seal_info); free(tpm_stored_data->tpm_seal_info); } else { TPM_PCRInfoLong_Delete((TPM_PCR_INFO_LONG *)tpm_stored_data->tpm_seal_info); free(tpm_stored_data->tpm_seal_info); } TPM_StoredData_Init(tpm_stored_data, version); } return; } /* TPM_StoredData_CheckTag() verifies the tag and et members of a TPM_STORED_DATA12 structure */ TPM_RESULT TPM_StoredData_CheckTag(TPM_STORED_DATA12 *tpm_stored_data12) { TPM_RESULT rc = 0; printf(" TPM_StoredData_CheckTag:\n"); if (rc == 0) { if (tpm_stored_data12->tag != TPM_TAG_STORED_DATA12) { printf("TPM_StoredData_CheckTag: Error, tag expected %04x found %04hx\n", TPM_TAG_STORED_DATA12, tpm_stored_data12->tag); rc = TPM_BAD_VERSION; } } return rc; } /* TPM_StoredData_GenerateDigest() generates a TPM_DIGEST over the TPM_STORED_DATA structure excluding the encDataSize and encData members. */ TPM_RESULT TPM_StoredData_GenerateDigest(TPM_DIGEST tpm_digest, TPM_STORED_DATA *tpm_stored_data, unsigned int version) { TPM_RESULT rc = 0; TPM_STORE_BUFFER sbuffer; /* TPM_STORED_DATA serialization */ printf(" TPM_StoredData_GenerateDigest:\n"); TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ /* serialize the TPM_STORED_DATA excluding the encData fields */ if (rc == 0) { rc = TPM_StoredData_StoreClearData(&sbuffer, tpm_stored_data, version); } if (rc == 0) { rc = TPM_SHA1Sbuffer(tpm_digest, &sbuffer); } TPM_Sbuffer_Delete(&sbuffer); /* @1 */ return rc; } /* Processing Functions */ /* TPM_SealCryptCommon() rev 98 Handles the encrypt/decrypt actions common to TPM_Sealx and TPM_Unseal 'encrypt TRUE for encryption, FALSE for decryption The output o1 must be freed by the caller. */ static TPM_RESULT TPM_SealCryptCommon(BYTE **o1, /* freed by caller */ TPM_ADIP_ENC_SCHEME adipEncScheme, TPM_SIZED_BUFFER *inData, TPM_AUTH_SESSION_DATA *auth_session_data, TPM_NONCE nonceOdd) { TPM_RESULT rc = 0; BYTE *x1; /* XOR string, MGF1 output */ TPM_DIGEST ctr; /* symmetric key algorithm CTR */ printf(" TPM_SealCryptCommon:\n"); x1 = NULL; /* freed @1 */ /* allocate for the output o1 */ if (rc == TPM_SUCCESS) { rc = TPM_Malloc(o1, inData->size); /* freed by caller */ } if (rc == TPM_SUCCESS) { TPM_PrintFourLimit(" TPM_SealCryptCommon: input data", inData->buffer, inData->size); } switch (adipEncScheme) { case TPM_ET_XOR: printf(" TPM_SealCryptCommon: TPM_ET_XOR\n"); if (rc == TPM_SUCCESS) { /* i. Use MGF1 to create string X1 of length sealedDataSize. The inputs to MGF1 are; authLastnonceEven, nonceOdd, "XOR", and authHandle -> sharedSecret. The four concatenated values form the Z value that is the seed for MFG1. */ rc = TPM_MGF1_GenerateArray(&x1, /* MGF1 array */ inData->size, /* MGF1 array length */ TPM_NONCE_SIZE + TPM_NONCE_SIZE + sizeof("XOR") -1 + TPM_DIGEST_SIZE, /* seed length */ TPM_NONCE_SIZE, auth_session_data->nonceEven, TPM_NONCE_SIZE, nonceOdd, sizeof("XOR") -1, "XOR", TPM_DIGEST_SIZE, auth_session_data->sharedSecret, 0, NULL); } /* ii. Create o1 by XOR of d1 -> data and X1 */ if (rc == TPM_SUCCESS) { TPM_PrintFour(" TPM_SealCryptCommon: XOR key", x1); TPM_XOR(*o1, inData->buffer, x1, inData->size); } break; case TPM_ET_AES128_CTR: printf(" TPM_SealCryptCommon: TPM_ET_AES128_CTR\n"); /* i. Create o1 by encrypting d1 -> data using the algorithm indicated by inData -> et */ /* ii. Key is from authHandle -> sharedSecret */ /* iii. IV is SHA-1 of (authLastNonceEven || nonceOdd) */ if (rc == TPM_SUCCESS) { rc = TPM_SHA1(ctr, TPM_NONCE_SIZE, auth_session_data->nonceEven, TPM_NONCE_SIZE, nonceOdd, 0, NULL); } if (rc == TPM_SUCCESS) { TPM_PrintFour(" TPM_SealCryptCommon: AES key", auth_session_data->sharedSecret); TPM_PrintFour(" TPM_SealCryptCommon: CTR", ctr); rc = TPM_SymmetricKeyData_CtrCrypt(*o1, /* output data */ inData->buffer, /* input data */ inData->size, /* data size */ auth_session_data->sharedSecret, /* key */ TPM_SECRET_SIZE, /* key size */ ctr, /* CTR */ TPM_DIGEST_SIZE); /* CTR size */ } break; default: printf("TPM_SealCryptCommon: Error, unsupported adipEncScheme %02x\n", adipEncScheme); rc = TPM_INAPPROPRIATE_ENC; break; } if (rc == 0) { TPM_PrintFour(" TPM_SealCryptCommon: output data", *o1); } free(x1); /* @1 */ return rc; } /* 10.1 TPM_Seal rev 110 The SEAL operation allows software to explicitly state the future "trusted" configuration that the platform must be in for the secret to be revealed. The SEAL operation also implicitly includes the relevant platform configuration (PCR-values) when the SEAL operation was performed. The SEAL operation uses the tpmProof value to BIND the blob to an individual TPM. TPM_Seal is used to encrypt private objects that can only be decrypted using TPM_Unseal. */ TPM_RESULT TPM_Process_Seal(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_KEY_HANDLE keyHandle; /* Handle of a loaded key that can perform seal operations. */ TPM_ENCAUTH encAuth; /* The encrypted authorization data for the sealed data. */ TPM_SIZED_BUFFER pcrInfo; /* The PCR selection information. The caller MAY use TPM_PCR_INFO_LONG. */ TPM_SIZED_BUFFER inData; /* The data to be sealed to the platform and any specified PCRs */ TPM_AUTHHANDLE authHandle; /* The authorization handle used for keyHandle authorization. Must be an OS_AP session for this command. */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* Ignored */ TPM_AUTHDATA pubAuth; /* The authorization digest for inputs and keyHandle. HMAC key: key.usageAuth. */ /* processing */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_SECRET *hmacKey; TPM_KEY *key = NULL; /* the key specified by keyHandle */ TPM_SECRET *keyUsageAuth; TPM_BOOL parentPCRStatus; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ unsigned int v1PcrVersion = 1; /* pcrInfo version */ TPM_STORED_DATA12 *s1_12; TPM_PCR_INFO tpm_pcr_info; /* deserialized pcrInfo v1 */ TPM_PCR_INFO_LONG tpm_pcr_info_long; /* deserialized pcrInfo v2 */ unsigned char *stream; uint32_t stream_size; TPM_DIGEST a1Auth; TPM_SEALED_DATA s2SealedData; /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_STORED_DATA s1StoredData; /* Encrypted, integrity-protected data object that is the result of the TPM_Seal operation. Returned as SealedData */ printf("TPM_Process_Seal: Ordinal Entry\n"); TPM_SizedBuffer_Init(&pcrInfo); /* freed @1 */ TPM_SizedBuffer_Init(&inData); /* freed @2 */ TPM_StoredData_Init(&s1StoredData, v1PcrVersion); /* freed @3, default is v1 */ TPM_PCRInfo_Init(&tpm_pcr_info); /* freed @4 */ TPM_PCRInfoLong_Init(&tpm_pcr_info_long); /* freed @5 */ TPM_SealedData_Init(&s2SealedData); /* freed @6 */ s1_12 = (TPM_STORED_DATA12 *)&s1StoredData; /* to avoid casts */ /* get inputs */ /* get keyHandle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&keyHandle, &command, ¶mSize); } /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get encAuth parameter */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_Seal: keyHandle %08x\n", keyHandle); returnCode = TPM_Authdata_Load(encAuth, &command, ¶mSize); } /* get pcrInfo parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_Load(&pcrInfo, &command, ¶mSize); } /* get inData parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_Load(&inData, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_Seal: Sealing %u bytes\n", inData.size); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag1(tag); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, pubAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_Seal: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* get the key corresponding to the keyHandle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyHandleEntries_GetKey(&key, &parentPCRStatus, tpm_state, keyHandle, FALSE, /* not r/o, using to encrypt */ FALSE, /* do not ignore PCRs */ FALSE); /* cannot use EK */ } /* get keyHandle -> usageAuth */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Key_GetUsageAuth(&keyUsageAuth, key); } /* get the session data */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_OSAP, TPM_ET_KEYHANDLE, ordinal, key, NULL, /* OIAP */ key->tpm_store_asymkey->pubDataDigest); /* OSAP */ } /* 1. Validate the authorization to use the key pointed to by keyHandle */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, pubAuth); /* Authorization digest for input */ } /* 2. If the inDataSize is 0 the TPM returns TPM_BAD_PARAMETER */ if (returnCode == TPM_SUCCESS) { if (inData.size == 0) { printf("TPM_Process_Seal: Error, inDataSize is 0\n"); returnCode = TPM_BAD_PARAMETER; } } /* 3. If the keyUsage field of the key indicated by keyHandle does not have the value TPM_KEY_STORAGE, the TPM must return the error code TPM_INVALID_KEYUSAGE. */ if (returnCode == TPM_SUCCESS) { if (key->keyUsage != TPM_KEY_STORAGE) { printf("TPM_Process_Seal: Error, key keyUsage %04hx must be TPM_KEY_STORAGE\n", key->keyUsage); returnCode = TPM_INVALID_KEYUSAGE; } } /* 4. If the keyHandle points to a migratable key then the TPM MUST return the error code TPM_INVALID_KEY_USAGE. */ if (returnCode == TPM_SUCCESS) { if (key->keyFlags & TPM_MIGRATABLE) { printf("TPM_Process_Seal: Error, key keyFlags %08x indicates migratable\n", key->keyFlags); returnCode = TPM_INVALID_KEYUSAGE; } } /* 5. Determine the version of pcrInfo */ if (returnCode == TPM_SUCCESS) { /* a. If pcrInfoSize is 0 */ if (pcrInfo.size == 0) { v1PcrVersion = 1; /* i. set V1 to 1 */ } else { /* b. Else */ /* i. Point X1 as TPM_PCR_INFO_LONG structure to pcrInfo */ /* ii. If X1 -> tag is TPM_TAG_PCR_INFO_LONG */ if (htons(*(uint16_t *)(pcrInfo.buffer)) == TPM_TAG_PCR_INFO_LONG) { v1PcrVersion = 2; /* (1) Set V1 to 2 */ } else { /* iii. Else */ v1PcrVersion = 1; /* (1) Set V1 to 1 */ } } /* 6. If V1 is 1 then */ /* a. Create S1 a TPM_STORED_DATA structure */ /* 7. else */ /* a. Create S1 a TPM_STORED_DATA12 structure */ /* b. Set S1 -> et to 0 */ /* 8. Set S1 -> encDataSize to 0 */ /* 9. Set S1 -> encData to all zeros */ printf("TPM_Process_Seal: V%u\n", v1PcrVersion); TPM_StoredData_Init(&s1StoredData, v1PcrVersion); /* 10. Set S1 -> sealInfoSize to pcrInfoSize */ /* NOTE This step is unnecessary. If pcrInfoSize is 0, sealInfoSize is already initialized to 0. If pcrInfoSize is non-zero, sealInfoSize is the result of serialization of the tpm_seal_info member, which is either a TPM_PCR_INFO or a TPM_PCR_INFO_LONG */ } /* 11. If pcrInfoSize is not 0 then */ if ((returnCode == TPM_SUCCESS) && (pcrInfo.size != 0)) { printf("TPM_Process_Seal: Creating PCR digest\n"); /* assign the stream, so pcrInfo is not altered */ stream = pcrInfo.buffer; stream_size = pcrInfo.size; /* a. if V1 is 1 then */ if (v1PcrVersion == 1) { /* i. Validate pcrInfo as a valid TPM_PCR_INFO structure, return TPM_BADINDEX on error */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_PCRInfo_Load(&tpm_pcr_info, &stream, &stream_size); if (returnCode != 0) { returnCode = TPM_BADINDEX; } } /* build the TPM_STORED_DATA S1 structure */ if (returnCode == TPM_SUCCESS) { /* ii. Set S1 -> sealInfo -> pcrSelection to pcrInfo -> pcrSelection */ returnCode = TPM_PCRInfo_CreateFromBuffer(&(s1StoredData.tpm_seal_info), &pcrInfo); } /* iii. Create h1 the composite hash of the PCR selected by pcrInfo -> pcrSelection */ /* iv. Set S1 -> sealInfo -> digestAtCreation to h1 */ /* NOTE hash directly to destination. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_PCRSelection_GenerateDigest(s1StoredData.tpm_seal_info->digestAtCreation, &(tpm_pcr_info.pcrSelection), tpm_state->tpm_stclear_data.PCRS); } /* v. Set S1 -> sealInfo -> digestAtRelease to pcrInfo -> digestAtRelease */ /* NOTE digestAtRelease copied during TPM_PCRInfo_CreateFromBuffer() */ } /* b. else (v1 is 2) */ else { /* i. Validate pcrInfo as a valid TPM_PCR_INFO_LONG structure, return TPM_BADINDEX on error */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_PCRInfoLong_Load(&tpm_pcr_info_long, &stream, &stream_size); if (returnCode != 0) { returnCode = TPM_BADINDEX; } } /* build the TPM_STORED_DATA S1 structure */ if (returnCode == TPM_SUCCESS) { /* ii. Set S1 -> sealInfo -> creationPCRSelection to pcrInfo -> creationPCRSelection */ /* iii. Set S1 -> sealInfo -> releasePCRSelection to pcrInfo -> releasePCRSelection */ /* iv. Set S1 -> sealInfo -> digestAtRelease to pcrInfo -> digestAtRelease */ /* v. Set S1 -> sealInfo -> localityAtRelease to pcrInfo -> localityAtRelease */ /* NOTE copied during TPM_PCRInfoLong_CreateFromBuffer() */ returnCode = TPM_PCRInfoLong_CreateFromBuffer(&(s1_12->tpm_seal_info_long), &pcrInfo); } if (returnCode == TPM_SUCCESS) { /* vi. Create h2 the composite hash of the PCR selected by pcrInfo -> creationPCRSelection */ /* vii. Set S1 -> sealInfo -> digestAtCreation to h2 */ /* NOTE hash directly to destination. */ returnCode = TPM_PCRSelection_GenerateDigest(s1_12->tpm_seal_info_long->digestAtCreation, &(tpm_pcr_info_long.creationPCRSelection), tpm_state->tpm_stclear_data.PCRS); } /* viii. Set S1 -> sealInfo -> localityAtCreation to TPM_STANY_FLAGS -> localityModifier */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Locality_Set(&(s1_12->tpm_seal_info_long->localityAtCreation), tpm_state->tpm_stany_flags.localityModifier); } } } /* 12. Create a1 by decrypting encAuth according to the ADIP indicated by authHandle. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessionData_Decrypt(a1Auth, NULL, encAuth, auth_session_data, NULL, NULL, FALSE); /* even and odd */ } /* 13. The TPM provides NO validation of a1. Well-known values (like all zeros) are valid and possible. */ /* 14. Create S2 a TPM_SEALED_DATA structure */ if (returnCode == TPM_SUCCESS) { /* a. Set S2 -> payload to TPM_PT_SEAL */ /* NOTE: Done at TPM_SealedData_Init() */ /* b. Set S2 -> tpmProof to TPM_PERMANENT_DATA -> tpmProof */ TPM_Secret_Copy(s2SealedData.tpmProof, tpm_state->tpm_permanent_data.tpmProof); /* c. Create h3 the SHA-1 of S1 */ /* d. Set S2 -> storedDigest to h3 */ returnCode = TPM_StoredData_GenerateDigest(s2SealedData.storedDigest, &s1StoredData, v1PcrVersion); } if (returnCode == TPM_SUCCESS) { /* e. Set S2 -> authData to a1 */ TPM_Secret_Copy(s2SealedData.authData, a1Auth); /* f. Set S2 -> dataSize to inDataSize */ /* g. Set S2 -> data to inData */ returnCode = TPM_SizedBuffer_Copy(&(s2SealedData.data), &inData); } /* 15. Validate that the size of S2 can be encrypted by the key pointed to by keyHandle, return TPM_BAD_DATASIZE on error */ /* 16. Create s3 the encryption of S2 using the key pointed to by keyHandle */ /* 17. Set continueAuthSession to FALSE */ if (returnCode == TPM_SUCCESS) { continueAuthSession = FALSE; } /* 18. Set S1 -> encDataSize to the size of s3 */ /* 19. Set S1 -> encData to s3 */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SealedData_GenerateEncData(&(s1StoredData.encData), &s2SealedData, key); } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_Seal: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* 20. Return S1 as sealedData */ returnCode = TPM_StoredData_Store(response, &s1StoredData, v1PcrVersion); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* owner HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ TPM_SizedBuffer_Delete(&pcrInfo); /* @1 */ TPM_SizedBuffer_Delete(&inData); /* @2 */ TPM_StoredData_Delete(&s1StoredData, v1PcrVersion); /* @3 */ TPM_PCRInfo_Delete(&tpm_pcr_info); /* @4 */ TPM_PCRInfoLong_Delete(&tpm_pcr_info_long); /* @5 */ TPM_SealedData_Delete(&s2SealedData); /* @6 */ return rcf; } /* 10.7 TPM_Sealx rev 110 The TPM_Sealx command works exactly like the TPM_Seal command with the additional requirement of encryption for the inData parameter. This command also places in the sealed blob the information that the TPM_Unseal also requires encryption. TPM_Sealx requires the use of 1.2 data structures. The actions are the same as TPM_Seal without the checks for 1.1 data structure usage. */ TPM_RESULT TPM_Process_Sealx(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_KEY_HANDLE keyHandle; /* Handle of a loaded key that can perform seal operations. */ TPM_ENCAUTH encAuth; /* The encrypted authorization data for the sealed data */ TPM_SIZED_BUFFER pcrInfo; /* If 0 there are no PCR registers in use. pcrInfo MUST use TPM_PCR_INFO_LONG */ TPM_SIZED_BUFFER inData; /* The data to be sealed to the platform and any specified PCRs */ TPM_AUTHHANDLE authHandle; /* The authorization session handle used for keyHandle authorization. Must be an OSAP session for this command. */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* Ignored */ TPM_AUTHDATA pubAuth; /* The authorization digest for inputs and keyHandle. HMAC key: key.usageAuth. */ /* processing */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_SECRET *hmacKey; TPM_KEY *key = NULL; /* the key specified by keyHandle */ TPM_SECRET *keyUsageAuth; TPM_BOOL parentPCRStatus; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_STORED_DATA12 s1StoredData; /* Encrypted, integrity-protected data object that is the result of the TPM_Seal operation. Returned as SealedData */ TPM_STORED_DATA *s1_11; /* 1.1 version to avoid casts */ TPM_SEALED_DATA s2SealedData; TPM_DIGEST a1Auth; BYTE *o1DecryptedData; printf("TPM_Process_Sealx: Ordinal Entry\n"); s1_11 = (TPM_STORED_DATA *)&s1StoredData; /* 1.1 version to avoid casts */ TPM_SizedBuffer_Init(&pcrInfo); /* freed @1 */ TPM_SizedBuffer_Init(&inData); /* freed @2 */ TPM_StoredData_Init(s1_11, 2); /* freed @3 */ TPM_SealedData_Init(&s2SealedData); /* freed @4 */ o1DecryptedData = NULL; /* freed @5 */ /* get inputs */ /* get keyHandle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&keyHandle, &command, ¶mSize); } /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get encAuth parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Authdata_Load(encAuth, &command, ¶mSize); } /* get pcrInfo parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_Load(&pcrInfo, &command, ¶mSize); } /* get inData parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_Load(&inData, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_Sealx: Sealing %u bytes\n", inData.size); TPM_PrintFourLimit("TPM_Process_Sealx: Sealing data", inData.buffer, inData.size); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag1(tag); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, pubAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_Sealx: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* get the key corresponding to the keyHandle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyHandleEntries_GetKey(&key, &parentPCRStatus, tpm_state, keyHandle, FALSE, /* not r/o, using to encrypt */ FALSE, /* do not ignore PCRs */ FALSE); /* cannot use EK */ } /* get keyHandle -> usageAuth */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Key_GetUsageAuth(&keyUsageAuth, key); } /* get the session data */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_OSAP, TPM_ET_KEYHANDLE, ordinal, key, NULL, /* OIAP */ key->tpm_store_asymkey->pubDataDigest); /* OSAP */ } /* 1. Validate the authorization to use the key pointed to by keyHandle */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, pubAuth); /* Authorization digest for input */ } /* 2. If the inDataSize is 0 the TPM returns TPM_BAD_PARAMETER */ if (returnCode == TPM_SUCCESS) { if (inData.size == 0) { printf("TPM_Process_Sealx: Error, inDataSize is 0\n"); returnCode = TPM_BAD_PARAMETER; } } /* 3. If the keyUsage field of the key indicated by keyHandle does not have the value TPM_KEY_STORAGE, the TPM must return the error code TPM_INVALID_KEYUSAGE. */ if (returnCode == TPM_SUCCESS) { if (key->keyUsage != TPM_KEY_STORAGE) { printf("TPM_Process_Sealx: Error, key keyUsage %04hx must be TPM_KEY_STORAGE\n", key->keyUsage); returnCode = TPM_INVALID_KEYUSAGE; } } /* 4. If the keyHandle points to a migratable key then the TPM MUST return the error code TPM_INVALID_KEY_USAGE. */ if (returnCode == TPM_SUCCESS) { if (key->keyFlags & TPM_MIGRATABLE) { printf("TPM_Process_Sealx: Error, key keyFlags %08x indicates migratable\n", key->keyFlags); returnCode = TPM_INVALID_KEYUSAGE; } } /* 5. Create S1 a TPM_STORED_DATA12 structure */ /* 6. Set S1 -> encDataSize to 0 */ /* 7. Set S1 -> encData to all zeros */ /* NOTE: Done by TPM_StoredData_Init() */ /* 8. Set S1 -> sealInfoSize to pcrInfoSize */ /* NOTE This step is unnecessary. If pcrInfoSize is 0, sealInfoSize is already initialized to 0. If pcrInfoSize is non-zero, sealInfoSize is the result of serialization of the tpm_seal_info member, which is a TPM_PCR_INFO_LONG */ /* 9. If pcrInfoSize is not 0 then */ if ((returnCode == TPM_SUCCESS) && (pcrInfo.size != 0)) { printf("TPM_Process_Sealx: Setting sealInfo to pcrInfo\n"); /* initializing the s -> TPM_PCR_INFO_LONG cache to the contents of pcrInfo */ /* a. Validate pcrInfo as a valid TPM_PCR_INFO_LONG structure, return TPM_BADINDEX on error */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_PCRInfoLong_CreateFromBuffer(&(s1StoredData.tpm_seal_info_long), &pcrInfo); if (returnCode != TPM_SUCCESS) { returnCode = TPM_BADINDEX; } } /* b. Set S1 -> sealInfo -> creationPCRSelection to pcrInfo -> creationPCRSelection */ /* c. Set S1 -> sealInfo -> releasePCRSelection to pcrInfo -> releasePCRSelection */ /* d. Set S1 -> sealInfo -> digestAtRelease to pcrInfo -> digestAtRelease */ /* e. Set S1 -> sealInfo -> localityAtRelease to pcrInfo -> localityAtRelease */ /* NOTE copied during TPM_PCRInfoLong_CreateFromBuffer() */ /* f. Create h2 the composite hash of the PCR selected by pcrInfo -> creationPCRSelection */ /* g. Set S1 -> sealInfo -> digestAtCreation to h2 */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_PCRSelection_GenerateDigest (s1StoredData.tpm_seal_info_long->digestAtCreation, &(s1StoredData.tpm_seal_info_long->creationPCRSelection), tpm_state->tpm_stclear_data.PCRS); } /* h. Set S1 -> sealInfo -> localityAtCreation to TPM_STANY_DATA -> localityModifier */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Locality_Set(&(s1StoredData.tpm_seal_info_long->localityAtCreation), tpm_state->tpm_stany_flags.localityModifier); } } /* 10. Create S2 a TPM_SEALED_DATA structure */ /* NOTE: Done at TPM_SealedData_Init() */ /* 11.Create a1 by decrypting encAuth according to the ADIP indicated by authHandle. */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_Sealx: Decrypting encAuth\n"); returnCode = TPM_AuthSessionData_Decrypt(a1Auth, /* a1 even */ NULL, /* a1 odd (2nd encAuth) */ encAuth, /* encAuthEven */ auth_session_data, NULL, /* nonceOdd */ NULL, /* encAuthOdd */ FALSE); /* even and odd */ } if (returnCode == TPM_SUCCESS) { TPM_PrintFour("TPM_Process_Sealx: Decrypted Auth", a1Auth); /* a. If authHandle indicates XOR encryption for the AuthData secrets */ if (auth_session_data->adipEncScheme == TPM_ET_XOR) { /* i. Set S1 -> et to TPM_ET_XOR || TPM_ET_KEY */ /* (1) TPM_ET_KEY is added because TPM_Unseal uses zero as a special value indicating no encryption. */ s1StoredData.et = TPM_ET_XOR | TPM_ET_KEY; } /* b. Else */ else { /* i. Set S1 -> et to algorithm indicated by authHandle */ s1StoredData.et = auth_session_data->adipEncScheme << 8; } } /* 12. The TPM provides NO validation of a1. Well-known values (like all zeros) are valid and possible. */ /* 13. If authHandle indicates XOR encryption */ /* a. Use MGF1 to create string X2 of length inDataSize. The inputs to MGF1 are; authLastNonceEven, nonceOdd, "XOR", and authHandle -> sharedSecret. The four concatenated values form the Z value that is the seed for MFG1. */ /* b. Create o1 by XOR of inData and x2 */ /* 14. Else */ /* a. Create o1 by decrypting inData using the algorithm indicated by authHandle */ /* b. Key is from authHandle -> sharedSecret */ /* c. CTR is SHA-1 of (authLastNonceEven || nonceOdd) */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_Sealx: decrypting inData\n"); returnCode = TPM_SealCryptCommon(&o1DecryptedData, /* freed by caller */ auth_session_data->adipEncScheme, &inData, auth_session_data, nonceOdd); } /* 15. Create S2 a TPM_SEALED_DATA structure */ if (returnCode == TPM_SUCCESS) { /* a. Set S2 -> payload to TPM_PT_SEAL */ /* NOTE: Done at TPM_SealedData_Init() */ /* b. Set S2 -> tpmProof to TPM_PERMANENT_DATA -> tpmProof */ TPM_Secret_Copy(s2SealedData.tpmProof, tpm_state->tpm_permanent_data.tpmProof); /* c. Create h3 the SHA-1 of S1 */ /* d. Set S2 -> storedDigest to h3 */ returnCode = TPM_StoredData_GenerateDigest(s2SealedData.storedDigest, s1_11, 2); } /* e. Set S2 -> authData to a1 */ if (returnCode == TPM_SUCCESS) { TPM_Secret_Copy(s2SealedData.authData, a1Auth); /* f. Set S2 -> dataSize to inDataSize */ /* g. Set S2 -> data to o1 */ returnCode = TPM_SizedBuffer_Set(&(s2SealedData.data), inData.size, o1DecryptedData); } /* 16. Validate that the size of S2 can be encrypted by the key pointed to by keyHandle, return */ /* TPM_BAD_DATASIZE on error */ /* 17. Create s3 the encryption of S2 using the key pointed to by keyHandle */ /* 18. Set continueAuthSession to FALSE */ if (returnCode == TPM_SUCCESS) { continueAuthSession = FALSE; } /* 19. Set S1 -> encDataSize to the size of s3 */ /* 20. Set S1 -> encData to s3 */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_Sealx: Encrypting sealed data\n"); returnCode = TPM_SealedData_GenerateEncData(&(s1StoredData.encData), &s2SealedData, key); } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_Sealx: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* 21. Return S1 as sealedData */ returnCode = TPM_StoredData_Store(response, s1_11, 2); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* owner HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ TPM_SizedBuffer_Delete(&pcrInfo); /* @1 */ TPM_SizedBuffer_Delete(&inData); /* @2 */ TPM_StoredData_Delete(s1_11, 2); /* @3 */ TPM_SealedData_Delete(&s2SealedData); /* @4 */ free(o1DecryptedData); /* @5 */ return rcf; } /* 10.2 TPM_Unseal rev 110 The TPM_Unseal operation will reveal TPM_Sealed data only if it was encrypted on this platform and the current configuration (as defined by the named PCR contents) is the one named as qualified to decrypt it. Internally, TPM_Unseal accepts a data blob generated by a TPM_Seal operation. TPM_Unseal decrypts the structure internally, checks the integrity of the resulting data, and checks that the PCR named has the value named during TPM_Seal. Additionally, the caller must supply appropriate authorization data for blob and for the key that was used to seal that data. If the integrity, platform configuration and authorization checks succeed, the sealed data is returned to the caller; otherwise, an error is generated. */ TPM_RESULT TPM_Process_Unseal(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_KEY_HANDLE parentHandle; /* Handle of a loaded key that can unseal the data. */ TPM_STORED_DATA inData; /* The encrypted data generated by TPM_Seal. */ TPM_AUTHHANDLE authHandle; /* The authorization handle used for parentHandle. */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization handle */ TPM_AUTHDATA parentAuth; /* The authorization digest for inputs and parentHandle. HMAC key: parentKey.usageAuth. */ TPM_AUTHHANDLE dataAuthHandle; /* The authorization handle used to authorize inData. */ TPM_NONCE datanonceOdd; /* Nonce generated by system associated with entityAuthHandle */ TPM_BOOL continueDataSession = TRUE; /* Continue usage flag for dataAuthHandle. */ TPM_AUTHDATA dataAuth; /* The authorization digest for the encrypted entity. HMAC key: entity.usageAuth. */ /* processing */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_BOOL dataAuthHandleValid = FALSE; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ TPM_AUTH_SESSION_DATA *data_auth_session_data = NULL; /* session data for dataAuthHandle */ TPM_SECRET *hmacKey; TPM_SECRET *dataHmacKey; unsigned int v1StoredDataVersion = 1; /* version of TPM_STORED_DATA inData */ TPM_KEY *parentKey; TPM_BOOL parentPCRStatus; TPM_SECRET *parentUsageAuth; TPM_SEALED_DATA d1SealedData; TPM_DIGEST h1StoredDataDigest; TPM_STORED_DATA12 *s2StoredData; BYTE *o1Encrypted; /* For ADIP encryption */ TPM_ADIP_ENC_SCHEME adipEncScheme; /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; uint32_t secretSize = 0; /* Decrypted data that had been sealed */ BYTE *secret = NULL; printf("TPM_Process_Unseal: Ordinal Entry\n"); TPM_StoredData_Init(&inData, v1StoredDataVersion); /* freed @1, default is v1 */ TPM_SealedData_Init(&d1SealedData); /* freed @2 */ o1Encrypted = NULL; /* freed @3 */ s2StoredData = (TPM_STORED_DATA12 *)&inData; /* inData when it's a TPM_STORED_DATA12 structure */ /* get inputs */ /* get parentHandle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&parentHandle, &command, ¶mSize); } /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get inData parameter */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_Unseal: parentHandle %08x\n", parentHandle); returnCode = TPM_StoredData_Load(&inData, &v1StoredDataVersion, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_Unseal: inData is v%u\n", v1StoredDataVersion); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag21(tag); } /* get the optional 'below the line' authorization parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, parentAuth, &command, ¶mSize); } if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { printf("TPM_Process_Unseal: authHandle %08x\n", authHandle); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Get(&dataAuthHandle, &dataAuthHandleValid, datanonceOdd, &continueDataSession, dataAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_Unseal: dataAuthHandle %08x\n", dataAuthHandle); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_Unseal: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; dataAuthHandleValid = FALSE; } /* Processing */ /* Verify that parentHandle points to a valid key. Get the TPM_KEY associated with parentHandle */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyHandleEntries_GetKey(&parentKey, &parentPCRStatus, tpm_state, parentHandle, FALSE, /* not r/o, using to decrypt */ FALSE, /* do not ignore PCRs */ FALSE); /* cannot use EK */ } /* get parentHandle -> usageAuth */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { returnCode = TPM_Key_GetUsageAuth(&parentUsageAuth, parentKey); } /* get the first session data */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_KEYHANDLE, ordinal, parentKey, parentUsageAuth, /* OIAP */ parentKey->tpm_store_asymkey->pubDataDigest); /*OSAP*/ } /* 1. The TPM MUST validate that parentAuth authorizes the use of the key in parentHandle, on error return TPM_AUTHFAIL */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, parentAuth); /* Authorization digest for input */ } /* if there are no parent auth parameters */ if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_AUTH2_COMMAND)) { if (parentKey->authDataUsage != TPM_AUTH_NEVER) { printf("TPM_Process_Unseal: Error, parent key authorization required\n"); returnCode = TPM_AUTHFAIL; } } /* 2. If the keyUsage field of the key indicated by parentHandle does not have the value TPM_KEY_STORAGE, the TPM MUST return the error code TPM_INVALID_KEYUSAGE. */ if (returnCode == TPM_SUCCESS) { if (parentKey->keyUsage != TPM_KEY_STORAGE) { printf("TPM_Process_Unseal: Error, key keyUsage %04hx must be TPM_KEY_STORAGE\n", parentKey->keyUsage); returnCode = TPM_INVALID_KEYUSAGE; } } /* 3. The TPM MUST check that the TPM_KEY_FLAGS -> Migratable flag has the value FALSE in the key indicated by parentKeyHandle. If not, the TPM MUST return the error code TPM_INVALID_KEYUSAGE */ if (returnCode == TPM_SUCCESS) { if (parentKey->keyFlags & TPM_MIGRATABLE) { printf("TPM_Process_Unseal: Error, key keyFlags %08x indicates migratable\n", parentKey->keyFlags); returnCode = TPM_INVALID_KEYUSAGE; } } /* 4. Determine the version of inData */ /* a. If inData -> tag = TPM_TAG_STORED_DATA12 */ /* i. Set V1 to 2 */ /* ii. Map S2 a TPM_STORED_DATA12 structure to inData */ /* b. Else If inData -> ver = 1.1 */ /* i. Set V1 to 1 */ /* ii. Map S2 a TPM_STORED_DATA structure to inData */ /* c. Else */ /* i. Return TPM_BAD_VERSION */ /* NOTE: Done during TPM_StoredData_Load() */ /* The extra indent of error checking is required because the next steps all return TPM_NOTSEALED_BLOB on error */ if (returnCode == TPM_SUCCESS) { /* 5. Create d1 by decrypting S2 -> encData using the key pointed to by parentHandle */ printf("TPM_Process_Unseal: Decrypting encData\n"); if (returnCode == TPM_SUCCESS) { returnCode = TPM_SealedData_DecryptEncData(&d1SealedData, /* TPM_SEALED_DATA */ &(inData.encData), parentKey); } /* 6. Validate d1 */ /* a. d1 MUST be a TPM_SEALED_DATA structure */ /* NOTE Done during TPM_SealedData_DecryptEncData() */ /* b. d1 -> tpmProof MUST match TPM_PERMANENT_DATA -> tpmProof */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_Unseal: Sealed data size %u\n", d1SealedData.data.size); TPM_PrintFour("TPM_Process_Unseal: Sealed data", d1SealedData.data.buffer); printf("TPM_Process_Unseal: Checking tpmProof\n"); returnCode = TPM_Secret_Compare(d1SealedData.tpmProof, tpm_state->tpm_permanent_data.tpmProof); } if (returnCode == TPM_SUCCESS) { /* c. Set S2 -> encDataSize to 0 */ /* d. Set S2 -> encData to all zeros */ /* NOTE: This would be done at cleanup */ TPM_SizedBuffer_Delete(&(inData.encData)); /* e. Create h1 the SHA-1 of S2 */ returnCode = TPM_StoredData_GenerateDigest(h1StoredDataDigest, &inData, v1StoredDataVersion); } /* f. d1 -> storedDigest MUST match h1 */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_Unseal: Checking storedDigest\n"); returnCode = TPM_Digest_Compare(d1SealedData.storedDigest, h1StoredDataDigest); } /* g. d1 -> payload MUST be TPM_PT_SEAL */ if (returnCode == TPM_SUCCESS) { if (d1SealedData.payload != TPM_PT_SEAL) { printf("TPM_Process_Unseal: Error, payload %02x not TPM_PT_SEAL\n", d1SealedData.payload); returnCode = TPM_NOTSEALED_BLOB; } } /* h. Any failure MUST return TPM_NOTSEALED_BLOB */ if (returnCode != TPM_SUCCESS) { returnCode = TPM_NOTSEALED_BLOB; } } /* 7. If S2 -> sealInfo is not 0 then */ /* NOTE: Done by _CheckDigest() */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_Unseal: Checking PCR digest\n"); /* a. If V1 is 1 then */ if (v1StoredDataVersion == 1) { /* i. Validate that S2 -> pcrInfo is a valid TPM_PCR_INFO structure */ /* NOTE: Done during TPM_StoredData_Load() */ /* ii. Create h2 the composite hash of the PCR selected by S2 -> pcrInfo -> pcrSelection */ /* c. Compare h2 with S2 -> pcrInfo -> digestAtRelease, on mismatch return TPM_WRONGPCRVALUE */ returnCode = TPM_PCRInfo_CheckDigest(inData.tpm_seal_info, tpm_state->tpm_stclear_data.PCRS); /* PCR array */ } /* b. If V1 is 2 then */ else { /* i. Validate that S2 -> pcrInfo is a valid TPM_PCR_INFO_LONG structure */ /* NOTE: Done during TPM_StoredData_Load() */ /* ii. Create h2 the composite hash of the PCR selected by S2 -> pcrInfo -> releasePCRSelection */ /* iii. Check that S2 -> pcrInfo -> localityAtRelease for TPM_STANY_DATA -> localityModifier is TRUE */ /* (1) For example if TPM_STANY_DATA -> localityModifier was 2 then S2 -> pcrInfo -> localityAtRelease -> TPM_LOC_TWO would have to be TRUE */ /* c. Compare h2 with S2 -> pcrInfo -> digestAtRelease, on mismatch return TPM_WRONGPCRVALUE */ returnCode = TPM_PCRInfoLong_CheckDigest(s2StoredData->tpm_seal_info_long, tpm_state->tpm_stclear_data.PCRS, /* PCR array */ tpm_state->tpm_stany_flags.localityModifier); } } /* 8. The TPM MUST validate authorization to use d1 by checking that the HMAC calculation using d1 -> authData as the shared secret matches the dataAuth. Return TPM_AUTHFAIL on mismatch. */ /* get the second session data */ /* NOTE: While OSAP isn't specifically excluded, there is currently no way to set up an OSAP session using TPM_SEALED_DATA as the entity */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetData(&data_auth_session_data, &dataHmacKey, tpm_state, dataAuthHandle, TPM_PID_OIAP, /* currently require OIAP */ 0, /* OSAP entity type */ ordinal, NULL, &(d1SealedData.authData), /* OIAP */ NULL); /* OSAP */ } if (returnCode == TPM_SUCCESS) { returnCode = TPM_Auth2data_Check(tpm_state, *dataHmacKey, /* HMAC key */ inParamDigest, data_auth_session_data, /* authorization session */ datanonceOdd, /* Nonce generated by system associated with authHandle */ continueDataSession, dataAuth); /* Authorization digest for input */ } if (returnCode == TPM_SUCCESS) { /* 9. If V1 is 2 and S2 -> et specifies encryption (i.e. is not all zeros) then */ if ((v1StoredDataVersion == 2) && (s2StoredData->et != 0x0000)) { /* a. If tag is not TPM_TAG_RQU_AUTH2_COMMAND, return TPM_AUTHFAIL */ if (returnCode == TPM_SUCCESS) { if (tag != TPM_TAG_RQU_AUTH2_COMMAND) { printf("TPM_Process_Unseal: Error, sealed with encryption but auth-1\n"); returnCode = TPM_AUTHFAIL; } } /* b. Verify that the authHandle session type is TPM_PID_OSAP or TPM_PID_DSAP, return TPM_BAD_MODE on error. */ if (returnCode == TPM_SUCCESS) { if ((auth_session_data->protocolID != TPM_PID_OSAP) && (auth_session_data->protocolID != TPM_PID_DSAP)) { printf("TPM_Process_Unseal: Error, sealed with encryption but OIAP\n"); returnCode = TPM_BAD_MODE; } } /* c. If MSB of S2 -> et is TPM_ET_XOR */ /* i. Use MGF1 to create string X1 of length sealedDataSize. The inputs to MGF1 are; authLastnonceEven, nonceOdd, "XOR", and authHandle -> sharedSecret. The four concatenated values form the Z value that is the seed for MFG1. */ /* d. Else */ /* i. Create o1 by encrypting d1 -> data using the algorithm indicated by inData -> et */ /* ii. Key is from authHandle -> sharedSecret */ /* iii. IV is SHA-1 of (authLastNonceEven || nonceOdd) */ if (returnCode == TPM_SUCCESS) { /* entity type MSB is ADIP encScheme */ adipEncScheme = (s2StoredData->et >> 8) & 0x00ff; printf("TPM_Process_Unseal: Encrypting the output, encScheme %02x\n", adipEncScheme); returnCode = TPM_SealCryptCommon(&o1Encrypted, adipEncScheme, &(d1SealedData.data), auth_session_data, nonceOdd); secretSize = d1SealedData.data.size; secret = o1Encrypted; } /* e. Set continueAuthSession to FALSE */ continueAuthSession = FALSE; } /* 10. else */ else { printf("TPM_Process_Unseal: No output encryption\n"); /* a. Set o1 to d1 -> data */ secretSize = d1SealedData.data.size; secret = d1SealedData.data.buffer; } } /* 11. Set the return secret as o1 */ /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_Unseal: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* return secretSize */ returnCode = TPM_Sbuffer_Append32(response, secretSize); } if (returnCode == TPM_SUCCESS) { /* return secret */ returnCode = TPM_Sbuffer_Append(response, secret, secretSize); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* calculate and set the below the line parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Set(response, *dataHmacKey, /* HMAC key */ data_auth_session_data, outParamDigest, datanonceOdd, continueDataSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueDataSession) && dataAuthHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, dataAuthHandle); } /* cleanup */ TPM_StoredData_Delete(&inData, v1StoredDataVersion); /* @1 */ TPM_SealedData_Delete(&d1SealedData); /* @2 */ free(o1Encrypted); /* @3 */ return rcf; } /* 10.3 TPM_UnBind rev 87 TPM_UnBind takes the data blob that is the result of a Tspi_Data_Bind command and decrypts it for export to the User. The caller must authorize the use of the key that will decrypt the incoming blob. UnBind operates on a block-by-block basis, and has no notion of any relation between one block and another. UnBind SHALL operate on a single block only. */ TPM_RESULT TPM_Process_UnBind(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_KEY_HANDLE keyHandle; /* The keyHandle identifier of a loaded key that can perform UnBind operations. */ TPM_SIZED_BUFFER inData; /* Encrypted blob to be decrypted */ TPM_AUTHHANDLE authHandle; /* The handle used for keyHandle authorization */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization handle */ TPM_AUTHDATA privAuth; /* The authorization digest that authorizes the inputs and use of keyHandle. HMAC key: key.usageAuth. */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_SECRET *hmacKey; TPM_KEY *key = NULL; /* the key specified by keyHandle */ TPM_SECRET *keyUsageAuth; TPM_RSA_KEY_PARMS *tpm_rsa_key_parms; /* for key */ TPM_BOOL parentPCRStatus; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ uint32_t decrypt_data_size; /* resulting decrypted data size */ BYTE *decrypt_data = NULL; /* The resulting decrypted data. */ unsigned char *stream; uint32_t stream_size; TPM_BOUND_DATA tpm_bound_data; /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; size_t outDataSize = 0; /* The length of the returned decrypted data */ BYTE *outData = NULL; /* The resulting decrypted data. */ printf("TPM_Process_UnBind: Ordinal Entry\n"); TPM_SizedBuffer_Init(&inData); /* freed @1 */ TPM_BoundData_Init(&tpm_bound_data); /* freed @3 */ /* get inputs */ /* get keyHandle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&keyHandle, &command, ¶mSize); } /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get areaToSignSize and areaToSign parameters */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_UnBind: keyHandle %08x\n", keyHandle); returnCode = TPM_SizedBuffer_Load(&inData, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_UnBind: UnBinding %u bytes\n", inData.size); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag10(tag); } /* get the optional 'below the line' authorization parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, privAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_UnBind: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* 1. If the inDataSize is 0 the TPM returns TPM_BAD_PARAMETER */ if (returnCode == TPM_SUCCESS) { if (inData.size == 0) { printf("TPM_Process_UnBind: Error, inDataSize is 0\n"); returnCode = TPM_BAD_PARAMETER; } } /* get the key corresponding to the keyHandle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyHandleEntries_GetKey(&key, &parentPCRStatus, tpm_state, keyHandle, FALSE, /* not read-only */ FALSE, /* do not ignore PCRs */ FALSE); /* cannot use EK */ } if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)){ if (key->authDataUsage != TPM_AUTH_NEVER) { printf("TPM_Process_UnBind: Error, authorization required\n"); returnCode = TPM_AUTHFAIL; } } /* get keyHandle -> usageAuth */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_Key_GetUsageAuth(&keyUsageAuth, key); } /* get the session data */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_KEYHANDLE, ordinal, key, keyUsageAuth, /* OIAP */ key->tpm_store_asymkey->pubDataDigest); /* OSAP */ } /* 2. Validate the authorization to use the key pointed to by keyHandle */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, privAuth); /* Authorization digest for input */ } /* 3. If the keyUsage field of the key referenced by keyHandle does not have the value TPM_KEY_BIND or TPM_KEY_LEGACY, the TPM must return the error code TPM_INVALID_KEYUSAGE */ if (returnCode == TPM_SUCCESS) { if ((key->keyUsage != TPM_KEY_BIND) && (key->keyUsage != TPM_KEY_LEGACY)) { printf("TPM_Process_UnBind: Error, invalid keyUsage %04hx\n", (key->keyUsage)); returnCode = TPM_INVALID_KEYUSAGE; } } /* Get the TPM_RSA_KEY_PARMS associated with key */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyParms_GetRSAKeyParms(&tpm_rsa_key_parms, &(key->algorithmParms)); } /* 4. Decrypt the inData using the key pointed to by keyHandle */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_RSAPrivateDecryptMalloc(&decrypt_data, /* decrypted data, freed @2 */ &decrypt_data_size, /* actual size of decrypted data data */ inData.buffer, inData.size, key); } if (returnCode == TPM_SUCCESS) { /* 5. if (keyHandle -> encScheme does not equal TPM_ES_RSAESOAEP_SHA1_MGF1) and (keyHandle -> keyUsage equals TPM_KEY_LEGACY), */ if ((key->algorithmParms.encScheme != TPM_ES_RSAESOAEP_SHA1_MGF1) && (key->keyUsage == TPM_KEY_LEGACY)) { printf("TPM_Process_UnBind: Legacy key\n"); /* a. The payload does not have TPM specific markers to validate, so no consistency check can be performed. */ /* b. Set the output parameter outData to the value of the decrypted value of inData. (Padding associated with the encryption wrapping of inData SHALL NOT be returned.) */ outData = decrypt_data; /* c. Set the output parameter outDataSize to the size of outData, as deduced from the decryption process. */ outDataSize = decrypt_data_size; } /* 6. else */ else { printf("TPM_Process_UnBind: Payload is TPM_BOUND_DATA structure\n"); /* a. Interpret the decrypted data under the assumption that it is a TPM_BOUND_DATA structure, and validate that the payload type is TPM_PT_BIND */ if (returnCode == TPM_SUCCESS) { stream = decrypt_data; stream_size = decrypt_data_size; returnCode = TPM_BoundData_Load(&tpm_bound_data, &stream, &stream_size); } if (returnCode == TPM_SUCCESS) { if (tpm_bound_data.payload != TPM_PT_BIND) { printf("TPM_Process_UnBind: Error, " "TPM_BOUND_DATA->payload %02x not TPM_PT_BIND\n", tpm_bound_data.payload); returnCode = TPM_INVALID_STRUCTURE; } } /* b. Set the output parameter outData to the value of TPM_BOUND_DATA -> payloadData. (Other parameters of TPM_BOUND_DATA SHALL NOT be returned. Padding associated with the encryption wrapping of inData SHALL NOT be returned.) */ if (returnCode == TPM_SUCCESS) { outData = tpm_bound_data.payloadData; /* c. Set the output parameter outDataSize to the size of outData, as deduced from the decryption process and the interpretation of TPM_BOUND_DATA. */ outDataSize = tpm_bound_data.payloadDataSize; } } } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_UnBind: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* 10. Return the computed outData */ /* append outDataSize */ returnCode = TPM_Sbuffer_Append32(response, outDataSize); } if (returnCode == TPM_SUCCESS) { /* append outData */ returnCode = TPM_Sbuffer_Append(response, outData, outDataSize); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ TPM_SizedBuffer_Delete(&inData); /* @1 */ free(decrypt_data); /* @2 */ TPM_BoundData_Delete(&tpm_bound_data); /* @3 */ return rcf; } /* 10.4 TPM_CreateWrapKey rev 114 The TPM_CreateWrapKey command both generates and creates a secure storage bundle for asymmetric keys. The newly created key can be locked to a specific PCR value by specifying a set of PCR registers. */ TPM_RESULT TPM_Process_CreateWrapKey(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_KEY_HANDLE parentHandle; /* Handle of a loaded key that can perform key wrapping. */ TPM_ENCAUTH dataUsageAuth; /* Encrypted usage authorization data for the key. */ TPM_ENCAUTH dataMigrationAuth; /* Encrypted migration authorization data for the key.*/ TPM_KEY keyInfo; /* Information about key to be created, pubkey.keyLength and keyInfo.encData elements are 0. MAY be TPM_KEY12 */ TPM_AUTHHANDLE authHandle; /* The authorization handle used for parent key authorization. Must be an OSAP session. */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* Ignored */ TPM_AUTHDATA pubAuth; /* The authorization digest that authorizes the use of the public key in parentHandle. HMAC key: parentKey.usageAuth. */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ TPM_SECRET *hmacKey; TPM_KEY *parentKey = NULL; /* the key specified by parentHandle */ TPM_BOOL parentPCRStatus; TPM_RSA_KEY_PARMS *keyInfoRSAParms = NULL; /* substructure of keyInfo */ TPM_SECRET du1UsageAuth; TPM_SECRET dm1MigrationAuth; TPM_STORE_ASYMKEY *wrappedStoreAsymkey; /* substructure of wrappedKey */ TPM_PCR_INFO wrappedPCRInfo; int ver; /* TPM_KEY or TPM_KEY12 */ /* output parameters */ TPM_KEY wrappedKey; /* The TPM_KEY structure which includes the public and encrypted private key. MAY be TPM_KEY12 */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; printf("TPM_Process_CreateWrapKey: Ordinal Entry\n"); TPM_Key_Init(&keyInfo); TPM_Key_Init(&wrappedKey); TPM_PCRInfo_Init(&wrappedPCRInfo); /* get inputs */ /* get parentHandle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&parentHandle, &command, ¶mSize); } /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get dataUsageAuth parameter */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CreateWrapKey: parentHandle %08x\n", parentHandle); returnCode = TPM_Authdata_Load(dataUsageAuth, &command, ¶mSize); } /* get dataMigrationAuth parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Authdata_Load(dataMigrationAuth, &command, ¶mSize); } /* get keyInfo parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Key_Load(&keyInfo, &command, ¶mSize); /* freed @1 */ } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag1(tag); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, pubAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_CreateWrapKey: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* get the key corresponding to the parentHandle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyHandleEntries_GetKey(&parentKey, &parentPCRStatus, tpm_state, parentHandle, FALSE, /* not r/o, using to encrypt w/public key */ FALSE, /* do not ignore PCRs */ FALSE); /* cannot use EK */ } /* get the session data */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_OSAP, TPM_ET_KEYHANDLE, ordinal, parentKey, NULL, /* OIAP */ parentKey->tpm_store_asymkey->pubDataDigest); /*OSAP*/ } /* 1. Validate the authorization to use the key pointed to by parentHandle. Return TPM_AUTHFAIL on any error. */ /* 2. Validate the session type for parentHandle is OSAP. */ if (returnCode == TPM_SUCCESS) { TPM_PrintFour("TPM_Process_CreateWrapKey: sharedSecret", auth_session_data->sharedSecret); returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, pubAuth); /* Authorization digest for input */ } /* 3. If the TPM is not designed to create a key of the type requested in keyInfo, return the error code TPM_BAD_KEY_PROPERTY */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CreateWrapKey: Checking key properties\n"); returnCode = TPM_Key_CheckProperties(&ver, &keyInfo, 0, tpm_state->tpm_permanent_flags.FIPS); } /* Get the TPM_RSA_KEY_PARMS associated with keyInfo */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CreateWrapKey: key parameters v = %d\n", ver); returnCode = TPM_KeyParms_GetRSAKeyParms(&keyInfoRSAParms, &(keyInfo.algorithmParms)); } /* 4. Verify that parentHandle->keyUsage equals TPM_KEY_STORAGE */ if (returnCode == TPM_SUCCESS) { if (parentKey->keyUsage != TPM_KEY_STORAGE) { printf("TPM_Process_CreateWrapKey: Error, parent keyUsage not TPM_KEY_STORAGE\n"); returnCode = TPM_INVALID_KEYUSAGE; } } /* 5. If parentHandle -> keyFlags -> migratable is TRUE and keyInfo -> keyFlags -> migratable is FALSE then return TPM_INVALID_KEYUSAGE */ if (returnCode == TPM_SUCCESS) { if ((parentKey->keyFlags & TPM_MIGRATABLE) && !(keyInfo.keyFlags & TPM_MIGRATABLE)) { printf("TPM_Process_CreateWrapKey: Error, parent not migratable\n"); returnCode = TPM_INVALID_KEYUSAGE; } } /* 6. Validate key parameters */ /* a. keyInfo -> keyUsage MUST NOT be TPM_KEY_IDENTITY or TPM_KEY_AUTHCHANGE. If it is, return TPM_INVALID_KEYUSAGE */ if (returnCode == TPM_SUCCESS) { if ((keyInfo.keyUsage == TPM_KEY_IDENTITY) || (keyInfo.keyUsage == TPM_KEY_AUTHCHANGE)) { printf("TPM_Process_CreateWrapKey: Error, Invalid key usage %04x\n", keyInfo.keyUsage); returnCode = TPM_INVALID_KEYUSAGE; } } /* b. If keyInfo -> keyFlags -> migrateAuthority is TRUE then return TPM_INVALID_KEYUSAGE */ if (returnCode == TPM_SUCCESS) { if (keyInfo.keyFlags & TPM_MIGRATEAUTHORITY) { printf("TPM_Process_CreateWrapKey: Error, Invalid key flags %08x\n", keyInfo.keyFlags); returnCode = TPM_INVALID_KEYUSAGE; } } /* 7. If TPM_PERMANENT_FLAGS -> FIPS is TRUE then a. If keyInfo -> keySize is less than 1024 return TPM_NOTFIPS b. If keyInfo -> authDataUsage specifies TPM_AUTH_NEVER return TPM_NOTFIPS c. If keyInfo -> keyUsage specifies TPM_KEY_LEGACY return TPM_NOTFIPS NOTE Done in step 3 TPM_Key_CheckProperties() */ /* 8. If keyInfo -> keyUsage equals TPM_KEY_STORAGE or TPM_KEY_MIGRATE i. algorithmID MUST be TPM_ALG_RSA ii. encScheme MUST be TPM_ES_RSAESOAEP_SHA1_MGF1 iii. sigScheme MUST be TPM_SS_NONE iv. key size MUST be 2048 v. exponentSize MUST be 0 NOTE Done in step 3 TPM_Key_CheckProperties() */ /* 9. Determine the version of key a.If keyInfo -> ver is 1.1 i. Set V1 to 1 ii. Map wrappedKey to a TPM_KEY structure iii. Validate all remaining TPM_KEY structures b. Else if keyInfo -> tag is TPM_TAG_KEY12 i. Set V1 to 2 ii. Map wrappedKey to a TPM_KEY12 structure iii. Validate all remaining TPM_KEY12 structures NOTE Check done by TPM_Key_CheckProperties() NOTE Map done by TPM_Key_GenerateRSA() */ /* 10..Create DU1 by decrypting dataUsageAuth according to the ADIP indicated by authHandle */ /* 11. Create DM1 by decrypting dataMigrationAuth according to the ADIP indicated by authHandle */ if (returnCode == TPM_SUCCESS) { TPM_AuthSessionData_Decrypt(du1UsageAuth, dm1MigrationAuth, dataUsageAuth, /* even encAuth */ auth_session_data, nonceOdd, dataMigrationAuth, /* odd encAuth */ TRUE); } /* 12. Set continueAuthSession to FALSE */ if (returnCode == TPM_SUCCESS) { continueAuthSession = FALSE; } /* 13. Generate asymmetric key according to algorithm information in keyInfo */ /* 14. Fill in the wrappedKey structure with information from the newly generated key. */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_CreateWrapKey: Generating key\n"); returnCode = TPM_Key_GenerateRSA(&wrappedKey, tpm_state, parentKey, tpm_state->tpm_stclear_data.PCRS, /* PCR array */ ver, keyInfo.keyUsage, keyInfo.keyFlags, keyInfo.authDataUsage, /* TPM_AUTH_DATA_USAGE */ &(keyInfo.algorithmParms), /* TPM_KEY_PARMS */ keyInfo.tpm_pcr_info, /* TPM_PCR_INFO */ keyInfo.tpm_pcr_info_long); /* TPM_PCR_INFO_LONG */ } if (returnCode == TPM_SUCCESS) { returnCode = TPM_Key_GetStoreAsymkey(&wrappedStoreAsymkey, &wrappedKey); } if (returnCode == TPM_SUCCESS) { /* a. Set wrappedKey -> encData -> usageAuth to DU1 */ TPM_Secret_Copy(wrappedStoreAsymkey->usageAuth, du1UsageAuth); /* b. If the KeyFlags -> migratable bit is set to 1, the wrappedKey -> encData -> migrationAuth SHALL contain the decrypted value from dataMigrationAuth. */ if (wrappedKey.keyFlags & TPM_MIGRATABLE) { TPM_Secret_Copy(wrappedStoreAsymkey->migrationAuth, dm1MigrationAuth); } /* c. If the KeyFlags -> migratable bit is set to 0, the wrappedKey -> encData -> migrationAuth SHALL be set to the value tpmProof */ else { TPM_Secret_Copy(wrappedStoreAsymkey->migrationAuth, tpm_state->tpm_permanent_data.tpmProof); } printf("TPM_Process_CreateWrapKey: wrappedKey.PCRInfoSize %d\n", wrappedKey.pcrInfo.size); } /* 15. If keyInfo->PCRInfoSize is non-zero. */ /* a. If V1 is 1 */ /* i. Set wrappedKey -> pcrInfo to a TPM_PCR_INFO structure using the pcrSelection to indicate the PCR's in use */ /* b. Else */ /* i. Set wrappedKey -> pcrInfo to a TPM_PCR_INFO_LONG structure */ /* c. Set wrappedKey -> pcrInfo to keyInfo -> pcrInfo */ /* d. Set wrappedKey -> digestAtCreation to the TPM_COMPOSITE_HASH indicated by creationPCRSelection */ /* e. If V1 is 2 set wrappedKey -> localityAtCreation to TPM_STANY_DATA -> locality */ /* NOTE Done by TPM_Key_GenerateRSA() */ /* 16. Encrypt the private portions of the wrappedKey structure using the key in parentHandle */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Key_GenerateEncData(&wrappedKey, parentKey); } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_CreateWrapKey: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* 17. Return the newly generated key in the wrappedKey parameter */ returnCode = TPM_Key_Store(response, &wrappedKey); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ TPM_Key_Delete(&keyInfo); /* @1 */ TPM_Key_Delete(&wrappedKey); /* @2 */ TPM_PCRInfo_Delete(&wrappedPCRInfo); /* @3 */ return rcf; } /* 27.8 TPM_LoadKey rev 114 Version 1.2 deprecates LoadKey due to the HMAC of the new keyhandle on return. The wrapping makes use of the handle difficult in an environment where the TSS, or other management entity, is changing the TPM handle to a virtual handle. Software using loadKey on a 1.2 TPM can have a collision with the returned handle as the 1.2 TPM uses random values in the lower three bytes of the handle. All new software must use LoadKey2 to allow management software the ability to manage the key handle. Before the TPM can use a key to either wrap, unwrap, bind, unbind, seal, unseal, sign or perform any other action, it needs to be present in the TPM. The TPM_LoadKey function loads the key into the TPM for further use. */ TPM_RESULT TPM_Process_LoadKey(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_KEY_HANDLE parentHandle; /* TPM handle of parent key. */ TPM_KEY *inKey; /* Incoming key structure, both encrypted private and clear public portions. MAY be TPM_KEY12 */ TPM_AUTHHANDLE authHandle; /* The authorization handle used for parentHandle authorization. */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = FALSE; /* The continue use flag for the authorization handle */ TPM_AUTHDATA parentAuth; /* The authorization digest for inputs and parentHandle. HMAC key: parentKey.usageAuth. */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_SECRET *hmacKey; TPM_BOOL key_added = FALSE; /* key has been added to handle list */ TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_KEY_HANDLE inKeyHandle; /* Internal TPM handle where decrypted key was loaded. */ printf("TPM_Process_LoadKey: Ordinal Entry\n"); inKey = NULL; /* freed @1 */ /* get inputs */ /* get parentHandle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&parentHandle, &command, ¶mSize); } /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* Allocate space for inKey. The key cannot be a local variable, since it persists in key storage after the command completes. */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_LoadKey: parentHandle %08x\n", parentHandle); returnCode = TPM_Malloc((unsigned char **)&inKey, sizeof(TPM_KEY)); /* freed @1 */ } /* get inKey parameter */ if (returnCode == TPM_SUCCESS) { TPM_Key_Init(inKey); /* freed @2 */ returnCode = TPM_Key_Load(inKey, &command, ¶mSize); /* freed @2 */ } if (returnCode == TPM_SUCCESS) { TPM_PrintFour("TPM_Process_LoadKey: inKey n", inKey->pubKey.buffer); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag10(tag); } /* get the optional 'below the line' authorization parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, parentAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_LoadKey: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_LoadKeyCommon(&inKeyHandle, /* output */ &key_added, /* output */ &hmacKey, /* output */ &auth_session_data, /* output */ tpm_state, tag, ordinal, parentHandle, inKey, inParamDigest, authHandle, /*uninitialized*/ nonceOdd, continueAuthSession, parentAuth); } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_LoadKey: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* return the key handle */ returnCode = TPM_Sbuffer_Append32(response, inKeyHandle); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ /* if there was a failure, delete inKey */ if ((rcf != 0) || (returnCode != TPM_SUCCESS)) { TPM_Key_Delete(inKey); /* @2 */ free(inKey); /* @1 */ if (key_added) { /* if there was a failure and inKey was stored in the handle list, free the handle. Ignore errors, since only one error code can be returned. */ TPM_KeyHandleEntries_DeleteHandle(tpm_state->tpm_key_handle_entries, inKeyHandle); } } return rcf; } /* 10.5 TPM_LoadKey2 rev 107 Before the TPM can use a key to either wrap, unwrap, unbind, seal, unseal, sign or perform any other action, it needs to be present in the TPM. The TPM_LoadKey2 function loads the key into the TPM for further use. The TPM assigns the key handle. The TPM always locates a loaded key by use of the handle. The assumption is that the handle may change due to key management operations. It is the responsibility of upper level software to maintain the mapping between handle and any label used by external software. This command has the responsibility of enforcing restrictions on the use of keys. For example, when attempting to load a STORAGE key it will be checked for the restrictions on a storage key (2048 size etc.). The load command must maintain a record of whether any previous key in the key hierarchy was bound to a PCR using parentPCRStatus. The flag parentPCRStatus enables the possibility of checking that a platform passed through some particular state or states before finishing in the current state. A grandparent key could be linked to state-1, a parent key could linked to state-2, and a child key could be linked to state-3, for example. The use of the child key then indicates that the platform passed through states 1 and 2 and is currently in state 3, in this example. TPM_Startup with stType == TPM_ST_CLEAR indicates that the platform has been reset, so the platform has not passed through the previous states. Hence keys with parentPCRStatus==TRUE must be unloaded if TPM_Startup is issued with stType == TPM_ST_CLEAR. If a TPM_KEY structure has been decrypted AND the integrity test using "pubDataDigest" has passed AND the key is non-migratory, the key must have been created by the TPM. So there is every reason to believe that the key poses no security threat to the TPM. While there is no known attack from a rogue migratory key, there is a desire to verify that a loaded migratory key is a real key, arising from a general sense of unease about execution of arbitrary data as a key. Ideally a consistency check would consist of an encrypt/decrypt cycle, but this may be expensive. For RSA keys, it is therefore suggested that the consistency test consists of dividing the supposed RSA product by the supposed RSA prime, and checking that there is no remainder. */ TPM_RESULT TPM_Process_LoadKey2(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_KEY_HANDLE parentHandle; /* TPM handle of parent key. */ TPM_KEY *inKey; /* Incoming key structure, both encrypted private and clear public portions. MAY be TPM_KEY12 */ TPM_AUTHHANDLE authHandle; /* The authorization handle used for parentHandle authorization. */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = FALSE; /* The continue use flag for the authorization handle */ TPM_AUTHDATA parentAuth; /* The authorization digest for inputs and parentHandle. HMAC key: parentKey.usageAuth. */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_SECRET *hmacKey; TPM_BOOL key_added = FALSE; /* key has been added to handle list */ TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_KEY_HANDLE inKeyHandle; /* Internal TPM handle where decrypted key was loaded. */ printf("TPM_Process_LoadKey2: Ordinal Entry\n"); inKey = NULL; /* freed @1 */ /* get inputs */ /* get parentHandle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&parentHandle, &command, ¶mSize); } /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* Allocate space for inKey. The key cannot be a local variable, since it persists in key storage after the command completes. */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_LoadKey2: parentHandle %08x\n", parentHandle); returnCode = TPM_Malloc((unsigned char **)&inKey, sizeof(TPM_KEY)); /* freed @1 */ } /* get inKey parameter */ if (returnCode == TPM_SUCCESS) { TPM_Key_Init(inKey); /* freed @2 */ returnCode = TPM_Key_Load(inKey, &command, ¶mSize); /* freed @2 */ } if (returnCode == TPM_SUCCESS) { TPM_PrintFour("TPM_Process_LoadKey2: inKey n", inKey->pubKey.buffer); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag10(tag); } /* get the optional 'below the line' authorization parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, parentAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_LoadKey2: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_LoadKeyCommon(&inKeyHandle, /* output */ &key_added, /* output */ &hmacKey, /* output */ &auth_session_data, /* output */ tpm_state, tag, ordinal, parentHandle, inKey, inParamDigest, authHandle, /* uninitialized */ nonceOdd, continueAuthSession, parentAuth); } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_LoadKey2: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; /* In TPM_LoadKey2, the inKeyHandle is not part of the output HMAC */ /* return the key handle */ returnCode = TPM_Sbuffer_Append32(response, inKeyHandle); } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ /* if there was a failure, delete inKey */ if ((rcf != 0) || (returnCode != TPM_SUCCESS)) { TPM_Key_Delete(inKey); /* @2 */ free(inKey); /* @1 */ if (key_added) { /* if there was a failure and inKey was stored in the handle list, free the handle. Ignore errors, since only one error code can be returned. */ TPM_KeyHandleEntries_DeleteHandle(tpm_state->tpm_key_handle_entries, inKeyHandle); } } return rcf; } /* TPM_LoadKeyCommon rev 114 Code common to TPM_LoadKey and TPM_LoadKey2. They differ only in whether the key handle is included in the response HMAC calculation. */ static TPM_RESULT TPM_LoadKeyCommon(TPM_KEY_HANDLE *inKeyHandle, /* output */ TPM_BOOL *key_added, /* output */ TPM_SECRET **hmacKey, /* output */ TPM_AUTH_SESSION_DATA **auth_session_data, /* output */ tpm_state_t *tpm_state, TPM_TAG tag, TPM_COMMAND_CODE ordinal, TPM_KEY_HANDLE parentHandle, TPM_KEY *inKey, TPM_DIGEST inParamDigest, TPM_AUTHHANDLE authHandle, TPM_NONCE nonceOdd, TPM_BOOL continueAuthSession, TPM_AUTHDATA parentAuth) { TPM_RESULT rc = 0; TPM_KEY *parentKey; /* the key specified by parentHandle */ TPM_SECRET *parentUsageAuth; TPM_BOOL parentPCRStatus; TPM_BOOL parentPCRUsage; int ver; printf("TPM_LoadKeyCommon:\n"); *key_added = FALSE; /* key has been added to handle list */ /* Verify that parentHandle points to a valid key. Get the TPM_KEY associated with parentHandle */ if (rc == TPM_SUCCESS) { rc = TPM_KeyHandleEntries_GetKey(&parentKey, &parentPCRStatus, tpm_state, parentHandle, FALSE, /* not r/o, using to decrypt */ FALSE, /* do not ignore PCRs */ FALSE); /* cannot use EK */ } /* check TPM_AUTH_DATA_USAGE authDataUsage */ if ((rc == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)) { if (parentKey->authDataUsage != TPM_AUTH_NEVER) { printf("TPM_LoadKeyCommon: Error, authorization required\n"); rc = TPM_AUTHFAIL; } } /* get parentHandle -> usageAuth */ if ((rc == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { rc = TPM_Key_GetUsageAuth(&parentUsageAuth, parentKey); } /* get the session data */ if ((rc == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { rc = TPM_AuthSessions_GetData(auth_session_data, hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_KEYHANDLE, ordinal, parentKey, parentUsageAuth, /* OIAP */ parentKey->tpm_store_asymkey->pubDataDigest); /* OSAP */ } /* 1. Validate the command and the parameters using parentAuth and parentHandle -> usageAuth */ if ((rc == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { rc = TPM_Authdata_Check(tpm_state, **hmacKey, /* HMAC key */ inParamDigest, *auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, parentAuth); /* Authorization digest for input */ } /* 2. If parentHandle -> keyUsage is NOT TPM_KEY_STORAGE return TPM_INVALID_KEYUSAGE */ if (rc == TPM_SUCCESS) { if (parentKey->keyUsage != TPM_KEY_STORAGE) { printf("TPM_LoadKeyCommon: Error, " "parentHandle -> keyUsage should be TPM_KEY_STORAGE, is %04x\n", parentKey->keyUsage); rc = TPM_INVALID_KEYUSAGE; } } /* 3. If the TPM is not designed to operate on a key of the type specified by inKey, return the error code TPM_BAD_KEY_PROPERTY. */ if (rc == TPM_SUCCESS) { rc = TPM_Key_CheckProperties(&ver, inKey, 0, tpm_state->tpm_permanent_flags.FIPS); printf("TPM_LoadKeyCommon: key parameters v = %d\n", ver); } /* 4. The TPM MUST handle both TPM_KEY and TPM_KEY12 structures. This step is done at TPM_Key_Load() */ /* 5. Decrypt the inKey -> privkey to obtain TPM_STORE_ASYMKEY structure using the key in parentHandle. */ if (rc == TPM_SUCCESS) { rc = TPM_Key_DecryptEncData(inKey, parentKey); } /* 6. Validate the integrity of inKey and decrypted TPM_STORE_ASYMKEY a. Reproduce inKey -> TPM_STORE_ASYMKEY -> pubDataDigest using the fields of inKey, and check that the reproduced value is the same as pubDataDigest */ if (rc == TPM_SUCCESS) { rc = TPM_Key_CheckPubDataDigest(inKey); } /* 7. Validate the consistency of the key and it's key usage. */ /* a. If inKey -> keyFlags -> migratable is TRUE, the TPM SHALL verify consistency of the public and private components of the asymmetric key pair. If inKey -> keyFlags -> migratable is FALSE, the TPM MAY verify consistency of the public and private components of the asymmetric key pair. The consistency of an RSA key pair MAY be verified by dividing the supposed (P*Q) product by a supposed prime and checking that there is no remainder. This step is done at TPM_Key_Load() */ /* b. If inKey -> keyUsage is TPM_KEY_IDENTITY, verify that inKey->keyFlags->migratable is FALSE. If it is not, return TPM_INVALID_KEYUSAGE */ if (rc == TPM_SUCCESS) { if ((inKey->keyUsage == TPM_KEY_IDENTITY) && (inKey->keyFlags & TPM_MIGRATABLE)) { printf("TPM_LoadKeyCommon: Error, identity key is migratable\n"); rc = TPM_INVALID_KEYUSAGE; } } /* c. If inKey -> keyUsage is TPM_KEY_AUTHCHANGE, return TPM_INVALID_KEYUSAGE */ if (rc == TPM_SUCCESS) { if (inKey->keyUsage == TPM_KEY_AUTHCHANGE) { printf("TPM_LoadKeyCommon: Error, keyUsage is TPM_KEY_AUTHCHANGE\n"); rc = TPM_INVALID_KEYUSAGE; } } /* d. If inKey -> keyFlags -> migratable equals 0 then verify that TPM_STORE_ASYMKEY -> migrationAuth equals TPM_PERMANENT_DATA -> tpmProof */ if (rc == TPM_SUCCESS) { if (!(inKey->keyFlags & TPM_MIGRATABLE)) { rc = TPM_Secret_Compare(tpm_state->tpm_permanent_data.tpmProof, inKey->tpm_store_asymkey->migrationAuth); if (rc != 0) { printf("TPM_LoadKeyCommon: Error, tpmProof mismatch\n"); rc = TPM_INVALID_KEYUSAGE; } } } /* e. Validate the mix of encryption and signature schemes f. If TPM_PERMANENT_FLAGS -> FIPS is TRUE then i. If keyInfo -> keySize is less than 1024 return TPM_NOTFIPS ii. If keyInfo -> authDataUsage specifies TPM_AUTH_NEVER return TPM_NOTFIPS iii. If keyInfo -> keyUsage specifies TPM_KEY_LEGACY return TPM_NOTFIPS g. If inKey -> keyUsage is TPM_KEY_STORAGE or TPM_KEY_MIGRATE i. algorithmID MUST be TPM_ALG_RSA ii. Key size MUST be 2048 iii. exponentSize MUST be 0 iv. sigScheme MUST be TPM_SS_NONE h. If inKey -> keyUsage is TPM_KEY_IDENTITY i. algorithmID MUST be TPM_ALG_RSA ii. Key size MUST be 2048 iv. exponentSize MUST be 0 iii. encScheme MUST be TPM_ES_NONE NOTE Done in step 3. */ if (rc == TPM_SUCCESS) { /* i. If the decrypted inKey -> pcrInfo is NULL, */ /* i. The TPM MUST set the internal indicator to indicate that the key is not using any PCR registers. */ /* j. Else */ /* i. The TPM MUST store pcrInfo in a manner that allows the TPM to calculate a composite hash whenever the key will be in use */ /* ii. The TPM MUST handle both version 1.1 TPM_PCR_INFO and 1.2 TPM_PCR_INFO_LONG structures according to the type of TPM_KEY structure */ /* (1) The TPM MUST validate the TPM_PCR_INFO or TPM_PCR_INFO_LONG structures for legal values. However, the digestAtRelease and localityAtRelease are not validated for authorization until use time.*/ /* NOTE TPM_Key_Load() loads the TPM_PCR_INFO or TPM_PCR_INFO_LONG cache */ } /* 8. Perform any processing necessary to make TPM_STORE_ASYMKEY key available for operations. */ /* NOTE Done at TPM_Key_Load() */ /* 9. Load key and key information into internal memory of the TPM. If insufficient memory exists return error TPM_NOSPACE. */ /* 10. Assign inKeyHandle according to internal TPM rules. */ /* 11. Set InKeyHandle -> parentPCRStatus to parentHandle -> parentPCRStatus. */ if (rc == TPM_SUCCESS) { *inKeyHandle = 0; /* no preferred value */ rc = TPM_KeyHandleEntries_AddKeyEntry(inKeyHandle, /* output */ tpm_state->tpm_key_handle_entries, /* input */ inKey, /* input */ parentPCRStatus, 0); /* keyControl */ } if (rc == TPM_SUCCESS) { printf(" TPM_LoadKeyCommon: Loaded key handle %08x\n", *inKeyHandle); /* remember that the handle has been added to handle list, so it can be deleted on error */ *key_added = TRUE; } /* 12. If parentHandle indicates it is using PCR registers then set inKeyHandle -> parentPCRStatus to TRUE. */ if (rc == TPM_SUCCESS) { rc = TPM_Key_GetPCRUsage(&parentPCRUsage, parentKey, 0); } if (rc == TPM_SUCCESS) { if (parentPCRUsage) { rc = TPM_KeyHandleEntries_SetParentPCRStatus(tpm_state->tpm_key_handle_entries, *inKeyHandle, TRUE); } } return rc; } /* 10.6 TPM_GetPubKey rev 102 The owner of a key may wish to obtain the public key value from a loaded key. This information may have privacy concerns so the command must have authorization from the key owner. */ TPM_RESULT TPM_Process_GetPubKey(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_KEY_HANDLE keyHandle; /* TPM handle of key. */ TPM_AUTHHANDLE authHandle; /* The authorization handle used for keyHandle authorization. */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /*The continue use flag for the authorization handle */ TPM_AUTHDATA keyAuth; /* Authorization HMAC key: key.usageAuth. */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_SECRET *hmacKey; TPM_KEY *key = NULL; /* the key specified by keyHandle */ TPM_BOOL parentPCRStatus; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ TPM_SECRET *keyUsageAuth; TPM_STORE_BUFFER pubkeyStream; /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; const unsigned char *pubkeyStreamBuffer; /* output */ uint32_t pubkeyStreamLength; printf("TPM_Process_GetPubKey: Ordinal Entry\n"); TPM_Sbuffer_Init(&pubkeyStream); /* freed @1 */ /* get inputs */ /* get keyHandle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&keyHandle, &command, ¶mSize); } /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; if (returnCode == TPM_SUCCESS) { printf("TPM_Process_GetPubKey: keyHandle %08x\n", keyHandle); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag10(tag); } /* get the optional 'below the line' authorization parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, keyAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_GetPubKey: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* get the key corresponding to the keyHandle parameter */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_GetPubKey: Key handle %08x\n", keyHandle); returnCode = TPM_KeyHandleEntries_GetKey(&key, &parentPCRStatus, tpm_state, keyHandle, TRUE, /* read-only */ FALSE, /* do not ignore PCRs */ FALSE); /* cannot use EK */ } /* 1. If tag = TPM_TAG_RQU_AUTH1_COMMAND then */ /* get keyHandle -> usageAuth */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_Key_GetUsageAuth(&keyUsageAuth, key); } /* get the session data */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_KEYHANDLE, ordinal, key, keyUsageAuth, /* OIAP */ key->tpm_store_asymkey->pubDataDigest); /* OSAP */ } /* a. Validate the command parameters using keyHandle -> usageAuth, on error return TPM_AUTHFAIL */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, keyAuth); /* Authorization digest for input */ } /* 2. Else */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)){ /* a. Verify that keyHandle -> authDataUsage is TPM_NO_READ_PUBKEY_AUTH or TPM_AUTH_NEVER, on error return TPM_AUTHFAIL */ #ifdef TPM_V12 if ((key->authDataUsage != TPM_NO_READ_PUBKEY_AUTH) && (key->authDataUsage != TPM_AUTH_NEVER)) { printf("TPM_Process_GetPubKey: Error, authorization required\n"); returnCode = TPM_AUTHFAIL; } #else /* TPM 1.1 does not have TPM_NO_READ_PUBKEY_AUTH */ if (key->authDataUsage != TPM_AUTH_NEVER) { printf("TPM_Process_GetPubKey: Error, authorization required\n"); returnCode = TPM_AUTHFAIL; } #endif } #ifdef TPM_V12 /* TPM 1.1 does not have readSRKPub */ if (returnCode == TPM_SUCCESS) { /* 3. If keyHandle == TPM_KH_SRK then */ if ((keyHandle == TPM_KH_SRK) && /* a. If TPM_PERMANENT_FLAGS -> readSRKPub is FALSE then return TPM_INVALID_KEYHANDLE */ !tpm_state->tpm_permanent_flags.readSRKPub) { printf("TPM_Process_GetPubKey: " "Error, keyHandle is TPM_KH_SRK and readSRKPub is FALSE\n"); returnCode = TPM_INVALID_KEYHANDLE; } } #endif /* 4. If keyHandle -> pcrInfoSize is not 0 */ /* a. If keyHandle -> keyFlags has pcrIgnoredOnRead set to FALSE */ /* i. Create a digestAtRelease according to the specified PCR registers and compare to keyHandle -> digestAtRelease and if a mismatch return TPM_WRONGPCRVAL */ /* ii. If specified validate any locality requests */ /* NOTE: Done at TPM_KeyHandleEntries_GetKey() */ /* 5. Create a TPM_PUBKEY structure and return */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Key_StorePubkey(&pubkeyStream, /* output */ &pubkeyStreamBuffer, /* output */ &pubkeyStreamLength, /* output */ key); /* input */ } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_GetPubKey: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* TPM_PUBKEY structure */ returnCode = TPM_Sbuffer_Append(response, pubkeyStreamBuffer, pubkeyStreamLength); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* owner HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ TPM_Sbuffer_Delete(&pubkeyStream); /* @1 */ return rcf; } libtpms-0.9.3/src/tpm12/tpm_storage.h000066400000000000000000000201271421143571500174310ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Storage Functions */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_storage.h 4071 2010-04-29 19:26:45Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_STORAGE_H #define TPM_STORAGE_H #include "tpm_global.h" #include "tpm_store.h" #include "tpm_types.h" /* TPM_BOUND_DATA */ void TPM_BoundData_Init(TPM_BOUND_DATA *tpm_bound_data); TPM_RESULT TPM_BoundData_Load(TPM_BOUND_DATA *tpm_bound_data, unsigned char **stream, uint32_t *stream_size); #if 0 TPM_RESULT TPM_BoundData_Store(TPM_STORE_BUFFER *sbuffer, const TPM_BOUND_DATA *tpm_bound_data); #endif void TPM_BoundData_Delete(TPM_BOUND_DATA *tpm_bound_data); /* TPM_SEALED_DATA */ void TPM_SealedData_Init(TPM_SEALED_DATA *tpm_sealed_data); TPM_RESULT TPM_SealedData_Load(TPM_SEALED_DATA *tpm_sealed_data, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_SealedData_Store(TPM_STORE_BUFFER *sbuffer, const TPM_SEALED_DATA *tpm_sealed_data); void TPM_SealedData_Delete(TPM_SEALED_DATA *tpm_sealed_data); TPM_RESULT TPM_SealedData_DecryptEncData(TPM_SEALED_DATA *tpm_sealed_data, TPM_SIZED_BUFFER *enc_data, TPM_KEY *tpm_key); TPM_RESULT TPM_SealedData_GenerateEncData(TPM_SIZED_BUFFER *enc_data, const TPM_SEALED_DATA *tpm_sealed_data, TPM_KEY *tpm_key); /* TPM_STORED_DATA */ void TPM_StoredData_Init(TPM_STORED_DATA *tpm_stored_data, unsigned int version); TPM_RESULT TPM_StoredData_Load(TPM_STORED_DATA *tpm_stored_data, unsigned int *version, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_StoredData_Store(TPM_STORE_BUFFER *sbuffer, TPM_STORED_DATA *tpm_stored_data, unsigned int version); void TPM_StoredData_Delete(TPM_STORED_DATA *tpm_stored_data, unsigned int version); TPM_RESULT TPM_StoredData_CheckTag(TPM_STORED_DATA12 *tpm_stored_data12); TPM_RESULT TPM_StoredData_StoreClearData(TPM_STORE_BUFFER *sbuffer, TPM_STORED_DATA *tpm_stored_data, unsigned int version); TPM_RESULT TPM_StoredData_GenerateDigest(TPM_DIGEST tpm_digest, TPM_STORED_DATA *tpm_stored_data, unsigned int version); /* Processing functions */ TPM_RESULT TPM_Process_Seal(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_Sealx(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_Unseal(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_UnBind(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_CreateWrapKey(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_LoadKey(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_LoadKey2(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_GetPubKey(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); #endif libtpms-0.9.3/src/tpm12/tpm_store.c000066400000000000000000000472741421143571500171300ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Safe Storage Buffer */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_store.c 4668 2012-01-25 21:16:48Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ /* Generally useful utilities to serialize structures to a stream */ #include #include #include #include "tpm_commands.h" #include "tpm_constants.h" #include "tpm_crypto.h" #include "tpm_debug.h" #include "tpm_error.h" #include "tpm_memory.h" #include "tpm_process.h" #include "tpm_store.h" /* ->buffer; beginning of buffer ->buffer_current; first empty position in buffer ->buffer_end; one past last valid position in buffer */ /* local prototypes */ static void TPM_Sbuffer_AdjustParamSize(TPM_STORE_BUFFER *sbuffer); static TPM_RESULT TPM_Sbuffer_AdjustReturnCode(TPM_STORE_BUFFER *sbuffer, TPM_RESULT returnCode); /* TPM_Sbuffer_Init() sets up a new serialize buffer. It should be called before the first use. */ void TPM_Sbuffer_Init(TPM_STORE_BUFFER *sbuffer) { sbuffer->buffer = NULL; sbuffer->buffer_current = NULL; sbuffer->buffer_end = NULL; } /* TPM_Sbuffer_Load() loads TPM_STORE_BUFFER that has been serialized using TPM_Sbuffer_AppendAsSizedBuffer(), as a size plus stream. */ TPM_RESULT TPM_Sbuffer_Load(TPM_STORE_BUFFER *sbuffer, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; uint32_t length; /* get the length of the stream to be loaded */ if (rc == 0) { rc = TPM_Load32(&length, stream, stream_size); } /* check stream_size */ if (rc == 0) { if (*stream_size < length) { printf("TPM_Sbuffer_Load: Error, stream_size %u less than %u\n", *stream_size, length); rc = TPM_BAD_PARAM_SIZE; } } if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, *stream, length); *stream += length; *stream_size -= length; } return rc; } /* TPM_Sbuffer_Store() cannot simply store the elements, as they are pointers. Rather, the TPM_Sbuffer_AppendAsSizedBuffer() function is used. */ /* TPM_Sbuffer_Delete() frees an existing buffer and reinitializes it. It must be called when a TPM_STORE_BUFFER is no longer required, to avoid a memory leak. The buffer can be reused, but in that case TPM_Sbuffer_Clear would be a better choice. */ void TPM_Sbuffer_Delete(TPM_STORE_BUFFER *sbuffer) { free(sbuffer->buffer); TPM_Sbuffer_Init(sbuffer); } /* TPM_Sbuffer_Clear() removes all data from an existing buffer, allowing reuse. Memory is NOT freed. */ void TPM_Sbuffer_Clear(TPM_STORE_BUFFER *sbuffer) { sbuffer->buffer_current = sbuffer->buffer; return; } /* TPM_Sbuffer_Get() gets the resulting byte buffer and its size. */ void TPM_Sbuffer_Get(TPM_STORE_BUFFER *sbuffer, const unsigned char **buffer, uint32_t *length) { *length = sbuffer->buffer_current - sbuffer->buffer; *buffer = sbuffer->buffer; return; } /* TPM_Sbuffer_GetAll() gets the resulting byte buffer and its size, as well as the total size. */ void TPM_Sbuffer_GetAll(TPM_STORE_BUFFER *sbuffer, unsigned char **buffer, uint32_t *length, uint32_t *total) { *length = sbuffer->buffer_current - sbuffer->buffer; *total = sbuffer->buffer_end - sbuffer->buffer; *buffer = sbuffer->buffer; return; } /* TPM_Sbuffer_Set() creates a TPM_STORE_BUFFER from 'buffer' - pointer to a buffer that was allocated (can be NULL) 'total' - the total number of allocated bytes (ignored if buffer is NULL) 'length' - the number of valid bytes in buffer (ignored if buffer is NULL, can be 0, cannot be greater than total. */ TPM_RESULT TPM_Sbuffer_Set(TPM_STORE_BUFFER *sbuffer, unsigned char *buffer, const uint32_t length, const uint32_t total) { TPM_RESULT rc = 0; if (rc == 0) { if (sbuffer == NULL) { printf("TPM_Sbuffer_Set: Error (fatal), sbuffer is NULL\n"); rc = TPM_FAIL; } } if (rc == 0) { if (buffer != NULL) { if (rc == 0) { if (length > total) { printf("TPM_Sbuffer_Set: Error (fatal), length %u > total %u\n", length, total); rc = TPM_FAIL; } } if (rc == 0) { sbuffer->buffer = buffer; sbuffer->buffer_current = buffer + length; sbuffer->buffer_end = buffer + total; } } else { /* buffer == NULL */ sbuffer->buffer = NULL; sbuffer->buffer_current = NULL; sbuffer->buffer_end = NULL; } } return rc; } /* TPM_Sbuffer_Append() is the basic function to append 'data' of size 'data_length' to the TPM_STORE_BUFFER Returns 0 if success, TPM_SIZE if the buffer cannot be allocated. */ TPM_RESULT TPM_Sbuffer_Append(TPM_STORE_BUFFER *sbuffer, const unsigned char *data, size_t data_length) { TPM_RESULT rc = 0; size_t free_length; /* length of free bytes in current buffer */ size_t current_size; /* size of current buffer */ size_t current_length; /* bytes in current buffer */ size_t new_size; /* size of new buffer */ /* can data fit? */ if (rc == 0) { /* cast safe as end is always greater than current */ free_length = (size_t)(sbuffer->buffer_end - sbuffer->buffer_current); /* if data cannot fit in buffer as sized */ if (free_length < data_length) { /* This test will fail long before the add uint32_t overflow */ if (rc == 0) { /* cast safe as current is always greater than start */ current_length = (size_t)(sbuffer->buffer_current - sbuffer->buffer); if ((current_length + data_length) > TPM_ALLOC_MAX) { printf("TPM_Sbuffer_Append: " "Error, size %lu + %lu greater than maximum allowed\n", (unsigned long)current_length, (unsigned long)data_length); rc = TPM_SIZE; } } if (rc == 0) { /* cast safe as end is always greater than start */ current_size = (size_t)(sbuffer->buffer_end - sbuffer->buffer); /* optimize realloc's by rounding up data_length to the next increment */ new_size = current_size + /* currently used */ ((((data_length - 1)/TPM_STORE_BUFFER_INCREMENT) + 1) * TPM_STORE_BUFFER_INCREMENT); /* but not greater than maximum buffer size */ if (new_size > TPM_ALLOC_MAX) { new_size = TPM_ALLOC_MAX; } printf(" TPM_Sbuffer_Append: data_length %lu, growing from %lu to %lu\n", (unsigned long)data_length, (unsigned long)current_size, (unsigned long)new_size); rc = TPM_Realloc(&(sbuffer->buffer), new_size); } if (rc == 0) { sbuffer->buffer_end = sbuffer->buffer + new_size; /* end */ sbuffer->buffer_current = sbuffer->buffer + current_length; /* new empty position */ } } } /* append the data */ if (rc == 0) { if (data_length > 0) { /* libtpms added (ubsan) */ memcpy(sbuffer->buffer_current, data, data_length); sbuffer->buffer_current += data_length; } } return rc; } /* TPM_Sbuffer_Append8() is a special append that appends a uint8_t */ TPM_RESULT TPM_Sbuffer_Append8(TPM_STORE_BUFFER *sbuffer, uint8_t data) { TPM_RESULT rc = 0; rc = TPM_Sbuffer_Append(sbuffer, (const unsigned char *)(&data), sizeof(uint8_t)); return rc; } /* TPM_Sbuffer_Append16() is a special append that converts a uint16_t to big endian (network byte order) and appends. */ TPM_RESULT TPM_Sbuffer_Append16(TPM_STORE_BUFFER *sbuffer, uint16_t data) { TPM_RESULT rc = 0; uint16_t ndata = htons(data); rc = TPM_Sbuffer_Append(sbuffer, (const unsigned char *)(&ndata), sizeof(uint16_t)); return rc; } /* TPM_Sbuffer_Append32() is a special append that converts a uint32_t to big endian (network byte order) and appends. */ TPM_RESULT TPM_Sbuffer_Append32(TPM_STORE_BUFFER *sbuffer, uint32_t data) { TPM_RESULT rc = 0; uint32_t ndata = htonl(data); rc = TPM_Sbuffer_Append(sbuffer, (const unsigned char *)(&ndata), sizeof(uint32_t)); return rc; } /* TPM_Sbuffer_AppendAsSizedBuffer() appends the source to the destination using the TPM_SIZED_BUFFER idiom. That is, for a uint32_t size is stored. Then the data is stored. Use this function when the stream is not self-describing and a size must be prepended. */ TPM_RESULT TPM_Sbuffer_AppendAsSizedBuffer(TPM_STORE_BUFFER *destSbuffer, TPM_STORE_BUFFER *srcSbuffer) { TPM_RESULT rc = 0; const unsigned char *buffer; uint32_t length; if (rc == 0) { TPM_Sbuffer_Get(srcSbuffer, &buffer, &length); rc = TPM_Sbuffer_Append32(destSbuffer, length); } if (rc == 0) { rc = TPM_Sbuffer_Append(destSbuffer, buffer, length); } return rc; } /* TPM_Sbuffer_AppendSBuffer() appends the source to the destination. The size is not prepended, so the stream must be self-describing. */ TPM_RESULT TPM_Sbuffer_AppendSBuffer(TPM_STORE_BUFFER *destSbuffer, TPM_STORE_BUFFER *srcSbuffer) { TPM_RESULT rc = 0; const unsigned char *buffer; uint32_t length; if (rc == 0) { TPM_Sbuffer_Get(srcSbuffer, &buffer, &length); rc = TPM_Sbuffer_Append(destSbuffer, buffer, length); } return rc; } /* TPM_Sbuffer_StoreInitialResponse() is a special purpose append specific to a TPM response. It appends the first 3 standard response parameters: - response_tag - parameter size - return code For some TPM commands, this is the entire response. Other times, additional parameters will be appended. See TPM_Sbuffer_StoreFinalResponse(). Returns: 0 success TPM_SIZE response could not fit in buffer */ TPM_RESULT TPM_Sbuffer_StoreInitialResponse(TPM_STORE_BUFFER *response, TPM_TAG request_tag, TPM_RESULT returnCode) { TPM_RESULT rc = 0; TPM_TAG response_tag; printf(" TPM_Sbuffer_StoreInitialResponse: returnCode %08x\n", returnCode); if (rc == 0) { if (request_tag == TPM_TAG_RQU_COMMAND) { response_tag = TPM_TAG_RSP_COMMAND; } else if (request_tag == TPM_TAG_RQU_AUTH1_COMMAND) { response_tag = TPM_TAG_RSP_AUTH1_COMMAND; } else if (request_tag == TPM_TAG_RQU_AUTH2_COMMAND) { response_tag = TPM_TAG_RSP_AUTH2_COMMAND; } /* input tag error, returnCode is handled by caller TPM_CheckRequestTag() */ else { response_tag = TPM_TAG_RSP_COMMAND; } } /* tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(response, response_tag); } /* paramSize */ if (rc == 0) { rc = TPM_Sbuffer_Append32(response, sizeof(TPM_TAG) + sizeof(uint32_t) + sizeof(TPM_RESULT)); } /* returnCode */ if (rc == 0) { rc = TPM_Sbuffer_Append32(response, returnCode); } return rc; } /* TPM_Sbuffer_StoreFinalResponse() is a special purpose append specific to a TPM response. It is used after TPM_Sbuffer_StoreInitialResponse() and all additional parameters are appended. 1 - If the additional parameters were successfully appended, this function adjusts the preliminary parameter size set by TPM_Sbuffer_StoreInitialResponse() to reflect the additional appends. 2 - If there was a failure during the additional appends, this function adjusts the return code and removes the additional appends. */ TPM_RESULT TPM_Sbuffer_StoreFinalResponse(TPM_STORE_BUFFER *sbuffer, TPM_RESULT returnCode, tpm_state_t *tpm_state) { TPM_RESULT rc = 0; const unsigned char *buffer; uint32_t length; printf(" TPM_Sbuffer_StoreFinalResponse: returnCode %08x\n", returnCode); /* determine whether the response would exceed the output buffer size */ TPM_Sbuffer_Get(sbuffer, &buffer, &length); if (length > TPM12_GetBufferSize()) { printf("TPM_Sbuffer_StoreFinalResponse: Error, response buffer %u exceeds max %u\n", length, TPM12_GetBufferSize()); returnCode = TPM_SIZE; } if (returnCode == TPM_SUCCESS) { TPM_Sbuffer_AdjustParamSize(sbuffer); } else { /* TPM_FAIL is reserved for "should never occur" errors that indicate a software or hardware failure */ if ((returnCode == TPM_FAIL) && (tpm_state != NULL)) { printf(" TPM_Sbuffer_StoreFinalResponse: Set testState to %u \n", TPM_TEST_STATE_FAILURE); tpm_state->testState = TPM_TEST_STATE_FAILURE; } rc = TPM_Sbuffer_AdjustReturnCode(sbuffer, returnCode); } return rc; } /* TPM_Sbuffer_AdjustParamSize() is a special purpose function to go back and adjust the response paramSize after the response buffer is complete */ static void TPM_Sbuffer_AdjustParamSize(TPM_STORE_BUFFER *sbuffer) { uint32_t paramSize; /* the correct paramsize */ uint32_t nParamSize; /* the correct paramsize, in network byte order */ uint32_t paramSizeOffset; /* actual size */ paramSize = sbuffer->buffer_current - sbuffer->buffer; paramSizeOffset = sizeof(TPM_TAG); nParamSize = htonl(paramSize); /* network byte order */ /* overwrite the original size */ memcpy(sbuffer->buffer + paramSizeOffset, &nParamSize, sizeof(uint32_t)); return; } /* TPM_Sbuffer_AdjustReturnCode() is a special function to go back and adjust the response tag and returnCode if there was a failure while appending the rest of the parameters. This should never fail, because sbuffer was allocated during TPM_Sbuffer_StoreInitialResponse(). */ static TPM_RESULT TPM_Sbuffer_AdjustReturnCode(TPM_STORE_BUFFER *sbuffer, TPM_RESULT returnCode) { TPM_RESULT rc = 0; if (rc == 0) { /* erase the previous result without freeing the buffer */ sbuffer->buffer_current = sbuffer->buffer; /* error tag */ rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_RSP_COMMAND); } /* paramSize */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, sizeof(TPM_TAG) + sizeof(uint32_t) + sizeof(TPM_RESULT)); } /* returnCode */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, returnCode); } return rc; } #if 0 /* Test appending to the TPM_STORE_BUFFER up to the limit */ TPM_RESULT TPM_Sbuffer_Test(void) { TPM_RESULT rc = 0; TPM_STORE_BUFFER sbuffer; size_t total_count; unsigned char count; unsigned char data[256]; /* dummy data */ printf(" TPM_Sbuffer_Test:\n"); TPM_Sbuffer_Init(&sbuffer); total_count = 0; while ((total_count != TPM_ALLOC_MAX) && rc == 0) { if (rc == 0) { rc = TPM_Random(&count, 1); } if (rc == 0) { printf(" TPM_Sbuffer_Test: count %u\n", count); /* last time through */ if (total_count + count > TPM_ALLOC_MAX) { count = TPM_ALLOC_MAX - total_count; } rc = TPM_Sbuffer_Append(&sbuffer,data, count); } if (rc == 0) { total_count += count; } printf(" TPM_Sbuffer_Test: total_count %lu\n", (unsigned long)total_count); } TPM_Sbuffer_Delete(&sbuffer); return rc; } #endif /* type to byte stream */ void STORE32(unsigned char *buffer, unsigned int offset, uint32_t value) { buffer[offset + 0] = value >> 24; buffer[offset + 1] = value >> 16; buffer[offset + 2] = value >> 8; buffer[offset + 3] = value >> 0; } void STORE16(unsigned char *buffer, unsigned int offset, uint16_t value) { buffer[offset + 0] = value >> 8; buffer[offset + 1] = value >> 0; } void STORE8(unsigned char *buffer, unsigned int offset, uint8_t value) { buffer[offset + 0] = value >> 0; } /* TPM_Bitmap_Load() is a safe loading of a TPM_BOOL from a bitmap. If 'pos' is >= 32, the function fails. TPM_BOOL is TRUE. if The bit at pos is set 'pos' is incremented after the load. */ TPM_RESULT TPM_Bitmap_Load(TPM_BOOL *tpm_bool, uint32_t tpm_bitmap, uint32_t *pos) { TPM_RESULT rc = 0; if (rc == 0) { if ((*pos) >= (sizeof(uint32_t) * CHAR_BIT)) { printf("TPM_Bitmap_Load: Error (fatal), loading from position %u\n", *pos); rc = TPM_FAIL; /* should never occur */ } } if (rc == 0) { *tpm_bool = (tpm_bitmap & (1 << (*pos))) != 0; (*pos)++; } return rc; } /* TPM_Bitmap_Store() is a safe storing of a TPM_BOOL into a bitmap. If 'pos' is >= 32, the function fails. The bit at pos is set if the TPM_BOOL is TRUE. 'pos' is incremented after the store. */ TPM_RESULT TPM_Bitmap_Store(uint32_t *tpm_bitmap, TPM_BOOL tpm_bool, uint32_t *pos) { TPM_RESULT rc = 0; if (rc == 0) { if ((*pos) >= (sizeof(uint32_t) * CHAR_BIT)) { printf("TPM_Bitmap_Store: Error (fatal), storing to position %u\n", *pos); rc = TPM_FAIL; /* should never occur */ } } if (rc == 0) { if (tpm_bool) { *tpm_bitmap |= (1 << (*pos)); } (*pos)++; } return rc; } libtpms-0.9.3/src/tpm12/tpm_store.h000066400000000000000000000121211421143571500171140ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Safe Storage Buffer */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_store.h 4668 2012-01-25 21:16:48Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_STORE_H #define TPM_STORE_H #include "tpm_global.h" #include "tpm_load.h" #include "tpm_types.h" void TPM_Sbuffer_Init(TPM_STORE_BUFFER *sbuffer); TPM_RESULT TPM_Sbuffer_Load(TPM_STORE_BUFFER *sbuffer, unsigned char **stream, uint32_t *stream_size); /* TPM_Sbuffer_Store(): See TPM_Sbuffer_AppendAsSizedBuffer() */ void TPM_Sbuffer_Delete(TPM_STORE_BUFFER *sbuffer); void TPM_Sbuffer_Clear(TPM_STORE_BUFFER *sbuffer); void TPM_Sbuffer_Get(TPM_STORE_BUFFER *sbuffer, const unsigned char **buffer, uint32_t *length); void TPM_Sbuffer_GetAll(TPM_STORE_BUFFER *sbuffer, unsigned char **buffer, uint32_t *length, uint32_t *total); TPM_RESULT TPM_Sbuffer_Set(TPM_STORE_BUFFER *sbuffer, unsigned char *buffer, const uint32_t length, const uint32_t total); TPM_RESULT TPM_Sbuffer_Append(TPM_STORE_BUFFER *sbuffer, const unsigned char *data, size_t data_length); TPM_RESULT TPM_Sbuffer_Append8(TPM_STORE_BUFFER *sbuffer, uint8_t data); TPM_RESULT TPM_Sbuffer_Append16(TPM_STORE_BUFFER *sbuffer, uint16_t data); TPM_RESULT TPM_Sbuffer_Append32(TPM_STORE_BUFFER *sbuffer, uint32_t data); TPM_RESULT TPM_Sbuffer_AppendAsSizedBuffer(TPM_STORE_BUFFER *destSbuffer, TPM_STORE_BUFFER *srcSbuffer); TPM_RESULT TPM_Sbuffer_AppendSBuffer(TPM_STORE_BUFFER *destSbuffer, TPM_STORE_BUFFER *srcSbuffer); TPM_RESULT TPM_Sbuffer_StoreInitialResponse(TPM_STORE_BUFFER *response, TPM_TAG response_tag, TPM_RESULT returnCode); TPM_RESULT TPM_Sbuffer_StoreFinalResponse(TPM_STORE_BUFFER *sbuffer, TPM_RESULT returnCode, tpm_state_t *tpm_state); #if 0 TPM_RESULT TPM_Sbuffer_Test(void); #endif /* type to byte stream */ void STORE32(unsigned char *buffer, unsigned int offset, uint32_t value); void STORE16(unsigned char *buffer, unsigned int offset, uint16_t value); void STORE8 (unsigned char *buffer, unsigned int offset, uint8_t value); /* load and store to bitmap */ TPM_RESULT TPM_Bitmap_Load(TPM_BOOL *tpm_bool, uint32_t tpm_bitmap, uint32_t *pos); TPM_RESULT TPM_Bitmap_Store(uint32_t *tpm_bitmap, TPM_BOOL tpm_bool, uint32_t *pos); /* generic function prototype for a structure store callback function */ typedef TPM_RESULT (*TPM_STORE_FUNCTION_T )(TPM_STORE_BUFFER *sbuffer, const void *tpm_structure); #endif libtpms-0.9.3/src/tpm12/tpm_structures.h000066400000000000000000003711431421143571500202170ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM Structures */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_structures.h 4528 2011-03-29 22:16:28Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_STRUCTURES_H #define TPM_STRUCTURES_H #include #include "tpm_constants.h" #include "tpm_memory.h" #include "tpm_types.h" #include "tpm_nvram_const.h" /* Sanity check on build macros are centralized here, since any TPM will use this header */ #if !defined (TPM_POSIX) && !defined (TPM_WINDOWS) && !defined(TPM_SYSTEM_P) #error "Must define either TPM_POSIX or TPM_WINDOWS or TPM_SYSTEM_P" #endif #if defined (TPM_NV_XCRYPTO_FLASH) && defined (TPM_NV_DISK) #error "Cannot define TPM_NV_XCRYPTO_FLASH and TPM_NV_DISK" #endif #if defined (TPM_WINDOWS) && defined (TPM_UNIX_DOMAIN_SOCKET) #error "Cannot define TPM_WINDOWS and TPM_UNIX_DOMAIN_SOCKET" #endif #if defined (TPM_USE_CHARDEV) && defined (TPM_UNIX_DOMAIN_SOCKET) #error "Cannot define TPM_USE_CHARDEV and TPM_UNIX_DOMAIN_SOCKET" #endif #if defined (TPM_NV_XCRYPTO_FLASH) && defined (TPM_UNIX_DOMAIN_SOCKET) #error "Cannot define TPM_NV_XCRYPTO_FLASH and TPM_UNIX_DOMAIN_SOCKET" #endif #if defined (TPM_XCRYPTO_USE_HW) && !defined(TPM_NV_XCRYPTO_FLASH) #error "TPM_XCRYPTO_USE_HW requires TPM_NV_XCRYPTO_FLASH" #endif #if defined (TPM_VTPM) && defined (TPM_UNIX_DOMAIN_SOCKET) #error "Cannot define TPM_VTPM and TPM_UNIX_DOMAIN_SOCKET" #endif #if defined (TPM_V11) && defined (TPM_V12) #error "Cannot define TPM_V12 and TPM_V11" #endif #if !defined (TPM_V11) && !defined (TPM_V12) #error "Must define either TPM_V12 or TPM_V11" #endif #if defined (TPM_DES) && defined (TPM_AES) #error "Cannot define TPM_DES and TPM_AES" #endif #if !defined (TPM_DES) && !defined (TPM_AES) #error "Must define either TPM_DES or TPM_AES" #endif /* This structure is typically a cast from a subset of a larger TPM structure. Two members - a 4 bytes size followed by a 4 bytes pointer to the data is a common TPM structure idiom. */ typedef struct tdTPM_SIZED_BUFFER { uint32_t size; BYTE *buffer; } TPM_SIZED_BUFFER; /* This structure implements a safe storage buffer, used throughout the code when serializing structures to a stream. */ typedef struct tdTPM_STORE_BUFFER { unsigned char *buffer; /* beginning of buffer */ unsigned char *buffer_current; /* first empty position in buffer */ unsigned char *buffer_end; /* one past last valid position in buffer */ } TPM_STORE_BUFFER; /* 5.1 TPM_STRUCT_VER rev 100 This indicates the version of the structure or TPM. Version 1.2 deprecates the use of this structure in all other structures. The structure is not deprecated as many of the structures that contain this structure are not deprecated. */ #define TPM_MAJOR 0x01 #if defined TPM_V12 #define TPM_MINOR 0x02 #endif #if defined TPM_V11 #define TPM_MINOR 0x01 #endif typedef struct tdTPM_STRUCT_VER { BYTE major; /* This SHALL indicate the major version of the structure. MUST be 0x01 */ BYTE minor; /* This SHALL indicate the minor version of the structure. MUST be 0x01 */ BYTE revMajor; /* This MUST be 0x00 on output, ignored on input */ BYTE revMinor; /* This MUST be 0x00 on output, ignored on input */ } TPM_STRUCT_VER; /* 5.2 TPM_VERSION_BYTE rev 87 Allocating a byte for the version information is wasteful of space. The current allocation does not provide sufficient resolution to indicate completely the version of the TPM. To allow for backwards compatibility the size of the structure does not change from 1.1. To enable minor version, or revision, numbers with 2-digit resolution, the byte representing a version splits into two BDC encoded nibbles. The ordering of the low and high order provides backwards compatibility with existing numbering. An example of an implementation of this is; a version of 1.23 would have the value 2 in bit positions 3-0 and the value 3 in bit positions 7-4. TPM_VERSION_BYTE is a byte. The byte is broken up according to the following rule 7-4 leastSigVer Least significant nibble of the minor version. MUST be values within the range of 0000-1001 3-0 mostSigVer Most significant nibble of the minor version. MUST be values within the range of 0000-1001 */ /* 5.3 TPM_VERSION rev 116 This structure provides information relative the version of the TPM. This structure should only be in use by TPM_GetCapability to provide the information relative to the TPM. */ typedef struct tdTPM_VERSION { TPM_VERSION_BYTE major; /* This SHALL indicate the major version of the TPM, mostSigVer MUST be 0x1, leastSigVer MUST be 0x0 */ TPM_VERSION_BYTE minor; /* This SHALL indicate the minor version of the TPM, mostSigVer MUST be 0x1 or 0x2, leastSigVer MUST be 0x0 */ BYTE revMajor; /* This SHALL be the value of the TPM_PERMANENT_DATA -> revMajor */ BYTE revMinor; /* This SHALL be the value of the TPM_PERMANENT_DATA -> revMinor */ } TPM_VERSION; /* 5.4 TPM_DIGEST rev 111 The digest value reports the result of a hash operation. In version 1 the hash algorithm is SHA-1 with a resulting hash result being 20 bytes or 160 bits. It is understood that algorithm agility is lost due to fixing the hash at 20 bytes and on SHA-1. The reason for fixing is due to the internal use of the digest. It is the authorization values, it provides the secrets for the HMAC and the size of 20 bytes determines the values that can be stored and encrypted. For this reason, the size is fixed and any changes to this value require a new version of the specification. The digestSize parameter MUST indicate the block size of the algorithm and MUST be 20 or greater. For all TPM v1 hash operations, the hash algorithm MUST be SHA-1 and the digestSize parameter is therefore equal to 20. */ #define TPM_DIGEST_SIZE 20 typedef BYTE TPM_DIGEST[TPM_DIGEST_SIZE]; #if 0 /* kgold - This was designed as a structure with one element. Changed to a simple BYTE array, like TPM_SECRET. */ typedef struct tdTPM_DIGEST { BYTE digest[TPM_DIGEST_SIZE]; /* This SHALL be the actual digest information */ } TPM_DIGEST; #endif /* Redefinitions */ typedef TPM_DIGEST TPM_CHOSENID_HASH; /* This SHALL be the digest of the chosen identityLabel and privacyCA for a new TPM identity.*/ typedef TPM_DIGEST TPM_COMPOSITE_HASH; /* This SHALL be the hash of a list of PCR indexes and PCR values that a key or data is bound to. */ typedef TPM_DIGEST TPM_DIRVALUE; /* This SHALL be the value of a DIR register */ typedef TPM_DIGEST TPM_HMAC; /* This shall be the output of the HMAC algorithm */ typedef TPM_DIGEST TPM_PCRVALUE; /* The value inside of the PCR */ typedef TPM_DIGEST TPM_AUDITDIGEST; /* This SHALL be the value of the current internal audit state */ /* 5.5 TPM_NONCE rev 99 A nonce is a random value that provides protection from replay and other attacks. Many of the commands and protocols in the specification require a nonce. This structure provides a consistent view of what a nonce is. */ #define TPM_NONCE_SIZE 20 typedef BYTE TPM_NONCE[TPM_NONCE_SIZE]; #if 0 /* kgold - This was designed as a structure with one element. Changed to a simple BYTE array, like TPM_SECRET. */ typedef struct tdTPM_NONCE { BYTE nonce[TPM_NONCE_SIZE]; /* This SHALL be the 20 bytes of random data. When created by the TPM the value MUST be the next 20 bytes from the RNG */ } TPM_NONCE; #endif typedef TPM_NONCE TPM_DAA_TPM_SEED; /* This SHALL be a random value generated by a TPM immediately after the EK is installed in that TPM, whenever an EK is installed in that TPM */ typedef TPM_NONCE TPM_DAA_CONTEXT_SEED; /* This SHALL be a random value */ /* 5.6 TPM_AUTHDATA rev 87 The authorization data is the information that is saved or passed to provide proof of ownership of an entity. For version 1 this area is always 20 bytes. */ #define TPM_AUTHDATA_SIZE 20 typedef BYTE TPM_AUTHDATA[TPM_AUTHDATA_SIZE]; #define TPM_SECRET_SIZE 20 typedef BYTE TPM_SECRET[TPM_SECRET_SIZE]; #if 0 /* kgold - define TPM_SECRET directly, so the size can be defined */ typedef TPM_AUTHDATA TPM_SECRET; /* A secret plain text value used in the authorization process. */ #endif typedef TPM_AUTHDATA TPM_ENCAUTH; /* A cipher text (encrypted) version of authorization data. The encryption mechanism depends on the context. */ /* 5.7 TPM_KEY_HANDLE_LIST rev 87 TPM_KEY_HANDLE_LIST is a structure used to describe the handles of all keys currently loaded into a TPM. */ #if 0 /* This is the version from the specification part 2 */ typedef struct tdTPM_KEY_HANDLE_LIST { uint16_t loaded; /* The number of keys currently loaded in the TPM. */ [size_is(loaded)] TPM_KEY_HANDLE handle[]; /* An array of handles, one for each key currently loaded in the TPM */ } TPM_KEY_HANDLE_LIST; #endif /* 5.11 TPM_CHANGEAUTH_VALIDATE rev 87 This structure provides an area that will stores the new authorization data and the challenger's nonce. */ typedef struct tdTPM_CHANGEAUTH_VALIDATE { TPM_SECRET newAuthSecret; /* This SHALL be the new authorization data for the target entity */ TPM_NONCE n1; /* This SHOULD be a nonce, to enable the caller to verify that the target TPM is on-line. */ } TPM_CHANGEAUTH_VALIDATE; /* PCR */ /* NOTE: The TPM requires and the code assumes a multiple of CHAR_BIT (8). 48 registers (6 bytes) may be a bad number, as it makes TPM_PCR_INFO and TPM_PCR_INFO_LONG indistinguishable in the first two bytes. */ #if defined TPM_V11 #define TPM_NUM_PCR 16 /* Use PC Client specification values */ #endif #if defined TPM_V12 #define TPM_NUM_PCR 24 /* Use PC Client specification values */ #endif #if (CHAR_BIT != 8) #error "CHAR_BIT must be 8" #endif #if ((TPM_NUM_PCR % 8) != 0) #error "TPM_NUM_PCR must be a multiple of 8" #endif /* 8.1 TPM_PCR_SELECTION rev 110 This structure provides a standard method of specifying a list of PCR registers. */ typedef struct tdTPM_PCR_SELECTION { uint16_t sizeOfSelect; /* The size in bytes of the pcrSelect structure */ BYTE pcrSelect[TPM_NUM_PCR/CHAR_BIT]; /* This SHALL be a bit map that indicates if a PCR is active or not */ } TPM_PCR_SELECTION; /* 8.2 TPM_PCR_COMPOSITE rev 97 The composite structure provides the index and value of the PCR register to be used when creating the value that SEALS an entity to the composite. */ typedef struct tdTPM_PCR_COMPOSITE { TPM_PCR_SELECTION select; /* This SHALL be the indication of which PCR values are active */ #if 0 uint32_t valueSize; /* This SHALL be the size of the pcrValue field (not the number of PCR's) */ TPM_PCRVALUE *pcrValue; /* This SHALL be an array of TPM_PCRVALUE structures. The values come in the order specified by the select parameter and are concatenated into a single blob */ #endif TPM_SIZED_BUFFER pcrValue; } TPM_PCR_COMPOSITE; /* 8.3 TPM_PCR_INFO rev 87 The TPM_PCR_INFO structure contains the information related to the wrapping of a key or the sealing of data, to a set of PCRs. */ typedef struct tdTPM_PCR_INFO { TPM_PCR_SELECTION pcrSelection; /* This SHALL be the selection of PCRs to which the data or key is bound. */ TPM_COMPOSITE_HASH digestAtRelease; /* This SHALL be the digest of the PCR indices and PCR values to verify when revealing Sealed Data or using a key that was wrapped to PCRs. NOTE: This is passed in by the host, and used as authorization to use the key */ TPM_COMPOSITE_HASH digestAtCreation; /* This SHALL be the composite digest value of the PCR values, at the time when the sealing is performed. NOTE: This is generated at key creation, but is just informative to the host, not used for authorization */ } TPM_PCR_INFO; /* 8.6 TPM_LOCALITY_SELECTION rev 87 When used with localityAtCreation only one bit is set and it corresponds to the locality of the command creating the structure. When used with localityAtRelease the bits indicate which localities CAN perform the release. */ typedef BYTE TPM_LOCALITY_SELECTION; #define TPM_LOC_FOUR 0x10 /* Locality 4 */ #define TPM_LOC_THREE 0x08 /* Locality 3 */ #define TPM_LOC_TWO 0x04 /* Locality 2 */ #define TPM_LOC_ONE 0x02 /* Locality 1 */ #define TPM_LOC_ZERO 0x01 /* Locality 0. This is the same as the legacy interface. */ #define TPM_LOC_ALL 0x1f /* kgold - added all localities */ #define TPM_LOC_MAX 4 /* kgold - maximum value for TPM_MODIFIER_INDICATOR */ /* 8.4 TPM_PCR_INFO_LONG rev 109 The TPM_PCR_INFO structure contains the information related to the wrapping of a key or the sealing of data, to a set of PCRs. The LONG version includes information necessary to properly define the configuration that creates the blob using the PCR selection. */ typedef struct tdTPM_PCR_INFO_LONG { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* This SHALL be TPM_TAG_PCR_INFO_LONG */ #endif TPM_LOCALITY_SELECTION localityAtCreation; /* This SHALL be the locality modifier of the function that creates the PCR info structure */ TPM_LOCALITY_SELECTION localityAtRelease; /* This SHALL be the locality modifier required to reveal Sealed Data or use a key that was wrapped to PCRs */ TPM_PCR_SELECTION creationPCRSelection; /* This SHALL be the selection of PCRs active when the blob is created */ TPM_PCR_SELECTION releasePCRSelection; /* This SHALL be the selection of PCRs to which the data or key is bound. */ TPM_COMPOSITE_HASH digestAtCreation; /* This SHALL be the composite digest value of the PCR values, at the time when the sealing is performed. */ TPM_COMPOSITE_HASH digestAtRelease; /* This SHALL be the digest of the PCR indices and PCR values to verify when revealing Sealed Data or using a key that was wrapped to PCRs. */ } TPM_PCR_INFO_LONG; /* 8.5 TPM_PCR_INFO_SHORT rev 87 This structure is for defining a digest at release when the only information that is necessary is the release configuration. */ typedef struct tdTPM_PCR_INFO_SHORT { TPM_PCR_SELECTION pcrSelection; /* This SHALL be the selection of PCRs that specifies the digestAtRelease */ TPM_LOCALITY_SELECTION localityAtRelease; /* This SHALL be the locality modifier required to release the information. This value must not be zero (0). */ TPM_COMPOSITE_HASH digestAtRelease; /* This SHALL be the digest of the PCR indices and PCR values to verify when revealing auth data */ } TPM_PCR_INFO_SHORT; /* 8.8 TPM_PCR_ATTRIBUTES rev 107 These attributes are available on a per PCR basis. The TPM is not required to maintain this structure internally to the TPM. When a challenger evaluates a PCR an understanding of this structure is vital to the proper understanding of the platform configuration. As this structure is static for all platforms of the same type the structure does not need to be reported with each quote. */ typedef struct tdTPM_PCR_ATTRIBUTES { TPM_BOOL pcrReset; /* A value of TRUE SHALL indicate that the PCR register can be reset using the TPM_PCR_RESET command. */ TPM_LOCALITY_SELECTION pcrExtendLocal; /* An indication of which localities can perform extends on the PCR. */ TPM_LOCALITY_SELECTION pcrResetLocal; /* An indication of which localities can reset the PCR */ } TPM_PCR_ATTRIBUTES; /* 9. Storage Structures */ /* 9.1 TPM_STORED_DATA rev 87 The definition of this structure is necessary to ensure the enforcement of security properties. This structure is in use by the TPM_Seal and TPM_Unseal commands to identify the PCR index and values that must be present to properly unseal the data. This structure only provides 1.1 data store and uses PCR_INFO 1. This structure is created during the TPM_Seal process. The confidential data is encrypted using a nonmigratable key. When the TPM_Unseal decrypts this structure the TPM_Unseal uses the public information in the structure to validate the current configuration and release the decrypted data 2. When sealInfoSize is not 0 sealInfo MUST be TPM_PCR_INFO */ typedef struct tdTPM_STORED_DATA { TPM_STRUCT_VER ver; /* This MUST be 1.1.0.0 */ TPM_SIZED_BUFFER sealInfo; #if 0 uint32_t sealInfoSize; /* Size of the sealInfo parameter */ BYTE* sealInfo; /* This SHALL be a structure of type TPM_PCR_INFO or a 0 length array if the data is not bound to PCRs. */ #endif TPM_SIZED_BUFFER encData; #if 0 uint32_t encDataSize; /* This SHALL be the size of the encData parameter */ BYTE* encData; /* This shall be an encrypted TPM_SEALED_DATA structure containing the confidential part of the data. */ #endif /* NOTE: kgold - Added this structure, a cache of PCRInfo when not NULL */ TPM_PCR_INFO *tpm_seal_info; } TPM_STORED_DATA; /* 9.2 TPM_STORED_DATA12 rev 101 The definition of this structure is necessary to ensure the enforcement of security properties. This structure is in use by the TPM_Seal and TPM_Unseal commands to identify the PCR index and values that must be present to properly unseal the data. 1. This structure is created during the TPM_Seal process. The confidential data is encrypted using a nonmigratable key. When the TPM_Unseal decrypts this structure the TPM_Unseal uses the public information in the structure to validate the current configuration and release the decrypted data. 2. If sealInfoSize is not 0 then sealInfo MUST be TPM_PCR_INFO_LONG */ typedef struct tdTPM_STORED_DATA12 { TPM_STRUCTURE_TAG tag; /* This SHALL be TPM_TAG_STORED_DATA12 */ TPM_ENTITY_TYPE et; /* The type of blob */ TPM_SIZED_BUFFER sealInfo; #if 0 uint32_t sealInfoSize; /* Size of the sealInfo parameter */ BYTE* sealInfo; /* This SHALL be a structure of type TPM_PCR_INFO_LONG or a 0 length array if the data is not bound to PCRs. */ #endif TPM_SIZED_BUFFER encData; #if 0 uint32_t encDataSize; /* This SHALL be the size of the encData parameter */ BYTE* encData; /* This shall be an encrypted TPM_SEALED_DATA structure containing the confidential part of the data. */ #endif /* NOTE: kgold - Added this structure, a cache of PCRInfo when not NULL */ TPM_PCR_INFO_LONG *tpm_seal_info_long; } TPM_STORED_DATA12; /* 9.3 TPM_SEALED_DATA rev 87 This structure contains confidential information related to sealed data, including the data itself. 1. To tie the TPM_STORED_DATA structure to the TPM_SEALED_DATA structure this structure contains a digest of the containing TPM_STORED_DATA structure. 2. The digest calculation does not include the encDataSize and encData parameters. */ typedef struct tdTPM_SEALED_DATA { TPM_PAYLOAD_TYPE payload; /* This SHALL indicate the payload type of TPM_PT_SEAL */ TPM_SECRET authData; /* This SHALL be the authorization data for this value */ TPM_SECRET tpmProof; /* This SHALL be a copy of TPM_PERMANENT_FLAGS -> tpmProof */ TPM_DIGEST storedDigest; /* This SHALL be a digest of the TPM_STORED_DATA structure, excluding the fields TPM_STORED_DATA -> encDataSize and TPM_STORED_DATA -> encData. */ TPM_SIZED_BUFFER data; /* This SHALL be the data to be sealed */ #if 0 uint32_t dataSize; /* This SHALL be the size of the data parameter */ BYTE* data; /* This SHALL be the data to be sealed */ #endif } TPM_SEALED_DATA; /* 9.4 TPM_SYMMETRIC_KEY rev 87 This structure describes a symmetric key, used during the process "Collating a Request for a Trusted Platform Module Identity". */ typedef struct tdTPM_SYMMETRIC_KEY { TPM_ALGORITHM_ID algId; /* This SHALL be the algorithm identifier of the symmetric key. */ TPM_ENC_SCHEME encScheme; /* This SHALL fully identify the manner in which the key will be used for encryption operations. */ uint16_t size; /* This SHALL be the size of the data parameter in bytes */ BYTE* data; /* This SHALL be the symmetric key data */ /* NOTE Cannot make this a TPM_SIZED_BUFFER because uint16_t */ } TPM_SYMMETRIC_KEY; /* 9.5 TPM_BOUND_DATA rev 87 This structure is defined because it is used by a TPM_UnBind command in a consistency check. The intent of TCG is to promote "best practice" heuristics for the use of keys: a signing key shouldn't be used for storage, and so on. These heuristics are used because of the potential threats that arise when the same key is used in different ways. The heuristics minimize the number of ways in which a given key can be used. One such heuristic is that a key of type TPM_KEY_BIND, and no other type of key, should always be used to create the blob that is unwrapped by TPM_UnBind. Binding is not a TPM function, so the only choice is to perform a check for the correct payload type when a blob is unwrapped by a key of type TPM_KEY_BIND. This requires the blob to have internal structure. Even though payloadData has variable size, TPM_BOUND_DATA deliberately does not include the size of payloadData. This is to maximise the size of payloadData that can be encrypted when TPM_BOUND_DATA is encrypted in a single block. When using TPM-UnBind to obtain payloadData, the size of payloadData is deduced as a natural result of the (RSA) decryption process. 1. This structure MUST be used for creating data when (wrapping with a key of type TPM_KEY_BIND) or (wrapping using the encryption algorithm TPM_ES_RSAESOAEP_SHA1_MGF1). If it is not, the TPM_UnBind command will fail. */ typedef struct tdTPM_BOUND_DATA { TPM_STRUCT_VER ver; /* This MUST be 1.1.0.0 */ TPM_PAYLOAD_TYPE payload; /* This SHALL be the value TPM_PT_BIND */ uint32_t payloadDataSize; /* NOTE: added, not part of serialization */ BYTE *payloadData; /* The bound data */ } TPM_BOUND_DATA; /* 10. TPM_KEY Complex */ /* 10.1.1 TPM_RSA_KEY_PARMS rev 87 This structure describes the parameters of an RSA key. */ /* TPM_RSA_KEY_LENGTH_MAX restricts the maximum size of an RSA key. It has two uses: - bounds the size of the TPM state - protects against a denial of service attack where the attacker creates a very large key */ #ifdef TPM_RSA_KEY_LENGTH_MAX /* if the builder defines a value */ #if ((TPM_RSA_KEY_LENGTH_MAX % 16) != 0) #error "TPM_RSA_KEY_LENGTH_MAX must be a multiple of 16" #endif #if (TPM_RSA_KEY_LENGTH_MAX < 2048) #error "TPM_RSA_KEY_LENGTH_MAX must be at least 2048" #endif #endif /* TPM_RSA_KEY_LENGTH_MAX */ #ifndef TPM_RSA_KEY_LENGTH_MAX /* default if the builder does not define a value */ #define TPM_RSA_KEY_LENGTH_MAX 2048 #endif typedef struct tdTPM_RSA_KEY_PARMS { uint32_t keyLength; /* This specifies the size of the RSA key in bits */ uint32_t numPrimes; /* This specifies the number of prime factors used by this RSA key. */ #if 0 uint32_t exponentSize; /* This SHALL be the size of the exponent. If the key is using the default exponent then the exponentSize MUST be 0. */ BYTE *exponent; /* The public exponent of this key */ #endif TPM_SIZED_BUFFER exponent; /* The public exponent of this key */ } TPM_RSA_KEY_PARMS; /* 10.1 TPM_KEY_PARMS rev 87 This provides a standard mechanism to define the parameters used to generate a key pair, and to store the parts of a key shared between the public and private key parts. */ typedef struct tdTPM_KEY_PARMS { TPM_ALGORITHM_ID algorithmID; /* This SHALL be the key algorithm in use */ TPM_ENC_SCHEME encScheme; /* This SHALL be the encryption scheme that the key uses to encrypt information */ TPM_SIG_SCHEME sigScheme; /* This SHALL be the signature scheme that the key uses to perform digital signatures */ #if 0 uint32_t parmSize; /* This SHALL be the size of the parms field in bytes */ BYTE* parms; /* This SHALL be the parameter information dependent upon the key algorithm. */ #endif TPM_SIZED_BUFFER parms; /* This SHALL be the parameter information dependent upon the key algorithm. */ /* NOTE: kgold - Added this structure. It acts as a cache of the result of parms and parmSize deserialization when non-NULL. */ TPM_RSA_KEY_PARMS *tpm_rsa_key_parms; } TPM_KEY_PARMS; /* 10.1.2 TPM_SYMMETRIC_KEY_PARMS rev 87 This structure describes the parameters for symmetric algorithms */ typedef struct tdTPM_SYMMETRIC_KEY_PARMS { uint32_t keyLength; /* This SHALL indicate the length of the key in bits */ uint32_t blockSize; /* This SHALL indicate the block size of the algorithm*/ uint32_t ivSize; /* This SHALL indicate the size of the IV */ BYTE *IV; /* The initialization vector */ } TPM_SYMMETRIC_KEY_PARMS; #if 0 /* 10.4 TPM_STORE_PUBKEY rev 99 This structure can be used in conjunction with a corresponding TPM_KEY_PARMS to construct a public key which can be unambiguously used. */ typedef struct tdTPM_STORE_PUBKEY { uint32_t keyLength; /* This SHALL be the length of the key field. */ BYTE *key; /* This SHALL be a structure interpreted according to the algorithm Id in the corresponding TPM_KEY_PARMS structure. */ } TPM_STORE_PUBKEY; #endif /* 10.7 TPM_STORE_PRIVKEY rev 87 This structure can be used in conjunction with a corresponding TPM_PUBKEY to construct a private key which can be unambiguously used. */ #if 0 typedef struct tdTPM_STORE_PRIVKEY { uint32_t keyLength; /* This SHALL be the length of the key field. */ BYTE* key; /* This SHALL be a structure interpreted according to the algorithm Id in the corresponding TPM_KEY structure. */ } TPM_STORE_PRIVKEY; #endif /* NOTE: Hard coded for RSA keys. This will change if other algorithms are supported */ typedef struct tdTPM_STORE_PRIVKEY { TPM_SIZED_BUFFER d_key; /* private key */ TPM_SIZED_BUFFER p_key; /* private prime factor */ TPM_SIZED_BUFFER q_key; /* private prime factor */ } TPM_STORE_PRIVKEY; /* 10.6 TPM_STORE_ASYMKEY rev 87 The TPM_STORE_ASYMKEY structure provides the area to identify the confidential information related to a key. This will include the private key factors for an asymmetric key. The structure is designed so that encryption of a TPM_STORE_ASYMKEY structure containing a 2048 bit RSA key can be done in one operation if the encrypting key is 2048 bits. Using typical RSA notation the structure would include P, and when loading the key include the unencrypted P*Q which would be used to recover the Q value. To accommodate the future use of multiple prime RSA keys the specification of additional prime factors is an optional capability. This structure provides the basis of defining the protection of the private key. Changes in this structure MUST be reflected in the TPM_MIGRATE_ASYMKEY structure (section 10.8). */ typedef struct tdTPM_STORE_ASYMKEY { TPM_PAYLOAD_TYPE payload; /* This SHALL set to TPM_PT_ASYM to indicate an asymmetric key. If used in TPM_CMK_ConvertMigration the value SHALL be TPM_PT_MIGRATE_EXTERNAL. If used in TPM_CMK_CreateKey the value SHALL be TPM_PT_MIGRATE_RESTRICTED */ TPM_SECRET usageAuth; /* This SHALL be the authorization data necessary to authorize the use of this value */ TPM_SECRET migrationAuth; /* This SHALL be the migration authorization data for a migratable key, or the TPM secret value tpmProof for a non-migratable key created by the TPM. If the TPM sets this parameter to the value tpmProof, then the TPM_KEY.keyFlags.migratable of the corresponding TPM_KEY structure MUST be set to 0. If this parameter is set to the migration authorization data for the key in parameter PrivKey, then the TPM_KEY.keyFlags.migratable of the corresponding TPM_KEY structure SHOULD be set to 1. */ TPM_DIGEST pubDataDigest; /* This SHALL be the digest of the corresponding TPM_KEY structure, excluding the fields TPM_KEY.encSize and TPM_KEY.encData. When TPM_KEY -> pcrInfoSize is 0 then the digest calculation has no input from the pcrInfo field. The pcrInfoSize field MUST always be part of the digest calculation. */ TPM_STORE_PRIVKEY privKey; /* This SHALL be the private key data. The privKey can be a variable length which allows for differences in the key format. The maximum size of the area would be 151 bytes. */ } TPM_STORE_ASYMKEY; /* 10.8 TPM_MIGRATE_ASYMKEY rev 87 The TPM_MIGRATE_ASYMKEY structure provides the area to identify the private key factors of a asymmetric key while the key is migrating between TPM's. This structure provides the basis of defining the protection of the private key. k1k2 - 132 privkey.key (128 + 4) k1 - 20, OAEP seed k2 - 112, partPrivKey TPM_STORE_PRIVKEY 4 partPrivKey.keyLength 108 partPrivKey.key (128 - 20) */ typedef struct tdTPM_MIGRATE_ASYMKEY { TPM_PAYLOAD_TYPE payload; /* This SHALL set to TPM_PT_MIGRATE or TPM_PT_CMK_MIGRATE to indicate an migrating asymmetric key or TPM_PT_MAINT to indicate a maintenance key. */ TPM_SECRET usageAuth; /* This SHALL be a copy of the usageAuth from the TPM_STORE_ASYMKEY structure. */ TPM_DIGEST pubDataDigest; /* This SHALL be a copy of the pubDataDigest from the TPM_STORE_ASYMKEY structure. */ #if 0 uint32_t partPrivKeyLen; /* This SHALL be the size of the partPrivKey field */ BYTE *partPrivKey; /* This SHALL be the k2 area as described in TPM_CreateMigrationBlob */ #endif TPM_SIZED_BUFFER partPrivKey; } TPM_MIGRATE_ASYMKEY; /* 10.2 TPM_KEY rev 87 The TPM_KEY structure provides a mechanism to transport the entire asymmetric key pair. The private portion of the key is always encrypted. The reason for using a size and pointer for the PCR info structure is save space when the key is not bound to a PCR. The only time the information for the PCR is kept with the key is when the key needs PCR info. The 1.2 version has a change in the PCRInfo area. For 1.2 the structure uses the TPM_PCR_INFO_LONG structure to properly define the PCR registers in use. */ typedef struct tdTPM_KEY { TPM_STRUCT_VER ver; /* This MUST be 1.1.0.0 */ TPM_KEY_USAGE keyUsage; /* This SHALL be the TPM key usage that determines the operations permitted with this key */ TPM_KEY_FLAGS keyFlags; /* This SHALL be the indication of migration, redirection etc.*/ TPM_AUTH_DATA_USAGE authDataUsage; /* This SHALL Indicate the conditions where it is required that authorization be presented.*/ TPM_KEY_PARMS algorithmParms; /* This SHALL be the information regarding the algorithm for this key*/ #if 0 uint32_t PCRInfoSize; /* This SHALL be the length of the pcrInfo parameter. If the key is not bound to a PCR this value SHOULD be 0.*/ BYTE* PCRInfo; /* This SHALL be a structure of type TPM_PCR_INFO, or an empty array if the key is not bound to PCRs.*/ TPM_STORE_PUBKEY pubKey; /* This SHALL be the public portion of the key */ uint32_t encDataSize; /* This SHALL be the size of the encData parameter. */ BYTE* encData; /* This SHALL be an encrypted TPM_STORE_ASYMKEY structure or TPM_MIGRATE_ASYMKEY structure */ #endif TPM_SIZED_BUFFER pcrInfo; TPM_SIZED_BUFFER pubKey; TPM_SIZED_BUFFER encData; /* This SHALL be an encrypted TPM_STORE_ASYMKEY structure or TPM_MIGRATE_ASYMKEY structure */ /* NOTE: kgold - Added these structures, a cache of PCRInfo when not NULL */ TPM_PCR_INFO *tpm_pcr_info; /* for TPM_KEY */ TPM_PCR_INFO_LONG *tpm_pcr_info_long; /* for TPM_KEY12 */ /* NOTE: kgold - Added these structures. They act as a cache of the result of encData decryption when non-NULL. In the case of internal keys (e.g. SRK) there is no encData, so these structures are always non-NULL. */ TPM_STORE_ASYMKEY *tpm_store_asymkey; TPM_MIGRATE_ASYMKEY *tpm_migrate_asymkey; } TPM_KEY; /* 10.3 TPM_KEY12 rev 87 This provides the same functionality as TPM_KEY but uses the new PCR_INFO_LONG structures and the new structure tagging. In all other aspects this is the same structure. */ /* NOTE: The TPM_KEY12 structure is never instantiated. It is just needed for the cast of TPM_KEY to get the TPM_KEY12->tag member. */ typedef struct tdTPM_KEY12 { TPM_STRUCTURE_TAG tag; /* MUST be TPM_TAG_KEY12 */ uint16_t fill; /* MUST be 0x0000 */ TPM_KEY_USAGE keyUsage; /* This SHALL be the TPM key usage that determines the operations permitted with this key */ TPM_KEY_FLAGS keyFlags; /* This SHALL be the indication of migration, redirection etc. */ TPM_AUTH_DATA_USAGE authDataUsage; /* This SHALL Indicate the conditions where it is required that authorization be presented. */ TPM_KEY_PARMS algorithmParms; /* This SHALL be the information regarding the algorithm for this key */ #if 0 uint32_t PCRInfoSize; /* This SHALL be the length of the pcrInfo parameter. If the key is not bound to a PCR this value SHOULD be 0. */ BYTE* PCRInfo; /* This SHALL be a structure of type TPM_PCR_INFO_LONG, or an empty array if the key is not bound to PCRs. */ TPM_STORE_PUBKEY pubKey; /* This SHALL be the public portion of the key */ uint32_t encDataSize; /* This SHALL be the size of the encData parameter. */ BYTE* encData; /* This SHALL be an encrypted TPM_STORE_ASYMKEY structure TPM_MIGRATE_ASYMKEY structure */ #endif TPM_SIZED_BUFFER pcrInfo; TPM_SIZED_BUFFER pubKey; TPM_SIZED_BUFFER encData; } TPM_KEY12; /* 10.5 TPM_PUBKEY rev 99 The TPM_PUBKEY structure contains the public portion of an asymmetric key pair. It contains all the information necessary for its unambiguous usage. It is possible to construct this structure from a TPM_KEY, using the algorithmParms and pubKey fields. The pubKey member of this structure shall contain the public key for a specific algorithm. */ typedef struct tdTPM_PUBKEY { TPM_KEY_PARMS algorithmParms; /* This SHALL be the information regarding this key */ #if 0 TPM_STORE_PUBKEY pubKey; /* This SHALL be the public key information */ #endif TPM_SIZED_BUFFER pubKey; } TPM_PUBKEY; /* 5.b. The TPM must support a minimum of 2 key slots. */ #ifdef TPM_KEY_HANDLES #if (TPM_KEY_HANDLES < 2) #error "TPM_KEY_HANDLES minimum is 2" #endif #endif /* Set the default to 3 so that there can be one owner evict key */ #ifndef TPM_KEY_HANDLES #define TPM_KEY_HANDLES 3 /* entries in global TPM_KEY_HANDLE_ENTRY array */ #endif /* TPM_GetCapability uses a uint_16 for the number of key slots */ #if (TPM_KEY_HANDLES > 0xffff) #error "TPM_KEY_HANDLES must be less than 0x10000" #endif /* The TPM does not have to support any minimum number of owner evict keys. Adjust this value to match the amount of NV space available. An owner evict key consumes about 512 bytes. A value greater than (TPM_KEY_HANDLES - 2) is useless, as the TPM reserves 2 key slots for non-owner evict keys to avoid blocking. */ #ifndef TPM_OWNER_EVICT_KEY_HANDLES #define TPM_OWNER_EVICT_KEY_HANDLES 1 #endif #if (TPM_OWNER_EVICT_KEY_HANDLES > (TPM_KEY_HANDLES - 2)) #error "TPM_OWNER_EVICT_KEY_HANDLES too large for TPM_KEY_HANDLES" #endif /* This is the version used by the TPM implementation. It is part of the global TPM state */ /* kgold: Added TPM_KEY member. There needs to be a mapping between a key handle and the pointer to TPM_KEY objects, and this seems to be the right place for it. */ typedef struct tdTPM_KEY_HANDLE_ENTRY { TPM_KEY_HANDLE handle; /* Handles for a key currently loaded in the TPM */ TPM_KEY *key; /* Pointer to the key object */ TPM_BOOL parentPCRStatus; /* TRUE if parent of this key uses PCR's */ TPM_KEY_CONTROL keyControl; /* Attributes that can control various aspects of key usage and manipulation. */ } TPM_KEY_HANDLE_ENTRY; /* 5.12 TPM_MIGRATIONKEYAUTH rev 87 This structure provides the proof that the associated public key has TPM Owner authorization to be a migration key. */ typedef struct tdTPM_MIGRATIONKEYAUTH { TPM_PUBKEY migrationKey; /* This SHALL be the public key of the migration facility */ TPM_MIGRATE_SCHEME migrationScheme; /* This shall be the type of migration operation.*/ TPM_DIGEST digest; /* This SHALL be the digest value of the concatenation of migration key, migration scheme and tpmProof */ } TPM_MIGRATIONKEYAUTH; /* 5.13 TPM_COUNTER_VALUE rev 87 This structure returns the counter value. For interoperability, the value size should be 4 bytes. */ #define TPM_COUNTER_LABEL_SIZE 4 #define TPM_COUNT_ID_NULL 0xffffffff /* unused value TPM_CAP_PROP_ACTIVE_COUNTER expects this value if no counter is active */ #define TPM_COUNT_ID_ILLEGAL 0xfffffffe /* after releasing an active counter */ typedef struct tdTPM_COUNTER_VALUE { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* TPM_TAG_COUNTER_VALUE */ #endif BYTE label[TPM_COUNTER_LABEL_SIZE]; /* The label for the counter */ TPM_ACTUAL_COUNT counter; /* The 32-bit counter value. */ /* NOTE: Added. TPMWG email says the specification structure is the public part, but these are vendor specific private members. */ TPM_SECRET authData; /* Authorization secret for counter */ TPM_BOOL valid; TPM_DIGEST digest; /* for OSAP comparison */ } TPM_COUNTER_VALUE; /* 5.14 TPM_SIGN_INFO Structure rev 102 This is an addition in 1.2 and is the structure signed for certain commands (e.g., TPM_ReleaseTransportSigned). Some commands have a structure specific to that command (e.g., TPM_Quote uses TPM_QUOTE_INFO) and do not use TPM_SIGN_INFO. TPM_Sign uses this structure when the signature scheme is TPM_SS_RSASSAPKCS1v15_INFO. */ #define TPM_SIGN_INFO_FIXED_SIZE 4 typedef struct tdTPM_SIGN_INFO { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* TPM_TAG_SIGNINFO */ #endif BYTE fixed[TPM_SIGN_INFO_FIXED_SIZE]; /* The ASCII text that identifies what function was performing the signing operation*/ TPM_NONCE replay; /* Nonce provided by caller to prevent replay attacks */ #if 0 uint32_t dataLen; /* The length of the data area */ BYTE* data; /* The data that is being signed */ #endif TPM_SIZED_BUFFER data; /* The data that is being signed */ } TPM_SIGN_INFO; /* 5.15 TPM_MSA_COMPOSITE Structure rev 87 TPM_MSA_COMPOSITE contains an arbitrary number of digests of public keys belonging to Migration Authorities. An instance of TPM_MSA_COMPOSITE is incorporated into the migrationAuth value of a certified-migration-key (CMK), and any of the Migration Authorities specified in that instance is able to approve the migration of that certified-migration-key. TPMs MUST support TPM_MSA_COMPOSITE structures with MSAlist of four (4) or less, and MAY support larger values of MSAlist. */ typedef struct tdTPM_MSA_COMPOSITE { uint32_t MSAlist; /* The number of migAuthDigests. MSAlist MUST be one (1) or greater. */ TPM_DIGEST *migAuthDigest; /* An arbitrary number of digests of public keys belonging to Migration Authorities. */ } TPM_MSA_COMPOSITE; /* 5.16 TPM_CMK_AUTH The signed digest of TPM_CMK_AUTH is a ticket to prove that the entity with public key "migrationAuthority" has approved the public key "destination Key" as a migration destination for the key with public key "sourceKey". Normally the digest of TPM_CMK_AUTH is signed by the private key corresponding to "migrationAuthority". To reduce data size, TPM_CMK_AUTH contains just the digests of "migrationAuthority", "destinationKey" and "sourceKey". */ typedef struct tdTPM_CMK_AUTH { TPM_DIGEST migrationAuthorityDigest; /* The digest of the public key of a Migration Authority */ TPM_DIGEST destinationKeyDigest; /* The digest of a TPM_PUBKEY structure that is an approved destination key for the private key associated with "sourceKey"*/ TPM_DIGEST sourceKeyDigest; /* The digest of a TPM_PUBKEY structure whose corresponding private key is approved by the Migration Authority to be migrated as a child to the destinationKey. */ } TPM_CMK_AUTH; /* 5.18 TPM_SELECT_SIZE rev 87 This structure provides the indication for the version and sizeOfSelect structure in GetCapability */ typedef struct tdTPM_SELECT_SIZE { BYTE major; /* This SHALL indicate the major version of the TPM. This MUST be 0x01 */ BYTE minor; /* This SHALL indicate the minor version of the TPM. This MAY be 0x01 or 0x02 */ uint16_t reqSize; /* This SHALL indicate the value for a sizeOfSelect field in the TPM_SELECTION structure */ } TPM_SELECT_SIZE; /* 5.19 TPM_CMK_MIGAUTH rev 89 Structure to keep track of the CMK migration authorization */ typedef struct tdTPM_CMK_MIGAUTH { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* Set to TPM_TAG_CMK_MIGAUTH */ #endif TPM_DIGEST msaDigest; /* The digest of a TPM_MSA_COMPOSITE structure containing the migration authority public key and parameters. */ TPM_DIGEST pubKeyDigest; /* The hash of the associated public key */ } TPM_CMK_MIGAUTH; /* 5.20 TPM_CMK_SIGTICKET rev 87 Structure to keep track of the CMK migration authorization */ typedef struct tdTPM_CMK_SIGTICKET { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* Set to TPM_TAG_CMK_SIGTICKET */ #endif TPM_DIGEST verKeyDigest; /* The hash of a TPM_PUBKEY structure containing the public key and parameters of the key that can verify the ticket */ TPM_DIGEST signedData; /* The ticket data */ } TPM_CMK_SIGTICKET; /* 5.21 TPM_CMK_MA_APPROVAL rev 87 Structure to keep track of the CMK migration authorization */ typedef struct tdTPM_CMK_MA_APPROVAL { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* Set to TPM_TAG_CMK_MA_APPROVAL */ #endif TPM_DIGEST migrationAuthorityDigest; /* The hash of a TPM_MSA_COMPOSITE structure containing the hash of one or more migration authority public keys and parameters. */ } TPM_CMK_MA_APPROVAL; /* 20.2 Delegate Definitions rev 101 The delegations are in a 64-bit field. Each bit describes a capability that the TPM Owner can delegate to a trusted process by setting that bit. Each delegation bit setting is independent of any other delegation bit setting in a row. If a TPM command is not listed in the following table, then the TPM Owner cannot delegate that capability to a trusted process. For the TPM commands that are listed in the following table, if the bit associated with a TPM command is set to zero in the row of the table that identifies a trusted process, then that process has not been delegated to use that TPM command. The minimum granularity for delegation is at the ordinal level. It is not possible to delegate an option of an ordinal. This implies that if the options present a difficulty and there is a need to separate the delegations then there needs to be a split into two separate ordinals. */ #define TPM_DEL_OWNER_BITS 0x00000001 #define TPM_DEL_KEY_BITS 0x00000002 typedef struct tdTPM_DELEGATIONS { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* This SHALL be TPM_TAG_DELEGATIONS */ #endif uint32_t delegateType; /* Owner or key */ uint32_t per1; /* The first block of permissions */ uint32_t per2; /* The second block of permissions */ } TPM_DELEGATIONS; /* 20.4 TPM_FAMILY_LABEL rev 85 Used in the family table to hold a one-byte numeric value (sequence number) that software can map to a string of bytes that can be displayed or used by applications. This is not sensitive data. */ #if 0 typedef struct tdTPM_FAMILY_LABEL { BYTE label; /* A sequence number that software can map to a string of bytes that can be displayed or used by the applications. This MUST not contain sensitive information. */ } TPM_FAMILY_LABEL; #endif typedef BYTE TPM_FAMILY_LABEL; /* NOTE: No need for a structure here */ /* 20.5 TPM_FAMILY_TABLE_ENTRY rev 101 The family table entry is an individual row in the family table. There are no sensitive values in a family table entry. Each family table entry contains values to facilitate table management: the familyID sequence number value that associates a family table row with one or more delegate table rows, a verification sequence number value that identifies when rows in the delegate table were last verified, and BYTE family label value that software can map to an ASCII text description of the entity using the family table entry */ typedef struct tdTPM_FAMILY_TABLE_ENTRY { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* This SHALL be TPM_TAG_FAMILY_TABLE_ENTRY */ #endif TPM_FAMILY_LABEL familyLabel; /* A sequence number that software can map to a string of bytes that can be displayed of used by the applications. This MUST not contain sensitive information. */ TPM_FAMILY_ID familyID; /* The family ID in use to tie values together. This is not a sensitive value. */ TPM_FAMILY_VERIFICATION verificationCount; /* The value inserted into delegation rows to indicate that they are the current generation of rows. Used to identify when a row in the delegate table was last verified. This is not a sensitive value. */ TPM_FAMILY_FLAGS flags; /* See section on TPM_FAMILY_FLAGS. */ /* NOTE Added */ TPM_BOOL valid; } TPM_FAMILY_TABLE_ENTRY; /* 20.6 TPM_FAMILY_TABLE rev 87 The family table is stored in a TPM shielded location. There are no confidential values in the family table. The family table contains a minimum of 8 rows. */ #ifdef TPM_NUM_FAMILY_TABLE_ENTRY_MIN #if (TPM_NUM_FAMILY_TABLE_ENTRY_MIN < 8) #error "TPM_NUM_FAMILY_TABLE_ENTRY_MIN minimum is 8" #endif #endif #ifndef TPM_NUM_FAMILY_TABLE_ENTRY_MIN #define TPM_NUM_FAMILY_TABLE_ENTRY_MIN 8 #endif typedef struct tdTPM_FAMILY_TABLE { TPM_FAMILY_TABLE_ENTRY famTableRow[TPM_NUM_FAMILY_TABLE_ENTRY_MIN]; } TPM_FAMILY_TABLE; /* 20.7 TPM_DELEGATE_LABEL rev 87 Used in both the delegate table and the family table to hold a string of bytes that can be displayed or used by applications. This is not sensitive data. */ #if 0 typedef struct tdTPM_DELEGATE_LABEL { BYTE label; /* A byte that can be displayed or used by the applications. This MUST not contain sensitive information. */ } TPM_DELEGATE_LABEL; #endif typedef BYTE TPM_DELEGATE_LABEL; /* NOTE: No need for structure */ /* 20.8 TPM_DELEGATE_PUBLIC rev 101 The information of a delegate row that is public and does not have any sensitive information. PCR_INFO_SHORT is appropriate here as the command to create this is done using owner authorization, hence the owner authorized the command and the delegation. There is no need to validate what configuration was controlling the platform during the blob creation. */ typedef struct tdTPM_DELEGATE_PUBLIC { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* This SHALL be TPM_TAG_DELEGATE_PUBLIC */ #endif TPM_DELEGATE_LABEL rowLabel; /* This SHALL be the label for the row. It MUST not contain any sensitive information. */ TPM_PCR_INFO_SHORT pcrInfo; /* This SHALL be the designation of the process that can use the permission. This is a not sensitive value. PCR_SELECTION may be NULL. If selected the pcrInfo MUST be checked on each use of the delegation. Use of the delegation is where the delegation is passed as an authorization handle. */ TPM_DELEGATIONS permissions; /* This SHALL be the permissions that are allowed to the indicated process. This is not a sensitive value. */ TPM_FAMILY_ID familyID; /* This SHALL be the family ID that identifies which family the row belongs to. This is not a sensitive value. */ TPM_FAMILY_VERIFICATION verificationCount; /* A copy of verificationCount from the associated family table. This is not a sensitive value. */ } TPM_DELEGATE_PUBLIC; /* 20.9 TPM_DELEGATE_TABLE_ROW rev 101 A row of the delegate table. */ typedef struct tdTPM_DELEGATE_TABLE_ROW { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* This SHALL be TPM_TAG_DELEGATE_TABLE_ROW */ #endif TPM_DELEGATE_PUBLIC pub; /* This SHALL be the public information for a table row. */ TPM_SECRET authValue; /* This SHALL be the authorization value that can use the permissions. This is a sensitive value. */ /* NOTE Added */ TPM_BOOL valid; } TPM_DELEGATE_TABLE_ROW; /* 20.10 TPM_DELEGATE_TABLE rev 87 This is the delegate table. The table contains a minimum of 2 rows. This will be an entry in the TPM_PERMANENT_DATA structure. */ #ifdef TPM_NUM_DELEGATE_TABLE_ENTRY_MIN #if (TPM_NUM_DELEGATE_TABLE_ENTRY_MIN < 2) #error "TPM_NUM_DELEGATE_TABLE_ENTRY_MIN minimum is 2" #endif #endif #ifndef TPM_NUM_DELEGATE_TABLE_ENTRY_MIN #define TPM_NUM_DELEGATE_TABLE_ENTRY_MIN 2 #endif typedef struct tdTPM_DELEGATE_TABLE { TPM_DELEGATE_TABLE_ROW delRow[TPM_NUM_DELEGATE_TABLE_ENTRY_MIN]; /* The array of delegations */ } TPM_DELEGATE_TABLE; /* 20.11 TPM_DELEGATE_SENSITIVE rev 115 The TPM_DELEGATE_SENSITIVE structure is the area of a delegate blob that contains sensitive information. This structure is normative for loading unencrypted blobs before there is an owner. It is informative for TPM_CreateOwnerDelegation and TPM_LoadOwnerDelegation after there is an owner and encrypted blobs are used, since the structure is under complete control of the TPM. */ typedef struct tdTPM_DELEGATE_SENSITIVE { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* This MUST be TPM_TAG_DELEGATE_SENSITIVE */ #endif TPM_SECRET authValue; /* AuthData value */ } TPM_DELEGATE_SENSITIVE; /* 20.12 TPM_DELEGATE_OWNER_BLOB rev 87 This data structure contains all the information necessary to externally store a set of owner delegation rights that can subsequently be loaded or used by this TPM. The encryption mechanism for the sensitive area is a TPM choice. The TPM may use asymmetric encryption and the SRK for the key. The TPM may use symmetric encryption and a secret key known only to the TPM. */ typedef struct tdTPM_DELEGATE_OWNER_BLOB { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* This MUST be TPM_TAG_DELG_OWNER_BLOB */ #endif TPM_DELEGATE_PUBLIC pub; /* The public information for this blob */ TPM_DIGEST integrityDigest; /* The HMAC to guarantee the integrity of the entire structure */ TPM_SIZED_BUFFER additionalArea; /* An area that the TPM can add to the blob which MUST NOT contain any sensitive information. This would include any IV material for symmetric encryption */ TPM_SIZED_BUFFER sensitiveArea; /* The area that contains the encrypted TPM_DELEGATE_SENSITIVE */ } TPM_DELEGATE_OWNER_BLOB; /* 20.13 TPM_DELEGATE_KEY_BLOB rev 87 A structure identical to TPM_DELEGATE_OWNER_BLOB but which stores delegation information for user keys. As compared to TPM_DELEGATE_OWNER_BLOB, it adds a hash of the corresponding public key value to the public information. */ typedef struct tdTPM_DELEGATE_KEY_BLOB { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* This MUST be TPM_TAG_DELG_KEY_BLOB */ #endif TPM_DELEGATE_PUBLIC pub; /* The public information for this blob */ TPM_DIGEST integrityDigest; /* The HMAC to guarantee the integrity of the entire structure */ TPM_DIGEST pubKeyDigest; /* The digest, that uniquely identifies the key for which this usage delegation applies. */ TPM_SIZED_BUFFER additionalArea; /* An area that the TPM can add to the blob which MUST NOT contain any sensitive information. This would include any IV material for symmetric encryption */ TPM_SIZED_BUFFER sensitiveArea; /* The area that contains the encrypted TPM_DELEGATE_SENSITIVE */ } TPM_DELEGATE_KEY_BLOB; /* 15.1 TPM_CURRENT_TICKS rev 110 This structure holds the current number of time ticks in the TPM. The value is the number of time ticks from the start of the current session. Session start is a variable function that is platform dependent. Some platforms may have batteries or other power sources and keep the TPM clock session across TPM initialization sessions. The element of the TPM_CURRENT_TICKS structure provides the number of microseconds per tick. The platform manufacturer must satisfy input clock requirements set by the TPM vendor to ensure the accuracy of the tickRate. No external entity may ever set the current number of time ticks held in TPM_CURRENT_TICKS. This value is always reset to 0 when a new clock session starts and increments under control of the TPM. Maintaining the relationship between the number of ticks counted by the TPM and some real world clock is a task for external software. */ /* This is not a true UINT64, but a special structure to hold currentTicks */ typedef struct tdTPM_UINT64 { uint32_t sec; uint32_t usec; } TPM_UINT64; typedef struct tdTPM_CURRENT_TICKS { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* TPM_TAG_CURRENT_TICKS */ #endif TPM_UINT64 currentTicks; /* The number of ticks since the start of this tick session */ /* upper is seconds, lower is useconds */ uint16_t tickRate; /* The number of microseconds per tick. The maximum resolution of the TPM tick counter is thus 1 microsecond. The minimum resolution SHOULD be 1 millisecond. */ TPM_NONCE tickNonce; /* TPM_NONCE tickNonce The nonce created by the TPM when resetting the currentTicks to 0. This indicates the beginning of a time session. This value MUST be valid before the first use of TPM_CURRENT_TICKS. The value can be set at TPM_Startup or just prior to first use. */ /* NOTE Added */ TPM_UINT64 initialTime; /* Time from TPM_GetTimeOfDay() */ } TPM_CURRENT_TICKS; /* 13. Transport Structures */ /* 13.1 TPM _TRANSPORT_PUBLIC rev 87 The public information relative to a transport session */ typedef struct tdTPM_TRANSPORT_PUBLIC { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* TPM_TAG_TRANSPORT_PUBLIC */ #endif TPM_TRANSPORT_ATTRIBUTES transAttributes; /* The attributes of this session */ TPM_ALGORITHM_ID algId; /* This SHALL be the algorithm identifier of the symmetric key. */ TPM_ENC_SCHEME encScheme; /* This SHALL fully identify the manner in which the key will be used for encryption operations. */ } TPM_TRANSPORT_PUBLIC; /* 13.2 TPM_TRANSPORT_INTERNAL rev 88 The internal information regarding transport session */ /* 7.6 TPM_STANY_DATA */ #ifdef TPM_MIN_TRANS_SESSIONS #if (TPM_MIN_TRANS_SESSIONS < 3) #error "TPM_MIN_TRANS_SESSIONS minimum is 3" #endif #endif #ifndef TPM_MIN_TRANS_SESSIONS #define TPM_MIN_TRANS_SESSIONS 3 #endif typedef struct tdTPM_TRANSPORT_INTERNAL { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* TPM_TAG_TRANSPORT_INTERNAL */ #endif TPM_AUTHDATA authData; /* The shared secret for this session */ TPM_TRANSPORT_PUBLIC transPublic; /* The public information of this session */ TPM_TRANSHANDLE transHandle; /* The handle for this session */ TPM_NONCE transNonceEven; /* The even nonce for the rolling protocol */ TPM_DIGEST transDigest; /* The log of transport events */ /* added kgold */ TPM_BOOL valid; /* entry is valid */ } TPM_TRANSPORT_INTERNAL; /* 13.3 TPM_TRANSPORT_LOG_IN rev 87 The logging of transport commands occurs in two steps, before execution with the input parameters and after execution with the output parameters. This structure is in use for input log calculations. */ typedef struct tdTPM_TRANSPORT_LOG_IN { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* TPM_TAG_TRANSPORT_LOG_IN */ #endif TPM_DIGEST parameters; /* The actual parameters contained in the digest are subject to the rules of the command using this structure. To find the exact calculation refer to the actions in the command using this structure. */ TPM_DIGEST pubKeyHash; /* The hash of any keys in the transport command */ } TPM_TRANSPORT_LOG_IN; /* 13.4 TPM_TRANSPORT_LOG_OUT rev 88 The logging of transport commands occurs in two steps, before execution with the input parameters and after execution with the output parameters. This structure is in use for output log calculations. This structure is in use for the INPUT logging during releaseTransport. */ typedef struct tdTPM_TRANSPORT_LOG_OUT { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* TPM_TAG_TRANSPORT_LOG_OUT */ #endif TPM_CURRENT_TICKS currentTicks; /* The current tick count. This SHALL be the value of the current TPM tick counter. */ TPM_DIGEST parameters; /* The actual parameters contained in the digest are subject to the rules of the command using this structure. To find the exact calculation refer to the actions in the command using this structure. */ TPM_MODIFIER_INDICATOR locality; /* The locality that called TPM_ExecuteTransport */ } TPM_TRANSPORT_LOG_OUT; /* 13.5 TPM_TRANSPORT_AUTH structure rev 87 This structure provides the validation for the encrypted AuthData value. */ typedef struct tdTPM_TRANSPORT_AUTH { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* TPM_TAG_TRANSPORT_AUTH */ #endif TPM_AUTHDATA authData; /* The AuthData value */ } TPM_TRANSPORT_AUTH; /* 22.3 TPM_DAA_ISSUER rev 91 This structure is the abstract representation of non-secret settings controlling a DAA context. The structure is required when loading public DAA data into a TPM. TPM_DAA_ISSUER parameters are normally held outside the TPM as plain text data, and loaded into a TPM when a DAA session is required. A TPM_DAA_ISSUER structure contains no integrity check: the TPM_DAA_ISSUER structure at time of JOIN is indirectly verified by the issuer during the JOIN process, and a digest of the verified TPM_DAA_ISSUER structure is held inside the TPM_DAA_TPM structure created by the JOIN process. Parameters DAA_digest_X are digests of public DAA_generic_X parameters, and used to verify that the correct value of DAA_generic_X has been loaded. DAA_generic_q is stored in its native form to reduce command complexity. */ typedef struct tdTPM_DAA_ISSUER { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* MUST be TPM_TAG_DAA_ISSUER */ #endif TPM_DIGEST DAA_digest_R0; /* A digest of the parameter "R0", which is not secret and may be common to many TPMs. */ TPM_DIGEST DAA_digest_R1; /* A digest of the parameter "R1", which is not secret and may be common to many TPMs. */ TPM_DIGEST DAA_digest_S0; /* A digest of the parameter "S0", which is not secret and may be common to many TPMs. */ TPM_DIGEST DAA_digest_S1; /* A digest of the parameter "S1", which is not secret and may be common to many TPMs. */ TPM_DIGEST DAA_digest_n; /* A digest of the parameter "n", which is not secret and may be common to many TPMs. */ TPM_DIGEST DAA_digest_gamma; /* A digest of the parameter "gamma", which is not secret and may be common to many TPMs. */ BYTE DAA_generic_q[26]; /* The parameter q, which is not secret and may be common to many TPMs. Note that q is slightly larger than a digest, but is stored in its native form to simplify the TPM_DAA_join command. Otherwise, JOIN requires 3 input parameters. */ } TPM_DAA_ISSUER; /* 22.4 TPM_DAA_TPM rev 91 This structure is the abstract representation of TPM specific parameters used during a DAA context. TPM-specific DAA parameters may be stored outside the TPM, and hence this structure is needed to save private DAA data from a TPM, or load private DAA data into a TPM. If a TPM_DAA_TPM structure is stored outside the TPM, it is stored in a confidential format that can be interpreted only by the TPM created it. This is to ensure that secret parameters are rendered confidential, and that both secret and non-secret data in TPM_DAA_TPM form a self-consistent set. TPM_DAA_TPM includes a digest of the public DAA parameters that were used during creation of the TPM_DAA_TPM structure. This is needed to verify that a TPM_DAA_TPM is being used with the public DAA parameters used to create the TPM_DAA_TPM structure. Parameters DAA_digest_v0 and DAA_digest_v1 are digests of public DAA_private_v0 and DAA_private_v1 parameters, and used to verify that the correct private parameters have been loaded. Parameter DAA_count is stored in its native form, because it is smaller than a digest, and is required to enforce consistency. */ typedef struct tdTPM_DAA_TPM { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* MUST be TPM_TAG_DAA_TPM */ #endif TPM_DIGEST DAA_digestIssuer; /* A digest of a TPM_DAA_ISSUER structure that contains the parameters used to generate this TPM_DAA_TPM structure. */ TPM_DIGEST DAA_digest_v0; /* A digest of the parameter "v0", which is secret and specific to this TPM. "v0" is generated during a JOIN phase. */ TPM_DIGEST DAA_digest_v1; /* A digest of the parameter "v1", which is secret and specific to this TPM. "v1" is generated during a JOIN phase. */ TPM_DIGEST DAA_rekey; /* A digest related to the rekeying process, which is not secret but is specific to this TPM, and must be consistent across JOIN/SIGN sessions. "rekey" is generated during a JOIN phase. */ uint32_t DAA_count; /* The parameter "count", which is not secret but must be consistent across JOIN/SIGN sessions. "count" is an input to the TPM from the host system. */ } TPM_DAA_TPM; /* 22.5 TPM_DAA_CONTEXT rev 91 TPM_DAA_CONTEXT structure is created and used inside a TPM, and never leaves the TPM. This entire section is informative as the TPM does not expose this structure. TPM_DAA_CONTEXT includes a digest of the public and private DAA parameters that were used during creation of the TPM_DAA_CONTEXT structure. This is needed to verify that a TPM_DAA_CONTEXT is being used with the public and private DAA parameters used to create the TPM_DAA_CONTEXT structure. */ typedef struct tdTPM_DAA_CONTEXT { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* MUST be TPM_TAG_DAA_CONTEXT */ #endif TPM_DIGEST DAA_digestContext; /* A digest of parameters used to generate this structure. The parameters vary, depending on whether the session is a JOIN session or a SIGN session. */ TPM_DIGEST DAA_digest; /* A running digest of certain parameters generated during DAA computation; operationally the same as a PCR (which holds a running digest of integrity metrics). */ TPM_DAA_CONTEXT_SEED DAA_contextSeed; /* The seed used to generate other DAA session parameters */ BYTE DAA_scratch[256]; /* Memory used to hold different parameters at different times of DAA computation, but only one parameter at a time. The maximum size of this field is 256 bytes */ BYTE DAA_stage; /* A counter, indicating the stage of DAA computation that was most recently completed. The value of the counter is zero if the TPM currently contains no DAA context. When set to zero (0) the TPM MUST clear all other fields in this structure. The TPM MUST set DAA_stage to 0 on TPM_Startup(ANY) */ TPM_BOOL DAA_scratch_null; } TPM_DAA_CONTEXT; /* 22.6 TPM_DAA_JOINDATA rev 91 This structure is the abstract representation of data that exists only during a specific JOIN session. */ typedef struct tdTPM_DAA_JOINDATA { BYTE DAA_join_u0[128]; /* A TPM-specific secret "u0", used during the JOIN phase, and discarded afterwards. */ BYTE DAA_join_u1[138]; /* A TPM-specific secret "u1", used during the JOIN phase, and discarded afterwards. */ TPM_DIGEST DAA_digest_n0; /* A digest of the parameter "n0", which is an RSA public key with exponent 2^16 +1 */ } TPM_DAA_JOINDATA; /* DAA Session structure */ #ifdef TPM_MIN_DAA_SESSIONS #if (TPM_MIN_DAA_SESSIONS < 1) #error "TPM_MIN_DAA_SESSIONS minimum is 1" #endif #endif #ifndef TPM_MIN_DAA_SESSIONS #define TPM_MIN_DAA_SESSIONS 1 #endif typedef struct tdTPM_DAA_SESSION_DATA { TPM_DAA_ISSUER DAA_issuerSettings; /* A set of DAA issuer parameters controlling a DAA session. (non-secret) */ TPM_DAA_TPM DAA_tpmSpecific; /* A set of DAA parameters associated with a specific TPM. (secret) */ TPM_DAA_CONTEXT DAA_session; /* A set of DAA parameters associated with a DAA session. (secret) */ TPM_DAA_JOINDATA DAA_joinSession; /* A set of DAA parameters used only during the JOIN phase of a DAA session, and generated by the TPM. (secret) */ /* added kgold */ TPM_HANDLE daaHandle; /* DAA session handle */ TPM_BOOL valid; /* array entry is valid */ /* FIXME should have handle type Join or Sign */ } TPM_DAA_SESSION_DATA; /* 22.8 TPM_DAA_BLOB rev 98 The structure passed during the join process */ typedef struct tdTPM_DAA_BLOB { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* MUST be TPM_TAG_DAA_BLOB */ #endif TPM_RESOURCE_TYPE resourceType; /* The resource type: enc(DAA_tpmSpecific) or enc(v0) or enc(v1) */ BYTE label[16]; /* Label for identification of the blob. Free format area. */ TPM_DIGEST blobIntegrity; /* The integrity of the entire blob including the sensitive area. This is a HMAC calculation with the entire structure (including sensitiveData) being the hash and daaProof is the secret */ TPM_SIZED_BUFFER additionalData; /* Additional information set by the TPM that helps define and reload the context. The information held in this area MUST NOT expose any information held in shielded locations. This should include any IV for symmetric encryption */ TPM_SIZED_BUFFER sensitiveData; /* A TPM_DAA_SENSITIVE structure */ #if 0 uint32_t additionalSize; [size_is(additionalSize)] BYTE* additionalData; uint32_t sensitiveSize; [size_is(sensitiveSize)] BYTE* sensitiveData; #endif } TPM_DAA_BLOB; /* 22.9 TPM_DAA_SENSITIVE rev 91 The encrypted area for the DAA parameters */ typedef struct tdTPM_DAA_SENSITIVE { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* MUST be TPM_TAG_DAA_SENSITIVE */ #endif TPM_SIZED_BUFFER internalData; /* DAA_tpmSpecific or DAA_private_v0 or DAA_private_v1 */ #if 0 uint32_t internalSize; [size_is(internalSize)] BYTE* internalData; #endif } TPM_DAA_SENSITIVE; /* 7.1 TPM_PERMANENT_FLAGS rev 110 These flags maintain state information for the TPM. The values are not affected by any TPM_Startup command. The flag history includes: Rev 62 specLevel 1 errataRev 0: 15 BOOLs Rev 85 specLevel 2 errataRev 0: 19 BOOLs Added: nvLocked, readSRKPub, tpmEstablished, maintenanceDone Rev 94 specLevel 2 errataRev 1: 19 BOOLs Rev 103 specLevel 2 errataRev 2: 20 BOOLs Added: disableFullDALogicInfo */ typedef struct tdTPM_PERMANENT_FLAGS { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* TPM_TAG_PERMANENT_FLAGS */ #endif TPM_BOOL disable; /* disable The state of the disable flag. The default state is TRUE */ TPM_BOOL ownership; /* The ability to install an owner. The default state is TRUE. */ TPM_BOOL deactivated; /* The state of the inactive flag. The default state is TRUE. */ TPM_BOOL readPubek; /* The ability to read the PUBEK without owner authorization. The default state is TRUE. set TRUE on owner clear set FALSE on take owner, disablePubekRead */ TPM_BOOL disableOwnerClear; /* Whether the owner authorized clear commands are active. The default state is FALSE. */ TPM_BOOL allowMaintenance; /* Whether the TPM Owner may create a maintenance archive. The default state is TRUE. */ TPM_BOOL physicalPresenceLifetimeLock; /* This bit can only be set to TRUE; it cannot be set to FALSE except during the manufacturing process. FALSE: The state of either physicalPresenceHWEnable or physicalPresenceCMDEnable MAY be changed. (DEFAULT) TRUE: The state of either physicalPresenceHWEnable or physicalPresenceCMDEnable MUST NOT be changed for the life of the TPM. */ TPM_BOOL physicalPresenceHWEnable; /* FALSE: Disable the hardware signal indicating physical presence. (DEFAULT) TRUE: Enables the hardware signal indicating physical presence. */ TPM_BOOL physicalPresenceCMDEnable; /* FALSE: Disable the command indicating physical presence. (DEFAULT) TRUE: Enables the command indicating physical presence. */ TPM_BOOL CEKPUsed; /* TRUE: The PRIVEK and PUBEK were created using TPM_CreateEndorsementKeyPair. FALSE: The PRIVEK and PUBEK were created using a manufacturer's process. NOTE: This flag has no default value as the key pair MUST be created by one or the other mechanism. */ TPM_BOOL TPMpost; /* TRUE: After TPM_Startup, if there is a call to TPM_ContinueSelfTest the TPM MUST execute the actions of TPM_SelfTestFull FALSE: After TPM_Startup, if there is a call to TPM_ContinueSelfTest the TPM MUST execute TPM_ContinueSelfTest If the TPM supports the implicit invocation of TPM_ContinueSelftTest upon the use of an untested resource, the TPM MUST use the TPMPost flag to call either TPM_ContinueSelfTest or TPM_SelfTestFull The TPM manufacturer sets this bit during TPM manufacturing and the bit is unchangeable after shipping the TPM The default state is FALSE */ TPM_BOOL TPMpostLock; /* With the clarification of TPMPost TPMpostLock is now unnecessary. This flag is now deprecated */ TPM_BOOL FIPS; /* TRUE: This TPM operates in FIPS mode FALSE: This TPM does NOT operate in FIPS mode */ TPM_BOOL tpmOperator; /* TRUE: The operator authorization value is valid FALSE: the operator authorization value is not set */ TPM_BOOL enableRevokeEK; /* TRUE: The TPM_RevokeTrust command is active FALSE: the TPM RevokeTrust command is disabled */ TPM_BOOL nvLocked; /* TRUE: All NV area authorization checks are active FALSE: No NV area checks are performed, except for maxNVWrites. FALSE is the default value */ TPM_BOOL readSRKPub; /* TRUE: GetPubKey will return the SRK pub key FALSE: GetPubKey will not return the SRK pub key Default SHOULD be FALSE */ TPM_BOOL tpmEstablished; /* TRUE: TPM_HASH_START has been executed at some time FALSE: TPM_HASH_START has not been executed at any time Default is FALSE - resets using TPM_ResetEstablishmentBit */ TPM_BOOL maintenanceDone; /* TRUE: A maintenance archive has been created for the current SRK */ #if (TPM_REVISION >= 103) /* added for rev 103 */ TPM_BOOL disableFullDALogicInfo; /* TRUE: The full dictionary attack TPM_GetCapability info is deactivated. The returned structure is TPM_DA_INFO_LIMITED. FALSE: The full dictionary attack TPM_GetCapability info is activated. The returned structure is TPM_DA_INFO. Default is FALSE. */ #endif /* NOTE: Cannot add vendor specific flags here, since TPM_GetCapability() returns the serialized structure */ } TPM_PERMANENT_FLAGS; /* 7.2 TPM_STCLEAR_FLAGS rev 109 These flags maintain state that is reset on each TPM_Startup(ST_Clear) command. The values are not affected by TPM_Startup(ST_State) commands. */ typedef struct tdTPM_STCLEAR_FLAGS { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* TPM_TAG_STCLEAR_FLAGS */ #endif TPM_BOOL deactivated; /* Prevents the operation of most capabilities. There is no default state. It is initialized by TPM_Startup to the same value as TPM_PERMANENT_FLAGS -> deactivated. TPM_SetTempDeactivated sets it to TRUE. */ TPM_BOOL disableForceClear; /* Prevents the operation of TPM_ForceClear when TRUE. The default state is FALSE. TPM_DisableForceClear sets it to TRUE. */ TPM_BOOL physicalPresence; /* Command assertion of physical presence. The default state is FALSE. This flag is affected by the TSC_PhysicalPresence command but not by the hardware signal. */ TPM_BOOL physicalPresenceLock; /* Indicates whether changes to the TPM_STCLEAR_FLAGS -> physicalPresence flag are permitted. TPM_Startup(ST_CLEAR) sets PhysicalPresenceLock to its default state of FALSE (allow changes to the physicalPresence flag). When TRUE, the physicalPresence flag is FALSE. TSC_PhysicalPresence can change the state of physicalPresenceLock. */ TPM_BOOL bGlobalLock; /* Set to FALSE on each TPM_Startup(ST_CLEAR). Set to TRUE when a write to NV_Index =0 is successful */ /* NOTE: Cannot add vendor specific flags here, since TPM_GetCapability() returns the serialized structure */ } TPM_STCLEAR_FLAGS; /* 7.3 TPM_STANY_FLAGS rev 87 These flags reset on any TPM_Startup command. */ typedef struct tdTPM_STANY_FLAGS { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* TPM_TAG_STANY_FLAGS */ #endif TPM_BOOL postInitialise; /* Prevents the operation of most capabilities. There is no default state. It is initialized by TPM_Init to TRUE. TPM_Startup sets it to FALSE. */ TPM_MODIFIER_INDICATOR localityModifier; /*This SHALL indicate for each command the presence of a locality modifier for the command. It MUST be set to NULL after the TPM executes each command. */ #if 0 TPM_BOOL transportExclusive; /* Defaults to FALSE. TRUE when there is an exclusive transport session active. Execution of ANY command other than TPM_ExecuteTransport or TPM_ReleaseTransportSigned MUST invalidate the exclusive transport session. */ #endif TPM_TRANSHANDLE transportExclusive; /* Defaults to 0x00000000, Set to the handle when an exclusive transport session is active */ TPM_BOOL TOSPresent; /* Defaults to FALSE Set to TRUE on TPM_HASH_START set to FALSE using setCapability */ /* NOTE: Added kgold */ TPM_BOOL stateSaved; /* Defaults to FALSE Set to TRUE on TPM_SaveState Set to FALSE on any other ordinal This is an optimization flag, so the file need not be deleted if it does not exist. */ } TPM_STANY_FLAGS; /* 7.4 TPM_PERMANENT_DATA rev 105 This structure contains the data fields that are permanently held in the TPM and not affected by TPM_Startup(any). Many of these fields contain highly confidential and privacy sensitive material. The TPM must maintain the protections around these fields. */ #ifdef TPM_MIN_COUNTERS #if (TPM_MIN_COUNTERS < 4) #error "TPM_MIN_COUNTERS minimum is 4" #endif #endif #ifndef TPM_MIN_COUNTERS #define TPM_MIN_COUNTERS 4 /* the minimum number of counters is 4 */ #endif #define TPM_DELEGATE_KEY TPM_KEY #define TPM_MAX_NV_WRITE_NOOWNER 64 /* Although the ordinal is 32 bits, only the lower 8 bits seem to be used. So for now, define an array of 256/8 bytes for ordinalAuditStatus - kgold */ #define TPM_ORDINALS_MAX 256 /* assumes a multiple of CHAR_BIT */ #define TPM_AUTHDIR_SIZE 1 /* Number of DIR registers */ typedef struct tdTPM_PERMANENT_DATA { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* TPM_TAG_PERMANENT_DATA */ #endif BYTE revMajor; /* This is the TPM major revision indicator. This SHALL be set by the TPME, only. The default value is manufacturer-specific. */ BYTE revMinor; /* This is the TPM minor revision indicator. This SHALL be set by the TPME, only. The default value is manufacturer-specific. */ TPM_SECRET tpmProof; /* This is a random number that each TPM maintains to validate blobs in the SEAL and other processes. The default value is manufacturer-specific. */ TPM_NONCE EKReset; /* Nonce held by TPM to validate TPM_RevokeTrust. This value is set as the next 20 bytes from the TPM RNG when the EK is set (was fipsReset - kgold) */ TPM_SECRET ownerAuth; /* This is the TPM-Owner's authorization data. The default value is manufacturer-specific. */ TPM_SECRET operatorAuth; /* The value that allows the execution of the SetTempDeactivated command */ TPM_DIRVALUE authDIR; /* The array of TPM Owner authorized DIR. Points to the same location as the NV index value. (kgold - was array of 1) */ #ifndef TPM_NOMAINTENANCE TPM_PUBKEY manuMaintPub; /* This is the manufacturer's public key to use in the maintenance operations. The default value is manufacturer-specific. */ #endif TPM_KEY endorsementKey; /* This is the TPM's endorsement key pair. */ TPM_KEY srk; /* This is the TPM's StorageRootKey. */ TPM_SYMMETRIC_KEY_TOKEN contextKey; /* This is the key in use to perform context saves. The key may be symmetric or asymmetric. The key size is predicated by the algorithm in use. */ TPM_SYMMETRIC_KEY_TOKEN delegateKey; /* This key encrypts delegate rows that are stored outside the TPM. */ TPM_COUNTER_VALUE auditMonotonicCounter; /* This SHALL be the audit monotonic counter for the TPM. This value starts at 0 and increments according to the rules of auditing */ TPM_COUNTER_VALUE monotonicCounter[TPM_MIN_COUNTERS]; /* This SHALL be the monotonic counters for the TPM. The individual counters start and increment according to the rules of monotonic counters. */ TPM_PCR_ATTRIBUTES pcrAttrib[TPM_NUM_PCR]; /* The attributes for all of the PCR registers supported by the TPM. */ BYTE ordinalAuditStatus[TPM_ORDINALS_MAX/CHAR_BIT]; /* Table indicating which ordinals are being audited. */ #if 0 /* kgold - The xcrypto RNG is good enough that this is not needed */ BYTE* rngState; /* State information describing the random number generator. */ #endif TPM_FAMILY_TABLE familyTable; /* The family table in use for delegations */ TPM_DELEGATE_TABLE delegateTable; /* The delegate table */ uint32_t lastFamilyID; /* A value that sets the high water mark for family ID's. Set to 0 during TPM manufacturing and never reset. */ uint32_t noOwnerNVWrite; /* The count of NV writes that have occurred when there is no TPM Owner. This value starts at 0 in manufacturing and after each TPM_OwnerClear. If the value exceeds 64 the TPM returns TPM_MAXNVWRITES to any command attempting to manipulate the NV storage. */ TPM_CMK_DELEGATE restrictDelegate; /* The settings that allow for the delegation and use on CMK keys. Default value is false. */ TPM_DAA_TPM_SEED tpmDAASeed; /* This SHALL be a random value generated after generation of the EK. tpmDAASeed does not change during TPM Owner changes. If the EK is removed (RevokeTrust) then the TPM MUST invalidate the tpmDAASeed. The owner can force a change in the value through TPM_SetCapability. (linked to daaProof) */ TPM_NONCE daaProof; /* This is a random number that each TPM maintains to validate blobs in the DAA processes. The default value is manufacturer-specific. The value is not changed when the owner is changed. It is changed when the EK changes. The owner can force a change in the value through TPM_SetCapability. */ TPM_SYMMETRIC_KEY_TOKEN daaBlobKey; /* This is the key in use to perform DAA encryption and decryption. The key may be symmetric or asymmetric. The key size is predicated by the algorithm in use. This value MUST be changed when daaProof changes. This key MUST NOT be a copy of the EK or SRK. (linked to daaProof) */ /* NOTE: added kgold */ TPM_BOOL ownerInstalled; /* TRUE: The TPM has an owner installed. FALSE: The TPM has no owner installed. (default) */ BYTE tscOrdinalAuditStatus; /* extra byte to track TSC ordinals */ TPM_BOOL allowLoadMaintPub; /* TRUE allows the TPM_LoadManuMaintPub command */ } TPM_PERMANENT_DATA; /* 7.6 TPM_STANY_DATA */ #ifdef TPM_MIN_AUTH_SESSIONS #if (TPM_MIN_AUTH_SESSIONS < 3) #error "TPM_MIN_AUTH_SESSIONS minimum is 3" #endif #endif #ifndef TPM_MIN_AUTH_SESSIONS #define TPM_MIN_AUTH_SESSIONS 3 #endif /* NOTE: Vendor specific */ typedef struct tdTPM_AUTH_SESSION_DATA { /* vendor specific */ TPM_AUTHHANDLE handle; /* Handle for a session */ TPM_PROTOCOL_ID protocolID; /* TPM_PID_OIAP, TPM_PID_OSAP, TPM_PID_DSAP */ TPM_ENT_TYPE entityTypeByte; /* The type of entity in use (TPM_ET_SRK, TPM_ET_OWNER, TPM_ET_KEYHANDLE ... */ TPM_ADIP_ENC_SCHEME adipEncScheme; /* ADIP encryption scheme */ TPM_NONCE nonceEven; /* OIAP, OSAP, DSAP */ TPM_SECRET sharedSecret; /* OSAP */ TPM_DIGEST entityDigest; /* OSAP tracks which entity established the OSAP session */ TPM_DELEGATE_PUBLIC pub; /* DSAP */ TPM_BOOL valid; /* added kgold: array entry is valid */ } TPM_AUTH_SESSION_DATA; /* 3. contextList MUST support a minimum of 16 entries, it MAY support more. */ #ifdef TPM_MIN_SESSION_LIST #if (TPM_MIN_SESSION_LIST < 16) #error "TPM_MIN_SESSION_LIST minimum is 16" #endif #endif #ifndef TPM_MIN_SESSION_LIST #define TPM_MIN_SESSION_LIST 16 #endif /* 7.5 TPM_STCLEAR_DATA rev 101 This is an informative structure and not normative. It is purely for convenience of writing the spec. Most of the data in this structure resets on TPM_Startup(ST_Clear). A TPM may implement rules that provide longer-term persistence for the data. The TPM reflects how it handles the data in various TPM_GetCapability fields including startup effects. */ typedef struct tdTPM_STCLEAR_DATA { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* TPM_TAG_STCLEAR_DATA */ #endif TPM_NONCE contextNonceKey; /* This is the nonce in use to properly identify saved key context blobs This SHALL be set to all zeros on each TPM_Startup (ST_Clear). */ TPM_COUNT_ID countID; /* This is the handle for the current monotonic counter. This SHALL be set to zero on each TPM_Startup(ST_Clear). */ uint32_t ownerReference; /* Points to where to obtain the owner secret in OIAP and OSAP commands. This allows a TSS to manage 1.1 applications on a 1.2 TPM where delegation is in operation. */ TPM_BOOL disableResetLock; /* Disables TPM_ResetLockValue upon authorization failure. The value remains TRUE for the timeout period. Default is FALSE. The value is in the STCLEAR_DATA structure as the implementation of this flag is TPM vendor specific. */ TPM_PCRVALUE PCRS[TPM_NUM_PCR]; /* Platform configuration registers */ #if (TPM_REVISION >= 103) /* added for rev 103 */ uint32_t deferredPhysicalPresence; /* The value can save the assertion of physicalPresence. Individual bits indicate to its ordinal that physicalPresence was previously asserted when the software state is such that it can no longer be asserted. Set to zero on each TPM_Startup(ST_Clear). */ #endif /* NOTE: Added for dictionary attack mitigation */ uint32_t authFailCount; /* number of authorization failures without a TPM_ResetLockValue */ uint32_t authFailTime; /* time of threshold failure in seconds */ /* NOTE: Moved from TPM_STANY_DATA. Saving this state is optional. This implementation does. */ TPM_AUTH_SESSION_DATA authSessions[TPM_MIN_AUTH_SESSIONS]; /* List of current sessions. Sessions can be OSAP, OIAP, DSAP and Transport */ /* NOTE: Added for transport */ TPM_TRANSPORT_INTERNAL transSessions[TPM_MIN_TRANS_SESSIONS]; /* 22.7 TPM_STANY_DATA Additions (for DAA) - moved to TPM_STCLEAR_DATA for startup state */ TPM_DAA_SESSION_DATA daaSessions[TPM_MIN_DAA_SESSIONS]; /* 1. The group of contextNonceSession, contextCount, contextList MUST reset at the same time. */ TPM_NONCE contextNonceSession; /* This is the nonce in use to properly identify saved session context blobs. This MUST be set to all zeros on each TPM_Startup (ST_Clear). The nonce MAY be set to null on TPM_Startup( any). */ uint32_t contextCount; /* This is the counter to avoid session context blob replay attacks. This MUST be set to 0 on each TPM_Startup (ST_Clear). The value MAY be set to 0 on TPM_Startup (any). */ uint32_t contextList[TPM_MIN_SESSION_LIST]; /* This is the list of outstanding session blobs. All elements of this array MUST be set to 0 on each TPM_Startup (ST_Clear). The values MAY be set to 0 on TPM_Startup (any). */ /* NOTE Added auditDigest effect, saved with ST_STATE */ TPM_DIGEST auditDigest; /* This is the extended value that is the audit log. This SHALL be set to all zeros at the start of each audit session. */ /* NOTE Storage for the ordinal response */ TPM_STORE_BUFFER ordinalResponse; /* outgoing response buffer for this ordinal */ } TPM_STCLEAR_DATA; /* 7.6 TPM_STANY_DATA rev 87 This is an informative structure and not normative. It is purely for convenience of writing the spec. Most of the data in this structure resets on TPM_Startup(ST_State). A TPM may implement rules that provide longer-term persistence for the data. The TPM reflects how it handles the data in various getcapability fields including startup effects. */ typedef struct tdTPM_STANY_DATA { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* TPM_TAG_STANY_DATA */ #endif TPM_CURRENT_TICKS currentTicks; /* This is the current tick counter. This is reset to 0 according to the rules when the TPM can tick. See the section on the tick counter for details. */ } TPM_STANY_DATA; /* 11. Signed Structures */ /* 11.1 TPM_CERTIFY_INFO rev 101 When the TPM certifies a key, it must provide a signature with a TPM identity key on information that describes that key. This structure provides the mechanism to do so. Key usage and keyFlags must have their upper byte set to zero to avoid collisions with the other signature headers. */ typedef struct tdTPM_CERTIFY_INFO { TPM_STRUCT_VER version; /* This MUST be 1.1.0.0 */ TPM_KEY_USAGE keyUsage; /* This SHALL be the same value that would be set in a TPM_KEY representation of the key to be certified. The upper byte MUST be zero */ TPM_KEY_FLAGS keyFlags; /* This SHALL be set to the same value as the corresponding parameter in the TPM_KEY structure that describes the public key that is being certified. The upper byte MUST be zero */ TPM_AUTH_DATA_USAGE authDataUsage; /* This SHALL be the same value that would be set in a TPM_KEY representation of the key to be certified */ TPM_KEY_PARMS algorithmParms; /* This SHALL be the same value that would be set in a TPM_KEY representation of the key to be certified */ TPM_DIGEST pubkeyDigest; /* This SHALL be a digest of the value TPM_KEY -> pubKey -> key in a TPM_KEY representation of the key to be certified */ TPM_NONCE data; /* This SHALL be externally provided data. */ TPM_BOOL parentPCRStatus; /* This SHALL indicate if any parent key was wrapped to a PCR */ TPM_SIZED_BUFFER pcrInfo; /* */ #if 0 uint32_t PCRInfoSize; /* This SHALL be the size of the pcrInfo parameter. A value of zero indicates that the key is not wrapped to a PCR */ BYTE* PCRInfo; /* This SHALL be the TPM_PCR_INFO structure. */ #endif /* NOTE: kgold - Added this structure, a cache of PCRInfo when not NULL */ TPM_PCR_INFO *tpm_pcr_info; } TPM_CERTIFY_INFO; /* 11.2 TPM_CERTIFY_INFO2 rev 101 When the TPM certifies a key, it must provide a signature with a TPM identity key on information that describes that key. This structure provides the mechanism to do so. Key usage and keyFlags must have their upper byte set to zero to avoid collisions with the other signature headers. */ typedef struct tdTPM_CERTIFY_INFO2 { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* MUST be TPM_TAG_CERTIFY_INFO2 */ #endif BYTE fill; /* MUST be 0x00 */ TPM_PAYLOAD_TYPE payloadType; /* This SHALL be the same value that would be set in a TPM_KEY representation of the key to be certified */ TPM_KEY_USAGE keyUsage; /* This SHALL be the same value that would be set in a TPM_KEY representation of the key to be certified. The upper byte MUST be zero */ TPM_KEY_FLAGS keyFlags; /* This SHALL be set to the same value as the corresponding parameter in the TPM_KEY structure that describes the public key that is being certified. The upper byte MUST be zero. */ TPM_AUTH_DATA_USAGE authDataUsage; /* This SHALL be the same value that would be set in a TPM_KEY representation of the key to be certified */ TPM_KEY_PARMS algorithmParms; /* This SHALL be the same value that would be set in a TPM_KEY representation of the key to be certified */ TPM_DIGEST pubkeyDigest; /* This SHALL be a digest of the value TPM_KEY -> pubKey -> key in a TPM_KEY representation of the key to be certified */ TPM_NONCE data; /* This SHALL be externally provided data. */ TPM_BOOL parentPCRStatus; /* This SHALL indicate if any parent key was wrapped to a PCR */ #if 0 uint32_t PCRInfoSize; /* This SHALL be the size of the pcrInfo parameter. A value of zero indicates that the key is not wrapped to a PCR */ BYTE* PCRInfo; /* This SHALL be the TPM_PCR_INFO_SHORT structure. */ #endif TPM_SIZED_BUFFER pcrInfo; #if 0 uint32_t migrationAuthoritySize; /* This SHALL be the size of migrationAuthority */ BYTE *migrationAuthority; /* If the key to be certified has [payload == TPM_PT_MIGRATE_RESTRICTED or payload ==TPM_PT_MIGRATE_EXTERNAL], migrationAuthority is the digest of the TPM_MSA_COMPOSITE and has TYPE == TPM_DIGEST. Otherwise it is NULL. */ #endif TPM_SIZED_BUFFER migrationAuthority; /* NOTE: kgold - Added this structure, a cache of PCRInfo when not NULL */ TPM_PCR_INFO_SHORT *tpm_pcr_info_short; } TPM_CERTIFY_INFO2; /* 11.3 TPM_QUOTE_INFO rev 87 This structure provides the mechanism for the TPM to quote the current values of a list of PCRs. */ typedef struct tdTPM_QUOTE_INFO { TPM_STRUCT_VER version; /* This MUST be 1.1.0.0 */ BYTE fixed[4]; /* This SHALL always be the string 'QUOT' */ TPM_COMPOSITE_HASH digestValue; /* This SHALL be the result of the composite hash algorithm using the current values of the requested PCR indices. */ TPM_NONCE externalData; /* 160 bits of externally supplied data */ } TPM_QUOTE_INFO; /* 11.4 TPM_QUOTE_INFO2 rev 87 This structure provides the mechanism for the TPM to quote the current values of a list of PCRs. */ typedef struct tdTPM_QUOTE_INFO2 { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* This SHALL be TPM_TAG_QUOTE_INFO2 */ #endif BYTE fixed[4]; /* This SHALL always be the string 'QUT2' */ TPM_NONCE externalData; /* 160 bits of externally supplied data */ TPM_PCR_INFO_SHORT infoShort; /* */ } TPM_QUOTE_INFO2; /* 12.1 TPM_EK_BLOB rev 87 This structure provides a wrapper to each type of structure that will be in use when the endorsement key is in use. */ typedef struct tdTPM_EK_BLOB { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* TPM_TAG_EK_BLOB */ #endif TPM_EK_TYPE ekType; /* This SHALL be set to reflect the type of blob in use */ TPM_SIZED_BUFFER blob; /* The blob of information depending on the type */ #if 0 uint32_t blobSize; /* */ [size_is(blobSize)] byte* blob; /* */ #endif } TPM_EK_BLOB; /* 12.2 TPM_EK_BLOB_ACTIVATE rev 87 This structure contains the symmetric key to encrypt the identity credential. This structure always is contained in a TPM_EK_BLOB. */ typedef struct tdTPM_EK_BLOB_ACTIVATE { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* TPM_TAG_EK_BLOB_ACTIVATE */ #endif TPM_SYMMETRIC_KEY sessionKey; /* This SHALL be the session key used by the CA to encrypt the TPM_IDENTITY_CREDENTIAL */ TPM_DIGEST idDigest; /* This SHALL be the digest of the TPM identity public key that is being certified by the CA */ TPM_PCR_INFO_SHORT pcrInfo; /* This SHALL indicate the PCR's and localities */ } TPM_EK_BLOB_ACTIVATE; /* 12.3 TPM_EK_BLOB_AUTH rev 87 This structure contains the symmetric key to encrypt the identity credential. This structure always is contained in a TPM_EK_BLOB. */ typedef struct tdTPM_EK_BLOB_AUTH { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* TPM_TAG_EK_BLOB_AUTH */ #endif TPM_SECRET authValue; /* This SHALL be the authorization value */ } TPM_EK_BLOB_AUTH; /* 12.5 TPM_IDENTITY_CONTENTS rev 87 TPM_MakeIdentity uses this structure and the signature of this structure goes to a privacy CA during the certification process. */ typedef struct tdTPM_IDENTITY_CONTENTS { TPM_STRUCT_VER ver; /* This MUST be 1.1.0.0 */ uint32_t ordinal; /* This SHALL be the ordinal of the TPM_MakeIdentity command. */ TPM_CHOSENID_HASH labelPrivCADigest; /* This SHALL be the result of hashing the chosen identityLabel and privacyCA for the new TPM identity */ TPM_PUBKEY identityPubKey; /* This SHALL be the public key structure of the identity key */ } TPM_IDENTITY_CONTENTS; /* 12.8 TPM_ASYM_CA_CONTENTS rev 87 This structure contains the symmetric key to encrypt the identity credential. */ typedef struct tdTPM_ASYM_CA_CONTENTS { TPM_SYMMETRIC_KEY sessionKey; /* This SHALL be the session key used by the CA to encrypt the TPM_IDENTITY_CREDENTIAL */ TPM_DIGEST idDigest; /* This SHALL be the digest of the TPM_PUBKEY of the key that is being certified by the CA */ } TPM_ASYM_CA_CONTENTS; /* 14. Audit Structures */ /* 14.1 TPM_AUDIT_EVENT_IN rev 87 This structure provides the auditing of the command upon receipt of the command. It provides the information regarding the input parameters. */ typedef struct tdTPM_AUDIT_EVENT_IN { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* TPM_TAG_AUDIT_EVENT_IN */ #endif TPM_DIGEST inputParms; /* Digest value according to the HMAC digest rules of the "above the line" parameters (i.e. the first HMAC digest calculation). When there are no HMAC rules, the input digest includes all parameters including and after the ordinal. */ TPM_COUNTER_VALUE auditCount; /* The current value of the audit monotonic counter */ } TPM_AUDIT_EVENT_IN; /* 14.2 TPM_AUDIT_EVENT_OUT rev 87 This structure reports the results of the command execution. It includes the return code and the output parameters. */ typedef struct tdTPM_AUDIT_EVENT_OUT { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* TPM_TAG_AUDIT_EVENT_OUT */ #endif TPM_DIGEST outputParms; /* Digest value according to the HMAC digest rules of the "above the line" parameters (i.e. the first HMAC digest calculation). When there are no HMAC rules, the output digest includes the return code, the ordinal, and all parameters after the return code. */ TPM_COUNTER_VALUE auditCount; /* The current value of the audit monotonic counter */ } TPM_AUDIT_EVENT_OUT; /* 18. Context structures */ /* 18.1 TPM_CONTEXT_BLOB rev 102 This is the header for the wrapped context. The blob contains all information necessary to reload the context back into the TPM. The additional data is used by the TPM manufacturer to save information that will assist in the reloading of the context. This area must not contain any shielded data. For instance, the field could contain some size information that allows the TPM more efficient loads of the context. The additional area could not contain one of the primes for a RSA key. To ensure integrity of the blob when using symmetric encryption the TPM vendor could use some valid cipher chaining mechanism. To ensure the integrity without depending on correct implementation, the TPM_CONTEXT_BLOB structure uses a HMAC of the entire structure using tpmProof as the secret value. Since both additionalData and sensitiveData are informative, any or all of additionalData could be moved to sensitiveData. */ #define TPM_CONTEXT_LABEL_SIZE 16 typedef struct tdTPM_CONTEXT_BLOB { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* MUST be TPM_TAG_CONTEXTBLOB */ #endif TPM_RESOURCE_TYPE resourceType; /* The resource type */ TPM_HANDLE handle; /* Previous handle of the resource */ BYTE label[TPM_CONTEXT_LABEL_SIZE]; /* Label for identification of the blob. Free format area. */ uint32_t contextCount; /* MUST be TPM_STANY_DATA -> contextCount when creating the structure. This value is ignored for context blobs that reference a key. */ TPM_DIGEST integrityDigest; /* The integrity of the entire blob including the sensitive area. This is a HMAC calculation with the entire structure (including sensitiveData) being the hash and tpmProof is the secret */ #if 0 uint32_t additionalSize; [size_is(additionalSize)] BYTE* additionalData; uint32_t sensitiveSize; [size_is(sensitiveSize)] BYTE* sensitiveData; #endif TPM_SIZED_BUFFER additionalData; /* Additional information set by the TPM that helps define and reload the context. The information held in this area MUST NOT expose any information held in shielded locations. This should include any IV for symmetric encryption */ TPM_SIZED_BUFFER sensitiveData; /* The normal information for the resource that can be exported */ } TPM_CONTEXT_BLOB; /* 18.2 TPM_CONTEXT_SENSITIVE rev 87 The internal areas that the TPM needs to encrypt and store off the TPM. This is an informative structure and the TPM can implement in any manner they wish. */ typedef struct tdTPM_CONTEXT_SENSITIVE { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* MUST be TPM_TAG_CONTEXT_SENSITIVE */ #endif TPM_NONCE contextNonce; /* On context blobs other than keys this MUST be TPM_STANY_DATA - > contextNonceSession For keys the value is TPM_STCLEAR_DATA -> contextNonceKey */ #if 0 uint32_t internalSize; [size_is(internalSize)] BYTE* internalData; #endif TPM_SIZED_BUFFER internalData; /* The internal data area */ } TPM_CONTEXT_SENSITIVE; /* 19.2 TPM_NV_ATTRIBUTES rev 99 This structure allows the TPM to keep track of the data and permissions to manipulate the area. */ typedef struct tdTPM_NV_ATTRIBUTES { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* TPM_TAG_NV_ATTRIBUTES */ #endif uint32_t attributes; /* The attribute area */ } TPM_NV_ATTRIBUTES; /* 19.3 TPM_NV_DATA_PUBLIC rev 110 This structure represents the public description and controls on the NV area. bReadSTClear and bWriteSTClear are volatile, in that they are set FALSE at TPM_Startup(ST_Clear). bWriteDefine is persistent, in that it remains TRUE through startup. A pcrSelect of 0 indicates that the digestAsRelease is not checked. In this case, the TPM is not required to consume NVRAM space to store the digest, although it may do so. When TPM_GetCapability (TPM_CAP_NV_INDEX) returns the structure, a TPM that does not store the digest can return zero. A TPM that does store the digest may return either the digest or zero. */ typedef struct tdTPM_NV_DATA_PUBLIC { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* This SHALL be TPM_TAG_NV_DATA_PUBLIC */ #endif TPM_NV_INDEX nvIndex; /* The index of the data area */ TPM_PCR_INFO_SHORT pcrInfoRead; /* The PCR selection that allows reading of the area */ TPM_PCR_INFO_SHORT pcrInfoWrite; /* The PCR selection that allows writing of the area */ TPM_NV_ATTRIBUTES permission; /* The permissions for manipulating the area */ TPM_BOOL bReadSTClear; /* Set to FALSE on each TPM_Startup(ST_Clear) and set to TRUE after a ReadValuexxx with datasize of 0 */ TPM_BOOL bWriteSTClear; /* Set to FALSE on each TPM_Startup(ST_CLEAR) and set to TRUE after a WriteValuexxx with a datasize of 0. */ TPM_BOOL bWriteDefine; /* Set to FALSE after TPM_NV_DefineSpace and set to TRUE after a successful WriteValuexxx with a datasize of 0 */ uint32_t dataSize; /* The size of the data area in bytes */ } TPM_NV_DATA_PUBLIC; /* 19.4 TPM_NV_DATA_SENSITIVE rev 101 This is an internal structure that the TPM uses to keep the actual NV data and the controls regarding the area. */ typedef struct tdTPM_NV_DATA_SENSITIVE { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* This SHALL be TPM_TAG_NV_DATA_SENSITIVE */ #endif TPM_NV_DATA_PUBLIC pubInfo; /* The public information regarding this area */ TPM_AUTHDATA authValue; /* The authorization value to manipulate the value */ BYTE *data; /* The data area. This MUST not contain any sensitive information as the TPM does not provide any confidentiality on the data. */ /* NOTE Added kg */ TPM_DIGEST digest; /* for OSAP comparison */ } TPM_NV_DATA_SENSITIVE; typedef struct tdTPM_NV_INDEX_ENTRIES { uint32_t nvIndexCount; /* number of entries */ TPM_NV_DATA_SENSITIVE *tpm_nvindex_entry; /* array of TPM_NV_DATA_SENSITIVE */ } TPM_NV_INDEX_ENTRIES; /* TPM_NV_DATA_ST This is a cache of the the NV defined space volatile flags, used during error rollback */ typedef struct tdTPM_NV_DATA_ST { TPM_NV_INDEX nvIndex; /* The index of the data area */ TPM_BOOL bReadSTClear; TPM_BOOL bWriteSTClear; } TPM_NV_DATA_ST; /* 21. Capability areas */ /* 21.6 TPM_CAP_VERSION_INFO rev 99 This structure is an output from a TPM_GetCapability -> TPM_CAP_VERSION_VAL request. TPM returns the current version and revision of the TPM. The specLevel and errataRev are defined in the document "Specification and File Naming Conventions" The tpmVendorID is a value unique to each vendor. It is defined in the document "TCG Vendor Naming". The vendor specific area allows the TPM vendor to provide support for vendor options. The TPM vendor may define the area to the TPM vendor's needs. */ typedef struct tdTPM_CAP_VERSION_INFO { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* MUST be TPM_TAG_CAP_VERSION_INFO */ #endif TPM_VERSION version; /* The version and revision */ uint16_t specLevel; /* A number indicating the level of ordinals supported */ BYTE errataRev; /* A number indicating the errata version of the specification */ BYTE tpmVendorID[4]; /* The vendor ID unique to each TPM manufacturer. */ uint16_t vendorSpecificSize; /* The size of the vendor specific area */ BYTE* vendorSpecific; /* Vendor specific information */ /* NOTE Cannot be TPM_SIZED_BUFFER, because of uint16_t */ } TPM_CAP_VERSION_INFO; /* 21.10 TPM_DA_ACTION_TYPE rev 100 This structure indicates the action taken when the dictionary attack mitigation logic is active, when TPM_DA_STATE is TPM_DA_STATE_ACTIVE. */ typedef struct tdTPM_DA_ACTION_TYPE { TPM_STRUCTURE_TAG tag; /* MUST be TPM_TAG_DA_ACTION_TYPE */ uint32_t actions; /* The action taken when TPM_DA_STATE is TPM_DA_STATE_ACTIVE. */ } TPM_DA_ACTION_TYPE; /* 21.7 TPM_DA_INFO rev 100 This structure is an output from a TPM_GetCapability -> TPM_CAP_DA_LOGIC request if TPM_PERMANENT_FLAGS -> disableFullDALogicInfo is FALSE. It returns static information describing the TPM response to authorization failures that might indicate a dictionary attack and dynamic information regarding the current state of the dictionary attack mitigation logic. */ typedef struct tdTPM_DA_INFO { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* MUST be TPM_TAG_DA_INFO */ #endif TPM_DA_STATE state; /* Dynamic. The actual state of the dictionary attack mitigation logic. See 21.9. */ uint16_t currentCount; /* Dynamic. The actual count of the authorization failure counter for the selected entity type */ uint16_t thresholdCount; /* Static. Dictionary attack mitigation threshold count for the selected entity type */ TPM_DA_ACTION_TYPE actionAtThreshold; /* Static Action of the TPM when currentCount passes thresholdCount. See 21.10. */ uint32_t actionDependValue; /* Dynamic. Action being taken when the dictionary attack mitigation logic is active. E.g., when actionAtThreshold is TPM_DA_ACTION_TIMEOUT, this is the lockout time remaining in seconds. */ TPM_SIZED_BUFFER vendorData; /* Vendor specific data field */ } TPM_DA_INFO; /* 21.8 TPM_DA_INFO_LIMITED rev 100 This structure is an output from a TPM_GetCapability -> TPM_CAP_DA_LOGIC request if TPM_PERMANENT_FLAGS -> disableFullDALogicInfo is TRUE. It returns static information describing the TPM response to authorization failures that might indicate a dictionary attack and dynamic information regarding the current state of the dictionary attack mitigation logic. This structure omits information that might aid an attacker. */ typedef struct tdTPM_DA_INFO_LIMITED { #ifdef TPM_USE_TAG_IN_STRUCTURE TPM_STRUCTURE_TAG tag; /* MUST be TPM_TAG_DA_INFO_LIMITED */ #endif TPM_DA_STATE state; /* Dynamic. The actual state of the dictionary attack mitigation logic. See 21.9. */ TPM_DA_ACTION_TYPE actionAtThreshold; /* Static Action of the TPM when currentCount passes thresholdCount. See 21.10. */ TPM_SIZED_BUFFER vendorData; /* Vendor specific data field */ } TPM_DA_INFO_LIMITED; #endif /* Sanity check the size of the NV file vs. the maximum allocation size The multipliers are very conservative */ #if (TPM_ALLOC_MAX < \ (4000 + \ (TPM_OWNER_EVICT_KEY_HANDLES * 2000) + \ TPM_MAX_NV_DEFINED_SPACE)) #error "TPM_ALLOC_MAX too small for NV file size" #endif /* Sanity check the size of the volatile file vs. the maximum allocation size The multipliers are very conservative */ #if (TPM_ALLOC_MAX < \ (4000 + \ TPM_KEY_HANDLES * 2000 + \ TPM_MIN_TRANS_SESSIONS * 500 + \ TPM_MIN_DAA_SESSIONS * 2000 + \ TPM_MIN_AUTH_SESSIONS * 500)) #error "TPM_ALLOC_MAX too small for volatile file size" #endif libtpms-0.9.3/src/tpm12/tpm_svnrevision.c000066400000000000000000000000561421143571500203440ustar00rootroot00000000000000const unsigned short tpm_svn_revision = 4766; libtpms-0.9.3/src/tpm12/tpm_svnrevision.h000066400000000000000000000047301421143571500203540ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM svn revision */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_svnrevision.h 4071 2010-04-29 19:26:45Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_REVISION_H #define TPM_REVISION_H extern const unsigned short tpm_svn_revision; #endif libtpms-0.9.3/src/tpm12/tpm_ticks.c000066400000000000000000000740471421143571500171070ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Tick Handler */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_ticks.c 4526 2011-03-24 21:14:42Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include #include #include "tpm_auth.h" #include "tpm_cryptoh.h" #include "tpm_debug.h" #include "tpm_digest.h" #include "tpm_error.h" #include "tpm_key.h" #include "tpm_structures.h" #include "tpm_nonce.h" #include "tpm_process.h" #include "tpm_time.h" #include "tpm_ticks.h" static void TPM_Uint64_ConvertFrom(uint32_t *upper, uint32_t *lower, uint32_t sec, uint32_t usec); static void TPM_Uint64_ConvertTo(uint32_t *sec, uint32_t *usec, uint32_t upper, uint32_t lower); /* UINT64 for currentTicks Internally, the UINT64 is stored as sec || usec. This makes calculations easy since TPM_GetTimeOfDay returns those structure elements. The TPM_Uint64_Store() function, the public interface, converts this to a true 64 bit integer. */ /* TPM_Uint64_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_Uint64_Init(TPM_UINT64 *tpm_uint64) { printf(" TPM_Uint64_Init:\n"); tpm_uint64->sec = 0; tpm_uint64->usec = 0; return; } /* TPM_Uint64_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes This function does the conversion from a 64 bit usec to sec / usec. */ TPM_RESULT TPM_Uint64_Load(TPM_UINT64 *tpm_uint64, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; uint32_t upper; uint32_t lower; printf(" TPM_Uint64_Load:\n"); /* load upper */ if (rc == 0) { rc = TPM_Load32(&upper, stream, stream_size); } /* load lower */ if (rc == 0) { rc = TPM_Load32(&lower, stream, stream_size); } /* convert from 64 bit usec to sec, usec */ if (rc == 0) { TPM_Uint64_ConvertTo(&(tpm_uint64->sec), &(tpm_uint64->usec), upper, lower); } return rc; } /* TPM_Uint64_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes This function does the conversion from sec / usec to a 64 bit usec. */ TPM_RESULT TPM_Uint64_Store(TPM_STORE_BUFFER *sbuffer, const TPM_UINT64 *tpm_uint64) { TPM_RESULT rc = 0; uint32_t upper; uint32_t lower; printf(" TPM_Uint64_Store:\n"); /* store upper */ if (rc == 0) { /* convert to 64 bit number */ TPM_Uint64_ConvertFrom(&upper, &lower, tpm_uint64->sec, tpm_uint64->usec); rc = TPM_Sbuffer_Append32(sbuffer, upper); } /* store lower */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, lower); } return rc; } void TPM_Uint64_Copy(TPM_UINT64 *dest, const TPM_UINT64 *src) { printf(" TPM_Uint64_Copy:\n"); dest->sec = src->sec; dest->usec = src->usec; return; } /* TPM_Uint64_ConvertFrom() does the calculation result = sec * 1000000 + usec and splits the result into two uint32_t's. This may not be portable if the compiler does not support long long. */ /* TPM_Uint64_ConvertTo() does the calculation uint32_t || uint32_t to sec and usec. This may not be portable if the compiler does not support long long. */ #if defined(TPM_POSIX) || defined(TPM_SYSTEM_P) static void TPM_Uint64_ConvertFrom(uint32_t *upper, uint32_t *lower, uint32_t sec, uint32_t usec) { long long result; printf(" TPM_Uint64_ConvertFrom: sec %u, usec %u\n", sec, usec); result = (sec * 1000000LL) + (long long)usec; printf(" TPM_Uint64_ConvertFrom: Result usec %llu, %llx\n", result, result); *upper = (result >> 32) & 0xffffffff; *lower = result & 0xffffffff; printf(" TPM_Uint64_ConvertFrom: Upper %u, %x\n", *upper, *upper); printf(" TPM_Uint64_ConvertFrom: Lower %u, %x\n", *lower, *lower); return; } static void TPM_Uint64_ConvertTo(uint32_t *sec, uint32_t *usec, uint32_t upper, uint32_t lower) { long long result; printf(" TPM_Uint64_ConvertTo: Upper %u, %x\n", upper, upper); printf(" TPM_Uint64_ConvertTo: Lower %u, %x\n", lower, lower); result = ((long long)upper << 32) | (long long)lower; printf(" TPM_Uint64_ConvertTo: Result usec %llu, %llx\n", result, result); *sec = result / 1000000LL; *usec = result % 1000000LL; printf(" TPM_Uint64_ConvertTo: sec %u, usec %u\n", *sec, *usec); return; } #endif TPM_RESULT TPM_Uint64_Test() { TPM_RESULT rc = 0; TPM_UINT64 uint64In; TPM_UINT64 uint64Out; TPM_STORE_BUFFER sbuffer; unsigned char *stream; uint32_t stream_size; printf(" TPM_Uint64_Test\n"); TPM_Sbuffer_Init(&sbuffer); uint64In.sec = 12345678; uint64In.usec = 781234; if (rc == 0) { rc = TPM_Uint64_Store(&sbuffer, &uint64In); } if (rc == 0) { TPM_Sbuffer_Get(&sbuffer, (const unsigned char **)&stream, &stream_size); rc = TPM_Uint64_Load(&uint64Out, &stream, &stream_size); } if (rc == 0) { if ((uint64In.sec != uint64Out.sec) || (uint64In.usec != uint64Out.usec)) { printf("TPM_Uint64_Test: Error (fatal)\n"); rc = TPM_FAILEDSELFTEST; } } TPM_Sbuffer_Delete(&sbuffer); return rc; } /* TPM_CURRENT_TICKS */ /* TPM_CurrentTicks_Init() initializes the tick structure */ void TPM_CurrentTicks_Init(TPM_CURRENT_TICKS *tpm_current_ticks) { printf(" TPM_CurrentTicks_Init:\n"); TPM_Uint64_Init(&(tpm_current_ticks->currentTicks)); tpm_current_ticks->tickRate = TPM_TICK_RATE; TPM_Nonce_Init(tpm_current_ticks->tickNonce); TPM_Uint64_Init(&(tpm_current_ticks->initialTime)); return; } /* TPM_CurrentTicks_Start() sets the initialTime member to the current time of day. It assumes TPM_CurrentTicks_Init() has been called */ TPM_RESULT TPM_CurrentTicks_Start(TPM_CURRENT_TICKS *tpm_current_ticks) { TPM_RESULT rc = 0; printf(" TPM_CurrentTicks_Start:\n"); if (rc == 0) { /* current is relative to the initial value, and is always 0 */ TPM_Uint64_Init(&(tpm_current_ticks->currentTicks)); /* save the current time */ rc = TPM_GetTimeOfDay(&(tpm_current_ticks->initialTime.sec), &(tpm_current_ticks->initialTime.usec)); } if (rc == 0) { tpm_current_ticks->tickRate = TPM_TICK_RATE; rc = TPM_Nonce_Generate(tpm_current_ticks->tickNonce); } return rc; } /* TPM_CurrentTicks_LoadAll() loads the standard TCG structure plus the SW TPM members deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_CurrentTicks_Init() */ TPM_RESULT TPM_CurrentTicks_LoadAll(TPM_CURRENT_TICKS *tpm_current_ticks, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_CurrentTicks_LoadAll:\n"); /* load tag */ if (rc == 0) { rc = TPM_CheckTag(TPM_TAG_CURRENT_TICKS, stream, stream_size); } /* load currentTicks */ if (rc == 0) { rc = TPM_Uint64_Load(&(tpm_current_ticks->currentTicks), stream, stream_size); } /* load tickRate */ if (rc == 0) { rc = TPM_Load16(&(tpm_current_ticks->tickRate), stream, stream_size); } /* load tickNonce */ if (rc == 0) { rc = TPM_Nonce_Load(tpm_current_ticks->tickNonce, stream, stream_size); } /* load initialTime */ if (rc == 0) { rc = TPM_Uint64_Load(&(tpm_current_ticks->initialTime), stream, stream_size); } return rc; } /* TPM_CurrentTicks_Store() stores the standard TCG structure serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_CurrentTicks_Store(TPM_STORE_BUFFER *sbuffer, const TPM_CURRENT_TICKS *tpm_current_ticks) { TPM_RESULT rc = 0; printf(" TPM_CurrentTicks_Store:\n"); /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_CURRENT_TICKS); } /* store currentTicks */ if (rc == 0) { rc = TPM_Uint64_Store(sbuffer, &(tpm_current_ticks->currentTicks)); } /* store tickRate */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, tpm_current_ticks->tickRate); } /* store tickNonce */ if (rc == 0) { rc = TPM_Nonce_Store(sbuffer, tpm_current_ticks->tickNonce); } return rc; } /* TPM_CurrentTicks_Store() stores the standard TCG structure plus the SW TPM members serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_CurrentTicks_StoreAll(TPM_STORE_BUFFER *sbuffer, const TPM_CURRENT_TICKS *tpm_current_ticks) { TPM_RESULT rc = 0; printf(" TPM_CurrentTicks_StoreAll:\n"); /* store tag */ if (rc == 0) { rc = TPM_CurrentTicks_Store(sbuffer, tpm_current_ticks); } /* store initialTime */ if (rc == 0) { rc = TPM_Uint64_Store(sbuffer, &(tpm_current_ticks->initialTime)); } return rc; } /* TPM_CurrentTicks_Update() updates the currentTicks member of TPM_CURRENT_TICKS relative to the initial time */ TPM_RESULT TPM_CurrentTicks_Update(TPM_CURRENT_TICKS *tpm_current_ticks) { TPM_RESULT rc = 0; uint32_t currentTimeSec; uint32_t currentTimeUsec; printf(" TPM_CurrentTicks_Update: Initial %u sec %u usec\n", tpm_current_ticks->initialTime.sec, tpm_current_ticks->initialTime.usec); /* get the current time of day */ if (rc == 0) { rc = TPM_GetTimeOfDay(¤tTimeSec, ¤tTimeUsec); } /* Calculate: currentTimeSec currentTimeUsec - initialTimeSec initialTimeUsec */ if (rc == 0) { /* case 1: no borrow */ if (currentTimeUsec >= tpm_current_ticks->initialTime.usec) { /* subtract usec */ tpm_current_ticks->currentTicks.usec = currentTimeUsec - tpm_current_ticks->initialTime.usec; /* check that time went forward */ if (currentTimeSec >= tpm_current_ticks->initialTime.sec) { /* subtract sec */ tpm_current_ticks->currentTicks.sec = currentTimeSec - tpm_current_ticks->initialTime.sec; } else { printf(" TPM_CurrentTicks_Update: Error (fatal), illegal current time\n"); rc = TPM_FAIL; } } /* case 2: borrow */ else { /* subtract usec with borrow */ tpm_current_ticks->currentTicks.usec = 1000000 + currentTimeUsec - tpm_current_ticks->initialTime.usec; /* check that time went forward, with borrow */ if ((currentTimeSec - 1) >= tpm_current_ticks->initialTime.sec) { /* subtract sec */ tpm_current_ticks->currentTicks.sec = currentTimeSec - 1 - tpm_current_ticks->initialTime.sec; } else { printf(" TPM_CurrentTicks_Update: Error (fatal), illegal current time\n"); rc = TPM_FAIL; } } } if (rc == 0) { printf(" TPM_CurrentTicks_Update: Ticks %u sec %u usec\n", tpm_current_ticks->currentTicks.sec, tpm_current_ticks->currentTicks.usec); } return rc; } /* TPM_CurrentTicks_Copy() copies the 'src' to 'dest' */ void TPM_CurrentTicks_Copy(TPM_CURRENT_TICKS *dest, TPM_CURRENT_TICKS *src) { printf(" TPM_CurrentTicks_Copy:\n"); TPM_Uint64_Copy(&(dest->currentTicks), &(src->currentTicks)); dest->tickRate = src->tickRate; TPM_Nonce_Copy(dest->tickNonce, src->tickNonce); TPM_Uint64_Copy(&(dest->initialTime), &(src->initialTime)); return; } /* Processing Functions */ /* 23. Timing Ticks rev 87 The TPM timing ticks are always available for use. The association of timing ticks to actual time is a protocol that occurs outside of the TPM. See the design document for details. The setting of the clock type variable is a one time operation that allows the TPM to be configured to the type of platform that is installed on. The ability for the TPM to continue to increment the timer ticks across power cycles of the platform is a TPM and platform manufacturer decision. */ /* 23.1 TPM_GetTicks rev 87 This command returns the current tick count of the TPM. This command returns the current time held in the TPM. It is the responsibility of the external system to maintain any relation between this time and a UTC value or local real time value. */ TPM_RESULT TPM_Process_GetTicks(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_CURRENT_TICKS *t1CurrentTicks = NULL; /* The current time held in the TPM */ printf("TPM_Process_GetTicks: Ordinal Entry\n"); /* get inputs */ /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALLOW_NO_OWNER); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag0(tag); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_GetTicks: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* Processing */ if (returnCode == TPM_SUCCESS) { /* 1. Set T1 to the internal TPM_CURRENT_TICKS structure */ t1CurrentTicks = &(tpm_state->tpm_stany_data.currentTicks); /* update the ticks based on the current time */ returnCode = TPM_CurrentTicks_Update(t1CurrentTicks); } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_GetTicks: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* 2. Return T1 as currentTime. */ returnCode = TPM_CurrentTicks_Store(response, t1CurrentTicks); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* cleanup */ return rcf; } /* 23.2 TPM_TickStampBlob rev 101 This command applies a time stamp to the passed blob. The TPM makes no representation regarding the blob merely that the blob was present at the TPM at the time indicated. The function performs a digital signature on the hash of digestToStamp and the current tick count. It is the responsibility of the external system to maintain any relation between tick count and a UTC value or local real time value. */ TPM_RESULT TPM_Process_TickStampBlob(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_KEY_HANDLE keyHandle; /* The keyHandle identifier of a loaded key that can perform digital signatures. */ TPM_NONCE antiReplay; /* Anti replay value added to signature */ TPM_DIGEST digestToStamp; /* The digest to perform the tick stamp on */ TPM_AUTHHANDLE authHandle; /* The authorization session handle used for keyHandle authorization */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization session handle */ TPM_AUTHDATA privAuth; /* The authorization session digest that authorizes the use of keyHandle. HMAC key: key.usageAuth */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ TPM_BOOL authHandleValid = FALSE; TPM_KEY *sigKey; /* signing key */ TPM_SECRET *keyUsageAuth; TPM_SECRET *hmacKey; TPM_BOOL parentPCRStatus; TPM_SIGN_INFO h1SignInfo; TPM_STORE_BUFFER h2Data; TPM_STORE_BUFFER h1sbuffer; /* serialization of h1SignInfo */ TPM_DIGEST h3Digest; /* digest to be signed */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_CURRENT_TICKS *currentTicks = NULL; /* The current time according to the TPM */ TPM_SIZED_BUFFER sig; /* The resulting digital signature. */ printf("TPM_Process_TickStampBlob: Ordinal Entry\n"); TPM_SizedBuffer_Init(&sig); /* freed @1 */ TPM_SignInfo_Init(&h1SignInfo); /* freed @2 */ TPM_Sbuffer_Init(&h2Data); /* freed @3 */ TPM_Sbuffer_Init(&h1sbuffer); /* freed @4 */ /* get inputs */ /* get keyHandle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&keyHandle, &command, ¶mSize); } /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get antiReplay parameter */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_TickStampBlob: keyHandle %08x\n", keyHandle); returnCode = TPM_Nonce_Load(antiReplay, &command, ¶mSize); } /* get digestToStamp parameter */ if (returnCode == TPM_SUCCESS) { TPM_PrintFour("TPM_Process_TickStampBlob: antiReplay", antiReplay); returnCode = TPM_Digest_Load(digestToStamp, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { TPM_PrintFour("TPM_Process_TickStampBlob: digestToStamp", digestToStamp); returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag10(tag); } /* get the optional 'below the line' authorization parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, privAuth, &command, ¶mSize); } if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { printf("TPM_Process_TickStampBlob: authHandle %08x\n", authHandle); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_TickStampBlob: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ /* get the key corresponding to the keyHandle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyHandleEntries_GetKey(&sigKey, &parentPCRStatus, tpm_state, keyHandle, FALSE, /* not read-only */ FALSE, /* do not ignore PCRs */ FALSE); /* cannot use EK */ } if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_COMMAND)) { if (sigKey->authDataUsage != TPM_AUTH_NEVER) { printf("TPM_Process_TickStampBlob: Error, authorization required\n"); returnCode = TPM_AUTHFAIL; } } /* get keyHandle -> usageAuth */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_Key_GetUsageAuth(&keyUsageAuth, sigKey); } /* get the session data */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_KEYHANDLE, ordinal, sigKey, keyUsageAuth, /* OIAP */ sigKey->tpm_store_asymkey->pubDataDigest); /* OSAP */ } /* 1. The TPM validates the AuthData to use the key pointed to by keyHandle. */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, privAuth); /* Authorization digest for input */ } /* 2. Validate that keyHandle -> keyUsage is TPM_KEY_SIGNING, TPM_KEY_IDENTITY or TPM_KEY_LEGACY, if not return the error code TPM_INVALID_KEYUSAGE. */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_TickStampBlob: Checking key properties\n"); if ((sigKey->keyUsage != TPM_KEY_SIGNING) && (sigKey->keyUsage != TPM_KEY_IDENTITY) && (sigKey->keyUsage != TPM_KEY_LEGACY)) { printf("TPM_Process_TickStampBlob: Error, keyUsage %04hx is invalid\n", sigKey->keyUsage); returnCode = TPM_INVALID_KEYUSAGE; } } /* 3. Validate that keyHandle -> sigScheme is TPM_SS_RSASSAPKCS1v15_SHA1 or TPM_SS_RSASSAPKCS1v15_INFO, if not return TPM_INAPPROPRIATE_SIG. */ if (returnCode == TPM_SUCCESS) { if ((sigKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1) && (sigKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_INFO)) { printf("TPM_Process_TickStampBlob: Error, invalid sigKey sigScheme %04hx\n", sigKey->algorithmParms.sigScheme); returnCode = TPM_INAPPROPRIATE_SIG; } } /* 4. If TPM_STCLEAR_DATA -> currentTicks is not properly initialized */ /* a. Initialize the TPM_STCLEAR_DATA -> currentTicks */ /* NOTE: Always initialized */ /* 5. Create T1, a TPM_CURRENT_TICKS structure. */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_TickStampBlob: Creating TPM_CURRENT_TICKS structure\n"); currentTicks = &(tpm_state->tpm_stany_data.currentTicks); /* update the ticks based on the current time */ returnCode = TPM_CurrentTicks_Update(currentTicks); } if (returnCode == TPM_SUCCESS) { /* 6. Create H1 a TPM_SIGN_INFO structure and set the structure defaults */ printf("TPM_Process_TickStampBlob: Creating TPM_SIGN_INFO structure\n"); /* NOTE: Done by TPM_SignInfo_Init() */ /* a. Set H1 -> fixed to 'TSTP' */ memcpy(h1SignInfo.fixed, "TSTP", TPM_SIGN_INFO_FIXED_SIZE); /* b. Set H1 -> replay to antiReplay */ TPM_Nonce_Copy(h1SignInfo.replay, antiReplay ); /* c. Create H2 the concatenation of digestToStamp || T1 */ /* add digestToStamp */ returnCode = TPM_Digest_Store(&h2Data, digestToStamp); } /* add T1 (currentTicks) */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CurrentTicks_Store(&h2Data, currentTicks); } /* d. Set H1 -> dataLen to the length of H2 */ /* e. Set H1 -> data */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_SetFromStore(&(h1SignInfo.data), &h2Data); } /* 7. The TPM computes the signature, sig, using the key referenced by keyHandle, using SHA-1 of H1 as the information to be signed */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_TickStampBlob: Digesting TPM_SIGN_INFO structure\n"); returnCode = TPM_SHA1_GenerateStructure(h3Digest, &h1SignInfo, (TPM_STORE_FUNCTION_T)TPM_SignInfo_Store); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_TickStampBlob: Signing TPM_SIGN_INFO digest\n"); returnCode = TPM_RSASignToSizedBuffer(&sig, /* signature */ h3Digest, /* message */ TPM_DIGEST_SIZE, /* message size */ sigKey); /* input, signing key */ } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_TickStampBlob: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* 7. The TPM returns T1 as currentTicks parameter */ returnCode = TPM_CurrentTicks_Store(response, currentTicks); } /* 6. Return the signature in sig */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SizedBuffer_Store(response, &sig); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* owner HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ TPM_SizedBuffer_Delete(&sig); /* @1 */ TPM_SignInfo_Delete(&h1SignInfo); /* @2 */ TPM_Sbuffer_Delete(&h2Data); /* @3 */ TPM_Sbuffer_Delete(&h1sbuffer); /* @4 */ return rcf; } libtpms-0.9.3/src/tpm12/tpm_ticks.h000066400000000000000000000107651421143571500171110ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Tick Handler */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_ticks.h 4114 2010-09-30 22:24:32Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_TICKS_H #define TPM_TICKS_H #include "tpm_types.h" #include "tpm_global.h" #include "tpm_structures.h" /* UINT64 */ void TPM_Uint64_Init(TPM_UINT64 *tpm_uint64); TPM_RESULT TPM_Uint64_Load(TPM_UINT64 *tpm_uint64, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_Uint64_Store(TPM_STORE_BUFFER *sbuffer, const TPM_UINT64 *tpm_uint64); void TPM_Uint64_Copy(TPM_UINT64 *dest, const TPM_UINT64 *src); TPM_RESULT TPM_Uint64_Test(void); /* TPM_CURRENT_TICKS */ void TPM_CurrentTicks_Init(TPM_CURRENT_TICKS *tpm_current_ticks); TPM_RESULT TPM_CurrentTicks_Store(TPM_STORE_BUFFER *sbuffer, const TPM_CURRENT_TICKS *tpm_current_ticks); TPM_RESULT TPM_CurrentTicks_LoadAll(TPM_CURRENT_TICKS *tpm_current_ticks, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_CurrentTicks_StoreAll(TPM_STORE_BUFFER *sbuffer, const TPM_CURRENT_TICKS *tpm_current_ticks); TPM_RESULT TPM_CurrentTicks_Start(TPM_CURRENT_TICKS *tpm_current_ticks); TPM_RESULT TPM_CurrentTicks_Update(TPM_CURRENT_TICKS *tpm_current_ticks); void TPM_CurrentTicks_Copy(TPM_CURRENT_TICKS *dest, TPM_CURRENT_TICKS *src); /* Processing Functions */ TPM_RESULT TPM_Process_GetTicks(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_TickStampBlob(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); #endif libtpms-0.9.3/src/tpm12/tpm_time.c000066400000000000000000000063571421143571500167270ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Time Utilities */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_time.c 4648 2011-10-25 19:22:18Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ /* TPM_GetTimeOfDay() calls platform specific code to get the time in seconds and microseconds */ #include #include "tpm_debug.h" #include "tpm_error.h" #include "tpm_time.h" /* TPM_GetTimeOfDay() gets the current time of day. Must return TPM_FAIL on error, so that the caller knows to shut down the TPM */ #ifdef TPM_POSIX #include TPM_RESULT TPM_GetTimeOfDay(uint32_t *tv_sec, uint32_t *tv_usec) { TPM_RESULT rc = 0; struct timeval tval; int irc; irc = gettimeofday(&tval, NULL ); /* get the time */ if (irc == 0) { *tv_sec = tval.tv_sec; *tv_usec = tval.tv_usec; printf(" TPM_GetTimeOfDay: %d sec %d usec\n",*tv_sec, *tv_usec); } else { printf("TPM_GetTimeOfDay: Error (fatal) getting time of day\n"); rc = TPM_FAIL; } return rc; } #endif libtpms-0.9.3/src/tpm12/tpm_time.h000066400000000000000000000050641421143571500167260ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM Time Utilities */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_time.h 4071 2010-04-29 19:26:45Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_TIME_H #define TPM_TIME_H #include "tpm_types.h" #define TPM_TICK_RATE 1 /* in usec for Linux */ TPM_RESULT TPM_GetTimeOfDay(uint32_t *tv_sec, uint32_t *tv_usec); #endif libtpms-0.9.3/src/tpm12/tpm_transport.c000066400000000000000000003300421421143571500200140ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Transport */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_transport.c 4719 2014-01-15 21:17:47Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include #include #include #include "tpm_audit.h" #include "tpm_auth.h" #include "tpm_crypto.h" #include "tpm_cryptoh.h" #include "tpm_debug.h" #include "tpm_digest.h" #include "tpm_error.h" #include "tpm_init.h" #include "tpm_key.h" #include "tpm_memory.h" #include "tpm_nonce.h" #include "tpm_process.h" #include "tpm_secret.h" #include "tpm_ticks.h" #include "tpm_transport.h" /* TPM_Transport_CryptMgf1() takes a 'src', a preallocated 'dest', and an MGF1 'pad' of length 'len'. 'size is the total length of 'src' and 'dest'. 'index' is the start of the encrypt area 'len' is the length of the encrypt area It copies 'src' to 'dest' up to 'index'. It then copies 'src' XOR'ed with 'pad' for 'len' It then copies the remainder of 'src' to 'dest' */ TPM_RESULT TPM_Transport_CryptMgf1(unsigned char *dest, const unsigned char *src, const unsigned char *pad, uint32_t size, uint32_t index, uint32_t len) { TPM_RESULT rc = 0; printf(" TPM_Transport_CryptMgf1: size %u index %u len %u\n", size, index, len); /* sanity check the length */ if (rc == 0) { if (index + len > size) { printf("TPM_Transport_CryptMgf1: Error (fatal), bad size\n"); rc = TPM_FAIL; /* internal error, should never occur */ } } if (rc == 0) { /* leading clear text area */ memcpy(dest, src, index); dest += index; src += index; /* encrypt area */ TPM_XOR(dest, pad, src, len); dest += len; src += len; /* trailing clear text area */ memcpy(dest, src, size - index - len); } return rc; } /* TPM_Transport_CryptSymmetric() takes a 'src', a preallocated 'dest', and a 'symmetric_key' 'pad_in' (CTR or IV) of length 'len'. 'size is the total length of 'src' and 'dest'. 'index' is the start of the encrypt area 'len' is the length of the encrypt area It copies 'src' to 'dest' up to 'index'. It then encrypts 'src' to 'dest' using 'symmetric_key and 'pad_in' for 'len' It then copies the remainder of 'src' to 'dest' */ TPM_RESULT TPM_Transport_CryptSymmetric(unsigned char *dest, const unsigned char *src, TPM_ALGORITHM_ID algId, /* algorithm */ TPM_ENC_SCHEME encScheme, /* mode */ const unsigned char *symmetric_key, uint32_t symmetric_key_size, unsigned char *pad_in, uint32_t pad_in_size, uint32_t size, uint32_t index, uint32_t len) { TPM_RESULT rc = 0; printf(" TPM_Transport_CryptSymmetric: size %u index %u len %u\n", size, index, len); /* sanity check the length */ if (rc == 0) { if (index + len > size) { printf("TPM_Transport_CryptSymmetric: Error (fatal), bad size\n"); rc = TPM_FAIL; /* internal error, should never occur */ } } if (rc == 0) { /* leading clear text area */ memcpy(dest, src, index); dest += index; src += index; /* encrypt area */ rc = TPM_SymmetricKeyData_StreamCrypt(dest, /* output */ src, /* input */ len, /* input */ algId, /* algorithm */ encScheme, /* mode */ symmetric_key, /* input */ symmetric_key_size, /* input */ pad_in, /* input */ pad_in_size); /* input */ } if (rc == 0) { dest += len; src += len; /* trailing clear text area */ memcpy(dest, src, size - index - len); } return rc; } /* Transport Sessions (the entire array) */ void TPM_TransportSessions_Init(TPM_TRANSPORT_INTERNAL *transSessions) { size_t i; printf(" TPM_TransportSessions_Init:\n"); for (i = 0 ; i < TPM_MIN_TRANS_SESSIONS ; i++) { TPM_TransportInternal_Init(&(transSessions[i])); } return; } /* TPM_TransportSessions_Load() reads a count of the number of stored sessions and then loads those sessions. deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_TransportSessions_Init() After use, call TPM_TransportSessions_Delete() to free memory */ TPM_RESULT TPM_TransportSessions_Load(TPM_TRANSPORT_INTERNAL *transSessions, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; size_t i; uint32_t activeCount; printf(" TPM_TransportSessions_Load:\n"); /* load active count */ if (rc == 0) { rc = TPM_Load32(&activeCount, stream, stream_size); } if (rc == 0) { if (activeCount > TPM_MIN_TRANS_SESSIONS) { printf("TPM_TransportSessions_Load: Error (fatal) %u sessions, %u slots\n", activeCount, TPM_MIN_TRANS_SESSIONS); rc = TPM_FAIL; } } if (rc == 0) { printf(" TPM_TransportSessions_Load: Loading %u sessions\n", activeCount); } for (i = 0 ; (rc == 0) && (i < activeCount) ; i++) { rc = TPM_TransportInternal_Load(&(transSessions[i]), stream, stream_size); } return rc; } /* TPM_TransportSessions_Store() stores a count of the active sessions, followed by the sessions. serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_TransportSessions_Store(TPM_STORE_BUFFER *sbuffer, TPM_TRANSPORT_INTERNAL *transSessions) { TPM_RESULT rc = 0; size_t i; uint32_t space; /* free transport session slots */ uint32_t activeCount; /* used transport session slots */ /* store active count */ if (rc == 0) { TPM_TransportSessions_GetSpace(&space, transSessions); activeCount = TPM_MIN_TRANS_SESSIONS - space; printf(" TPM_TransSessions_Store: Storing %u sessions\n", activeCount); rc = TPM_Sbuffer_Append32(sbuffer, activeCount); } /* store transport sessions */ for (i = 0 ; (rc == 0) && (i < TPM_MIN_TRANS_SESSIONS) ; i++) { if ((transSessions[i]).valid) { /* if the session is active */ rc = TPM_TransportInternal_Store(sbuffer, &(transSessions[i])); } } return rc; } /* TPM_TransportSessions_Delete() terminates all sessions No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_TransportSessions_Init to set members back to default values The object itself is not freed */ void TPM_TransportSessions_Delete(TPM_TRANSPORT_INTERNAL *transSessions) { size_t i; printf(" TPM_TransportSessions_Delete:\n"); for (i = 0 ; i < TPM_MIN_TRANS_SESSIONS ; i++) { TPM_TransportInternal_Delete(&(transSessions[i])); } return; } /* TPM_TransportSessions_IsSpace() returns 'isSpace' TRUE if an entry is available, FALSE if not. If TRUE, 'index' holds the first free position. */ void TPM_TransportSessions_IsSpace(TPM_BOOL *isSpace, uint32_t *index, TPM_TRANSPORT_INTERNAL *transSessions) { printf(" TPM_TransportSessions_IsSpace:\n"); for (*index = 0, *isSpace = FALSE ; *index < TPM_MIN_TRANS_SESSIONS ; (*index)++) { if (!((transSessions[*index]).valid)) { printf(" TPM_TransportSessions_IsSpace: Found space at %u\n", *index); *isSpace = TRUE; break; } } return; } /* TPM_TransportSessions_GetSpace() returns the number of unused transport sessions. */ void TPM_TransportSessions_GetSpace(uint32_t *space, TPM_TRANSPORT_INTERNAL *transSessions) { uint32_t i; printf(" TPM_TransportSessions_GetSpace:\n"); for (*space = 0 , i = 0 ; i < TPM_MIN_TRANS_SESSIONS ; i++) { if (!((transSessions[i]).valid)) { (*space)++; } } return; } /* TPM_TransportSessions_StoreHandles() stores - the number of loaded sessions - a list of session handles */ TPM_RESULT TPM_TransportSessions_StoreHandles(TPM_STORE_BUFFER *sbuffer, TPM_TRANSPORT_INTERNAL *transSessions) { TPM_RESULT rc = 0; uint16_t i; uint32_t space; printf(" TPM_TransportSessions_StoreHandles:\n"); /* get the number of loaded handles */ if (rc == 0) { TPM_TransportSessions_GetSpace(&space, transSessions); /* store loaded handle count. Cast safe because of TPM_MIN_TRANS_SESSIONS value */ printf(" TPM_TransportSessions_StoreHandles: %u handles\n", TPM_MIN_TRANS_SESSIONS - space); rc = TPM_Sbuffer_Append16(sbuffer, (uint16_t)(TPM_MIN_TRANS_SESSIONS - space)); } for (i = 0 ; (rc == 0) && (i < TPM_MIN_TRANS_SESSIONS) ; i++) { if ((transSessions[i]).valid) { /* if the index is loaded */ rc = TPM_Sbuffer_Append32(sbuffer, (transSessions[i]).transHandle); /* store it */ } } return rc; } /* TPM_TransportSessions_GetNewHandle() checks for space in the transport sessions table. If there is space, it returns a TPM_TRANSPORT_INTERNAL entry in 'tpm_transport_internal'. The entry is marked 'valid'. Returns TPM_RESOURCES if there is no space in the transport sessions table. */ TPM_RESULT TPM_TransportSessions_GetNewHandle(TPM_TRANSPORT_INTERNAL **tpm_transport_internal, TPM_TRANSPORT_INTERNAL *transportSessions) { TPM_RESULT rc = 0; uint32_t index; TPM_BOOL isSpace; TPM_TRANSHANDLE transportHandle = 0; /* no suggested value */ printf(" TPM_TransportSessions_GetNewHandle:\n"); /* is there an empty entry, get the location index */ if (rc == 0) { TPM_TransportSessions_IsSpace(&isSpace, &index, transportSessions); if (!isSpace) { printf("TPM_TransportSessions_GetNewHandle: Error, " "no space in TransportSessions table\n"); rc = TPM_RESOURCES; } } /* assign transport handle */ if (rc == 0) { rc = TPM_Handle_GenerateHandle(&transportHandle, /* I/O */ transportSessions, /* handle array */ FALSE, /* keepHandle */ FALSE, /* isKeyHandle */ (TPM_GETENTRY_FUNCTION_T)TPM_TransportSessions_GetEntry); } if (rc == 0) { printf(" TPM_TransportSessions_GetNewHandle: Assigned handle %08x\n", transportHandle); /* return the TPM_TRANSPORT_INTERNAL */ *tpm_transport_internal = &(transportSessions[index]); /* assign the handle */ (*tpm_transport_internal)->transHandle = transportHandle; (*tpm_transport_internal)->valid = TRUE; } return rc; } /* TPM_TransportSessions_GetEntry() searches all 'transportSessions' entries for the entry matching the handle, and returns the TPM_TRANSPORT_INTERNAL entry associated with the handle. Returns 0 for success TPM_INVALID_AUTHHANDLE if the handle is not found */ TPM_RESULT TPM_TransportSessions_GetEntry(TPM_TRANSPORT_INTERNAL **tpm_transport_internal, TPM_TRANSPORT_INTERNAL *transportSessions, /* array */ TPM_TRANSHANDLE transportHandle) /* input */ { TPM_RESULT rc = 0; size_t i; TPM_BOOL found; printf(" TPM_TransportSessions_GetEntry: transportHandle %08x\n", transportHandle); for (i = 0, found = FALSE ; (i < TPM_MIN_TRANS_SESSIONS) && !found ; i++) { if ((transportSessions[i].valid) && (transportSessions[i].transHandle == transportHandle)) { /* found */ found = TRUE; *tpm_transport_internal = &(transportSessions[i]); } } if (!found) { printf(" TPM_TransportSessions_GetEntry: transport session handle %08x not found\n", transportHandle); rc = TPM_INVALID_AUTHHANDLE; } return rc; } /* TPM_TransportSessions_AddEntry() adds an TPM_TRANSPORT_INTERNAL object to the list. If *tpm_handle == 0, a value is assigned. If *tpm_handle != 0, that value is used if it it not currently in use. The handle is returned in tpm_handle. */ TPM_RESULT TPM_TransportSessions_AddEntry(TPM_HANDLE *tpm_handle, /* i/o */ TPM_BOOL keepHandle, /* input */ TPM_TRANSPORT_INTERNAL *transSessions, /* input */ TPM_TRANSPORT_INTERNAL *tpm_transport_internal) /* in */ { TPM_RESULT rc = 0; uint32_t index; TPM_BOOL isSpace; printf(" TPM_TransportSessions_AddEntry: handle %08x, keepHandle %u\n", *tpm_handle, keepHandle); /* check for valid TPM_TRANSPORT_INTERNAL */ if (rc == 0) { if (tpm_transport_internal == NULL) { /* NOTE: should never occur */ printf("TPM_TransportSessions_AddEntry: Error (fatal), NULL TPM_TRANSPORT_INTERNAL\n"); rc = TPM_FAIL; } } /* is there an empty entry, get the location index */ if (rc == 0) { TPM_TransportSessions_IsSpace(&isSpace, &index, transSessions); if (!isSpace) { printf("TPM_TransportSessions_AddEntry: Error, transport session entries full\n"); rc = TPM_RESOURCES; } } if (rc == 0) { rc = TPM_Handle_GenerateHandle(tpm_handle, /* I/O */ transSessions, /* handle array */ keepHandle, /* keepHandle */ FALSE, /* isKeyHandle */ (TPM_GETENTRY_FUNCTION_T)TPM_TransportSessions_GetEntry); } if (rc == 0) { tpm_transport_internal->transHandle = *tpm_handle; tpm_transport_internal->valid = TRUE; TPM_TransportInternal_Copy(&(transSessions[index]), tpm_transport_internal); printf(" TPM_TransportSessions_AddEntry: Index %u handle %08x\n", index, transSessions[index].transHandle); } return rc; } /* TPM_TransportSessions_TerminateHandle() terminates the session associated with 'transporthHandle'. If the session is exclusive (indicated by a match with TPM_STANY_FLAGS -> transportExclusive), clear that flag. */ TPM_RESULT TPM_TransportSessions_TerminateHandle(TPM_TRANSPORT_INTERNAL *transportSessions, TPM_TRANSHANDLE transportHandle, TPM_TRANSHANDLE *transportExclusive) { TPM_RESULT rc = 0; TPM_TRANSPORT_INTERNAL *tpm_transport_internal; printf(" TPM_TransportSessions_TerminateHandle: Handle %08x\n", transportHandle); /* get the TPM_TRANSPORT_INTERNAL associated with the TPM_TRANSHANDLE */ if (rc == 0) { rc = TPM_TransportSessions_GetEntry(&tpm_transport_internal, transportSessions, transportHandle); } /* if the session being terminated is exclusive, reset the flag */ if (rc == 0) { if (transportHandle == *transportExclusive) { printf(" TPM_TransportSessions_TerminateHandle: Is exclusive transport session\n"); if (!(tpm_transport_internal->transPublic.transAttributes & TPM_TRANSPORT_EXCLUSIVE)) { printf("TPM_TransportSessions_TerminateHandle: Error (fatal), " "attribute is not exclusive\n"); rc = TPM_FAIL; /* internal error, should not occur */ } *transportExclusive = 0; } } /* invalidate the valid handle */ if (rc == 0) { TPM_TransportInternal_Delete(tpm_transport_internal); } return rc; } /* TPM_TRANSPORT_PUBLIC */ /* TPM_TransportPublic_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_TransportPublic_Init(TPM_TRANSPORT_PUBLIC *tpm_transport_public) { printf(" TPM_TransportPublic_Init:\n"); tpm_transport_public->transAttributes = 0; tpm_transport_public->algId = 0; tpm_transport_public->encScheme = TPM_ES_NONE; return; } /* TPM_TransportPublic_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_TransportPublic_Init() After use, call TPM_TransportPublic_Delete() to free memory */ TPM_RESULT TPM_TransportPublic_Load(TPM_TRANSPORT_PUBLIC *tpm_transport_public, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_TransportPublic_Load:\n"); /* check tag */ if (rc == 0) { rc = TPM_CheckTag(TPM_TAG_TRANSPORT_PUBLIC, stream, stream_size); } /* load transAttributes */ if (rc == 0) { rc = TPM_Load32(&(tpm_transport_public->transAttributes ), stream, stream_size); } /* load algId */ if (rc == 0) { rc = TPM_Load32(&(tpm_transport_public->algId), stream, stream_size); } /* load encScheme */ if (rc == 0) { rc = TPM_Load16(&(tpm_transport_public->encScheme), stream, stream_size); } return rc; } /* TPM_TransportPublic_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_TransportPublic_Store(TPM_STORE_BUFFER *sbuffer, const TPM_TRANSPORT_PUBLIC *tpm_transport_public) { TPM_RESULT rc = 0; printf(" TPM_TransportPublic_Store:\n"); /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_TRANSPORT_PUBLIC); } /* store transAttributes */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_transport_public->transAttributes); } /* store algId */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_transport_public->algId); } /* store encScheme */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, tpm_transport_public->encScheme); } return rc; } /* TPM_TransportPublic_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_TransportPublic_Init to set members back to default values The object itself is not freed */ void TPM_TransportPublic_Delete(TPM_TRANSPORT_PUBLIC *tpm_transport_public) { printf(" TPM_TransportPublic_Delete:\n"); if (tpm_transport_public != NULL) { TPM_TransportPublic_Init(tpm_transport_public); } return; } /* TPM_TransportPublic_Copy() copies the 'src' to the 'dest' structure */ TPM_RESULT TPM_TransportPublic_Copy(TPM_TRANSPORT_PUBLIC *dest, const TPM_TRANSPORT_PUBLIC *src) { TPM_RESULT rc = 0; printf(" TPM_TransportPublic_Copy:\n"); /* copy transAttributes */ dest->transAttributes = src->transAttributes; /* copy algId */ dest->algId = src->algId; /* copy encScheme */ dest->encScheme = src->encScheme; return rc; } /* TPM_TransportPublic_CheckAlgId() returns 'supported' TRUE if the transport encryption algorithm is supported by the TPM */ void TPM_TransportPublic_CheckAlgId(TPM_BOOL *supported, TPM_ALGORITHM_ID algId) { printf(" TPM_TransportPublic_CheckAlgId: %08x\n", algId); switch (algId) { /* supported protocols */ case TPM_ALG_MGF1: case TPM_ALG_AES128: *supported = TRUE; break; /* unsupported protocols */ case TPM_ALG_RSA: case TPM_ALG_SHA: case TPM_ALG_HMAC: case TPM_ALG_AES192: case TPM_ALG_AES256: default: *supported = FALSE; break; } return; } /* TPM_TransportPublic_CheckEncScheme() returns success and the blockSize if the transport algId and encScheme are supported by the TPM. */ TPM_RESULT TPM_TransportPublic_CheckEncScheme(uint32_t *blockSize, TPM_ALGORITHM_ID algId, TPM_ENC_SCHEME encScheme, TPM_BOOL FIPS) { TPM_RESULT rc = 0; printf(" TPM_TransportPublic_CheckEncScheme: algId %08x encScheme %04hx\n", algId, encScheme); switch (algId) { /* supported protocols with no encScheme */ case TPM_ALG_MGF1: *blockSize = 0; /* MGF1 does not use blocks */ if (FIPS) { printf("TPM_TransportPublic_CheckEncScheme: Error, " "TPM_ALG_MGF1 not supported in FIPS\n"); rc = TPM_INAPPROPRIATE_ENC; } /* For TPM_ALG_MGF1, TPM_ENC_SCHEME is not used. The TPM MAY validate that TPM_ENC_SCHEME is TPM_ES_NONE. */ if (encScheme != TPM_ES_NONE) { printf("TPM_TransportPublic_CheckEncScheme: Error, " "TPM_ALG_MGF1 must use TPM_ES_NONE\n"); rc = TPM_INAPPROPRIATE_ENC; } break; /* protocols with encScheme */ case TPM_ALG_AES128: switch(encScheme) { case TPM_ES_SYM_CTR: /* CTR mode */ case TPM_ES_SYM_OFB: /* OFB mode */ *blockSize = 128/8; break; default: printf("TPM_TransportPublic_CheckEncScheme: Error, AES128 encScheme not supported\n"); rc = TPM_INAPPROPRIATE_ENC; break; } break; /* unsupported protocols */ case TPM_ALG_AES192: case TPM_ALG_AES256: case TPM_ALG_RSA: case TPM_ALG_SHA: case TPM_ALG_HMAC: case TPM_ALG_XOR: default: printf("TPM_TransportPublic_CheckEncScheme: Error, algId not supported\n"); rc = TPM_BAD_KEY_PROPERTY; break; } return rc; } /* TPM_TRANSPORT_INTERNAL */ /* TPM_TransportInternal_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_TransportInternal_Init(TPM_TRANSPORT_INTERNAL *tpm_transport_internal) { printf(" TPM_TransportInternal_Init:\n"); TPM_Secret_Init(tpm_transport_internal->authData); TPM_TransportPublic_Init(&(tpm_transport_internal->transPublic)); tpm_transport_internal->transHandle = 0; TPM_Nonce_Init(tpm_transport_internal->transNonceEven); TPM_Digest_Init(tpm_transport_internal->transDigest); tpm_transport_internal->valid = FALSE; return; } /* TPM_TransportInternal_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_TransportInternal_Init() After use, call TPM_TransportInternal_Delete() to free memory */ TPM_RESULT TPM_TransportInternal_Load(TPM_TRANSPORT_INTERNAL *tpm_transport_internal, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_TransportInternal_Load:\n"); /* check tag */ if (rc == 0) { rc = TPM_CheckTag(TPM_TAG_TRANSPORT_INTERNAL, stream, stream_size); } /* load authData */ if (rc == 0) { rc = TPM_Secret_Load(tpm_transport_internal->authData, stream, stream_size); } /* load transPublic */ if (rc == 0) { rc = TPM_TransportPublic_Load(&(tpm_transport_internal->transPublic), stream, stream_size); } /* load transHandle */ if (rc == 0) { rc = TPM_Load32(&(tpm_transport_internal->transHandle), stream, stream_size); } /* load transNonceEven */ if (rc == 0) { rc = TPM_Nonce_Load(tpm_transport_internal->transNonceEven, stream, stream_size); } /* load transDigest */ if (rc == 0) { rc = TPM_Digest_Load(tpm_transport_internal->transDigest, stream, stream_size); } /* load valid */ if (rc == 0) { tpm_transport_internal->valid = TRUE; } return rc; } /* TPM_TransportInternal_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_TransportInternal_Store(TPM_STORE_BUFFER *sbuffer, const TPM_TRANSPORT_INTERNAL *tpm_transport_internal) { TPM_RESULT rc = 0; printf(" TPM_TransportInternal_Store:\n"); /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_TRANSPORT_INTERNAL); } /* store authData */ if (rc == 0) { rc = TPM_Secret_Store(sbuffer, tpm_transport_internal->authData); } /* store transPublic */ if (rc == 0) { rc = TPM_TransportPublic_Store(sbuffer, &(tpm_transport_internal->transPublic)); } /* store transHandle */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_transport_internal->transHandle); } /* store transNonceEven */ if (rc == 0) { rc = TPM_Nonce_Store(sbuffer, tpm_transport_internal->transNonceEven); } /* store transDigest */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_transport_internal->transDigest); } return rc; } /* TPM_TransportInternal_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_TransportInternal_Init to set members back to default values The object itself is not freed */ void TPM_TransportInternal_Delete(TPM_TRANSPORT_INTERNAL *tpm_transport_internal) { printf(" TPM_TransportInternal_Delete:\n"); if (tpm_transport_internal != NULL) { TPM_TransportPublic_Delete(&(tpm_transport_internal->transPublic)); TPM_TransportInternal_Init(tpm_transport_internal); } return; } /* TPM_TransportInternal_Copy() copies the source to the destination. */ void TPM_TransportInternal_Copy(TPM_TRANSPORT_INTERNAL *dest_transport_internal, TPM_TRANSPORT_INTERNAL *src_transport_internal) { TPM_Secret_Copy(dest_transport_internal->authData, src_transport_internal->authData); TPM_TransportPublic_Copy(&(dest_transport_internal->transPublic), &(src_transport_internal->transPublic)); dest_transport_internal->transHandle = src_transport_internal->transHandle; TPM_Nonce_Copy(dest_transport_internal->transNonceEven, src_transport_internal->transNonceEven); TPM_Digest_Copy(dest_transport_internal->transDigest, src_transport_internal->transDigest); dest_transport_internal->valid = src_transport_internal->valid; } /* TPM_TransportInternal_Check() checks the authorization of a command. There is no need to protect against dictionary attacks. The first failure terminates the transport session. Returns TPM_AUTH2FAIL if the TPM_AUTHDATA does not match. */ TPM_RESULT TPM_TransportInternal_Check(TPM_DIGEST inParamDigest, /* digest of inputs above line */ TPM_TRANSPORT_INTERNAL *tpm_transport_internal, TPM_NONCE transNonceOdd, /* Nonce generated by system associated with transHandle */ TPM_BOOL continueTransSession, TPM_AUTHDATA transAuth) /* Authorization digest for input */ { TPM_RESULT rc = 0; TPM_BOOL valid; printf(" TPM_TransportInternal_Check:\n"); if (rc == 0) { TPM_PrintFour(" TPM_TransportInternal_Check: inParamDigest", inParamDigest); TPM_PrintFour(" TPM_TransportInternal_Check: usageAuth (key)", tpm_transport_internal->authData); TPM_PrintFour(" TPM_TransportInternal_Check: nonceEven", tpm_transport_internal->transNonceEven); TPM_PrintFour(" TPM_TransportInternal_Check: nonceOdd", transNonceOdd); printf (" TPM_TransportInternal_Check: continueSession %02x\n", continueTransSession); /* HMAC the inParamDigest, transLastNonceEven, transNonceOdd, continueTransSession */ /* transLastNonceEven is retrieved from internal transport session storage */ rc = TPM_HMAC_Check(&valid, transAuth, /* expected, from command */ tpm_transport_internal->authData, /* key */ sizeof(TPM_DIGEST), inParamDigest, /* command digest */ sizeof(TPM_NONCE), tpm_transport_internal->transNonceEven, /* 2H */ sizeof(TPM_NONCE), transNonceOdd, /* 3H */ sizeof(TPM_BOOL), &continueTransSession, /* 4H */ 0, NULL); } if (rc == 0) { if (!valid) { printf("TPM_TransportInternal_Check: Error, authorization failed\n"); rc = TPM_AUTH2FAIL; } } return rc; } /* TPM_TransportInternal_Set() sets the transport response transAuth. It conditionally generates the next transNonceEven. It appends transNonceEven and continueTransSession to the response. It generates transAuth using outParamDigest and the standard 'below the line' HMAC rules and appends it to the response. */ TPM_RESULT TPM_TransportInternal_Set(TPM_STORE_BUFFER *response, TPM_TRANSPORT_INTERNAL *tpm_transport_internal, TPM_DIGEST outParamDigest, TPM_NONCE transNonceOdd, TPM_BOOL continueTransSession, TPM_BOOL generateNonceEven) { TPM_RESULT rc = 0; TPM_AUTHDATA transAuth; /* The authorization digest for the returned parameters */ printf(" TPM_TransportInternal_Set:\n"); /* generate transNonceEven if not already done by caller */ if ((rc == 0) && generateNonceEven) { rc = TPM_Nonce_Generate(tpm_transport_internal->transNonceEven); } /* append transNonceEven */ if (rc == 0) { rc = TPM_Nonce_Store(response, tpm_transport_internal->transNonceEven); } /* append continueTransSession*/ if (rc == 0) { rc = TPM_Sbuffer_Append(response, &continueTransSession, sizeof(TPM_BOOL)); } /* Calculate transAuth using the transport session authData */ if (rc == 0) { rc = TPM_Authdata_Generate(transAuth, /* result */ tpm_transport_internal->authData, /* HMAC key */ outParamDigest, /* params */ tpm_transport_internal->transNonceEven, transNonceOdd, continueTransSession); } /* append transAuth */ if (rc == 0) { rc = TPM_Authdata_Store(response, transAuth); } return rc; } /* TPM_TRANSPORT_LOG_IN */ /* TPM_TransportLogIn_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_TransportLogIn_Init(TPM_TRANSPORT_LOG_IN *tpm_transport_log_in) { printf(" TPM_TransportLogIn_Init:\n"); TPM_Digest_Init(tpm_transport_log_in->parameters); TPM_Digest_Init(tpm_transport_log_in->pubKeyHash); return; } /* TPM_TransportLogIn_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_TransportLogIn_Store(TPM_STORE_BUFFER *sbuffer, const TPM_TRANSPORT_LOG_IN *tpm_transport_log_in) { TPM_RESULT rc = 0; printf(" TPM_TransportLogIn_Store:\n"); /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_TRANSPORT_LOG_IN); } /* store parameters */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_transport_log_in->parameters); } /* store pubKeyHash */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_transport_log_in->pubKeyHash); } return rc; } /* TPM_TransportLogIn_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_TransportLogIn_Init to set members back to default values The object itself is not freed */ void TPM_TransportLogIn_Delete(TPM_TRANSPORT_LOG_IN *tpm_transport_log_in) { printf(" TPM_TransportLogIn_Delete:\n"); if (tpm_transport_log_in != NULL) { TPM_TransportLogIn_Init(tpm_transport_log_in); } return; } /* TPM_TransportLogIn_Extend() extends 'tpm_digest' tpm_digest = SHA-1 (tpm_digest || tpm_transport_log_in) */ TPM_RESULT TPM_TransportLogIn_Extend(TPM_DIGEST tpm_digest, TPM_TRANSPORT_LOG_IN *tpm_transport_log_in) { TPM_RESULT rc = 0; TPM_STORE_BUFFER sbuffer; const unsigned char *buffer; /* serialized buffer */ uint32_t length; /* serialization length */ printf(" TPM_TransportLogIn_Extend:\n"); TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ /* serialize TPM_TRANSPORT_LOG_IN */ if (rc == 0) { rc = TPM_TransportLogIn_Store(&sbuffer, tpm_transport_log_in); } if (rc == 0) { /* get the TPM_TRANSPORT_LOG_IN serialization results */ TPM_Sbuffer_Get(&sbuffer, &buffer, &length); TPM_PrintAll(" TPM_TransportLogIn_Extend: transDigest in", tpm_digest, TPM_DIGEST_SIZE); TPM_PrintAll(" TPM_TransportLogIn_Extend", buffer, length); rc = TPM_SHA1(tpm_digest, TPM_DIGEST_SIZE, tpm_digest, length, buffer, 0, NULL); TPM_PrintAll(" TPM_TransportLogIn_Extend: transDigest out", tpm_digest, TPM_DIGEST_SIZE); } TPM_Sbuffer_Delete(&sbuffer); /* @1 */ return rc; } /* TPM_TRANSPORT_LOG_OUT */ /* TPM_TransportLogOut_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_TransportLogOut_Init(TPM_TRANSPORT_LOG_OUT *tpm_transport_log_out) { printf(" TPM_TransportLogOut_Init:\n"); TPM_CurrentTicks_Init(&(tpm_transport_log_out->currentTicks)); TPM_Digest_Init(tpm_transport_log_out->parameters); tpm_transport_log_out = 0; return; } /* TPM_TransportLogOut_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_TransportLogOut_Store(TPM_STORE_BUFFER *sbuffer, const TPM_TRANSPORT_LOG_OUT *tpm_transport_log_out) { TPM_RESULT rc = 0; printf(" TPM_TransportLogOut_Store:\n"); /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_TRANSPORT_LOG_OUT); } /* store currentTicks */ if (rc == 0) { rc = TPM_CurrentTicks_Store(sbuffer, &(tpm_transport_log_out->currentTicks)); } /* store parameters */ if (rc == 0) { rc = TPM_Digest_Store(sbuffer, tpm_transport_log_out->parameters); } /* store locality */ if (rc == 0) { rc = TPM_Sbuffer_Append32(sbuffer, tpm_transport_log_out->locality); } return rc; } /* TPM_TransportLogOut_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_TransportLogOut_Init to set members back to default values The object itself is not freed */ void TPM_TransportLogOut_Delete(TPM_TRANSPORT_LOG_OUT *tpm_transport_log_out) { printf(" TPM_TransportLogOut_Delete:\n"); if (tpm_transport_log_out != NULL) { TPM_TransportLogOut_Init(tpm_transport_log_out); } return; } /* TPM_TransportLogOut_Extend() extends 'tpm_digest' tpm_digest = SHA-1 (tpm_digest || tpm_transport_log_out) */ TPM_RESULT TPM_TransportLogOut_Extend(TPM_DIGEST tpm_digest, TPM_TRANSPORT_LOG_OUT *tpm_transport_log_out) { TPM_RESULT rc = 0; TPM_STORE_BUFFER sbuffer; const unsigned char *buffer; /* serialized buffer */ uint32_t length; /* serialization length */ printf(" TPM_TransportLogOut_Extend:\n"); TPM_Sbuffer_Init(&sbuffer); /* freed @1 */ /* serialize TPM_TRANSPORT_LOG_OUT */ if (rc == 0) { rc = TPM_TransportLogOut_Store(&sbuffer, tpm_transport_log_out); } if (rc == 0) { /* get the TPM_TRANSPORT_LOG_OUT serialization results */ TPM_Sbuffer_Get(&sbuffer, &buffer, &length); TPM_PrintAll(" TPM_TransportLogOut_Extend: transDigest in", tpm_digest, TPM_DIGEST_SIZE); TPM_PrintAll(" TPM_TransportLogOut_Extend:", buffer, length); rc = TPM_SHA1(tpm_digest, TPM_DIGEST_SIZE, tpm_digest, length, buffer, 0, NULL); TPM_PrintAll(" TPM_TransportLogOut_Extend: transDigest out", tpm_digest, TPM_DIGEST_SIZE); } TPM_Sbuffer_Delete(&sbuffer); /* @1 */ return rc; } /* TPM_TRANSPORT_AUTH */ /* TPM_TransportAuth_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_TransportAuth_Init(TPM_TRANSPORT_AUTH *tpm_transport_auth) { printf(" TPM_TransportAuth_Init:\n"); TPM_Secret_Init(tpm_transport_auth->authData); return; } /* TPM_TransportAuth_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_TransportAuth_Init() After use, call TPM_TransportAuth_Delete() to free memory */ TPM_RESULT TPM_TransportAuth_Load(TPM_TRANSPORT_AUTH *tpm_transport_auth, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_TransportAuth_Load:\n"); /* check tag */ if (rc == 0) { rc = TPM_CheckTag(TPM_TAG_TRANSPORT_AUTH, stream, stream_size); } /* load authData */ if (rc == 0) { rc = TPM_Secret_Load(tpm_transport_auth->authData, stream, stream_size); } return rc; } /* TPM_TransportAuth_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_TransportAuth_Store(TPM_STORE_BUFFER *sbuffer, const TPM_TRANSPORT_AUTH *tpm_transport_auth) { TPM_RESULT rc = 0; printf(" TPM_TransportAuth_Store:\n"); /* store tag */ if (rc == 0) { rc = TPM_Sbuffer_Append16(sbuffer, TPM_TAG_TRANSPORT_AUTH); } /* store authData */ if (rc == 0) { rc = TPM_Secret_Store(sbuffer, tpm_transport_auth->authData); } return rc; } /* TPM_TransportAuth_Delete() No-OP if the parameter is NULL, else: frees memory allocated for the object sets pointers to NULL calls TPM_TransportAuth_Init to set members back to default values The object itself is not freed */ void TPM_TransportAuth_Delete(TPM_TRANSPORT_AUTH *tpm_transport_auth) { printf(" TPM_TransportAuth_Delete:\n"); if (tpm_transport_auth != NULL) { TPM_TransportAuth_Init(tpm_transport_auth); } return; } /* TPM_TransportAuth_DecryptSecret() decrypts the secret using the private key. The result is deserialized and stored in the TPM_TRANSPORT_AUTH structure. */ TPM_RESULT TPM_TransportAuth_DecryptSecret(TPM_TRANSPORT_AUTH *tpm_transport_auth, /* result */ TPM_SIZED_BUFFER *secret, /* encrypted input */ TPM_KEY *tpm_key) /* key for decrypting */ { TPM_RESULT rc = 0; unsigned char *decryptData = NULL; /* freed @1 */ uint32_t decryptDataLength = 0; /* actual valid data */ unsigned char *stream; uint32_t stream_size; printf(" TPM_TransportAuth_DecryptSecret:\n"); /* allocate space for the decrypted data */ if (rc == 0) { rc = TPM_RSAPrivateDecryptMalloc(&decryptData, /* decrypted data */ &decryptDataLength, /* actual size of decrypted data */ secret->buffer, /* encrypted data */ secret->size, /* encrypted data size */ tpm_key); } /* load the TPM_TRANSPORT_AUTH structure from the decrypted data stream */ if (rc == 0) { /* use temporary variables, because TPM_TransportAuth_Load() moves the stream */ stream = decryptData; stream_size = decryptDataLength; rc = TPM_TransportAuth_Load(tpm_transport_auth, &stream, &stream_size); } free(decryptData); /* @1 */ return rc; } /* Processing Functions */ /* 24.1 TPM_EstablishTransport rev 98 This establishes the transport session. Depending on the attributes specified for the session this may establish shared secrets, encryption keys, and session logs. The session will be in use for by the TPM_ExecuteTransport command. The only restriction on what can happen inside of a transport session is that there is no "nesting" of sessions. It is permissible to perform operations that delete internal state and make the TPM inoperable. */ TPM_RESULT TPM_Process_EstablishTransport(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_KEY_HANDLE encHandle; /* The handle to the key that encrypted the blob */ TPM_TRANSPORT_PUBLIC transPublic; /* The public information describing the transport session */ TPM_SIZED_BUFFER secret; /* The encrypted secret area */ TPM_AUTHHANDLE authHandle; /* The authorization session handle used for keyHandle authorization */ TPM_NONCE nonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession = TRUE; /* The continue use flag for the authorization session handle */ TPM_AUTHDATA keyAuth; /* Authorization. HMAC key: encKey.usageAuth */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for dataAuthHandle */ TPM_SECRET *hmacKey; TPM_KEY *encKey = NULL; /* the key specified by encHandle */ TPM_BOOL parentPCRStatus; TPM_SECRET *encKeyUsageAuth; TPM_AUTHDATA *a1AuthData = NULL; TPM_TRANSPORT_INTERNAL *t1TpmTransportInternal; TPM_TRANSPORT_AUTH k1TransportAuth; uint32_t blockSize; /* symmetric key block size, not used */ TPM_TRANSPORT_LOG_IN l1TransportLogIn; TPM_TRANSPORT_LOG_OUT l2TransportLogOut; TPM_STORE_BUFFER transPublicSbuffer; /* serialized transPublic */ const unsigned char *transPublicBuffer; /* serialized buffer */ uint32_t transPublicLength; /* serialization length */ TPM_STORE_BUFFER currentTicksSbuffer; /* serialized currentTicks */ const unsigned char *currentTicksBuffer; /* serialized buffer */ uint32_t currentTicksLength; /* serialization length */ TPM_COMMAND_CODE nOrdinal; /* ordinal in nbo */ uint32_t nSecretSize; /* secretSize in nbo */ TPM_RESULT nReturnCode; /* returnCode in nbo */ TPM_MODIFIER_INDICATOR nLocality; /* locality in nbo */ TPM_BOOL trans_session_added = FALSE; /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_CURRENT_TICKS currentTicks; /* The current tick count */ TPM_NONCE transNonceEven; /* The even nonce in use for subsequent execute transport */ printf("TPM_Process_EstablishTransport: Ordinal Entry\n"); TPM_TransportPublic_Init(&transPublic); /* freed @1 */ TPM_SizedBuffer_Init(&secret); /* freed @2 */ TPM_CurrentTicks_Init(¤tTicks); /* no need to free */ TPM_TransportAuth_Init(&k1TransportAuth); /* freed @4 */ TPM_TransportLogIn_Init(&l1TransportLogIn); /* freed @5 */ TPM_TransportLogOut_Init(&l2TransportLogOut); /* freed @6 */ TPM_Sbuffer_Init(&transPublicSbuffer); /* freed @7 */ TPM_Sbuffer_Init(¤tTicksSbuffer); /* freed @8 */ /* get inputs */ /* get encHandle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&encHandle, &command, ¶mSize); } /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get transPublic */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_EstablishTransport: keyHandle %08x\n", encHandle); returnCode = TPM_TransportPublic_Load(&transPublic, &command, ¶mSize); } /* get secret */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_EstablishTransport: transPublic->transAttributes %08x\n", transPublic.transAttributes); returnCode = TPM_SizedBuffer_Load(&secret, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag10(tag); } /* get the optional 'below the line' authorization parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, nonceOdd, &continueAuthSession, keyAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_EstablishTransport: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { authHandleValid = FALSE; } /* Processing */ if (returnCode == TPM_SUCCESS) { /* 1. If encHandle is TPM_KH_TRANSPORT then */ if (encHandle == TPM_KH_TRANSPORT) { printf("TPM_Process_EstablishTransport: TPM_KH_TRANSPORT clear text secret\n"); /* a. If tag is NOT TPM_TAG_RQU_COMMAND return TPM_BADTAG */ if (returnCode == TPM_SUCCESS) { if (tag != TPM_TAG_RQU_COMMAND) { printf("TPM_Process_EstablishTransport: Error, " "TPM_KH_TRANSPORT but not auth-0\n"); returnCode = TPM_BADTAG; } } /* b. If transPublic -> transAttributes specifies TPM_TRANSPORT_ENCRYPT return TPM_BAD_SCHEME */ if (returnCode == TPM_SUCCESS) { if (transPublic.transAttributes & TPM_TRANSPORT_ENCRYPT) { printf("TPM_Process_EstablishTransport: Error, " "TPM_KH_TRANSPORT but TPM_TRANSPORT_ENCRYPT\n"); returnCode = TPM_BAD_SCHEME; } } /* c. If secretSize is not 20 return TPM_BAD_PARAM_SIZE */ if (returnCode == TPM_SUCCESS) { if (secret.size != TPM_DIGEST_SIZE) { printf("TPM_Process_EstablishTransport: Error, secretSize %u not %u\n", secret.size, TPM_DIGEST_SIZE); returnCode = TPM_BAD_PARAM_SIZE; } } /* d. Set A1 to secret */ if (returnCode == TPM_SUCCESS) { a1AuthData = (TPM_AUTHDATA *)(secret.buffer); TPM_PrintFour("TPM_Process_EstablishTransport: transport clear text authData", *a1AuthData); } } /* 2. Else */ else { printf("TPM_Process_EstablishTransport: Decrypt secret\n"); /* get the key corresponding to the encHandle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyHandleEntries_GetKey(&encKey, &parentPCRStatus, tpm_state, encHandle, FALSE, /* not r/o, using to encrypt */ FALSE, /* do not ignore PCRs */ FALSE); /* cannot use EK */ } /* a. encHandle -> keyUsage MUST be TPM_KEY_STORAGE or TPM_KEY_LEGACY return TPM_INVALID_KEYUSAGE on error */ if (returnCode == TPM_SUCCESS) { if ((encKey->keyUsage != TPM_KEY_STORAGE) && (encKey->keyUsage != TPM_KEY_LEGACY)) { printf("TPM_Process_EstablishTransport: Error, " "key keyUsage %04hx must be TPM_KEY_STORAGE or TPM_KEY_LEGACY\n", encKey->keyUsage); returnCode = TPM_INVALID_KEYUSAGE; } } /* b. If encHandle -> authDataUsage does not equal TPM_AUTH_NEVER and tag is NOT TPM_TAG_RQU_AUTH1_COMMAND return TPM_AUTHFAIL */ if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_AUTH1_COMMAND)) { if (encKey->authDataUsage != TPM_AUTH_NEVER) { printf("TPM_Process_EstablishTransport: Error, " "encKey authorization required\n"); returnCode = TPM_AUTHFAIL; } } /* get encHandle -> usageAuth */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_Key_GetUsageAuth(&encKeyUsageAuth, encKey); } /* get the session data */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_KEYHANDLE, ordinal, encKey, encKeyUsageAuth, /* OIAP */ encKey->tpm_store_asymkey-> pubDataDigest); /*OSAP */ } /* c. Using encHandle -> usageAuth, validate the AuthData to use the key and the parameters to the command */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* HMAC key */ inParamDigest, auth_session_data, /* authorization session */ nonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, keyAuth); /* Authorization digest for input */ } /* d. Create K1 a TPM_TRANSPORT_AUTH structure by decrypting secret using the key pointed to by encHandle */ /* e. Validate K1 for tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_TransportAuth_DecryptSecret(&k1TransportAuth, &secret, encKey); } /* f. Set A1 to K1 -> authData */ if (returnCode == TPM_SUCCESS) { a1AuthData = &(k1TransportAuth.authData); TPM_PrintFour("TPM_Process_EstablishTransport: transport decrypted authData", *a1AuthData); } } } if (returnCode == TPM_SUCCESS) { TPM_PrintFour("TPM_Process_EstablishTransport: transport authData", *a1AuthData); } /* 3. If transPublic -> transAttributes has TPM_TRANSPORT_ENCRYPT */ if ((returnCode == TPM_SUCCESS) && (transPublic.transAttributes & TPM_TRANSPORT_ENCRYPT)) { printf("TPM_Process_EstablishTransport: Check encrypt attributes\n"); /* a. If TPM_PERMANENT_FLAGS -> FIPS is true and transPublic -> algId is equal to TPM_ALG_MGF1 return TPM_INAPPROPRIATE_ENC */ /* b. Check if the transPublic -> algId is supported, if not return TPM_BAD_KEY_PROPERTY */ /* c. If transPublic -> algid is TPM_ALG_AESXXX, check that transPublic -> encScheme is supported, if not return TPM_INAPPROPRIATE_ENC */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_TransportPublic_CheckEncScheme(&blockSize, transPublic.algId, transPublic.encScheme, tpm_state->tpm_permanent_flags.FIPS); } /* d. Perform any initializations necessary for the algorithm */ } /* 4. Generate transNonceEven from the TPM RNG */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Nonce_Generate(transNonceEven); } /* 5. Create T1 a TPM_TRANSPORT_INTERNAL structure */ /* NOTE Done by TPM_TransportInternal_Init() */ /* a. Ensure that the TPM has sufficient internal space to allocate the transport session, return TPM_RESOURCES on error */ /* b. Assign a T1 -> transHandle value. This value is assigned by the TPM */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_EstablishTransport: Construct TPM_TRANSPORT_INTERNAL\n"); returnCode = TPM_TransportSessions_GetNewHandle(&t1TpmTransportInternal, tpm_state->tpm_stclear_data.transSessions); } if (returnCode == TPM_SUCCESS) { /* record that the entry is allocated, for invalidation on error */ trans_session_added = TRUE; /* c. Set T1 -> transDigest to NULL */ TPM_Digest_Init(t1TpmTransportInternal->transDigest); /* d. Set T1 -> transPublic to transPublic */ TPM_TransportPublic_Copy(&(t1TpmTransportInternal->transPublic), &transPublic); /* e. Set T1-> transNonceEven to transNonceEven */ TPM_Nonce_Copy(t1TpmTransportInternal->transNonceEven , transNonceEven); /* f. Set T1 -> authData to A1 */ TPM_Secret_Copy(t1TpmTransportInternal->authData, *a1AuthData); /* 6. If TPM_STANY_DATA -> currentTicks is not properly initialized */ /* a. Initialize the TPM_STANY_DATA -> currentTicks */ returnCode = TPM_CurrentTicks_Update(&(tpm_state->tpm_stany_data.currentTicks)); } /* 7. Set currentTicks to TPM_STANY_DATA -> currentTicks */ if (returnCode == TPM_SUCCESS) { TPM_CurrentTicks_Copy(¤tTicks, &(tpm_state->tpm_stany_data.currentTicks)); } /* 8. If T1 -> transPublic -> transAttributes has TPM_TRANSPORT_LOG set then */ if ((returnCode == TPM_SUCCESS) && (t1TpmTransportInternal->transPublic.transAttributes & TPM_TRANSPORT_LOG)) { printf("TPM_Process_EstablishTransport: Construct TPM_TRANSPORT_LOG_IN\n"); /* a. Create L1 a TPM_TRANSPORT_LOG_IN structure */ /* NOTE Done by TPM_TransportLogIn_Init() */ /* i. Set L1 -> parameters to SHA-1 (ordinal || transPublic || secretSize || secret) */ /* serialize transPublic */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_TransportPublic_Store(&transPublicSbuffer, &transPublic); } if (returnCode == TPM_SUCCESS) { /* get the transPublic serialization results */ TPM_Sbuffer_Get(&transPublicSbuffer, &transPublicBuffer, &transPublicLength); /* digest the fields */ nOrdinal = htonl(ordinal); nSecretSize = htonl(secret.size); returnCode = TPM_SHA1(l1TransportLogIn.parameters, sizeof(TPM_COMMAND_CODE), &nOrdinal, transPublicLength, transPublicBuffer, sizeof(uint32_t), &nSecretSize, secret.size, secret.buffer, 0, NULL); } if (returnCode == TPM_SUCCESS) { /* ii. Set L1 -> pubKeyHash to NULL */ /* NOTE Done by TPM_TransportLogIn_Init() */ /* iii. Set T1 -> transDigest to SHA-1 (T1 -> transDigest || L1) */ printf("TPM_Process_EstablishTransport: Extend transDigest with input\n"); returnCode = TPM_TransportLogIn_Extend(t1TpmTransportInternal->transDigest, &l1TransportLogIn); } /* b. Create L2 a TPM_TRANSPORT_LOG_OUT structure */ /* NOTE Done by TPM_TransportLogOut_Init() */ /* i. Set L2 -> parameters to SHA-1 (returnCode || ordinal || locality || currentTicks || transNonceEven) */ /* serialize currentTicks */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_EstablishTransport: Construct TPM_TRANSPORT_LOG_OUT\n"); returnCode = TPM_CurrentTicks_Store(¤tTicksSbuffer, ¤tTicks); } if (returnCode == TPM_SUCCESS) { /* get the currentTicks serialization results */ TPM_Sbuffer_Get(¤tTicksSbuffer, ¤tTicksBuffer, ¤tTicksLength); nReturnCode = htonl(returnCode); nLocality = htonl(tpm_state->tpm_stany_flags.localityModifier); returnCode = TPM_SHA1(l2TransportLogOut.parameters, sizeof(TPM_RESULT), &nReturnCode, sizeof(TPM_COMMAND_CODE), &nOrdinal, sizeof(TPM_MODIFIER_INDICATOR), &nLocality, currentTicksLength, currentTicksBuffer, TPM_NONCE_SIZE, transNonceEven, 0, NULL); } if (returnCode == TPM_SUCCESS) { /* ii. Set L2 -> locality to the locality of this command */ l2TransportLogOut.locality = tpm_state->tpm_stany_flags.localityModifier; /* iii. Set L2 -> currentTicks to currentTicks, this MUST be the same value that is returned in the currentTicks parameter */ TPM_CurrentTicks_Copy(&(l2TransportLogOut.currentTicks), ¤tTicks); /* iv. Set T1 -> transDigest to SHA-1 (T1 -> transDigest || L2) */ printf("TPM_Process_EstablishTransport: Extend transDigest with output\n"); returnCode = TPM_TransportLogOut_Extend(t1TpmTransportInternal->transDigest, &l2TransportLogOut); } } /* 9. If T1 -> transPublic -> transAttributes has TPM_TRANSPORT_EXCLUSIVE then set TPM_STANY_FLAGS -> transportExclusive to TRUE */ if (returnCode == TPM_SUCCESS) { if (t1TpmTransportInternal->transPublic.transAttributes & TPM_TRANSPORT_EXCLUSIVE) { printf("TPM_Process_EstablishTransport: Session is exclusive\n"); tpm_state->tpm_stany_flags.transportExclusive = t1TpmTransportInternal->transHandle; } } /* a. Execution of any command other than TPM_ExecuteTransport or TPM_ReleaseTransportSigned targeting this transport session will cause the abnormal invalidation of this transport session transHandle */ /* b. The TPM gives no indication, other than invalidation of transHandle, that the session is terminated */ /* NOTE Done by TPM_Process_Preprocess() */ /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_EstablishTransport: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { /* 10. Return T1 -> transHandle as transHandle */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Sbuffer_Append32(response, t1TpmTransportInternal->transHandle); } if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* return locality */ returnCode = TPM_Sbuffer_Append32(response, tpm_state->tpm_stany_flags.localityModifier); } /* return currentTicks */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CurrentTicks_Store(response, ¤tTicks); } if (returnCode == TPM_SUCCESS) { /* return transNonceEven */ returnCode = TPM_Nonce_Store(response, transNonceEven); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the below the line parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH1_COMMAND)) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* owner HMAC key */ auth_session_data, outParamDigest, nonceOdd, continueAuthSession); } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING))) && trans_session_added) { TPM_TransportSessions_TerminateHandle(tpm_state->tpm_stclear_data.transSessions, t1TpmTransportInternal->transHandle, &(tpm_state->tpm_stany_flags.transportExclusive)); } /* cleanup */ TPM_TransportPublic_Delete(&transPublic); /* @1 */ TPM_SizedBuffer_Delete(&secret); /* @2 */ TPM_TransportAuth_Delete(&k1TransportAuth); /* @4 */ TPM_TransportLogIn_Delete(&l1TransportLogIn); /* @5 */ TPM_TransportLogOut_Delete(&l2TransportLogOut); /* @6 */ TPM_Sbuffer_Delete(&transPublicSbuffer); /* @7 */ TPM_Sbuffer_Delete(¤tTicksSbuffer); /* @8 */ return rcf; } /* 24.2 TPM_ExecuteTransport rev 117 Delivers a wrapped TPM command to the TPM where the TPM unwraps the command and then executes the command. TPM_ExecuteTransport uses the same rolling nonce paradigm as other authorized TPM commands. The even nonces start in EstablishTransport and change on each invocation of TPM_ExecuteTransport. The only restriction on what can happen inside of a transport session is that there is no "nesting" of sessions. It is permissible to perform operations that delete internal state and make the TPM inoperable. Because, in general, key handles are not logged, a digest of the corresponding public key is logged. In cases where the key handle is logged (e.g. TPM_OwnerReadInternalPub), the public key is also logged. The wrapped command is audited twice - once according to the actions of TPM_ExecuteTransport and once within the wrapped command itself according to the special rules for auditing a command wrapped in an encrypted transport session. */ TPM_RESULT TPM_Process_ExecuteTransport(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_SIZED_BUFFER wrappedCmd; /* The wrapped command */ TPM_TRANSHANDLE transHandle; /* The transport session handle */ TPM_NONCE transNonceOdd; /* Nonce generated by caller */ TPM_BOOL continueTransSession; /* The continue use flag for the authorization session handle */ TPM_AUTHDATA transAuth; /* HMAC for transHandle key: transHandle -> authData */ /* processing parameters */ /* unsigned char * inParamStart; /\* starting point of inParam's *\/ */ /* unsigned char * inParamEnd; /\* ending point of inParam's *\/ */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transHandleValid = FALSE; TPM_TRANSPORT_INTERNAL *t1TpmTransportInternal; TPM_TRANSPORT_INTERNAL t1TransportCopy; /* because original might be invalidated */ TPM_BOOL transportWrappable; /* inner command can be wrapped in transport */ uint32_t keyHandles; /* number of key handles in ordw */ uint32_t keyHandle1Index; /* index of key handles in wrapped command */ uint32_t keyHandle2Index; TPM_KEY_HANDLE keyHandle1; /* key handles in wrapped command */ TPM_KEY_HANDLE keyHandle2; uint32_t blockSize; /* symmetric key block size, if needed */ TPM_RESOURCE_TYPE wrappedResourceType; /* for key handle special cases */ TPM_COMMAND_CODE ordw; /* wrapped ORDW */ uint32_t e1Dataw; /* index into wrapped E1 */ uint32_t len1; /* wrapped LEN1 */ unsigned char *g1Mgf1; /* input MGF1 XOR string */ unsigned char *g2Mgf1; /* output MGF1 XOR string */ unsigned char *decryptCmd; /* decrypted wrapped command */ unsigned char *cmdStream; /* temporary for constructing decryptCmd */ uint32_t cmdStreamSize; TPM_COMMAND_CODE nOrdw; /* ordinal in nbo */ TPM_COMMAND_CODE nOrdet; /* ordinal in nbo */ uint32_t nWrappedCmdSize; /* wrappedCmdSize in nbo */ TPM_DIGEST h1InWrappedDigest; TPM_DIGEST h2OutWrappedDigest; TPM_TRANSPORT_LOG_IN l2TransportLogIn; TPM_TRANSPORT_LOG_OUT l3TransportLogOut; TPM_DIGEST k2PubkeyDigest; TPM_DIGEST k3PubkeyDigest; TPM_KEY *k2Key; /* wrapped command keys */ TPM_KEY *k3Key; TPM_BOOL parentPCRStatus; TPM_STORE_BUFFER wrappedRspSbuffer; const unsigned char *wrappedRspStream; uint32_t wrappedRspStreamSize; uint32_t s2Dataw; /* index into S2 */ uint32_t len2; /* length of S2 */ TPM_RESULT rcw; /* wrapped return code */ TPM_RESULT nRcw; /* return code in nbo */ TPM_STORE_BUFFER currentTicksSbuffer; const unsigned char *currentTicksBuffer; /* serialized buffer */ uint32_t currentTicksLength; /* serialization length */ TPM_RESULT nRCet; /* return code in nbo */ TPM_MODIFIER_INDICATOR nLocality; /* locality in nbo */ uint32_t nWrappedRspStreamSize; /* wrappedRspStreamSize in nbo */ unsigned char *encryptRsp; /* encrypted response */ /* output parameters */ TPM_DIGEST outParamDigest; TPM_UINT64 currentTicks; /* The current ticks when the command was executed */ TPM_SIZED_BUFFER wrappedRsp; /* The wrapped response */ printf("TPM_Process_ExecuteTransport: Ordinal Entry\n"); transportInternal = transportInternal; /* TPM_ExecuteTransport cannot be wrapped */ TPM_SizedBuffer_Init(&wrappedCmd); /* freed @1 */ TPM_SizedBuffer_Init(&wrappedRsp); /* freed @2 */ g1Mgf1 = NULL; /* freed @3 */ decryptCmd = NULL; /* freed @4 */ TPM_TransportLogIn_Init(&l2TransportLogIn); /* freed @5 */ TPM_TransportLogOut_Init(&l3TransportLogOut); /* freed @6 */ TPM_Sbuffer_Init(&wrappedRspSbuffer); /* freed @7 */ TPM_Sbuffer_Init(¤tTicksSbuffer); /* freed @8 */ g2Mgf1 = NULL; /* freed @9 */ TPM_TransportInternal_Init(&t1TransportCopy); /* freed @10 */ encryptRsp = NULL; /* freed @11 */ /* get inputs */ if (returnCode == TPM_SUCCESS) { /* save the starting point of inParam's for authorization and auditing */ /* inParamStart = command; */ /* get wrappedCmd */ returnCode = TPM_SizedBuffer_Load(&wrappedCmd, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_ExecuteTransport: wrapped command size %u\n", wrappedCmd.size); /* save the ending point of inParam's for authorization and auditing */ /* inParamEnd = command; */ /* NOTE: The common TPM_GetInParamDigest() is not called here, since inParamDigest cannot be calculated until the wrapped command is decrypted */ returnCode = TPM_OrdinalAuditStatus_GetAuditStatus(&auditStatus, ordinal, &(tpm_state->tpm_permanent_data)); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag1(tag); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Get(&transHandle, &transHandleValid, transNonceOdd, &continueTransSession, transAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_ExecuteTransport: transHandle %08x\n", transHandle); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_ExecuteTransport: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { transHandleValid = FALSE; } /* Processing */ /* if there is an active exclusive transport session and it's not this session, terminate it */ if (returnCode == TPM_SUCCESS) { if ((tpm_state->tpm_stany_flags.transportExclusive != 0) && (tpm_state->tpm_stany_flags.transportExclusive != transHandle)) { returnCode = TPM_TransportSessions_TerminateHandle (tpm_state->tpm_stclear_data.transSessions, tpm_state->tpm_stany_flags.transportExclusive, &(tpm_state->tpm_stany_flags.transportExclusive)); } } /* 1. Using transHandle locate the TPM_TRANSPORT_INTERNAL structure T1 */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_TransportSessions_GetEntry(&t1TpmTransportInternal, tpm_state->tpm_stclear_data.transSessions, transHandle); } /* For the corner case where the wrapped command invalidates the transport session, make a copy for the response. */ if (returnCode == TPM_SUCCESS) { TPM_TransportInternal_Copy(&t1TransportCopy, t1TpmTransportInternal); } /* 2. Parse wrappedCmd */ /* a. Set TAGw, LENw, and ORDw to the parameters from wrappedCmd */ /* b. Set E1 to DATAw */ /* i. This pointer is ordinal dependent and requires the execute transport command to parse wrappedCmd */ /* c. Set LEN1 to the length of DATAw */ /* i. DATAw always ends at the start of AUTH1w if AUTH1w is present */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_OrdinalTable_ParseWrappedCmd(&e1Dataw, /* index into wrappedCmd */ &len1, &keyHandles, &keyHandle1Index, /* index into key handles */ &keyHandle2Index, &ordw, &transportWrappable, &wrappedCmd); if (returnCode != TPM_SUCCESS) { printf("TPM_Process_ExecuteTransport: Error parsing wrapped command\n"); } } /* 3. If LEN1 is less than 0, or if ORDw is unknown, unimplemented, or cannot be determined a. Return TPM_BAD_PARAMETER */ if (returnCode == TPM_SUCCESS) { if (wrappedCmd.size < e1Dataw + len1) { printf("TPM_Process_ExecuteTransport: Error (fatal), wrappedCmdSize %u e1 %u len1 %u\n", wrappedCmd.size, e1Dataw, len1); returnCode = TPM_FAIL; /* internal error, should never occur */ } } /* allocate memory for the decrypted command, which is always the same length as the encrypted command */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Malloc(&decryptCmd, wrappedCmd.size); } /* 4. If T1 -> transPublic -> transAttributes has TPM_TRANSPORT_ENCRYPT set then */ if ((returnCode == TPM_SUCCESS) && (t1TransportCopy.transPublic.transAttributes & TPM_TRANSPORT_ENCRYPT) && (len1 != 0)) { /* some commands have no DATAw area to encrypt */ /* a. If T1 -> transPublic -> algId is TPM_ALG_MGF1 */ if (t1TransportCopy.transPublic.algId == TPM_ALG_MGF1) { printf("TPM_Process_ExecuteTransport: Wrapped command MGF1 encrypted\n"); /* i. Using the MGF1 function, create string G1 of length LEN1. The inputs to the MGF1 are transLastNonceEven, transNonceOdd, "in", and T1 -> authData. These four values concatenated together form the Z value that is the seed for the MGF1. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_MGF1_GenerateArray(&g1Mgf1, /* G1 MGF1 array */ len1, /* G1 length */ TPM_NONCE_SIZE + TPM_NONCE_SIZE + sizeof("in") - 1 + TPM_AUTHDATA_SIZE, /* seed length */ TPM_NONCE_SIZE, t1TransportCopy.transNonceEven, TPM_NONCE_SIZE, transNonceOdd, sizeof("in") - 1, "in", TPM_AUTHDATA_SIZE, t1TransportCopy.authData, 0, NULL); } /* ii. Create C1 by performing an XOR of G1 and wrappedCmd starting at E1. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Transport_CryptMgf1(decryptCmd, /* output */ wrappedCmd.buffer, /* input */ g1Mgf1, /* XOR pad */ wrappedCmd.size, /* total size of buffers */ e1Dataw, /* start of encrypted part */ len1); /* length of encrypted part */ } } /* b. If the encryption algorithm requires an IV or CTR calculate the IV or CTR value */ else { printf("TPM_Process_ExecuteTransport: " "Wrapped command algId %08x encScheme %04hx encrypted\n", t1TransportCopy.transPublic.algId, t1TransportCopy.transPublic.encScheme); /* This function call should not fail, as the parameters were checked at TPM_EstablishTransport. The call is used here to get the block size. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_TransportPublic_CheckEncScheme(&blockSize, t1TransportCopy.transPublic.algId, t1TransportCopy.transPublic.encScheme, tpm_state->tpm_permanent_flags.FIPS); } /* i. Using the MGF1 function, create string IV1 or CTR1 with a length set by the block size of the encryption algorithm. The inputs to the MGF1 are transLastNonceEven, transNonceOdd, and "in". These three values concatenated together form the Z value that is the seed for the MGF1. Note that any terminating characters within the string "in" are ignored, so a total of 42 bytes are hashed. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_MGF1_GenerateArray(&g1Mgf1, /* G1 MGF1 array */ blockSize, /* G1 length */ TPM_NONCE_SIZE + TPM_NONCE_SIZE + sizeof("in") - 1, /* seed length */ TPM_NONCE_SIZE, t1TransportCopy.transNonceEven, TPM_NONCE_SIZE, transNonceOdd, sizeof("in") - 1, "in", 0, NULL); } /* ii. The symmetric key is taken from the first bytes of T1 -> authData. */ /* iii. Decrypt DATAw and replace the DATAw area of E1 creating C1 */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Transport_CryptSymmetric(decryptCmd, /* output */ wrappedCmd.buffer, /* input */ t1TransportCopy.transPublic.algId, t1TransportCopy.transPublic.encScheme, t1TransportCopy.authData, /* key */ TPM_AUTHDATA_SIZE, /* key size */ g1Mgf1, /* pad, IV or CTR */ blockSize, wrappedCmd.size, /* total size of buffers */ e1Dataw, /* start of encrypted part */ len1); /* length of encrypted part */ } } /* 4.c. TPM_OSAP, TPM_OIAP have no parameters encrypted */ /* NOTE Handled by len1 = 0 */ /* 4.d. TPM_DSAP has special rules for parameter encryption */ /* NOTE Handled by setting inputHandleSize to all but entityValue */ } /* 5. Else (no encryption) */ else if (returnCode == TPM_SUCCESS) { printf("TPM_Process_ExecuteTransport: Wrapped command not encrypted\n"); /* a. Set C1 to the DATAw area E1 of wrappedCmd */ memcpy(decryptCmd, wrappedCmd.buffer, wrappedCmd.size); } /* Now that the wrapped command is decrypted, handle the special cases (e.g., TPM_FlushSpecific and TPM_SaveContext) where the handle may or may not be a key handle, dependent on the value of resourceType */ if ((returnCode == TPM_SUCCESS) && (keyHandles == 0xffffffff)) { printf("TPM_Process_ExecuteTransport: key handles special case\n"); /* point to the resourceType in the decrypted stream, directly after the key handle */ cmdStream = decryptCmd + keyHandle1Index + sizeof(TPM_KEY_HANDLE); cmdStreamSize = wrappedCmd.size - keyHandle1Index - sizeof(TPM_KEY_HANDLE); returnCode = TPM_Load32(&wrappedResourceType, &cmdStream , &cmdStreamSize ); } /* ii. If the resourceType is TPM_RT_KEY, then the public key MUST be logged */ if ((returnCode == TPM_SUCCESS) && (keyHandles == 0xffffffff)) { printf("TPM_Process_ExecuteTransport: special case resource type %08x\n", wrappedResourceType); if (wrappedResourceType == TPM_RT_KEY) { printf("TPM_Process_ExecuteTransport: Special case, 1 key handle\n"); keyHandles = 1; } else { keyHandles = 0; } } /* 6. Create H1 the SHA-1 of (ORDw || C1). */ /* a. C1 MUST point at the decrypted DATAw area of E1 */ /* b. The TPM MAY use this calculation for both execute transport authorization, authorization of the wrapped command and transport log creation */ if (returnCode == TPM_SUCCESS) { TPM_PrintFour("TPM_Process_ExecuteTransport: DATAw decrypted", decryptCmd); printf("TPM_Process_ExecuteTransport: Create H1\n"); nOrdw = htonl(ordw); returnCode = TPM_SHA1(h1InWrappedDigest, sizeof(TPM_COMMAND_CODE), &nOrdw, len1, decryptCmd + e1Dataw, 0, NULL); } /* 7. Validate the incoming transport session authorization */ /* a. Set inParamDigest to SHA-1 (ORDet || wrappedCmdSize || H1) */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_ExecuteTransport: Validate AUTHet\n"); nOrdet = htonl(ordinal); nWrappedCmdSize = htonl(wrappedCmd.size); returnCode = TPM_SHA1(inParamDigest, sizeof(TPM_COMMAND_CODE), &nOrdet, sizeof(uint32_t), &nWrappedCmdSize, TPM_DIGEST_SIZE, h1InWrappedDigest, 0, NULL); } /* b. Calculate the HMAC of (inParamDigest || transLastNonceEven || transNonceOdd || continueTransSession) using T1 -> authData as the HMAC key */ /* c. Validate transAuth, on errors return TPM_AUTHFAIL */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_TransportInternal_Check(inParamDigest, &t1TransportCopy, /* transport session */ transNonceOdd, /* Nonce generated by system associated with authHandle */ continueTransSession, transAuth); /* Authorization digest for input */ } /* 8. If TPM_ExecuteTransport requires auditing */ /* a. Create TPM_AUDIT_EVENT_IN using H1 */ /* NOTE: Done during response */ /* 9. If ORDw is from the list of following commands return TPM_NO_WRAP_TRANSPORT */ /* a. TPM_EstablishTransport */ /* b. TPM_ExecuteTransport */ /* c. TPM_ReleaseTransportSigned */ if (returnCode == TPM_SUCCESS) { if (!transportWrappable) { printf("TPM_Process_ExecuteTransport: Error, ordinal %08x cannot be wrapped\n", ordw); returnCode = TPM_NO_WRAP_TRANSPORT; } } /* 10. If T1 -> transPublic -> transAttributes has TPM_TRANSPORT_LOG set then */ if ((returnCode == TPM_SUCCESS) && (t1TransportCopy.transPublic.transAttributes & TPM_TRANSPORT_LOG)) { printf("TPM_Process_ExecuteTransport: Create transport log\n"); /* a. Create L2 a TPM_TRANSPORT_LOG_IN structure */ /* NOTE Done by TPM_TransportLogIn_Init() */ /* b. Set L2 -> parameters to H1 */ TPM_Digest_Copy(l2TransportLogIn.parameters, h1InWrappedDigest); /* c. If ORDw is a command with no key handles */ /* i. Set L2 -> pubKeyHash to NULL */ /* NOTE Done by TPM_TransportLogIn_Init() */ if ((returnCode == TPM_SUCCESS) && ((keyHandles == 1) || (keyHandles == 2))) { if (returnCode == TPM_SUCCESS) { /* point to the first key handle in the decrypted stream */ cmdStream = decryptCmd + keyHandle1Index; cmdStreamSize = wrappedCmd.size - keyHandle1Index; /* get the key handle */ returnCode = TPM_Load32(&keyHandle1, &cmdStream, &cmdStreamSize); } /* get the first key */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_ExecuteTransport: Create pubKeyHash for key 1 handle %08x\n", keyHandle1); returnCode = TPM_KeyHandleEntries_GetKey(&k2Key, &parentPCRStatus, tpm_state, keyHandle1, TRUE, /* read-only */ FALSE, /* do not ignore PCRs */ TRUE); /* can use EK */ } /* 10.d. If ORDw is a command with one key handle */ /* 10.i. Create K2 the hash of the TPM_STORE_PUBKEY structure of the key pointed to by the key handle. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SHA1_GenerateStructure(k2PubkeyDigest, &(k2Key->pubKey), (TPM_STORE_FUNCTION_T)TPM_SizedBuffer_Store); } } if ((returnCode == TPM_SUCCESS) && (keyHandles == 1)) { printf("TPM_Process_ExecuteTransport: Digesting one public key\n"); /* 10.ii. Set L2 -> pubKeyHash to SHA-1 (K2) */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SHA1(l2TransportLogIn.pubKeyHash, TPM_DIGEST_SIZE, k2PubkeyDigest, 0, NULL); } } /* 10.e. If ORDw is a command with two key handles */ if ((returnCode == TPM_SUCCESS) && (keyHandles == 2)) { printf("TPM_Process_ExecuteTransport: Digesting two public keys\n"); /* i. Create K2 the hash of the TPM_STORE_PUBKEY structure of the key pointed to by the first key handle. */ /* NOTE Done above for 1 or 2 key case */ if (returnCode == TPM_SUCCESS) { /* point to the second key handle in the decrypted stream */ cmdStream = decryptCmd + keyHandle2Index; cmdStreamSize = wrappedCmd.size - keyHandle2Index; /* get the key handle */ returnCode = TPM_Load32(&keyHandle2, &cmdStream, &cmdStreamSize); } /* get the second key */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_ExecuteTransport: Create pubKeyHash for key 2 handle %08x\n", keyHandle2); returnCode = TPM_KeyHandleEntries_GetKey(&k3Key, &parentPCRStatus, tpm_state, keyHandle2, TRUE, /* read-only */ FALSE, /* do not ignore PCRs */ TRUE); /* can use EK */ } /* ii. Create K3 the hash of the TPM_STORE_PUBKEY structure of the key pointed to by the second key handle. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SHA1_GenerateStructure(k3PubkeyDigest, &(k3Key->pubKey), (TPM_STORE_FUNCTION_T)TPM_SizedBuffer_Store); } /* 10.iii. Set L2 -> pubKeyHash to SHA-1 (K2 || K3) */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SHA1(l2TransportLogIn.pubKeyHash, TPM_DIGEST_SIZE, k2PubkeyDigest, TPM_DIGEST_SIZE, k3PubkeyDigest, 0, NULL); } } /* 10.f. Set T1 -> transDigest to the SHA-1 (T1 -> transDigest || L2) */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_ExecuteTransport: Extend transDigest with input\n"); returnCode = TPM_TransportLogIn_Extend(t1TransportCopy.transDigest, &l2TransportLogIn); } /* 10.g. If ORDw is a command with key handles, and the key is not loaded, return TPM_INVALID_KEYHANDLE. */ /* NOTE Done by TPM_KeyHandleEntries_GetKey() */ } /* 11. Send the wrapped command to the normal TPM command parser, the output is C2 and the return code is RCw */ /* a. If ORDw is a command that is audited then the TPM MUST perform the input and output audit of the command as part of this action */ /* b. The TPM MAY use H1 as the data value in the authorization and audit calculations during the execution of C1 */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_ExecuteTransport: Call wrapped command\n"); returnCode = TPM_Process_Wrapped(&wrappedRspSbuffer, /* response buffer */ decryptCmd, /* complete command array */ wrappedCmd.size, /* actual bytes in command */ tpm_state, &t1TransportCopy); /* TPM_ExecuteTransport */ printf("TPM_Process_ExecuteTransport: Completed wrapped command\n"); } /* 12. Set CT1 to TPM_STANY_DATA -> currentTicks -> currentTicks and return CT1 in the currentTicks output parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CurrentTicks_Update(&(tpm_state->tpm_stany_data.currentTicks)); } if (returnCode == TPM_SUCCESS) { TPM_Uint64_Copy(¤tTicks, &(tpm_state->tpm_stany_data.currentTicks.currentTicks)); } if (returnCode == TPM_SUCCESS) { returnCode = TPM_Uint64_Store(¤tTicksSbuffer, &(tpm_state->tpm_stany_data.currentTicks.currentTicks)); } /* 13. Calculate S2 the pointer to the DATAw area of C2 */ /* a. Calculate LEN2 the length of S2 according to the same rules that calculated LEN1 */ if (returnCode == TPM_SUCCESS) { /* get the response buffer and length */ TPM_Sbuffer_Get(&wrappedRspSbuffer, &wrappedRspStream, &wrappedRspStreamSize); /* parse the three standard input parameters, check paramSize against wrappedRsp->size */ returnCode = TPM_OrdinalTable_ParseWrappedRsp(&s2Dataw, &len2, &rcw, ordw, wrappedRspStream, wrappedRspStreamSize); } /* 14. Create H2 the SHA-1 of (RCw || ORDw || S2) */ /* a. The TPM MAY use this calculation for execute transport authorization and transport log out creation */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_ExecuteTransport: Create H2\n"); nRcw = htonl(rcw); /* The TPM_ExecuteTransport input ordinal and output ordinal, currentTicks and locality are not audited. This was simply an error, and not a deliberate attempt to make TPM_ExecuteTransport different from other ordinals. */ returnCode = TPM_SHA1(h2OutWrappedDigest, sizeof(TPM_RESULT), &nRcw, sizeof(TPM_COMMAND_CODE), &nOrdw, len2, wrappedRspStream + s2Dataw, 0, NULL); } /* 15. Calculate the outgoing transport session authorization */ /* a. Create the new transNonceEven for the output of the command */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Nonce_Generate(t1TransportCopy.transNonceEven); } /* b. Set outParamDigest to SHA-1 (RCet || ORDet || TPM_STANY_DATA -> currentTicks -> currentTicks || locality || wrappedRspSize || H2) */ if (returnCode == TPM_SUCCESS) { nRCet = htonl(returnCode); TPM_Sbuffer_Get(¤tTicksSbuffer, ¤tTicksBuffer, ¤tTicksLength); nLocality = htonl(tpm_state->tpm_stany_flags.localityModifier); nWrappedRspStreamSize = htonl(wrappedRspStreamSize); returnCode = TPM_SHA1(outParamDigest, sizeof(TPM_RESULT), &nRCet, sizeof(TPM_COMMAND_CODE), &nOrdet, currentTicksLength, currentTicksBuffer, sizeof(TPM_MODIFIER_INDICATOR), &nLocality, sizeof(uint32_t), &nWrappedRspStreamSize, TPM_DIGEST_SIZE, h2OutWrappedDigest, 0, NULL); } /* c. Calculate transAuth, the HMAC of (outParamDigest || transNonceEven || transNonceOdd || continueTransSession) using T1 -> authData as the HMAC key */ /* NOTE: Done as part of response */ /* 16. If T1 -> transPublic -> transAttributes has TPM_TRANSPORT_LOG set then */ if ((returnCode == TPM_SUCCESS) && (t1TransportCopy.transPublic.transAttributes & TPM_TRANSPORT_LOG)) { /* a. Create L3 a TPM_TRANSPORT_LOG_OUT structure */ /* NOTE Done by TPM_TransportLogOut_Init() */ /* b. Set L3 -> parameters to H2 */ TPM_Digest_Copy(l3TransportLogOut.parameters, h2OutWrappedDigest); /* c. Set L3 -> currentTicks to TPM_STANY_DATA -> currentTicks */ TPM_CurrentTicks_Copy(&(l3TransportLogOut.currentTicks), &(tpm_state->tpm_stany_data.currentTicks)); /* d. Set L3 -> locality to TPM_STANY_DATA -> localityModifier */ l3TransportLogOut.locality = tpm_state->tpm_stany_flags.localityModifier; /* e. Set T1 -> transDigest to the SHA-1 (T1 -> transDigest || L3) */ printf("TPM_Process_ExecuteTransport: Extend transDigest with output\n"); returnCode = TPM_TransportLogOut_Extend(t1TransportCopy.transDigest, &l3TransportLogOut); } /* allocate memory for the encrypted response, which is always the same length as the decrypted response */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Malloc(&encryptRsp, wrappedRspStreamSize); } /* 17. If T1 -> transPublic -> transAttributes has TPM_TRANSPORT_ENCRYPT set then */ if ((returnCode == TPM_SUCCESS) && (t1TransportCopy.transPublic.transAttributes & TPM_TRANSPORT_ENCRYPT) && (len2 != 0)) { /* some commands have no DATAw area to encrypt */ /* NOTE No TPM_OSAP encryption handled by len2 = 0 */ /* a. If T1 -> transPublic -> algId is TPM_ALG_MGF1 */ if (t1TransportCopy.transPublic.algId == TPM_ALG_MGF1) { printf("TPM_Process_ExecuteTransport: Wrapped response MGF1 encrypted\n"); /* i. Using the MGF1 function, create string G2 of length LEN2. The inputs to the MGF1 are transNonceEven, transNonceOdd, "out", and T1 -> authData. These four values concatenated together form the Z value that is the seed for the MGF1. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_MGF1_GenerateArray(&g2Mgf1, /* G2 MGF1 array */ len2, /* G2 length */ TPM_NONCE_SIZE + TPM_NONCE_SIZE + sizeof("out") - 1 + TPM_AUTHDATA_SIZE, /* seed length */ TPM_NONCE_SIZE, t1TransportCopy.transNonceEven, TPM_NONCE_SIZE, transNonceOdd, sizeof("out") - 1, "out", TPM_AUTHDATA_SIZE, t1TransportCopy.authData, 0, NULL); } /* ii. Create E2 by performing an XOR of G2 and C2 starting at S2. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Transport_CryptMgf1(encryptRsp, wrappedRspStream, g2Mgf1, wrappedRspStreamSize, s2Dataw, len2); } } /* b. Else */ else { printf("TPM_Process_ExecuteTransport: " "Wrapped response algId %08x encScheme %04hx encrypted\n", t1TransportCopy.transPublic.algId, t1TransportCopy.transPublic.encScheme); /* This function call should not fail, as the parameters were checked at TPM_EstablishTransport. The call is used here to get the block size. This is a duplicate of the call for the command. However, there are cases where there is no encrypted command (len1 == 0) so the call was not made. Rather than keep track of whether blockSize is valid, it's clearer to just call the function twice in some cases. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_TransportPublic_CheckEncScheme(&blockSize, t1TransportCopy.transPublic.algId, t1TransportCopy.transPublic.encScheme, tpm_state->tpm_permanent_flags.FIPS); } /* i. Create IV2 or CTR2 using the same algorithm as IV1 or CTR1 with the input values transNonceEven, transNonceOdd, and "out". Note that any terminating characters within the string "out" are ignored, so a total of 43 bytes are hashed. */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_MGF1_GenerateArray(&g2Mgf1, /* G2 MGF1 array */ blockSize, /* G2 length */ TPM_NONCE_SIZE + TPM_NONCE_SIZE + sizeof("out") - 1, /* seed length */ TPM_NONCE_SIZE, t1TransportCopy.transNonceEven, TPM_NONCE_SIZE, transNonceOdd, sizeof("out") - 1, "out", 0, NULL); } /* ii. The symmetric key is taken from the first bytes of T1 -> authData */ /* iii. Create E2 by encrypting C2 starting at S2 */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Transport_CryptSymmetric(encryptRsp, /* output */ wrappedRspStream, /* input */ t1TransportCopy.transPublic.algId, t1TransportCopy.transPublic.encScheme, t1TransportCopy.authData, /* key */ TPM_AUTHDATA_SIZE, /* key size */ g2Mgf1, /* pad, IV or CTR */ blockSize, wrappedRspStreamSize, /* total size of buffers */ s2Dataw, /* start of encrypted part */ len2); /* length of encrypted part */ } } } /* 18. Else (no encryption) */ else if (returnCode == TPM_SUCCESS) { printf("TPM_Process_ExecuteTransport: Wrapped response not encrypted\n"); /* a. Set E2 to the DATAw area S2 of wrappedRsp */ memcpy(encryptRsp, wrappedRspStream ,wrappedRspStreamSize); } /* 19. If continueTransSession is FALSE */ /* a. Invalidate all session data related to transHandle */ /* NOTE: Done after response */ /* 20. If TPM_ExecuteTranport requires auditing */ /* a. Create TPM_AUDIT_EVENT_OUT using H2 */ /* NOTE: Done during response */ /* 21. Return C2 but with S2 replaced by E2 in the wrappedRsp parameter */ if (returnCode == TPM_SUCCESS) { /* if the wrapped command invalidated the transport session, set continueTransSession to FALSE */ if (!(t1TpmTransportInternal->valid)) { continueTransSession = FALSE; } /* if the session is still valid, copy the copy back to the original so the log gets updated */ else { TPM_TransportInternal_Copy(t1TpmTransportInternal, &t1TransportCopy); } } /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_ExecuteTransport: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { /* return currentTicks */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Sbuffer_Append(response, currentTicksBuffer, currentTicksLength); } /* return locality */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Sbuffer_Append32(response, tpm_state->tpm_stany_flags.localityModifier); } /* return wrappedRspSize */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Sbuffer_Append32(response, wrappedRspStreamSize); } /* return wrappedRsp */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Sbuffer_Append(response, encryptRsp, wrappedRspStreamSize); } /* non-standard - digest the above the line output parameters, H1 used */ /* non-standard - calculate and set the below the line parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_TransportInternal_Set(response, &t1TransportCopy, outParamDigest, transNonceOdd, continueTransSession, FALSE); /* transNonceEven already generated */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, FALSE, /* transportEncrypt */ h1InWrappedDigest, h2OutWrappedDigest, /* exception to normal digest */ ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueTransSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueTransSession) && transHandleValid) { TPM_TransportSessions_TerminateHandle(tpm_state->tpm_stclear_data.transSessions, transHandle, &(tpm_state->tpm_stany_flags.transportExclusive)); } /* cleanup */ TPM_SizedBuffer_Delete(&wrappedCmd); /* @1 */ TPM_SizedBuffer_Delete(&wrappedRsp); /* @2 */ free(g1Mgf1); /* @3 */ free (decryptCmd); /* @4 */ TPM_TransportLogIn_Delete(&l2TransportLogIn); /* @5 */ TPM_TransportLogOut_Delete(&l3TransportLogOut); /* @6 */ TPM_Sbuffer_Delete(&wrappedRspSbuffer); /* @7 */ TPM_Sbuffer_Delete(¤tTicksSbuffer); /* @8 */ free(g2Mgf1); /* @9 */ TPM_TransportInternal_Delete(&t1TransportCopy); /* @10 */ free(encryptRsp); /* @11 */ return rcf; } /* 24.3 TPM_ReleaseTransportSigned rev 101 This command completes the transport session. If logging for this session is turned on, then this command returns a hash of all operations performed during the session along with a digital signature of the hash. This command serves no purpose if logging is turned off, and results in an error if attempted. This command uses two authorization sessions, the key that will sign the log and the authorization from the session. Having the session authorization proves that the requester that is signing the log is the owner of the session. If this restriction is not put in then an attacker can close the log and sign using their own key. The hash of the session log includes the information associated with the input phase of execution of the TPM_ReleaseTransportSigned command. It cannot include the output phase information. */ TPM_RESULT TPM_Process_ReleaseTransportSigned(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal) { TPM_RESULT rcf = 0; /* fatal error precluding response */ TPM_RESULT returnCode = TPM_SUCCESS; /* command return code */ /* input parameters */ TPM_KEY_HANDLE keyHandle; /* Handle of a loaded key that will perform the signing */ TPM_NONCE antiReplay; /* Value provided by caller for anti-replay protection */ TPM_AUTHHANDLE authHandle; /* The authorization session to use key */ TPM_NONCE authNonceOdd; /* Nonce generated by system associated with authHandle */ TPM_BOOL continueAuthSession; /* The continue use flag for the authorization session handle */ TPM_AUTHDATA keyAuth; /* The authorization session digest that authorizes the use of key. HMAC key: key -> usageAuth */ TPM_TRANSHANDLE transHandle; /* The transport session handle */ TPM_NONCE transNonceOdd; /* Nonce supplied by caller for transport session */ TPM_BOOL continueTransSession = TRUE; /* The continue use flag for the authorization session handle */ TPM_AUTHDATA transAuth; /* HMAC for transport session key: tranHandle -> authData */ /* processing parameters */ unsigned char * inParamStart; /* starting point of inParam's */ unsigned char * inParamEnd; /* ending point of inParam's */ TPM_DIGEST inParamDigest; TPM_BOOL auditStatus; /* audit the ordinal */ TPM_BOOL transportEncrypt; /* wrapped in encrypted transport session */ TPM_BOOL authHandleValid = FALSE; TPM_BOOL transHandleValid = FALSE; TPM_AUTH_SESSION_DATA *auth_session_data = NULL; /* session data for authHandle */ TPM_TRANSPORT_INTERNAL *t1TpmTransportInternal = NULL; TPM_SECRET *hmacKey; TPM_KEY *sigKey = NULL; /* the key specified by keyHandle */ TPM_BOOL parentPCRStatus; TPM_SECRET *keyUsageAuth; TPM_TRANSPORT_LOG_OUT a1TransportLogOut; TPM_SIGN_INFO h1SignInfo; TPM_DIGEST h1Digest; /* digest of h1SignInfo */ /* output parameters */ uint32_t outParamStart; /* starting point of outParam's */ uint32_t outParamEnd; /* ending point of outParam's */ TPM_DIGEST outParamDigest; TPM_CURRENT_TICKS *currentTicks = NULL; /* The current time according to the TPM */ TPM_SIZED_BUFFER signature; /* The signature of the digest */ printf("TPM_Process_ReleaseTransportSigned: Ordinal Entry\n"); TPM_SizedBuffer_Init(&signature); /* freed @1 */ TPM_TransportLogOut_Init(&a1TransportLogOut); /* freed @2 */ TPM_SignInfo_Init(&h1SignInfo); /* freed @3 */ /* get inputs */ /* get keyHandle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Load32(&keyHandle, &command, ¶mSize); } /* save the starting point of inParam's for authorization and auditing */ inParamStart = command; /* get antiReplay */ if (returnCode == TPM_SUCCESS) { printf("TPM_Process_ReleaseTransportSigned: keyHandle %08x\n", keyHandle ); returnCode = TPM_Nonce_Load(antiReplay, &command, ¶mSize); } /* save the ending point of inParam's for authorization and auditing */ inParamEnd = command; /* digest the input parameters */ if (returnCode == TPM_SUCCESS) { TPM_PrintFour("TPM_Process_ReleaseTransportSigned: antiReplay", antiReplay); returnCode = TPM_GetInParamDigest(inParamDigest, /* output */ &auditStatus, /* output */ &transportEncrypt, /* output */ tpm_state, tag, ordinal, inParamStart, inParamEnd, transportInternal); } /* check state */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckState(tpm_state, tag, TPM_CHECK_ALL); } /* check tag */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CheckRequestTag21(tag); } /* get the optional 'below the line' authorization parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { returnCode = TPM_AuthParams_Get(&authHandle, &authHandleValid, authNonceOdd, &continueAuthSession, keyAuth, &command, ¶mSize); printf("TPM_Process_ReleaseTransportSigned: authHandle %08x\n", authHandle); } /* get the 'below the line' authorization parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_AuthParams_Get(&transHandle, &transHandleValid, transNonceOdd, &continueTransSession, transAuth, &command, ¶mSize); } if (returnCode == TPM_SUCCESS) { printf("TPM_Process_ReleaseTransportSigned: transHandle %08x\n", transHandle); } if (returnCode == TPM_SUCCESS) { if (paramSize != 0) { printf("TPM_Process_ReleaseTransportSigned: Error, command has %u extra bytes\n", paramSize); returnCode = TPM_BAD_PARAM_SIZE; } } /* do not terminate sessions if the command did not parse correctly */ if (returnCode != TPM_SUCCESS) { transHandleValid = FALSE; } /* Processing */ /* if there is an active exclusive transport session and it's not this session, terminate it */ if (returnCode == TPM_SUCCESS) { if ((tpm_state->tpm_stany_flags.transportExclusive != 0) && (tpm_state->tpm_stany_flags.transportExclusive != transHandle)) { returnCode = TPM_TransportSessions_TerminateHandle(tpm_state->tpm_stclear_data.transSessions, tpm_state->tpm_stany_flags.transportExclusive, &(tpm_state->tpm_stany_flags.transportExclusive)); } } /* 1. Using transHandle locate the TPM_TRANSPORT_INTERNAL structure T1 */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_TransportSessions_GetEntry(&t1TpmTransportInternal, tpm_state->tpm_stclear_data.transSessions, transHandle); } /* get the key corresponding to the keyHandle parameter */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_KeyHandleEntries_GetKey(&sigKey, &parentPCRStatus, tpm_state, keyHandle, FALSE, /* not r/o, used to sign */ FALSE, /* do not ignore PCRs */ FALSE); /* cannot use EK */ } /* 2. Validate that keyHandle -> sigScheme is TPM_SS_RSASSAPKCS1v15_SHA1 or TPM_SS_RSASSAPKCS1v15_INFO, if not return TPM_INAPPROPRIATE_SIG. */ if (returnCode == TPM_SUCCESS) { if ((sigKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1) && (sigKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_INFO)) { printf("TPM_Process_ReleaseTransportSigned: Error, invalid sigKey sigScheme %04hx\n", sigKey->algorithmParms.sigScheme); returnCode = TPM_INAPPROPRIATE_SIG; } } if ((returnCode == TPM_SUCCESS) && (tag != TPM_TAG_RQU_AUTH2_COMMAND)) { if (sigKey->authDataUsage != TPM_AUTH_NEVER) { printf("TPM_Process_ReleaseTransportSigned: Error, authorization required\n"); returnCode = TPM_AUTHFAIL; } } /* get keyHandle -> usageAuth */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { returnCode = TPM_Key_GetUsageAuth(&keyUsageAuth, sigKey); } /* get the session data */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { returnCode = TPM_AuthSessions_GetData(&auth_session_data, &hmacKey, tpm_state, authHandle, TPM_PID_NONE, TPM_ET_KEYHANDLE, ordinal, sigKey, keyUsageAuth, /* OIAP */ sigKey->tpm_store_asymkey->pubDataDigest); /* OSAP */ } /* 3. Validate that keyHandle -> keyUsage is TPM_KEY_SIGNING, if not return TPM_INVALID_KEYUSAGE */ if (returnCode == TPM_SUCCESS) { if (sigKey ->keyUsage != TPM_KEY_SIGNING) { printf("TPM_Process_ReleaseTransportSigned: Error, keyUsage %04hx is invalid\n", sigKey ->keyUsage); returnCode = TPM_INVALID_KEYUSAGE; } } /* 4. Using key -> authData validate the command and parameters, on error return TPM_AUTHFAIL */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { returnCode = TPM_Authdata_Check(tpm_state, *hmacKey, /* HMAC key */ inParamDigest, auth_session_data, /* authorization session */ authNonceOdd, /* Nonce generated by system associated with authHandle */ continueAuthSession, keyAuth); /* Authorization digest for input */ } /* 5. Using transHandle -> authData validate the command and parameters, on error return TPM_AUTH2FAIL */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_TransportInternal_Check(inParamDigest, t1TpmTransportInternal, /* transport session */ transNonceOdd, /* Nonce generated by system associated with authHandle */ continueTransSession, transAuth); /* Authorization digest for input */ } /* 7. Else */ if (returnCode == TPM_SUCCESS) { if (!(t1TpmTransportInternal->transPublic.transAttributes & TPM_TRANSPORT_LOG)) { /* a. Return TPM_BAD_MODE */ printf("TPM_Process_ReleaseTransportSigned: Error, TPM_TRANSPORT_LOG not set\n"); returnCode = TPM_BAD_MODE; } } /* 6. If T1 -> transAttributes has TPM_TRANSPORT_LOG set then update the current ticks structure */ if (returnCode == TPM_SUCCESS) { currentTicks = &(tpm_state->tpm_stany_data.currentTicks); /* update the ticks based on the current time */ returnCode = TPM_CurrentTicks_Update(currentTicks); } if (returnCode == TPM_SUCCESS) { /* a. Create A1 a TPM_TRANSPORT_LOG_OUT structure */ /* NOTE Done by TPM_TransportLogOut_Init() */ /* b. Set A1 -> parameters to the SHA-1 (ordinal || antiReplay) */ TPM_Digest_Copy(a1TransportLogOut.parameters, inParamDigest); /* c. Set A1 -> currentTicks to TPM_STANY_DATA -> currentTicks */ TPM_CurrentTicks_Copy(&(a1TransportLogOut.currentTicks), currentTicks); /* d. Set A1 -> locality to the locality modifier for this command */ a1TransportLogOut.locality = tpm_state->tpm_stany_flags.localityModifier; /* e. Set T1 -> transDigest to SHA-1 (T1 -> transDigest || A1) */ printf("TPM_Process_ReleaseTransportSigned: Extend transDigest with output\n"); returnCode = TPM_TransportLogOut_Extend(t1TpmTransportInternal->transDigest, &a1TransportLogOut); } if (returnCode == TPM_SUCCESS) { /* 8. Create H1 a TPM_SIGN_INFO structure and set the structure defaults */ /* NOTE: Done by TPM_SignInfo_Init() */ /* a. Set H1 -> fixed to "TRAN" */ memcpy(h1SignInfo.fixed, "TRAN", TPM_SIGN_INFO_FIXED_SIZE); /* b. Set H1 -> replay to antiReplay */ TPM_Nonce_Copy(h1SignInfo.replay, antiReplay); /* c. Set H1 -> data to T1 -> transDigest */ returnCode = TPM_SizedBuffer_Set(&(h1SignInfo.data), TPM_DIGEST_SIZE, t1TpmTransportInternal->transDigest); } /* d. Sign SHA-1 hash of H1 using the key pointed to by keyHandle */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_SHA1_GenerateStructure(h1Digest, &h1SignInfo, (TPM_STORE_FUNCTION_T)TPM_SignInfo_Store); TPM_PrintAll("TPM_Process_ReleaseTransportSigned: h1Digest", h1Digest, TPM_DIGEST_SIZE); } if (returnCode == TPM_SUCCESS) { returnCode = TPM_RSASignToSizedBuffer(&signature, /* signature */ h1Digest, /* message */ TPM_DIGEST_SIZE, /* message size */ sigKey); /* input, signing key */ } /* 9. Invalidate all session data related to T1 */ /* NOTE Done after response */ /* 10. Set continueTransSession to FALSE */ if (returnCode == TPM_SUCCESS) { continueTransSession = FALSE; } /* 11. Return TPM_SUCCESS */ /* response */ /* standard response: tag, (dummy) paramSize, returnCode. Failure is fatal. */ if (rcf == 0) { printf("TPM_Process_ReleaseTransportSigned: Ordinal returnCode %08x %u\n", returnCode, returnCode); rcf = TPM_Sbuffer_StoreInitialResponse(response, tag, returnCode); } /* success response, append the rest of the parameters. */ if (rcf == 0) { if (returnCode == TPM_SUCCESS) { /* checkpoint the beginning of the outParam's */ outParamStart = response->buffer_current - response->buffer; /* return locality */ returnCode = TPM_Sbuffer_Append32(response, tpm_state->tpm_stany_flags.localityModifier); } /* return currentTicks */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_CurrentTicks_Store(response, currentTicks); } if (returnCode == TPM_SUCCESS) { /* return signature */ returnCode = TPM_SizedBuffer_Store(response, &signature); /* checkpoint the end of the outParam's */ outParamEnd = response->buffer_current - response->buffer; } /* digest the above the line output parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_GetOutParamDigest(outParamDigest, /* output */ auditStatus, /* input audit status */ transportEncrypt, tag, returnCode, ordinal, /* command ordinal */ response->buffer + outParamStart, /* start */ outParamEnd - outParamStart); /* length */ } /* calculate and set the optional below the line parameters */ if ((returnCode == TPM_SUCCESS) && (tag == TPM_TAG_RQU_AUTH2_COMMAND)) { returnCode = TPM_AuthParams_Set(response, *hmacKey, /* owner HMAC key */ auth_session_data, outParamDigest, authNonceOdd, continueAuthSession); } /* calculate and set the below the line parameters */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_TransportInternal_Set(response, t1TpmTransportInternal, outParamDigest, transNonceOdd, continueTransSession, TRUE); /* generate transNonceEven */ } /* audit if required */ if ((returnCode == TPM_SUCCESS) && auditStatus) { returnCode = TPM_ProcessAudit(tpm_state, transportEncrypt, inParamDigest, outParamDigest, ordinal); } /* adjust the initial response */ rcf = TPM_Sbuffer_StoreFinalResponse(response, returnCode, tpm_state); } /* if there was an error, or continueTransSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueTransSession) && transHandleValid) { TPM_TransportSessions_TerminateHandle(tpm_state->tpm_stclear_data.transSessions, transHandle, &(tpm_state->tpm_stany_flags.transportExclusive)); } /* if there was an error, or continueAuthSession is FALSE, terminate the session */ if (((rcf != 0) || ((returnCode != TPM_SUCCESS) && (returnCode != TPM_DEFEND_LOCK_RUNNING)) || !continueAuthSession) && authHandleValid) { TPM_AuthSessions_TerminateHandle(tpm_state->tpm_stclear_data.authSessions, authHandle); } /* cleanup */ TPM_SizedBuffer_Delete(&signature); /* @1 */ TPM_TransportLogOut_Delete(&a1TransportLogOut); /* @2 */ TPM_SignInfo_Delete(&h1SignInfo); /* @3 */ return rcf; } libtpms-0.9.3/src/tpm12/tpm_transport.h000066400000000000000000000264011421143571500200220ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Transport */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_transport.h 4526 2011-03-24 21:14:42Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_TRANSPORT_H #define TPM_TRANSPORT_H #include "tpm_global.h" /* Transport Encryption for wrapped commands and responses */ TPM_RESULT TPM_Transport_CryptMgf1(unsigned char *dest, const unsigned char *src, const unsigned char *pad, uint32_t size, uint32_t index, uint32_t len); TPM_RESULT TPM_Transport_CryptSymmetric(unsigned char *dest, const unsigned char *src, TPM_ALGORITHM_ID algId, TPM_ENC_SCHEME encScheme, const unsigned char *symmetric_key, uint32_t symmetric_key_size, unsigned char *pad_in, uint32_t pad_in_size, uint32_t size, uint32_t index, uint32_t len); /* Transport Sessions (the entire array) */ void TPM_TransportSessions_Init(TPM_TRANSPORT_INTERNAL *transSessions); TPM_RESULT TPM_TransportSessions_Load(TPM_TRANSPORT_INTERNAL *transSessions, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_TransportSessions_Store(TPM_STORE_BUFFER *sbuffer, TPM_TRANSPORT_INTERNAL *transSessions); void TPM_TransportSessions_Delete(TPM_TRANSPORT_INTERNAL *transSessions); void TPM_TransportSessions_IsSpace(TPM_BOOL *isSpace, uint32_t *index, TPM_TRANSPORT_INTERNAL *transSessions); void TPM_TransportSessions_GetSpace(uint32_t *space, TPM_TRANSPORT_INTERNAL *transSessions); TPM_RESULT TPM_TransportSessions_StoreHandles(TPM_STORE_BUFFER *sbuffer, TPM_TRANSPORT_INTERNAL *transSessions); TPM_RESULT TPM_TransportSessions_GetNewHandle(TPM_TRANSPORT_INTERNAL **tpm_transport_internal, TPM_TRANSPORT_INTERNAL *transportSessions); TPM_RESULT TPM_TransportSessions_GetEntry(TPM_TRANSPORT_INTERNAL **tpm_transport_internal , TPM_TRANSPORT_INTERNAL *transportSessions, TPM_TRANSHANDLE transportHandle); TPM_RESULT TPM_TransportSessions_AddEntry(TPM_HANDLE *tpm_handle, TPM_BOOL keepHandle, TPM_TRANSPORT_INTERNAL *transSessions, TPM_TRANSPORT_INTERNAL *tpm_transport_internal); TPM_RESULT TPM_TransportSessions_TerminateHandle(TPM_TRANSPORT_INTERNAL *tpm_transport_internal, TPM_TRANSHANDLE transportHandle, TPM_TRANSHANDLE *transportExclusive); /* TPM_TRANSPORT_PUBLIC */ void TPM_TransportPublic_Init(TPM_TRANSPORT_PUBLIC *tpm_transport_public); TPM_RESULT TPM_TransportPublic_Load(TPM_TRANSPORT_PUBLIC *tpm_transport_public, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_TransportPublic_Store(TPM_STORE_BUFFER *sbuffer, const TPM_TRANSPORT_PUBLIC *tpm_transport_public); void TPM_TransportPublic_Delete(TPM_TRANSPORT_PUBLIC *tpm_transport_public); TPM_RESULT TPM_TransportPublic_Copy(TPM_TRANSPORT_PUBLIC *dest, const TPM_TRANSPORT_PUBLIC *src); void TPM_TransportPublic_CheckAlgId(TPM_BOOL *supported, TPM_ALGORITHM_ID algId); TPM_RESULT TPM_TransportPublic_CheckEncScheme(uint32_t *blockSize, TPM_ALGORITHM_ID algId, TPM_ENC_SCHEME encScheme, TPM_BOOL FIPS); /* TPM_TRANSPORT_INTERNAL */ void TPM_TransportInternal_Init(TPM_TRANSPORT_INTERNAL *tpm_transport_internal); TPM_RESULT TPM_TransportInternal_Load(TPM_TRANSPORT_INTERNAL *tpm_transport_internal, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_TransportInternal_Store(TPM_STORE_BUFFER *sbuffer, const TPM_TRANSPORT_INTERNAL *tpm_transport_internal); void TPM_TransportInternal_Delete(TPM_TRANSPORT_INTERNAL *tpm_transport_internal); void TPM_TransportInternal_Copy(TPM_TRANSPORT_INTERNAL *dest_transport_internal, TPM_TRANSPORT_INTERNAL *src_transport_internal); TPM_RESULT TPM_TransportInternal_Check(TPM_DIGEST inParamDigest, TPM_TRANSPORT_INTERNAL *tpm_transport_internal, TPM_NONCE transNonceOdd, TPM_BOOL continueTransSession, TPM_AUTHDATA transAuth); TPM_RESULT TPM_TransportInternal_Set(TPM_STORE_BUFFER *response, TPM_TRANSPORT_INTERNAL *tpm_transport_internal, TPM_DIGEST outParamDigest, TPM_NONCE transNonceOdd, TPM_BOOL continueTransSession, TPM_BOOL generateNonceEven); /* TPM_TRANSPORT_LOG_IN */ void TPM_TransportLogIn_Init(TPM_TRANSPORT_LOG_IN *tpm_transport_log_in); TPM_RESULT TPM_TransportLogIn_Store(TPM_STORE_BUFFER *sbuffer, const TPM_TRANSPORT_LOG_IN *tpm_transport_log_in); void TPM_TransportLogIn_Delete(TPM_TRANSPORT_LOG_IN *tpm_transport_log_in); TPM_RESULT TPM_TransportLogIn_Extend(TPM_DIGEST tpm_digest, TPM_TRANSPORT_LOG_IN *tpm_transport_log_in); /* TPM_TRANSPORT_LOG_OUT */ void TPM_TransportLogOut_Init(TPM_TRANSPORT_LOG_OUT *tpm_transport_log_out); TPM_RESULT TPM_TransportLogOut_Store(TPM_STORE_BUFFER *sbuffer, const TPM_TRANSPORT_LOG_OUT *tpm_transport_log_out); void TPM_TransportLogOut_Delete(TPM_TRANSPORT_LOG_OUT *tpm_transport_log_out); TPM_RESULT TPM_TransportLogOut_Extend(TPM_DIGEST tpm_digest, TPM_TRANSPORT_LOG_OUT *tpm_transport_log_out); /* TPM_TRANSPORT_AUTH */ void TPM_TransportAuth_Init(TPM_TRANSPORT_AUTH *tpm_transport_auth); TPM_RESULT TPM_TransportAuth_Load(TPM_TRANSPORT_AUTH *tpm_transport_auth, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_TransportAuth_Store(TPM_STORE_BUFFER *sbuffer, const TPM_TRANSPORT_AUTH *tpm_transport_auth); void TPM_TransportAuth_Delete(TPM_TRANSPORT_AUTH *tpm_transport_auth); TPM_RESULT TPM_TransportAuth_DecryptSecret(TPM_TRANSPORT_AUTH *tpm_transport_auth, TPM_SIZED_BUFFER *secret, TPM_KEY *tpm_key); /* Command Processing Functions */ TPM_RESULT TPM_Process_EstablishTransport(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_ExecuteTransport(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); TPM_RESULT TPM_Process_ReleaseTransportSigned(tpm_state_t *tpm_state, TPM_STORE_BUFFER *response, TPM_TAG tag, uint32_t paramSize, TPM_COMMAND_CODE ordinal, unsigned char *command, TPM_TRANSPORT_INTERNAL *transportInternal); #endif libtpms-0.9.3/src/tpm12/tpm_ver.c000066400000000000000000000230551421143571500165570ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Ver Structure Handler */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_ver.c 4071 2010-04-29 19:26:45Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include #include "tpm_debug.h" #include "tpm_error.h" #include "tpm_structures.h" #include "tpm_ver.h" /* TPM_STRUCT_VER This indicates the version of the structure. Version 1.2 deprecates the use of this structure in all other structures. The structure is not deprecated as many of the structures that contain this structure are not deprecated. The rationale behind keeping this structure and adding the new version structure is that in version 1.1 this structure was in use for two purposes. The first was to indicate the structure version, and in that mode the revMajor and revMinor were supposed to be set to 0. The second use was in TPM_GetCapability and the structure would then return the correct revMajor and revMinor. This use model caused problems in keeping track of when the revs were or were not set and how software used the information. Version 1.2 went to structure tags. Some structures did not change and the TPM_STRUCT_VER is still in use. To avoid the problems from 1.1 this structure now is a fixed value and only remains for backwards compatibility. Structure versioning comes from the tag on the structure and the TPM_GetCapability response for TPM versioning uses TPM_VERSION. */ /* TPM_StructVer_Init() sets members to default values sets all pointers to NULL and sizes to 0 always succeeds - no return code */ void TPM_StructVer_Init(TPM_STRUCT_VER *tpm_struct_ver) { printf(" TPM_StructVer_Init:\n"); tpm_struct_ver->major = 0x01; tpm_struct_ver->minor = 0x01; tpm_struct_ver->revMajor = 0x00; tpm_struct_ver->revMinor = 0x00; return; } /* TPM_StructVer_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes */ TPM_RESULT TPM_StructVer_Load(TPM_STRUCT_VER *tpm_struct_ver, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_StructVer_Load:\n"); if (rc == 0) { rc = TPM_Load8(&(tpm_struct_ver->major), stream, stream_size); } if (rc == 0) { rc = TPM_Load8(&(tpm_struct_ver->minor), stream, stream_size); } if (rc == 0) { rc = TPM_Load8(&(tpm_struct_ver->revMajor), stream, stream_size); } if (rc == 0) { rc = TPM_Load8(&(tpm_struct_ver->revMinor), stream, stream_size); } return rc; } /* TPM_StructVer_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_StructVer_Store(TPM_STORE_BUFFER *sbuffer, const TPM_STRUCT_VER *tpm_struct_ver) { TPM_RESULT rc = 0; printf(" TPM_StructVer_Store:\n"); if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_struct_ver->major), sizeof(BYTE)); } if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_struct_ver->minor), sizeof(BYTE)); } if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_struct_ver->revMajor), sizeof(BYTE)); } if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_struct_ver->revMinor), sizeof(BYTE)); } return rc; } /* TPM_StructVer_Copy() copies the src to the destination. */ void TPM_StructVer_Copy(TPM_STRUCT_VER *tpm_struct_ver_dest, TPM_STRUCT_VER *tpm_struct_ver_src) { printf(" TPM_StructVer_Copy:\n"); tpm_struct_ver_dest->major = tpm_struct_ver_src->major; tpm_struct_ver_dest->minor = tpm_struct_ver_src->minor; tpm_struct_ver_dest->revMajor = tpm_struct_ver_src->revMajor; tpm_struct_ver_dest->revMinor = tpm_struct_ver_src->revMinor; return; } /* TPM_StructVer_CheckVer() checks that the major and minor version are 0x01, 0x01 */ TPM_RESULT TPM_StructVer_CheckVer(TPM_STRUCT_VER *tpm_struct_ver) { TPM_RESULT rc = 0; printf(" TPM_StructVer_CheckVer: version %u.%u.%u.%u\n", tpm_struct_ver->major, tpm_struct_ver->minor, tpm_struct_ver->revMajor, tpm_struct_ver->revMinor); if ((tpm_struct_ver->major != 0x01) || (tpm_struct_ver->minor != 0x01)) { printf("TPM_StructVer_CheckVer: Error checking version\n"); rc = TPM_BAD_VERSION; } return rc; } /* TPM_VERSION This structure provides information relative the version of the TPM. This structure should only be in use by TPM_GetCapability to provide the information relative to the TPM. */ void TPM_Version_Init(TPM_VERSION *tpm_version) { printf(" TPM_Version_Init:\n"); tpm_version->major = 0; tpm_version->minor = 0; tpm_version->revMajor = 0; tpm_version->revMinor = 0; return; } void TPM_Version_Set(TPM_VERSION *tpm_version, TPM_PERMANENT_DATA *tpm_permanent_data) { printf(" TPM_Version_Set:\n"); /* This SHALL indicate the major version of the TPM, mostSigVer MUST be 0x01, leastSigVer MUST be 0x00 */ tpm_version->major = TPM_MAJOR; /* This SHALL indicate the minor version of the TPM, mostSigVer MUST be 0x01 or 0x02, leastSigVer MUST be 0x00 */ tpm_version->minor = TPM_MINOR; /* This SHALL be the value of the TPM_PERMANENT_DATA -> revMajor */ tpm_version->revMajor = tpm_permanent_data->revMajor; /* This SHALL be the value of the TPM_PERMANENT_DATA -> revMinor */ tpm_version->revMinor = tpm_permanent_data->revMinor; return; } #if 0 /* TPM_Version_Load() deserialize the structure from a 'stream' 'stream_size' is checked for sufficient data returns 0 or error codes Before use, call TPM_Version_Init() */ TPM_RESULT TPM_Version_Load(TPM_VERSION *tpm_version, unsigned char **stream, uint32_t *stream_size) { TPM_RESULT rc = 0; printf(" TPM_Version_Load:\n"); /* load major */ if (rc == 0) { rc = TPM_Load8(&(tpm_version->major), stream, stream_size); } /* load minor */ if (rc == 0) { rc = TPM_Load8(&(tpm_version->minor), stream, stream_size); } /* load revMajor */ if (rc == 0) { rc = TPM_Load8(&(tpm_version->revMajor), stream, stream_size); } /* load revMinor */ if (rc == 0) { rc = TPM_Load8(&(tpm_version->revMinor), stream, stream_size); } return rc; } #endif /* TPM_Version_Store() serialize the structure to a stream contained in 'sbuffer' returns 0 or error codes */ TPM_RESULT TPM_Version_Store(TPM_STORE_BUFFER *sbuffer, const TPM_VERSION *tpm_version) { TPM_RESULT rc = 0; printf(" TPM_Version_Store:\n"); /* store major */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_version->major), sizeof(BYTE)); } /* store minor */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_version->minor), sizeof(BYTE)); } /* store revMajor */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_version->revMajor), sizeof(BYTE)); } /* store revMinor */ if (rc == 0) { rc = TPM_Sbuffer_Append(sbuffer, &(tpm_version->revMinor), sizeof(BYTE)); } return rc; } libtpms-0.9.3/src/tpm12/tpm_ver.h000066400000000000000000000071241421143571500165630ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Ver Structure Handler */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_ver.h 4071 2010-04-29 19:26:45Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_VER_H #define TPM_VER_H #include "tpm_types.h" #include "tpm_store.h" #include "tpm_structures.h" /* TPM_STRUCT_VER */ void TPM_StructVer_Init(TPM_STRUCT_VER *tpm_struct_ver); TPM_RESULT TPM_StructVer_Load(TPM_STRUCT_VER *tpm_struct_ver, unsigned char **stream, uint32_t *stream_size); TPM_RESULT TPM_StructVer_Store(TPM_STORE_BUFFER *sbuffer, const TPM_STRUCT_VER *tpm_struct_ver); void TPM_StructVer_Copy(TPM_STRUCT_VER *tpm_struct_ver_dest, TPM_STRUCT_VER *tpm_struct_ver_src); TPM_RESULT TPM_StructVer_CheckVer(TPM_STRUCT_VER *tpm_struct_ver); /* TPM_VERSION */ void TPM_Version_Init(TPM_VERSION *tpm_version); void TPM_Version_Set(TPM_VERSION *tpm_version, TPM_PERMANENT_DATA *tpm_permanent_data); #if 0 TPM_RESULT TPM_Version_Load(TPM_VERSION *tpm_version, unsigned char **stream, uint32_t *stream_size); #endif TPM_RESULT TPM_Version_Store(TPM_STORE_BUFFER *sbuffer, const TPM_VERSION *tpm_version); void TPM_Version_Delete(TPM_VERSION *tpm_version); #endif libtpms-0.9.3/src/tpm2/000077500000000000000000000000001421143571500146515ustar00rootroot00000000000000libtpms-0.9.3/src/tpm2/ACT.h000066400000000000000000000205241421143571500154340ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Authenticated Countdown Timer */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id$ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2019 */ /* */ /********************************************************************************/ // 5.24 ACT.h #ifndef _ACT_H_ #define _ACT_H_ #include "TpmProfile.h" #if !(defined RH_ACT_0) || (RH_ACT_0 != YES) # undef RH_ACT_0 # define RH_ACT_0 NO # define IF_ACT_0_IMPLEMENTED(op) #else # define IF_ACT_0_IMPLEMENTED(op) op(0) #endif #if !(defined RH_ACT_1) || (RH_ACT_1 != YES) # undef RH_ACT_1 # define RH_ACT_1 NO # define IF_ACT_1_IMPLEMENTED(op) #else # define IF_ACT_1_IMPLEMENTED(op) op(1) #endif #if !(defined RH_ACT_2) || (RH_ACT_2 != YES) # undef RH_ACT_2 # define RH_ACT_2 NO # define IF_ACT_2_IMPLEMENTED(op) #else # define IF_ACT_2_IMPLEMENTED(op) op(2) #endif #if !(defined RH_ACT_3) || (RH_ACT_3 != YES) # undef RH_ACT_3 # define RH_ACT_3 NO # define IF_ACT_3_IMPLEMENTED(op) #else # define IF_ACT_3_IMPLEMENTED(op) op(3) #endif #if !(defined RH_ACT_4) || (RH_ACT_4 != YES) # undef RH_ACT_4 # define RH_ACT_4 NO # define IF_ACT_4_IMPLEMENTED(op) #else # define IF_ACT_4_IMPLEMENTED(op) op(4) #endif #if !(defined RH_ACT_5) || (RH_ACT_5 != YES) # undef RH_ACT_5 # define RH_ACT_5 NO # define IF_ACT_5_IMPLEMENTED(op) #else # define IF_ACT_5_IMPLEMENTED(op) op(5) #endif #if !(defined RH_ACT_6) || (RH_ACT_6 != YES) # undef RH_ACT_6 # define RH_ACT_6 NO # define IF_ACT_6_IMPLEMENTED(op) #else # define IF_ACT_6_IMPLEMENTED(op) op(6) #endif #if !(defined RH_ACT_7) || (RH_ACT_7 != YES) # undef RH_ACT_7 # define RH_ACT_7 NO # define IF_ACT_7_IMPLEMENTED(op) #else # define IF_ACT_7_IMPLEMENTED(op) op(7) #endif #if !(defined RH_ACT_8) || (RH_ACT_8 != YES) # undef RH_ACT_8 # define RH_ACT_8 NO # define IF_ACT_8_IMPLEMENTED(op) #else # define IF_ACT_8_IMPLEMENTED(op) op(8) #endif #if !(defined RH_ACT_9) || (RH_ACT_9 != YES) # undef RH_ACT_9 # define RH_ACT_9 NO # define IF_ACT_9_IMPLEMENTED(op) #else # define IF_ACT_9_IMPLEMENTED(op) op(9) #endif #if !(defined RH_ACT_A) || (RH_ACT_A != YES) # undef RH_ACT_A # define RH_ACT_A NO # define IF_ACT_A_IMPLEMENTED(op) #else # define IF_ACT_A_IMPLEMENTED(op) op(A) #endif #if !(defined RH_ACT_B) || (RH_ACT_B != YES) # undef RH_ACT_B # define RH_ACT_B NO # define IF_ACT_B_IMPLEMENTED(op) #else # define IF_ACT_B_IMPLEMENTED(op) op(B) #endif #if !(defined RH_ACT_C) || (RH_ACT_C != YES) # undef RH_ACT_C # define RH_ACT_C NO # define IF_ACT_C_IMPLEMENTED(op) #else # define IF_ACT_C_IMPLEMENTED(op) op(C) #endif #if !(defined RH_ACT_D) || (RH_ACT_D != YES) # undef RH_ACT_D # define RH_ACT_D NO # define IF_ACT_D_IMPLEMENTED(op) #else # define IF_ACT_D_IMPLEMENTED(op) op(D) #endif #if !(defined RH_ACT_E) || (RH_ACT_E != YES) # undef RH_ACT_E # define RH_ACT_E NO # define IF_ACT_E_IMPLEMENTED(op) #else # define IF_ACT_E_IMPLEMENTED(op) op(E) #endif #if !(defined RH_ACT_F) || (RH_ACT_F != YES) # undef RH_ACT_F # define RH_ACT_F NO # define IF_ACT_F_IMPLEMENTED(op) #else # define IF_ACT_F_IMPLEMENTED(op) op(F) #endif #ifndef TPM_RH_ACT_0 #error Need numeric definition for TPM_RH_ACT_0 #endif #ifndef TPM_RH_ACT_1 # define TPM_RH_ACT_1 (TPM_RH_ACT_0 + 1) #endif #ifndef TPM_RH_ACT_2 # define TPM_RH_ACT_2 (TPM_RH_ACT_0 + 2) #endif #ifndef TPM_RH_ACT_3 # define TPM_RH_ACT_3 (TPM_RH_ACT_0 + 3) #endif #ifndef TPM_RH_ACT_4 # define TPM_RH_ACT_4 (TPM_RH_ACT_0 + 4) #endif #ifndef TPM_RH_ACT_5 # define TPM_RH_ACT_5 (TPM_RH_ACT_0 + 5) #endif #ifndef TPM_RH_ACT_6 # define TPM_RH_ACT_6 (TPM_RH_ACT_0 + 6) #endif #ifndef TPM_RH_ACT_7 # define TPM_RH_ACT_7 (TPM_RH_ACT_0 + 7) #endif #ifndef TPM_RH_ACT_8 # define TPM_RH_ACT_8 (TPM_RH_ACT_0 + 8) #endif #ifndef TPM_RH_ACT_9 # define TPM_RH_ACT_9 (TPM_RH_ACT_0 + 9) #endif #ifndef TPM_RH_ACT_A # define TPM_RH_ACT_A (TPM_RH_ACT_0 + 0xA) #endif #ifndef TPM_RH_ACT_B # define TPM_RH_ACT_B (TPM_RH_ACT_0 + 0xB) #endif #ifndef TPM_RH_ACT_C # define TPM_RH_ACT_C (TPM_RH_ACT_0 + 0xC) #endif #ifndef TPM_RH_ACT_D # define TPM_RH_ACT_D (TPM_RH_ACT_0 + 0xD) #endif #ifndef TPM_RH_ACT_E # define TPM_RH_ACT_E (TPM_RH_ACT_0 + 0xE) #endif #ifndef TPM_RH_ACT_F # define TPM_RH_ACT_F (TPM_RH_ACT_0 + 0xF) #endif #define FOR_EACH_ACT(op) \ IF_ACT_0_IMPLEMENTED(op) \ IF_ACT_1_IMPLEMENTED(op) \ IF_ACT_2_IMPLEMENTED(op) \ IF_ACT_3_IMPLEMENTED(op) \ IF_ACT_4_IMPLEMENTED(op) \ IF_ACT_5_IMPLEMENTED(op) \ IF_ACT_6_IMPLEMENTED(op) \ IF_ACT_7_IMPLEMENTED(op) \ IF_ACT_8_IMPLEMENTED(op) \ IF_ACT_9_IMPLEMENTED(op) \ IF_ACT_A_IMPLEMENTED(op) \ IF_ACT_B_IMPLEMENTED(op) \ IF_ACT_C_IMPLEMENTED(op) \ IF_ACT_D_IMPLEMENTED(op) \ IF_ACT_E_IMPLEMENTED(op) \ IF_ACT_F_IMPLEMENTED(op) // This is the mask for ACT that are implemented //#define ACT_MASK(N) | (1 << 0x##N) //#define ACT_IMPLEMENTED_MASK (0 FOR_EACH_ACT(ACT_MASK)) #define CASE_ACT_HANDLE(N) case TPM_RH_ACT_##N: #define CASE_ACT_NUMBER(N) case 0x##N: typedef struct ACT_STATE { UINT32 remaining; TPM_ALG_ID hashAlg; TPM2B_DIGEST authPolicy; } ACT_STATE, *P_ACT_STATE; #endif // _ACT_H_ libtpms-0.9.3/src/tpm2/ACTCommands.c000066400000000000000000000101221421143571500171020ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Authenticated COuntdown Timer Commands */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id$ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2019 */ /* */ /********************************************************************************/ #include "Tpm.h" #include "ACT_SetTimeout_fp.h" #if CC_ACT_SetTimeout // Conditional expansion of this file /* Error Returns Meaning */ /* TPM_RC_RETRY returned when an update for the selected ACT is already pending */ /* TPM_RC_VALUE attempt to disable signaling from an ACT that has not expired */ TPM_RC TPM2_ACT_SetTimeout( ACT_SetTimeout_In *in // IN: input parameter list ) { // If 'startTimeout' is UINT32_MAX, then this is an attempt to disable the ACT // and turn off the signaling for the ACT. This is only valid if the ACT // is signaling. if((in->startTimeout == UINT32_MAX) && !ActGetSignaled(in->actHandle)) return TPM_RC_VALUE + RC_ACT_SetTimeout_startTimeout; return ActCounterUpdate(in->actHandle, in->startTimeout); } #endif // CC_ACT_SetTimeout libtpms-0.9.3/src/tpm2/ACT_SetTimeout_fp.h000066400000000000000000000073541421143571500203110ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM2_ACT_SetTimeout Header */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id$ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2019 */ /* */ /********************************************************************************/ #ifndef ACT_SETTIMEOUT_FP_H #define ACT_SETTIMEOUT_FP_H typedef struct { TPMI_RH_ACT actHandle; UINT32 startTimeout; } ACT_SetTimeout_In; #define RC_ACT_SetTimeout_actHandle (TPM_RC_H + TPM_RC_1) #define RC_ACT_SetTimeout_startTimeout (TPM_RC_H + TPM_RC_2) TPM_RC TPM2_ACT_SetTimeout( ACT_SetTimeout_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/ACT_spt.c000066400000000000000000000270631421143571500163220ustar00rootroot00000000000000/********************************************************************************/ /* */ /* ACT Command Support */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Object_spt.c 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2020 */ /* */ /********************************************************************************/ /* 7.8 ACT Support (ACT_spt.c) */ /* 7.8.1 Introduction */ /* This code implements the ACT update code. It does not use a mutex. This code uses a platform service (_plat__ACT_UpdateCounter()) that returns false if the update is not accepted. If this occurs, then TPM_RC_RETRY should be sent to the caller so that they can retry the operation later. The implementation of this is platform dependent but the reference uses a simple flag to indicate that an update is pending and the only process that can clear that flag is the process that does the actual update. */ /* 7.8.2 Includes */ #include "Tpm.h" #include "ACT_spt_fp.h" #include "Platform_fp.h" #include "PlatformACT_fp.h" /* added kgold */ /* 7.8.3 Functions */ /* 7.8.3.1 _ActResume() */ /* This function does the resume processing for an ACT. It updates the saved count and turns signaling back on if necessary. */ #ifndef __ACT_DISABLED // libtpms added static void _ActResume( UINT32 act, //IN: the act number ACT_STATE *actData //IN: pointer to the saved ACT data ) { // If the act was non-zero, then restore the counter value. if(actData->remaining > 0) _plat__ACT_UpdateCounter(act, actData->remaining); // if the counter was zero and the ACT signaling, enable the signaling. else if(go.signaledACT & (1 << act)) _plat__ACT_SetSignaled(act, TRUE); } #endif // libtpms added /* 7.8.3.2 ActStartup() */ /* This function is called by TPM2_Startup() to initialize the ACT counter values. */ BOOL ActStartup( STARTUP_TYPE type ) { // Reset all the ACT hardware _plat__ACT_Initialize(); // If this not a cold start, copy all the current 'signaled' settings to // 'preservedSignaled'. #ifndef __ACT_DISABLED // libtpms added if (g_powerWasLost) go.preservedSignaled = 0; else go.preservedSignaled |= go.signaledACT; #endif // libtpms added // For TPM_RESET or TPM_RESTART, the ACTs will all be disabled and the output // de-asserted. if(type != SU_RESUME) { #ifndef __ACT_DISABLED // libtpms added go.signaledACT = 0; #endif // libtpms added #define CLEAR_ACT_POLICY(N) \ go.ACT_##N.hashAlg = TPM_ALG_NULL; \ go.ACT_##N.authPolicy.b.size = 0; FOR_EACH_ACT(CLEAR_ACT_POLICY) } else { // Resume each of the implemented ACT #define RESUME_ACT(N) _ActResume(0x##N, &go.ACT_##N); FOR_EACH_ACT(RESUME_ACT) } // set no ACT updated since last startup. This is to enable the halving of the // timeout value s_ActUpdated = 0; _plat__ACT_EnableTicks(TRUE); return TRUE; } /* 7.8.3.3 _ActSaveState() */ /* Get the counter state and the signaled state for an ACT. If the ACT has not been updated since the last time it was saved, then divide the count by 2. */ #ifndef __ACT_DISABLED // libtpms added static void _ActSaveState( UINT32 act, P_ACT_STATE actData ) { actData->remaining = _plat__ACT_GetRemaining(act); // If the ACT hasn't been updated since the last startup, then it should be // be halved. if((s_ActUpdated & (1 << act)) == 0) { // Don't halve if the count is set to max or if halving would make it zero if((actData->remaining != UINT32_MAX) && (actData->remaining > 1)) actData->remaining /= 2; } if(_plat__ACT_GetSignaled(act)) go.signaledACT |= (1 << act); } /* 7.8.3.4 ActGetSignaled() */ /* This function returns the state of the signaled flag associated with an ACT. */ BOOL ActGetSignaled( TPM_RH actHandle ) { UINT32 act = actHandle - TPM_RH_ACT_0; // return _plat__ACT_GetSignaled(act); } #endif // libtpms added /* 7.8.3.5 ActShutdown() */ /* This function saves the current state of the counters */ BOOL ActShutdown( TPM_SU state //IN: the type of the shutdown. ) { // if this is not shutdown state, then the only type of startup is TPM_RESTART // so the timer values will be cleared. If this is shutdown state, get the current // countdown and signaled values. Plus, if the counter has not been updated // since the last restart, divide the time by 2 so that there is no attack on the // countdown by saving the countdown state early and then not using the TPM. if(state == TPM_SU_STATE) { // This will be populated as each of the ACT is queried #ifndef __ACT_DISABLED // libtpms added go.signaledACT = 0; #endif // libtpms added // Get the current count and the signaled state #define SAVE_ACT_STATE(N) _ActSaveState(0x##N, &go.ACT_##N); FOR_EACH_ACT(SAVE_ACT_STATE); } return TRUE; } /* 7.8.3.6 ActIsImplemented() */ /* This function determines if an ACT is implemented in both the TPM and the platform code. */ BOOL ActIsImplemented( UINT32 act ) { #define CASE_ACT_ // This switch accounts for the TPM implemented values. switch(act) { #ifndef __ACT_DISABLED // libtpms added FOR_EACH_ACT(CASE_ACT_NUMBER) // This ensures that the platorm implemented the values implemented by // the TPM return _plat__ACT_GetImplemented(act); #endif // libtpms added default: break; } return FALSE; } /* 7.8.3.7 ActCounterUpdate() */ /* This function updates the ACT counter. If the counter already has a pending update, it returns TPM_RC_RETRY so that the update can be tried again later. */ #if CC_ACT_SetTimeout // libtpms added TPM_RC ActCounterUpdate( TPM_RH handle, //IN: the handle of the act UINT32 newValue //IN: the value to set in the ACT ) { UINT32 act; TPM_RC result; // act = handle - TPM_RH_ACT_0; // This should never fail, but... if(!_plat__ACT_GetImplemented(act)) result = TPM_RC_VALUE; else { // Will need to clear orderly so fail if we are orderly and NV is not available if(NV_IS_ORDERLY) RETURN_IF_NV_IS_NOT_AVAILABLE; // if the attempt to update the counter fails, it means that there is an // update pending so wait until it has occurred and then do an update. if(!_plat__ACT_UpdateCounter(act, newValue)) result = TPM_RC_RETRY; else { // Indicate that the ACT has been updated since last TPM2_Startup(). s_ActUpdated |= (UINT16)(1 << act); // Clear the preservedSignaled attribute. go.preservedSignaled &= ~((UINT16)(1 << act)); // Need to clear the orderly flag g_clearOrderly = TRUE; result = TPM_RC_SUCCESS; } } return result; } #endif // libtpms added /* 7.8.3.8 ActGetCapabilityData() */ /* This function returns the list of ACT data */ /* Return Value Meaning */ /* YES if more ACT data is available */ /* NO if no more ACT data to */ TPMI_YES_NO ActGetCapabilityData( TPM_HANDLE actHandle, // IN: the handle for the starting ACT UINT32 maxCount, // IN: maximum allowed return values TPML_ACT_DATA *actList // OUT: ACT data list ) { // Initialize output property list actList->count = 0; // Make sure that the starting handle value is in range (again) if((actHandle < TPM_RH_ACT_0) || (actHandle > TPM_RH_ACT_F)) return FALSE; // The maximum count of curves we may return is MAX_ECC_CURVES if(maxCount > MAX_ACT_DATA) maxCount = MAX_ACT_DATA; // Scan the ACT data from the starting ACT for(; actHandle <= TPM_RH_ACT_F; actHandle++) { UINT32 act = actHandle - TPM_RH_ACT_0; if(actList->count < maxCount) { if(ActIsImplemented(act)) { TPMS_ACT_DATA *actData = &actList->actData[actList->count]; // memset(&actData->attributes, 0, sizeof(actData->attributes)); actData->handle = actHandle; actData->timeout = _plat__ACT_GetRemaining(act); if (_plat__ACT_GetSignaled(act)) SET_ATTRIBUTE(actData->attributes, TPMA_ACT, signaled); else CLEAR_ATTRIBUTE(actData->attributes, TPMA_ACT, signaled); actList->count++; } } else { if(_plat__ACT_GetImplemented(act)) return YES; } } // If we get here, either all of the ACT values were put in the list, or the list // was filled and there are no more ACT values to return return NO; } libtpms-0.9.3/src/tpm2/ACT_spt_fp.h000066400000000000000000000077751421143571500170240ustar00rootroot00000000000000/********************************************************************************/ /* */ /* ACT Command Support */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id$ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2019 */ /* */ /********************************************************************************/ #ifndef ACT_SPT_FP_H #define ACT_SPT_FP_H BOOL ActStartup( STARTUP_TYPE type ); BOOL ActGetSignaled( TPM_RH actHandle ); BOOL ActShutdown( TPM_SU state //IN: the type of the shutdown. ); BOOL ActIsImplemented( UINT32 act ); TPM_RC ActCounterUpdate( TPM_RH handle, //IN: the handle of the act UINT32 newValue //IN: the value to set in the ACT ); TPMI_YES_NO ActGetCapabilityData( TPM_HANDLE actHandle, // IN: the handle for the starting ACT UINT32 maxCount, // IN: maximum allowed return values TPML_ACT_DATA *actList // OUT: ACT data list ); #endif libtpms-0.9.3/src/tpm2/ActivateCredential_fp.h000066400000000000000000000101161421143571500212410ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: ActivateCredential_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef ACTIVATECREDENTIAL_FP_H #define ACTIVATECREDENTIAL_FP_H typedef struct { TPMI_DH_OBJECT activateHandle; TPMI_DH_OBJECT keyHandle; TPM2B_ID_OBJECT credentialBlob; TPM2B_ENCRYPTED_SECRET secret; } ActivateCredential_In; #define RC_ActivateCredential_activateHandle (TPM_RC_H + TPM_RC_1) #define RC_ActivateCredential_keyHandle (TPM_RC_H + TPM_RC_2) #define RC_ActivateCredential_credentialBlob (TPM_RC_P + TPM_RC_1) #define RC_ActivateCredential_secret (TPM_RC_P + TPM_RC_2) typedef struct { TPM2B_DIGEST certInfo; } ActivateCredential_Out; TPM_RC TPM2_ActivateCredential( ActivateCredential_In *in, // IN: input parameter list ActivateCredential_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/AlgorithmCap.c000066400000000000000000000232341421143571500173730ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Algorithm Property Definitions */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: AlgorithmCap.c 1594 2020-03-26 22:15:48Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2020 */ /* */ /********************************************************************************/ /* 9.1 AlgorithmCap.c */ /* 9.1.1 Description */ /* This file contains the algorithm property definitions for the algorithms and the code for the TPM2_GetCapability() to return the algorithm properties. */ /* 9.1.2 Includes and Defines */ #include "Tpm.h" typedef struct { TPM_ALG_ID algID; TPMA_ALGORITHM attributes; } ALGORITHM; static const ALGORITHM s_algorithms[] = { // The entries in this table need to be in ascending order but the table doesn't // need to be full (gaps are allowed). One day, a tool might exist to fill in the // table from the TPM_ALG description #if ALG_RSA {TPM_ALG_RSA, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 1, 0, 0, 0, 0, 0)}, #endif #if ALG_TDES {TPM_ALG_TDES, TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 0, 0, 0)}, #endif #if ALG_SHA1 {TPM_ALG_SHA1, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 0, 0)}, #endif {TPM_ALG_HMAC, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 1, 0, 0, 0)}, #if ALG_AES {TPM_ALG_AES, TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 0, 0, 0)}, #endif #if ALG_MGF1 {TPM_ALG_MGF1, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 1, 0)}, #endif {TPM_ALG_KEYEDHASH, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 1, 0, 1, 1, 0, 0)}, #if ALG_XOR {TPM_ALG_XOR, TPMA_ALGORITHM_INITIALIZER(0, 1, 1, 0, 0, 0, 0, 0, 0)}, #endif #if ALG_SHA256 {TPM_ALG_SHA256, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 0, 0)}, #endif #if ALG_SHA384 {TPM_ALG_SHA384, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 0, 0)}, #endif #if ALG_SHA512 {TPM_ALG_SHA512, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 0, 0)}, #endif #if ALG_SM3_256 {TPM_ALG_SM3_256, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 0, 0)}, #endif #if ALG_SM4 {TPM_ALG_SM4, TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 0, 0, 0)}, #endif #if ALG_RSASSA {TPM_ALG_RSASSA, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 1, 0, 0, 0)}, #endif #if ALG_RSAES {TPM_ALG_RSAES, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 0, 1, 0, 0)}, #endif #if ALG_RSAPSS {TPM_ALG_RSAPSS, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 1, 0, 0, 0)}, #endif #if ALG_OAEP {TPM_ALG_OAEP, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 0, 1, 0, 0)}, #endif #if ALG_ECDSA {TPM_ALG_ECDSA, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 1, 0, 0, 0)}, #endif #if ALG_ECDH {TPM_ALG_ECDH, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 0, 0, 1, 0)}, #endif #if ALG_ECDAA {TPM_ALG_ECDAA, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 1, 0, 0, 0)}, #endif #if ALG_SM2 {TPM_ALG_SM2, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 1, 0, 1, 0)}, #endif #if ALG_ECSCHNORR {TPM_ALG_ECSCHNORR, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 1, 0, 0, 0)}, #endif #if ALG_ECMQV {TPM_ALG_ECMQV, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 0, 0, 0, 0, 1, 0)}, #endif #if ALG_KDF1_SP800_56A {TPM_ALG_KDF1_SP800_56A, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 1, 0)}, #endif #if ALG_KDF2 {TPM_ALG_KDF2, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 1, 0)}, #endif #if ALG_KDF1_SP800_108 {TPM_ALG_KDF1_SP800_108, TPMA_ALGORITHM_INITIALIZER(0, 0, 1, 0, 0, 0, 0, 1, 0)}, #endif #if ALG_ECC {TPM_ALG_ECC, TPMA_ALGORITHM_INITIALIZER(1, 0, 0, 1, 0, 0, 0, 0, 0)}, #endif {TPM_ALG_SYMCIPHER, TPMA_ALGORITHM_INITIALIZER(0, 0, 0, 1, 0, 0, 0, 0, 0)}, #if ALG_CAMELLIA {TPM_ALG_CAMELLIA, TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 0, 0, 0)}, #endif #if ALG_CMAC {TPM_ALG_CMAC, TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 1, 0, 0, 0)}, #endif #if ALG_CTR {TPM_ALG_CTR, TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 1, 0, 0)}, #endif #if ALG_OFB {TPM_ALG_OFB, TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 1, 0, 0)}, #endif #if ALG_CBC {TPM_ALG_CBC, TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 1, 0, 0)}, #endif #if ALG_CFB {TPM_ALG_CFB, TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 1, 0, 0)}, #endif #if ALG_ECB {TPM_ALG_ECB, TPMA_ALGORITHM_INITIALIZER(0, 1, 0, 0, 0, 0, 1, 0, 0)}, #endif }; /* 9.1.3 AlgorithmCapGetImplemented() */ /* This function is used by TPM2_GetCapability() to return a list of the implemented algorithms. */ /* Return Values Meaning */ /* YES more algorithms to report */ /* NO no more algorithms to report */ TPMI_YES_NO AlgorithmCapGetImplemented( TPM_ALG_ID algID, // IN: the starting algorithm ID UINT32 count, // IN: count of returned algorithms TPML_ALG_PROPERTY *algList // OUT: algorithm list ) { TPMI_YES_NO more = NO; UINT32 i; UINT32 algNum; // initialize output algorithm list algList->count = 0; // The maximum count of algorithms we may return is MAX_CAP_ALGS. if(count > MAX_CAP_ALGS) count = MAX_CAP_ALGS; // Compute how many algorithms are defined in s_algorithms array. algNum = sizeof(s_algorithms) / sizeof(s_algorithms[0]); // Scan the implemented algorithm list to see if there is a match to 'algID'. for(i = 0; i < algNum; i++) { // If algID is less than the starting algorithm ID, skip it if(s_algorithms[i].algID < algID) continue; if(algList->count < count) { // If we have not filled up the return list, add more algorithms // to it algList->algProperties[algList->count].alg = s_algorithms[i].algID; algList->algProperties[algList->count].algProperties = s_algorithms[i].attributes; algList->count++; } else { // If the return list is full but we still have algorithms // available, report this and stop scanning. more = YES; break; } } return more; } /* 9.1.4 AlgorithmGetImplementedVector() This function returns the bit vector of the implemented algorithms. */ LIB_EXPORT void AlgorithmGetImplementedVector( ALGORITHM_VECTOR *implemented // OUT: the implemented bits are SET ) { int index; // Nothing implemented until we say it is MemorySet(implemented, 0, sizeof(ALGORITHM_VECTOR)); // Go through the list of implemented algorithms and SET the corresponding bit in // in the implemented vector for(index = (sizeof(s_algorithms) / sizeof(s_algorithms[0])) - 1; index >= 0; index--) SET_BIT(s_algorithms[index].algID, *implemented); return; } libtpms-0.9.3/src/tpm2/AlgorithmCap_fp.h000066400000000000000000000074311421143571500200660ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: AlgorithmCap_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 */ /* */ /********************************************************************************/ #ifndef ALGORITHMCAP_FP_H #define ALGORITHMCAP_FP_H TPMI_YES_NO AlgorithmCapGetImplemented( TPM_ALG_ID algID, // IN: the starting algorithm ID UINT32 count, // IN: count of returned algorithms TPML_ALG_PROPERTY *algList // OUT: algorithm list ); LIB_EXPORT void AlgorithmGetImplementedVector( ALGORITHM_VECTOR *implemented // OUT: the implemented bits are SET ); #endif libtpms-0.9.3/src/tpm2/AlgorithmTests.c000066400000000000000000001037531421143571500177770ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Code to perform the various self-test functions. */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: AlgorithmTests.c 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2021 */ /* */ /********************************************************************************/ /* 10.2.1 AlgorithmTests.c */ /* 10.2.1.1 Introduction */ /* This file contains the code to perform the various self-test functions. */ /* 10.2.1.2 Includes and Defines */ #include "Tpm.h" #define SELF_TEST_DATA #if SELF_TEST /* These includes pull in the data structures. They contain data definitions for the various tests. */ #include "SelfTest.h" #include "SymmetricTest.h" #include "RsaTestData.h" #include "EccTestData.h" #include "HashTestData.h" #include "KdfTestData.h" #define TEST_DEFAULT_TEST_HASH(vector) \ if(TEST_BIT(DEFAULT_TEST_HASH, g_toTest)) \ TestHash(DEFAULT_TEST_HASH, vector); /* Make sure that the algorithm has been tested */ #define CLEAR_BOTH(alg) { CLEAR_BIT(alg, *toTest); \ if(toTest != &g_toTest) \ CLEAR_BIT(alg, g_toTest); } #define SET_BOTH(alg) { SET_BIT(alg, *toTest); \ if(toTest != &g_toTest) \ SET_BIT(alg, g_toTest); } #define TEST_BOTH(alg) ((toTest != &g_toTest) \ ? TEST_BIT(alg, *toTest) || TEST_BIT(alg, g_toTest) \ : TEST_BIT(alg, *toTest)) /* Can only cancel if doing a list. */ #define CHECK_CANCELED \ if(_plat__IsCanceled() && toTest != &g_toTest) \ return TPM_RC_CANCELED; /* 10.2.1.3 Hash Tests */ /* 10.2.1.3.1 Description */ /* The hash test does a known-value HMAC using the specified hash algorithm. */ /* 10.2.1.3.2 TestHash() */ /* The hash test function. */ static TPM_RC TestHash( TPM_ALG_ID hashAlg, ALGORITHM_VECTOR *toTest ) { TPM2B_DIGEST computed; // value computed HMAC_STATE state; UINT16 digestSize; const TPM2B *testDigest = NULL; // TPM2B_TYPE(HMAC_BLOCK, DEFAULT_TEST_HASH_BLOCK_SIZE); pAssert(hashAlg != TPM_ALG_NULL); #define HASH_CASE_FOR_TEST(HASH, hash) case ALG_##HASH##_VALUE: \ testDigest = &c_##HASH##_digest.b; \ break; switch(hashAlg) { FOR_EACH_HASH(HASH_CASE_FOR_TEST) default: FAIL(FATAL_ERROR_INTERNAL); } // Clear the to-test bits CLEAR_BOTH(hashAlg); // If there is an algorithm without test vectors, then assume that things are OK. if(testDigest == NULL || testDigest->size == 0) return TPM_RC_SUCCESS; // Set the HMAC key to twice the digest size digestSize = CryptHashGetDigestSize(hashAlg); CryptHmacStart(&state, hashAlg, digestSize * 2, (BYTE *)c_hashTestKey.t.buffer); CryptDigestUpdate(&state.hashState, 2 * CryptHashGetBlockSize(hashAlg), (BYTE *)c_hashTestData.t.buffer); computed.t.size = digestSize; CryptHmacEnd(&state, digestSize, computed.t.buffer); if((testDigest->size != computed.t.size) || (memcmp(testDigest->buffer, computed.t.buffer, computed.b.size) != 0)) { SELF_TEST_FAILURE; } return TPM_RC_SUCCESS; } // libtpms added begin #if SMAC_IMPLEMENTED && ALG_CMAC static TPM_RC TestSMAC( ALGORITHM_VECTOR *toTest ) { HMAC_STATE state; UINT16 copied; BYTE out[MAX_SYM_BLOCK_SIZE]; UINT32 outSize = sizeof(out); UINT16 blocksize; int i; TPMU_PUBLIC_PARMS cmac_keyParms; // initializing this statically seems impossible with gcc... cmac_keyParms.symDetail.sym.algorithm = TPM_ALG_AES; cmac_keyParms.symDetail.sym.keyBits.sym = 128; for (i = 0; CMACTests[i].key; i++ ) { blocksize = CryptMacStart(&state, &cmac_keyParms, TPM_ALG_CMAC, CMACTests[i].key); pAssert(blocksize <= outSize); CryptDigestUpdate(&state.hashState, CMACTests[i].datalen, CMACTests[i].data); copied = CryptMacEnd(&state, outSize, out); if((CMACTests[i].outlen != copied) || (memcmp(out, CMACTests[i].out, CMACTests[i].outlen) != 0)) { SELF_TEST_FAILURE; } } return TPM_RC_SUCCESS; } #endif // libtpms added end /* 10.2.1.4 Symmetric Test Functions */ /* 10.2.1.4.1 MakeIv() */ /* Internal function to make the appropriate IV depending on the mode. */ static UINT32 MakeIv( TPM_ALG_ID mode, // IN: symmetric mode UINT32 size, // IN: block size of the algorithm BYTE *iv // OUT: IV to fill in ) { BYTE i; if(mode == TPM_ALG_ECB) return 0; if(mode == TPM_ALG_CTR) { // The test uses an IV that has 0xff in the last byte for(i = 1; i <= size; i++) *iv++ = 0xff - (BYTE)(size - i); } else { for(i = 0; i < size; i++) *iv++ = i; } return size; } /* 10.2.1.4.2 TestSymmetricAlgorithm() */ /* Function to test a specific algorithm, key size, and mode. */ static void TestSymmetricAlgorithm( const SYMMETRIC_TEST_VECTOR *test, // TPM_ALG_ID mode // ) { BYTE encrypted[MAX_SYM_BLOCK_SIZE * 2]; BYTE decrypted[MAX_SYM_BLOCK_SIZE * 2]; TPM2B_IV iv; // libtpms added beging if (test->dataOut[mode - TPM_ALG_CTR] == NULL) return; // libtpms added end // // Get the appropriate IV iv.t.size = (UINT16)MakeIv(mode, test->ivSize, iv.t.buffer); // Encrypt known data CryptSymmetricEncrypt(encrypted, test->alg, test->keyBits, test->key, &iv, mode, test->dataInOutSize, test->dataIn); // Check that it matches the expected value if(!MemoryEqual(encrypted, test->dataOut[mode - TPM_ALG_CTR], test->dataInOutSize)) { SELF_TEST_FAILURE; } // Reinitialize the iv for decryption MakeIv(mode, test->ivSize, iv.t.buffer); CryptSymmetricDecrypt(decrypted, test->alg, test->keyBits, test->key, &iv, mode, test->dataInOutSize, test->dataOut[mode - TPM_ALG_CTR]); // Make sure that it matches what we started with if(!MemoryEqual(decrypted, test->dataIn, test->dataInOutSize)) { SELF_TEST_FAILURE; } } /* 10.2.1.4.3 AllSymsAreDone() */ /* Checks if both symmetric algorithms have been tested. This is put here so that addition of a symmetric algorithm will be relatively easy to handle */ /* Return Value Meaning */ /* TRUE(1) all symmetric algorithms tested */ /* FALSE(0) not all symmetric algorithms tested */ static BOOL AllSymsAreDone( ALGORITHM_VECTOR *toTest ) { return (!TEST_BOTH(TPM_ALG_AES) && !TEST_BOTH(TPM_ALG_SM4)); } /* 10.2.1.4.4 AllModesAreDone() */ /* Checks if all the modes have been tested */ /* Return Value Meaning */ /* TRUE(1) all modes tested */ /* FALSE(0) all modes not tested */ static BOOL AllModesAreDone( ALGORITHM_VECTOR *toTest ) { TPM_ALG_ID alg; for(alg = SYM_MODE_FIRST; alg <= SYM_MODE_LAST; alg++) if(TEST_BOTH(alg)) return FALSE; return TRUE; } /* 10.2.1.4.5 TestSymmetric() */ /* If alg is a symmetric block cipher, then all of the modes that are selected are tested. If alg is a mode, then all algorithms of that mode are tested. */ static TPM_RC TestSymmetric( TPM_ALG_ID alg, ALGORITHM_VECTOR *toTest ) { SYM_INDEX index; TPM_ALG_ID mode; // if(!TEST_BIT(alg, *toTest)) return TPM_RC_SUCCESS; if(alg == TPM_ALG_AES || alg == TPM_ALG_SM4 || alg == TPM_ALG_CAMELLIA || alg == TPM_ALG_TDES) { // Will test the algorithm for all modes and key sizes CLEAR_BOTH(alg); // A test this algorithm for all modes for(index = 0; index < NUM_SYMS; index++) { if(c_symTestValues[index].alg == alg) { for(mode = SYM_MODE_FIRST; mode <= SYM_MODE_LAST; mode++) { if(TEST_BIT(mode, g_implementedAlgorithms)) // libtpms always test implemented modes TestSymmetricAlgorithm(&c_symTestValues[index], mode); } } } // if all the symmetric tests are done if(AllSymsAreDone(toTest)) { // all symmetric algorithms tested so no modes should be set for(alg = SYM_MODE_FIRST; alg <= SYM_MODE_LAST; alg++) CLEAR_BOTH(alg); } } else if(SYM_MODE_FIRST <= alg && alg <= SYM_MODE_LAST) { // Test this mode for all key sizes and algorithms for(index = 0; index < NUM_SYMS; index++) { // The mode testing only comes into play when doing self tests // by command. When doing self tests by command, the block ciphers are // tested first. That means that all of their modes would have been // tested for all key sizes. If there is no block cipher left to // test, then clear this mode bit. if(!TEST_BIT(TPM_ALG_AES, *toTest) && !TEST_BIT(TPM_ALG_SM4, *toTest)) { CLEAR_BOTH(alg); } else { for(index = 0; index < NUM_SYMS; index++) { if(TEST_BIT(c_symTestValues[index].alg, *toTest)) TestSymmetricAlgorithm(&c_symTestValues[index], alg); } // have tested this mode for all algorithms CLEAR_BOTH(alg); } } if(AllModesAreDone(toTest)) { CLEAR_BOTH(TPM_ALG_AES); CLEAR_BOTH(TPM_ALG_SM4); } } else pAssert(alg == 0 && alg != 0); return TPM_RC_SUCCESS; } /* 10.2.1.5 RSA Tests */ #if ALG_RSA /* 10.2.1.5.1 Introduction */ /* The tests are for public key only operations and for private key operations. Signature verification and encryption are public key operations. They are tested by using a KVT. For signature verification, this means that a known good signature is checked by CryptRsaValidateSignature(). If it fails, then the TPM enters failure mode. For encryption, the TPM encrypts known values using the selected scheme and checks that the returned value matches the expected value. */ /* For private key operations, a full scheme check is used. For a signing key, a known key is used to sign a known message. Then that signature is verified. since the signature may involve use of random values, the signature will be different each time and we can't always check that the signature matches a known value. The same technique is used for decryption (RSADP/RSAEP). */ /* When an operation uses the public key and the verification has not been tested, the TPM will do a KVT. */ /* The test for the signing algorithm is built into the call for the algorithm */ /* 10.2.1.5.2 RsaKeyInitialize() */ /* The test key is defined by a public modulus and a private prime. The TPM's RSA code computes the second prime and the private exponent. */ static void RsaKeyInitialize( OBJECT *testObject ) { MemoryCopy2B(&testObject->publicArea.unique.rsa.b, (P2B)&c_rsaPublicModulus, sizeof(c_rsaPublicModulus)); MemoryCopy2B(&testObject->sensitive.sensitive.rsa.b, (P2B)&c_rsaPrivatePrime, sizeof(testObject->sensitive.sensitive.rsa.t.buffer)); testObject->publicArea.parameters.rsaDetail.keyBits = RSA_TEST_KEY_SIZE * 8; // Use the default exponent testObject->publicArea.parameters.rsaDetail.exponent = 0; testObject->attributes.privateExp = 0; } /* 10.2.1.5.3 TestRsaEncryptDecrypt() */ /* These tests are for a public key encryption that uses a random value. */ static TPM_RC TestRsaEncryptDecrypt( TPM_ALG_ID scheme, // IN: the scheme ALGORITHM_VECTOR *toTest // ) { TPM2B_PUBLIC_KEY_RSA testInput; TPM2B_PUBLIC_KEY_RSA testOutput; OBJECT testObject; const TPM2B_RSA_TEST_KEY *kvtValue = NULL; TPM_RC result = TPM_RC_SUCCESS; const TPM2B *testLabel = NULL; TPMT_RSA_DECRYPT rsaScheme; // // Don't need to initialize much of the test object but do need to initialize // the flag indicating that the private exponent has been computed. testObject.attributes.privateExp = CLEAR; RsaKeyInitialize(&testObject); rsaScheme.scheme = scheme; rsaScheme.details.anySig.hashAlg = DEFAULT_TEST_HASH; CLEAR_BOTH(scheme); CLEAR_BOTH(TPM_ALG_NULL); if(scheme == TPM_ALG_NULL) { // This is an encryption scheme using the private key without any encoding. memcpy(testInput.t.buffer, c_RsaTestValue, sizeof(c_RsaTestValue)); testInput.t.size = sizeof(c_RsaTestValue); if(TPM_RC_SUCCESS != CryptRsaEncrypt(&testOutput, &testInput.b, &testObject, &rsaScheme, NULL, NULL)) { SELF_TEST_FAILURE; } if(!MemoryEqual(testOutput.t.buffer, c_RsaepKvt.buffer, c_RsaepKvt.size)) { SELF_TEST_FAILURE; } MemoryCopy2B(&testInput.b, &testOutput.b, sizeof(testInput.t.buffer)); if(TPM_RC_SUCCESS != CryptRsaDecrypt(&testOutput.b, &testInput.b, &testObject, &rsaScheme, NULL)) { SELF_TEST_FAILURE; } if(!MemoryEqual(testOutput.t.buffer, c_RsaTestValue, sizeof(c_RsaTestValue))) { SELF_TEST_FAILURE; } } else { // TPM_ALG_RSAES: // This is an decryption scheme using padding according to // PKCS#1v2.1, 7.2. This padding uses random bits. To test a public // key encryption that uses random data, encrypt a value and then // decrypt the value and see that we get the encrypted data back. // The hash is not used by this encryption so it can be TMP_ALG_NULL // TPM_ALG_OAEP_: // This is also an decryption scheme and it also uses a // pseudo-random // value. However, this also uses a hash algorithm. So, we may need // to test that algorithm before use. if(scheme == TPM_ALG_OAEP) { TEST_DEFAULT_TEST_HASH(toTest); kvtValue = &c_OaepKvt; testLabel = OAEP_TEST_STRING; } else if(scheme == TPM_ALG_RSAES) { kvtValue = &c_RsaesKvt; testLabel = NULL; } else { SELF_TEST_FAILURE; } // Only use a digest-size portion of the test value memcpy(testInput.t.buffer, c_RsaTestValue, DEFAULT_TEST_DIGEST_SIZE); testInput.t.size = DEFAULT_TEST_DIGEST_SIZE; // See if the encryption works if(TPM_RC_SUCCESS != CryptRsaEncrypt(&testOutput, &testInput.b, &testObject, &rsaScheme, testLabel, NULL)) { SELF_TEST_FAILURE; } MemoryCopy2B(&testInput.b, &testOutput.b, sizeof(testInput.t.buffer)); // see if we can decrypt this value and get the original data back if(TPM_RC_SUCCESS != CryptRsaDecrypt(&testOutput.b, &testInput.b, &testObject, &rsaScheme, testLabel)) { SELF_TEST_FAILURE; } // See if the results compare if(testOutput.t.size != DEFAULT_TEST_DIGEST_SIZE || !MemoryEqual(testOutput.t.buffer, c_RsaTestValue, DEFAULT_TEST_DIGEST_SIZE)) { SELF_TEST_FAILURE; } // Now check that the decryption works on a known value MemoryCopy2B(&testInput.b, (P2B)kvtValue, sizeof(testInput.t.buffer)); if(TPM_RC_SUCCESS != CryptRsaDecrypt(&testOutput.b, &testInput.b, &testObject, &rsaScheme, testLabel)) { SELF_TEST_FAILURE; } if(testOutput.t.size != DEFAULT_TEST_DIGEST_SIZE || !MemoryEqual(testOutput.t.buffer, c_RsaTestValue, DEFAULT_TEST_DIGEST_SIZE)) { SELF_TEST_FAILURE; } } return result; } /* 10.2.1.5.4 TestRsaSignAndVerify() */ /* This function does the testing of the RSA sign and verification functions. This test does a KVT. */ static TPM_RC TestRsaSignAndVerify( TPM_ALG_ID scheme, ALGORITHM_VECTOR *toTest ) { TPM_RC result = TPM_RC_SUCCESS; OBJECT testObject; TPM2B_DIGEST testDigest; TPMT_SIGNATURE testSig; // Do a sign and signature verification. // RSASSA: // This is a signing scheme according to PKCS#1-v2.1 8.2. It does not // use random data so there is a KVT for the signing operation. On // first use of the scheme for signing, use the TPM's RSA key to // sign a portion of c_RsaTestData and compare the results to c_RsassaKvt. Then // decrypt the data to see that it matches the starting value. This verifies // the signature with a KVT // Clear the bits indicating that the function has not been checked. This is to // prevent looping CLEAR_BOTH(scheme); CLEAR_BOTH(TPM_ALG_NULL); CLEAR_BOTH(TPM_ALG_RSA); RsaKeyInitialize(&testObject); memcpy(testDigest.t.buffer, (BYTE *)c_RsaTestValue, DEFAULT_TEST_DIGEST_SIZE); testDigest.t.size = DEFAULT_TEST_DIGEST_SIZE; testSig.sigAlg = scheme; testSig.signature.rsapss.hash = DEFAULT_TEST_HASH; // RSAPSS: // This is a signing scheme a according to PKCS#1-v2.2 8.1 it uses // random data in the signature so there is no KVT for the signing // operation. To test signing, the TPM will use the TPM's RSA key // to sign a portion of c_RsaTestValue and then it will verify the // signature. For verification, c_RsapssKvt is verified before the // user signature blob is verified. The worst case for testing of this // algorithm is two private and one public key operation. // The process is to sign known data. If RSASSA is being done, verify that the // signature matches the precomputed value. For both, use the signed value and // see that the verification says that it is a good signature. Then // if testing RSAPSS, do a verify of a known good signature. This ensures that // the validation function works. if(TPM_RC_SUCCESS != CryptRsaSign(&testSig, &testObject, &testDigest, NULL)) { SELF_TEST_FAILURE; } // For RSASSA, make sure the results is what we are looking for if(testSig.sigAlg == TPM_ALG_RSASSA) { if(testSig.signature.rsassa.sig.t.size != RSA_TEST_KEY_SIZE || !MemoryEqual(c_RsassaKvt.buffer, testSig.signature.rsassa.sig.t.buffer, RSA_TEST_KEY_SIZE)) { SELF_TEST_FAILURE; } } // See if the TPM will validate its own signatures if(TPM_RC_SUCCESS != CryptRsaValidateSignature(&testSig, &testObject, &testDigest)) { SELF_TEST_FAILURE; } // If this is RSAPSS, check the verification with known signature // Have to copy because CrytpRsaValidateSignature() eats the signature if(TPM_ALG_RSAPSS == scheme) { MemoryCopy2B(&testSig.signature.rsapss.sig.b, (P2B)&c_RsapssKvt, sizeof(testSig.signature.rsapss.sig.t.buffer)); if(TPM_RC_SUCCESS != CryptRsaValidateSignature(&testSig, &testObject, &testDigest)) { SELF_TEST_FAILURE; } } return result; } /* 10.2.1.5.5 TestRSA() */ /* Function uses the provided vector to indicate which tests to run. It will clear the vector after each test is run and also clear g_toTest */ static TPM_RC TestRsa( TPM_ALG_ID alg, ALGORITHM_VECTOR *toTest ) { TPM_RC result = TPM_RC_SUCCESS; // switch(alg) { case TPM_ALG_NULL: // This is the RSAEP/RSADP function. If we are processing a list, don't // need to test these now because any other test will validate // RSAEP/RSADP. Can tell this is list of test by checking to see if // 'toTest' is pointing at g_toTest. If so, this is an isolated test // an need to go ahead and do the test; if((toTest == &g_toTest) || (!TEST_BIT(TPM_ALG_RSASSA, *toTest) && !TEST_BIT(TPM_ALG_RSAES, *toTest) && !TEST_BIT(TPM_ALG_RSAPSS, *toTest) && !TEST_BIT(TPM_ALG_OAEP, *toTest))) // Not running a list of tests or no other tests on the list // so run the test now result = TestRsaEncryptDecrypt(alg, toTest); // if not running the test now, leave the bit on, just in case things // get interrupted break; case TPM_ALG_OAEP: case TPM_ALG_RSAES: result = TestRsaEncryptDecrypt(alg, toTest); break; case TPM_ALG_RSAPSS: case TPM_ALG_RSASSA: result = TestRsaSignAndVerify(alg, toTest); break; default: SELF_TEST_FAILURE; } return result; } #endif // TPM_ALG_RSA /* 10.2.1.6 ECC Tests */ #if ALG_ECC /* 10.2.1.6.1 LoadEccParameter() */ /* This function is mostly for readability and type checking */ static void LoadEccParameter( TPM2B_ECC_PARAMETER *to, // target const TPM2B_EC_TEST *from // source ) { MemoryCopy2B(&to->b, &from->b, sizeof(to->t.buffer)); } /* 10.2.1.6.2 LoadEccPoint() */ static void LoadEccPoint( TPMS_ECC_POINT *point, // target const TPM2B_EC_TEST *x, // source const TPM2B_EC_TEST *y ) { MemoryCopy2B(&point->x.b, (TPM2B *)x, sizeof(point->x.t.buffer)); MemoryCopy2B(&point->y.b, (TPM2B *)y, sizeof(point->y.t.buffer)); } /* 10.2.1.6.3 TestECDH() */ /* This test does a KVT on a point multiply. */ static TPM_RC TestECDH( TPM_ALG_ID scheme, // IN: for consistency ALGORITHM_VECTOR *toTest // IN/OUT: modified after test is run ) { TPMS_ECC_POINT Z; TPMS_ECC_POINT Qe; TPM2B_ECC_PARAMETER ds; TPM_RC result = TPM_RC_SUCCESS; // NOT_REFERENCED(scheme); CLEAR_BOTH(TPM_ALG_ECDH); LoadEccParameter(&ds, &c_ecTestKey_ds); LoadEccPoint(&Qe, &c_ecTestKey_QeX, &c_ecTestKey_QeY); if(TPM_RC_SUCCESS != CryptEccPointMultiply(&Z, c_testCurve, &Qe, &ds, NULL, NULL)) { SELF_TEST_FAILURE; } if(!MemoryEqual2B(&c_ecTestEcdh_X.b, &Z.x.b) || !MemoryEqual2B(&c_ecTestEcdh_Y.b, &Z.y.b)) { SELF_TEST_FAILURE; } return result; } /* 10.2.1.6.4 TestEccSignAndVerify() */ static TPM_RC TestEccSignAndVerify( TPM_ALG_ID scheme, ALGORITHM_VECTOR *toTest ) { OBJECT testObject; TPMT_SIGNATURE testSig; TPMT_ECC_SCHEME eccScheme; testSig.sigAlg = scheme; testSig.signature.ecdsa.hash = DEFAULT_TEST_HASH; eccScheme.scheme = scheme; eccScheme.details.anySig.hashAlg = DEFAULT_TEST_HASH; CLEAR_BOTH(scheme); CLEAR_BOTH(TPM_ALG_ECDH); // ECC signature verification testing uses a KVT. switch(scheme) { case TPM_ALG_ECDSA: LoadEccParameter(&testSig.signature.ecdsa.signatureR, &c_TestEcDsa_r); LoadEccParameter(&testSig.signature.ecdsa.signatureS, &c_TestEcDsa_s); break; case TPM_ALG_ECSCHNORR: LoadEccParameter(&testSig.signature.ecschnorr.signatureR, &c_TestEcSchnorr_r); LoadEccParameter(&testSig.signature.ecschnorr.signatureS, &c_TestEcSchnorr_s); break; case TPM_ALG_SM2: // don't have a test for SM2 return TPM_RC_SUCCESS; default: SELF_TEST_FAILURE; break; } TEST_DEFAULT_TEST_HASH(toTest); // Have to copy the key. This is because the size used in the test vectors // is the size of the ECC parameter for the test key while the size of a point // is TPM dependent MemoryCopy2B(&testObject.sensitive.sensitive.ecc.b, &c_ecTestKey_ds.b, sizeof(testObject.sensitive.sensitive.ecc.t.buffer)); LoadEccPoint(&testObject.publicArea.unique.ecc, &c_ecTestKey_QsX, &c_ecTestKey_QsY); testObject.publicArea.parameters.eccDetail.curveID = c_testCurve; if(TPM_RC_SUCCESS != CryptEccValidateSignature(&testSig, &testObject, (TPM2B_DIGEST *)&c_ecTestValue.b)) { SELF_TEST_FAILURE; } CHECK_CANCELED; // Now sign and verify some data if(TPM_RC_SUCCESS != CryptEccSign(&testSig, &testObject, (TPM2B_DIGEST *)&c_ecTestValue, &eccScheme, NULL)) { SELF_TEST_FAILURE; } CHECK_CANCELED; if(TPM_RC_SUCCESS != CryptEccValidateSignature(&testSig, &testObject, (TPM2B_DIGEST *)&c_ecTestValue)) { SELF_TEST_FAILURE; } CHECK_CANCELED; return TPM_RC_SUCCESS; } /* 10.2.1.6.5 TestKDFa() */ static TPM_RC TestKDFa( ALGORITHM_VECTOR *toTest ) { static TPM2B_KDF_TEST_KEY keyOut; UINT32 counter = 0; // CLEAR_BOTH(TPM_ALG_KDF1_SP800_108); keyOut.t.size = CryptKDFa(KDF_TEST_ALG, &c_kdfTestKeyIn.b, &c_kdfTestLabel.b, &c_kdfTestContextU.b, &c_kdfTestContextV.b, TEST_KDF_KEY_SIZE * 8, keyOut.t.buffer, &counter, FALSE); if ( keyOut.t.size != TEST_KDF_KEY_SIZE || !MemoryEqual(keyOut.t.buffer, c_kdfTestKeyOut.t.buffer, TEST_KDF_KEY_SIZE)) SELF_TEST_FAILURE; return TPM_RC_SUCCESS; } /* 10.2.1.6.6 TestEcc() */ static TPM_RC TestEcc( TPM_ALG_ID alg, ALGORITHM_VECTOR *toTest ) { TPM_RC result = TPM_RC_SUCCESS; NOT_REFERENCED(toTest); switch(alg) { case TPM_ALG_ECC: case TPM_ALG_ECDH: // If this is in a loop then see if another test is going to deal with // this. // If toTest is not a self-test list if((toTest == &g_toTest) // or this is the only ECC test in the list || !(TEST_BIT(TPM_ALG_ECDSA, *toTest) || TEST_BIT(TPM_ALG_ECSCHNORR, *toTest) || TEST_BIT(TPM_ALG_SM2, *toTest))) { result = TestECDH(alg, toTest); } break; case TPM_ALG_ECDSA: case TPM_ALG_ECSCHNORR: case TPM_ALG_SM2: result = TestEccSignAndVerify(alg, toTest); break; default: SELF_TEST_FAILURE; break; } return result; } #endif // TPM_ALG_ECC /* 10.2.1.6.4 TestAlgorithm() */ /* Dispatches to the correct test function for the algorithm or gets a list of testable algorithms. */ /* If toTest is not NULL, then the test decisions are based on the algorithm selections in toTest. Otherwise, g_toTest is used. When bits are clear in g_toTest they will also be cleared toTest. */ /* If there doesn't happen to be a test for the algorithm, its associated bit is quietly cleared. */ /* If alg is zero (TPM_ALG_ERROR), then the toTest vector is cleared of any bits for which there is no test (i.e. no tests are actually run but the vector is cleared). */ /* NOTE: toTest will only ever have bits set for implemented algorithms but alg can be anything. */ /* Error Returns Meaning */ /* TPM_RC_CANCELED test was canceled */ LIB_EXPORT TPM_RC TestAlgorithm( TPM_ALG_ID alg, ALGORITHM_VECTOR *toTest ) { TPM_ALG_ID first = (alg == TPM_ALG_ERROR) ? TPM_ALG_FIRST : alg; TPM_ALG_ID last = (alg == TPM_ALG_ERROR) ? TPM_ALG_LAST : alg; BOOL doTest = (alg != TPM_ALG_ERROR); TPM_RC result = TPM_RC_SUCCESS; if(toTest == NULL) toTest = &g_toTest; // This is kind of strange. This function will either run a test of the selected // algorithm or just clear a bit if there is no test for the algorithm. So, // either this loop will be executed once for the selected algorithm or once for // each of the possible algorithms. If it is executed more than once ('alg' == // TPM_ALG_ERROR), then no test will be run but bits will be cleared for // unimplemented algorithms. This was done this way so that there is only one // case statement with all of the algorithms. It was easier to have one case // statement than to have multiple ones to manage whenever an algorithm ID is // added. for(alg = first; (alg <= last); alg++) { // if 'alg' was TPM_ALG_ERROR, then we will be cycling through // values, some of which may not be implemented. If the bit in toTest // happens to be set, then we could either generated an assert, or just // silently CLEAR it. Decided to just clear. if(!TEST_BIT(alg, g_implementedAlgorithms)) { CLEAR_BIT(alg, *toTest); continue; } // Process whatever is left. // NOTE: since this switch will only be called if the algorithm is // implemented, it is not necessary to modify this list except to comment // out the algorithms for which there is no test switch(alg) { // Symmetric block ciphers #if ALG_AES case TPM_ALG_AES: // libtpms added begin #if SMAC_IMPLEMENTED && ALG_CMAC if (doTest) { result = TestSMAC(toTest); if (result != TPM_RC_SUCCESS) break; } #endif // libtpms added end #endif #if ALG_SM4 // if SM4 is implemented, its test is like other block ciphers but there // aren't any test vectors for it yet // case TPM_ALG_SM4: #endif #if ALG_CAMELLIA case TPM_ALG_CAMELLIA: // libtpms activated #endif #if ALG_TDES case TPM_ALG_TDES: // libtpms added #endif // Symmetric modes #if !ALG_CFB # error CFB is required in all TPM implementations #endif // !TPM_ALG_CFB case TPM_ALG_CFB: if(doTest) result = TestSymmetric(alg, toTest); break; #if ALG_CTR case TPM_ALG_CTR: #endif // TPM_ALG_CRT #if ALG_OFB case TPM_ALG_OFB: #endif // TPM_ALG_OFB #if ALG_CBC case TPM_ALG_CBC: #endif // TPM_ALG_CBC #if ALG_ECB case TPM_ALG_ECB: #endif if(doTest) result = TestSymmetric(alg, toTest); else // If doing the initialization of g_toTest vector, only need // to test one of the modes for the symmetric algorithms. If // initializing for a SelfTest(FULL_TEST), allow all the modes. if(toTest == &g_toTest) CLEAR_BIT(alg, *toTest); break; #if !ALG_HMAC # error HMAC is required in all TPM implementations #endif case TPM_ALG_HMAC: // Clear the bit that indicates that HMAC is required because // HMAC is used as the basic test for all hash algorithms. CLEAR_BOTH(alg); // Testing HMAC means test the default hash if(doTest) TestHash(DEFAULT_TEST_HASH, toTest); else // If not testing, then indicate that the hash needs to be // tested because this uses HMAC SET_BOTH(DEFAULT_TEST_HASH); break; // Have to use two arguments for the macro even though only the first is used in the // expansion. #define HASH_CASE_TEST(HASH, hash) \ case ALG_##HASH##_VALUE: FOR_EACH_HASH(HASH_CASE_TEST) #undef HASH_CASE_TEST if(doTest) result = TestHash(alg, toTest); break; // RSA-dependent #if ALG_RSA case TPM_ALG_RSA: CLEAR_BOTH(alg); if(doTest) result = TestRsa(TPM_ALG_NULL, toTest); else SET_BOTH(TPM_ALG_NULL); break; case TPM_ALG_RSASSA: case TPM_ALG_RSAES: case TPM_ALG_RSAPSS: case TPM_ALG_OAEP: case TPM_ALG_NULL: // used or RSADP if(doTest) result = TestRsa(alg, toTest); break; #endif // ALG_RSA #if ALG_KDF1_SP800_108 case TPM_ALG_KDF1_SP800_108: if(doTest) result = TestKDFa(toTest); break; #endif // ALG_KDF1_SP800_108 #if ALG_ECC // ECC dependent but no tests // case TPM_ALG_ECDAA: // case TPM_ALG_ECMQV: // case TPM_ALG_KDF1_SP800_56a: // case TPM_ALG_KDF2: // case TPM_ALG_MGF1: case TPM_ALG_ECC: CLEAR_BOTH(alg); if(doTest) result = TestEcc(TPM_ALG_ECDH, toTest); else SET_BOTH(TPM_ALG_ECDH); break; case TPM_ALG_ECDSA: case TPM_ALG_ECDH: case TPM_ALG_ECSCHNORR: // case TPM_ALG_SM2: if(doTest) result = TestEcc(alg, toTest); break; #endif // ALG_ECC default: CLEAR_BIT(alg, *toTest); break; } if(result != TPM_RC_SUCCESS) break; } return result; } #endif // SELF_TESTS libtpms-0.9.3/src/tpm2/AlgorithmTests_fp.h000066400000000000000000000067631421143571500204740ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: AlgorithmTests_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 */ /* */ /********************************************************************************/ #ifndef ALGORITHMTESTS_FP_H #define ALGORITHMTESTS_FP_H LIB_EXPORT TPM_RC TestAlgorithm( TPM_ALG_ID alg, ALGORITHM_VECTOR *toTest ); #endif libtpms-0.9.3/src/tpm2/AsymmetricCommands.c000066400000000000000000000313511421143571500206170ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Asymmetric Commands */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: AsymmetricCommands.c 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ #include "Tpm.h" #include "RSA_Encrypt_fp.h" #if CC_RSA_Encrypt // Conditional expansion of this file TPM_RC TPM2_RSA_Encrypt( RSA_Encrypt_In *in, // IN: input parameter list RSA_Encrypt_Out *out // OUT: output parameter list ) { TPM_RC result; OBJECT *rsaKey; TPMT_RSA_DECRYPT *scheme; // Input Validation rsaKey = HandleToObject(in->keyHandle); // selected key must be an RSA key if(rsaKey->publicArea.type != TPM_ALG_RSA) return TPM_RCS_KEY + RC_RSA_Encrypt_keyHandle; // selected key must have the decryption attribute if(!IS_ATTRIBUTE(rsaKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt)) return TPM_RCS_ATTRIBUTES + RC_RSA_Encrypt_keyHandle; // Is there a label? if(!IsLabelProperlyFormatted(&in->label.b)) return TPM_RCS_VALUE + RC_RSA_Encrypt_label; // Command Output // Select a scheme for encryption scheme = CryptRsaSelectScheme(in->keyHandle, &in->inScheme); if(scheme == NULL) return TPM_RCS_SCHEME + RC_RSA_Encrypt_inScheme; // Encryption. TPM_RC_VALUE, or TPM_RC_SCHEME errors my be returned buy // CryptEncyptRSA. out->outData.t.size = sizeof(out->outData.t.buffer); result = CryptRsaEncrypt(&out->outData, &in->message.b, rsaKey, scheme, &in->label.b, NULL); return result; } #endif // CC_RSA_Encrypt #include "Tpm.h" #include "RSA_Decrypt_fp.h" #if CC_RSA_Decrypt // Conditional expansion of this file TPM_RC TPM2_RSA_Decrypt( RSA_Decrypt_In *in, // IN: input parameter list RSA_Decrypt_Out *out // OUT: output parameter list ) { TPM_RC result; OBJECT *rsaKey; TPMT_RSA_DECRYPT *scheme; // Input Validation rsaKey = HandleToObject(in->keyHandle); // The selected key must be an RSA key if(rsaKey->publicArea.type != TPM_ALG_RSA) return TPM_RCS_KEY + RC_RSA_Decrypt_keyHandle; // The selected key must be an unrestricted decryption key if(IS_ATTRIBUTE(rsaKey->publicArea.objectAttributes, TPMA_OBJECT, restricted) || !IS_ATTRIBUTE(rsaKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt)) return TPM_RCS_ATTRIBUTES + RC_RSA_Decrypt_keyHandle; // NOTE: Proper operation of this command requires that the sensitive area // of the key is loaded. This is assured because authorization is required // to use the sensitive area of the key. In order to check the authorization, // the sensitive area has to be loaded, even if authorization is with policy. // If label is present, make sure that it is a NULL-terminated string if(!IsLabelProperlyFormatted(&in->label.b)) return TPM_RCS_VALUE + RC_RSA_Decrypt_label; // Command Output // Select a scheme for decrypt. scheme = CryptRsaSelectScheme(in->keyHandle, &in->inScheme); if(scheme == NULL) return TPM_RCS_SCHEME + RC_RSA_Decrypt_inScheme; // Decryption. TPM_RC_VALUE, TPM_RC_SIZE, and TPM_RC_KEY error may be // returned by CryptRsaDecrypt. // NOTE: CryptRsaDecrypt can also return TPM_RC_ATTRIBUTES or TPM_RC_BINDING // when the key is not a decryption key but that was checked above. out->message.t.size = sizeof(out->message.t.buffer); result = CryptRsaDecrypt(&out->message.b, &in->cipherText.b, rsaKey, scheme, &in->label.b); return result; } #endif // CC_RSA_Decrypt #include "Tpm.h" #include "ECDH_KeyGen_fp.h" #if CC_ECDH_KeyGen // Conditional expansion of this file TPM_RC TPM2_ECDH_KeyGen( ECDH_KeyGen_In *in, // IN: input parameter list ECDH_KeyGen_Out *out // OUT: output parameter list ) { OBJECT *eccKey; TPM2B_ECC_PARAMETER sensitive; TPM_RC result; // Input Validation eccKey = HandleToObject(in->keyHandle); // Referenced key must be an ECC key if(eccKey->publicArea.type != TPM_ALG_ECC) return TPM_RCS_KEY + RC_ECDH_KeyGen_keyHandle; // Command Output do { TPMT_PUBLIC *keyPublic = &eccKey->publicArea; // Create ephemeral ECC key result = CryptEccNewKeyPair(&out->pubPoint.point, &sensitive, keyPublic->parameters.eccDetail.curveID); if(result == TPM_RC_SUCCESS) { // Compute Z result = CryptEccPointMultiply(&out->zPoint.point, keyPublic->parameters.eccDetail.curveID, &keyPublic->unique.ecc, &sensitive, NULL, NULL); // The point in the key is not on the curve. Indicate // that the key is bad. if(result == TPM_RC_ECC_POINT) return TPM_RCS_KEY + RC_ECDH_KeyGen_keyHandle; // The other possible error from CryptEccPointMultiply is // TPM_RC_NO_RESULT indicating that the multiplication resulted in // the point at infinity, so get a new random key and start over // BTW, this never happens. } } while(result == TPM_RC_NO_RESULT); return result; } #endif // CC_ECDH_KeyGen #include "Tpm.h" #include "ECDH_ZGen_fp.h" #if CC_ECDH_ZGen // Conditional expansion of this file TPM_RC TPM2_ECDH_ZGen( ECDH_ZGen_In *in, // IN: input parameter list ECDH_ZGen_Out *out // OUT: output parameter list ) { TPM_RC result; OBJECT *eccKey; // Input Validation eccKey = HandleToObject(in->keyHandle); // Selected key must be a non-restricted, decrypt ECC key if(eccKey->publicArea.type != TPM_ALG_ECC) return TPM_RCS_KEY + RC_ECDH_ZGen_keyHandle; // Selected key needs to be unrestricted with the 'decrypt' attribute if(IS_ATTRIBUTE(eccKey->publicArea.objectAttributes, TPMA_OBJECT, restricted) || !IS_ATTRIBUTE(eccKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt)) return TPM_RCS_ATTRIBUTES + RC_ECDH_ZGen_keyHandle; // Make sure the scheme allows this use if(eccKey->publicArea.parameters.eccDetail.scheme.scheme != TPM_ALG_ECDH && eccKey->publicArea.parameters.eccDetail.scheme.scheme != TPM_ALG_NULL) return TPM_RCS_SCHEME + RC_ECDH_ZGen_keyHandle; // Command Output // Compute Z. TPM_RC_ECC_POINT or TPM_RC_NO_RESULT may be returned here. result = CryptEccPointMultiply(&out->outPoint.point, eccKey->publicArea.parameters.eccDetail.curveID, &in->inPoint.point, &eccKey->sensitive.sensitive.ecc, NULL, NULL); if(result != TPM_RC_SUCCESS) return RcSafeAddToResult(result, RC_ECDH_ZGen_inPoint); return result; } #endif // CC_ECDH_ZGen #include "Tpm.h" #include "ECC_Parameters_fp.h" #if CC_ECC_Parameters // Conditional expansion of this file TPM_RC TPM2_ECC_Parameters( ECC_Parameters_In *in, // IN: input parameter list ECC_Parameters_Out *out // OUT: output parameter list ) { // Command Output // Get ECC curve parameters if(CryptEccGetParameters(in->curveID, &out->parameters)) return TPM_RC_SUCCESS; else return TPM_RCS_VALUE + RC_ECC_Parameters_curveID; } #endif // CC_ECC_Parameters #include "Tpm.h" #include "ZGen_2Phase_fp.h" #if CC_ZGen_2Phase // Conditional expansion of this file TPM_RC TPM2_ZGen_2Phase( ZGen_2Phase_In *in, // IN: input parameter list ZGen_2Phase_Out *out // OUT: output parameter list ) { TPM_RC result; OBJECT *eccKey; TPM2B_ECC_PARAMETER r; TPM_ALG_ID scheme; // Input Validation eccKey = HandleToObject(in->keyA); // keyA must be an ECC key if(eccKey->publicArea.type != TPM_ALG_ECC) return TPM_RCS_KEY + RC_ZGen_2Phase_keyA; // keyA must not be restricted and must be a decrypt key if(IS_ATTRIBUTE(eccKey->publicArea.objectAttributes, TPMA_OBJECT, restricted) || !IS_ATTRIBUTE(eccKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt)) return TPM_RCS_ATTRIBUTES + RC_ZGen_2Phase_keyA; // if the scheme of keyA is TPM_ALG_NULL, then use the input scheme; otherwise // the input scheme must be the same as the scheme of keyA scheme = eccKey->publicArea.parameters.asymDetail.scheme.scheme; if(scheme != TPM_ALG_NULL) { if(scheme != in->inScheme) return TPM_RCS_SCHEME + RC_ZGen_2Phase_inScheme; } else scheme = in->inScheme; if(scheme == TPM_ALG_NULL) return TPM_RCS_SCHEME + RC_ZGen_2Phase_inScheme; // Input points must be on the curve of keyA if(!CryptEccIsPointOnCurve(eccKey->publicArea.parameters.eccDetail.curveID, &in->inQsB.point)) return TPM_RCS_ECC_POINT + RC_ZGen_2Phase_inQsB; if(!CryptEccIsPointOnCurve(eccKey->publicArea.parameters.eccDetail.curveID, &in->inQeB.point)) return TPM_RCS_ECC_POINT + RC_ZGen_2Phase_inQeB; if(!CryptGenerateR(&r, &in->counter, eccKey->publicArea.parameters.eccDetail.curveID, NULL)) return TPM_RCS_VALUE + RC_ZGen_2Phase_counter; // Command Output result = CryptEcc2PhaseKeyExchange(&out->outZ1.point, &out->outZ2.point, eccKey->publicArea.parameters.eccDetail.curveID, scheme, &eccKey->sensitive.sensitive.ecc, &r, &in->inQsB.point, &in->inQeB.point); if(result == TPM_RC_SCHEME) return TPM_RCS_SCHEME + RC_ZGen_2Phase_inScheme; if(result == TPM_RC_SUCCESS) CryptEndCommit(in->counter); return result; } #endif // CC_ZGen_2Phase libtpms-0.9.3/src/tpm2/Attest_spt.c000066400000000000000000000217651421143571500171620ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Attest_spt.c 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2018 */ /* */ /********************************************************************************/ #include "Tpm.h" #include "Attest_spt_fp.h" /* 7.2.2 Functions */ /* 7.2.2.1 FillInAttestInfo() */ /* Fill in common fields of TPMS_ATTEST structure. */ void FillInAttestInfo( TPMI_DH_OBJECT signHandle, // IN: handle of signing object TPMT_SIG_SCHEME *scheme, // IN/OUT: scheme to be used for signing TPM2B_DATA *data, // IN: qualifying data TPMS_ATTEST *attest // OUT: attest structure ) { OBJECT *signObject = HandleToObject(signHandle); // Magic number attest->magic = TPM_GENERATED_VALUE; if(signObject == NULL) { // The name for a null handle is TPM_RH_NULL // This is defined because UINT32_TO_BYTE_ARRAY does a cast. If the // size of the cast is smaller than a constant, the compiler warns // about the truncation of a constant value. TPM_HANDLE nullHandle = TPM_RH_NULL; attest->qualifiedSigner.t.size = sizeof(TPM_HANDLE); UINT32_TO_BYTE_ARRAY(nullHandle, attest->qualifiedSigner.t.name); } else { // Certifying object qualified name // if the scheme is anonymous, this is an empty buffer if(CryptIsSchemeAnonymous(scheme->scheme)) attest->qualifiedSigner.t.size = 0; else attest->qualifiedSigner = signObject->qualifiedName; } // current clock in plain text TimeFillInfo(&attest->clockInfo); // Firmware version in plain text attest->firmwareVersion = ((UINT64)gp.firmwareV1 << (sizeof(UINT32) * 8)); attest->firmwareVersion += gp.firmwareV2; // Check the hierarchy of sign object. For NULL sign handle, the hierarchy // will be TPM_RH_NULL if((signObject == NULL) || (!signObject->attributes.epsHierarchy && !signObject->attributes.ppsHierarchy)) { // For signing key that is not in platform or endorsement hierarchy, // obfuscate the reset, restart and firmware version information UINT64 obfuscation[2]; CryptKDFa(CONTEXT_INTEGRITY_HASH_ALG, &gp.shProof.b, OBFUSCATE_STRING, &attest->qualifiedSigner.b, NULL, 128, (BYTE *)&obfuscation[0], NULL, FALSE); // Obfuscate data attest->firmwareVersion += obfuscation[0]; attest->clockInfo.resetCount += (UINT32)(obfuscation[1] >> 32); attest->clockInfo.restartCount += (UINT32)obfuscation[1]; } // External data if(CryptIsSchemeAnonymous(scheme->scheme)) attest->extraData.t.size = 0; else { // If we move the data to the attestation structure, then it is not // used in the signing operation except as part of the signed data attest->extraData = *data; data->t.size = 0; } } /* 7.2.2.2 SignAttestInfo() */ /* Sign a TPMS_ATTEST structure. If signHandle is TPM_RH_NULL, a null signature is returned. */ /* Error Returns Meaning */ /* TPM_RC_ATTRIBUTES signHandle references not a signing key */ /* TPM_RC_SCHEME scheme is not compatible with signHandle type */ /* TPM_RC_VALUE digest generated for the given scheme is greater than the modulus of signHandle (for an RSA key); invalid commit status or failed to generate r value (for an ECC key) */ TPM_RC SignAttestInfo( OBJECT *signKey, // IN: sign object TPMT_SIG_SCHEME *scheme, // IN: sign scheme TPMS_ATTEST *certifyInfo, // IN: the data to be signed TPM2B_DATA *qualifyingData, // IN: extra data for the signing // process TPM2B_ATTEST *attest, // OUT: marshaled attest blob to be // signed TPMT_SIGNATURE *signature // OUT: signature ) { BYTE *buffer; HASH_STATE hashState; TPM2B_DIGEST digest; TPM_RC result; // Marshal TPMS_ATTEST structure for hash buffer = attest->t.attestationData; attest->t.size = TPMS_ATTEST_Marshal(certifyInfo, &buffer, NULL); if(signKey == NULL) { signature->sigAlg = TPM_ALG_NULL; result = TPM_RC_SUCCESS; } else { TPMI_ALG_HASH hashAlg; // Compute hash hashAlg = scheme->details.any.hashAlg; // need to set the receive buffer to get something put in it digest.t.size = sizeof(digest.t.buffer); digest.t.size = CryptHashBlock(hashAlg, attest->t.size, attest->t.attestationData, digest.t.size, digest.t.buffer); // If there is qualifying data, need to rehash the data // hash(qualifyingData || hash(attestationData)) if(qualifyingData->t.size != 0) { CryptHashStart(&hashState, hashAlg); CryptDigestUpdate2B(&hashState, &qualifyingData->b); CryptDigestUpdate2B(&hashState, &digest.b); CryptHashEnd2B(&hashState, &digest.b); } // Sign the hash. A TPM_RC_VALUE, TPM_RC_SCHEME, or // TPM_RC_ATTRIBUTES error may be returned at this point result = CryptSign(signKey, scheme, &digest, signature); // Since the clock is used in an attestation, the state in NV is no longer // "orderly" with respect to the data in RAM if the signature is valid if(result == TPM_RC_SUCCESS) { // Command uses the clock so need to clear the orderly state if it is // set. result = NvClearOrderly(); } } return result; } /* 7.2.2.3 IsSigningObject() */ /* Checks to see if the object is OK for signing. This is here rather than in Object_spt.c because all the attestation commands use this file but not Object_spt.c. */ /* Return Values Meaning */ /* TRUE object may sign */ /* FALSE object may not sign */ BOOL IsSigningObject( OBJECT *object // IN: ) { return ((object == NULL) || ((IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, sign) && object->publicArea.type != TPM_ALG_SYMCIPHER))); } libtpms-0.9.3/src/tpm2/Attest_spt_fp.h000066400000000000000000000103641421143571500176450ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Attest_spt_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 */ /* */ /********************************************************************************/ #ifndef ATTEST_SPT_FP_H #define ATTEST_SPT_FP_H void FillInAttestInfo( TPMI_DH_OBJECT signHandle, // IN: handle of signing object TPMT_SIG_SCHEME *scheme, // IN/OUT: scheme to be used for signing TPM2B_DATA *data, // IN: qualifying data TPMS_ATTEST *attest // OUT: attest structure ); TPM_RC SignAttestInfo( OBJECT *signKey, // IN: sign object TPMT_SIG_SCHEME *scheme, // IN: sign scheme TPMS_ATTEST *certifyInfo, // IN: the data to be signed TPM2B_DATA *qualifyingData, // IN: extra data for the signing // process TPM2B_ATTEST *attest, // OUT: marshaled attest blob to be // signed TPMT_SIGNATURE *signature // OUT: signature ); BOOL IsSigningObject( OBJECT *object // IN: ); #endif libtpms-0.9.3/src/tpm2/AttestationCommands.c000066400000000000000000000564101421143571500210040ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Attestation Commands */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: AttestationCommands.c 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2021 */ /* */ /********************************************************************************/ #include "Tpm.h" #include "Attest_spt_fp.h" #include "Certify_fp.h" #if CC_Certify // Conditional expansion of this file TPM_RC TPM2_Certify( Certify_In *in, // IN: input parameter list Certify_Out *out // OUT: output parameter list ) { TPMS_ATTEST certifyInfo; OBJECT *signObject = HandleToObject(in->signHandle); OBJECT *certifiedObject = HandleToObject(in->objectHandle); // Input validation if(!IsSigningObject(signObject)) return TPM_RCS_KEY + RC_Certify_signHandle; if(!CryptSelectSignScheme(signObject, &in->inScheme)) return TPM_RCS_SCHEME + RC_Certify_inScheme; // Command Output // Filling in attest information // Common fields FillInAttestInfo(in->signHandle, &in->inScheme, &in->qualifyingData, &certifyInfo); // Certify specific fields certifyInfo.type = TPM_ST_ATTEST_CERTIFY; // NOTE: the certified object is not allowed to be TPM_ALG_NULL so // 'certifiedObject' will never be NULL certifyInfo.attested.certify.name = certifiedObject->name; // When using an anonymous signing scheme, need to set the qualified Name to the // empty buffer to avoid correlation between keys if(CryptIsSchemeAnonymous(in->inScheme.scheme)) certifyInfo.attested.certify.qualifiedName.t.size = 0; else certifyInfo.attested.certify.qualifiedName = certifiedObject->qualifiedName; // Sign attestation structure. A NULL signature will be returned if // signHandle is TPM_RH_NULL. A TPM_RC_NV_UNAVAILABLE, TPM_RC_NV_RATE, // TPM_RC_VALUE, TPM_RC_SCHEME or TPM_RC_ATTRIBUTES error may be returned // by SignAttestInfo() return SignAttestInfo(signObject, &in->inScheme, &certifyInfo, &in->qualifyingData, &out->certifyInfo, &out->signature); } #endif // CC_Certify #include "Tpm.h" #include "Attest_spt_fp.h" #include "CertifyCreation_fp.h" #if CC_CertifyCreation // Conditional expansion of this file TPM_RC TPM2_CertifyCreation( CertifyCreation_In *in, // IN: input parameter list CertifyCreation_Out *out // OUT: output parameter list ) { TPMT_TK_CREATION ticket; TPMS_ATTEST certifyInfo; OBJECT *certified = HandleToObject(in->objectHandle); OBJECT *signObject = HandleToObject(in->signHandle); // Input Validation if(!IsSigningObject(signObject)) return TPM_RCS_KEY + RC_CertifyCreation_signHandle; if(!CryptSelectSignScheme(signObject, &in->inScheme)) return TPM_RCS_SCHEME + RC_CertifyCreation_inScheme; // CertifyCreation specific input validation // Re-compute ticket TicketComputeCreation(in->creationTicket.hierarchy, &certified->name, &in->creationHash, &ticket); // Compare ticket if(!MemoryEqual2B(&ticket.digest.b, &in->creationTicket.digest.b)) return TPM_RCS_TICKET + RC_CertifyCreation_creationTicket; // Command Output // Common fields FillInAttestInfo(in->signHandle, &in->inScheme, &in->qualifyingData, &certifyInfo); // CertifyCreation specific fields // Attestation type certifyInfo.type = TPM_ST_ATTEST_CREATION; certifyInfo.attested.creation.objectName = certified->name; // Copy the creationHash certifyInfo.attested.creation.creationHash = in->creationHash; // Sign attestation structure. A NULL signature will be returned if // signObject is TPM_RH_NULL. A TPM_RC_NV_UNAVAILABLE, TPM_RC_NV_RATE, // TPM_RC_VALUE, TPM_RC_SCHEME or TPM_RC_ATTRIBUTES error may be returned at // this point return SignAttestInfo(signObject, &in->inScheme, &certifyInfo, &in->qualifyingData, &out->certifyInfo, &out->signature); } #endif // CC_CertifyCreation #include "Tpm.h" #include "Attest_spt_fp.h" #include "Quote_fp.h" #if CC_Quote // Conditional expansion of this file TPM_RC TPM2_Quote( Quote_In *in, // IN: input parameter list Quote_Out *out // OUT: output parameter list ) { TPMI_ALG_HASH hashAlg; TPMS_ATTEST quoted; OBJECT *signObject = HandleToObject(in->signHandle); // Input Validation if(!IsSigningObject(signObject)) return TPM_RCS_KEY + RC_Quote_signHandle; if(!CryptSelectSignScheme(signObject, &in->inScheme)) return TPM_RCS_SCHEME + RC_Quote_inScheme; // Command Output // Filling in attest information // Common fields // FillInAttestInfo may return TPM_RC_SCHEME or TPM_RC_KEY FillInAttestInfo(in->signHandle, &in->inScheme, &in->qualifyingData, "ed); // Quote specific fields // Attestation type quoted.type = TPM_ST_ATTEST_QUOTE; // Get hash algorithm in sign scheme. This hash algorithm is used to // compute PCR digest. If there is no algorithm, then the PCR cannot // be digested and this command returns TPM_RC_SCHEME hashAlg = in->inScheme.details.any.hashAlg; if(hashAlg == TPM_ALG_NULL) return TPM_RCS_SCHEME + RC_Quote_inScheme; // Compute PCR digest PCRComputeCurrentDigest(hashAlg, &in->PCRselect, "ed.attested.quote.pcrDigest); // Copy PCR select. "PCRselect" is modified in PCRComputeCurrentDigest // function quoted.attested.quote.pcrSelect = in->PCRselect; // Sign attestation structure. A NULL signature will be returned if // signObject is NULL. return SignAttestInfo(signObject, &in->inScheme, "ed, &in->qualifyingData, &out->quoted, &out->signature); } #endif // CC_Quote #include "Tpm.h" #include "Attest_spt_fp.h" #include "GetSessionAuditDigest_fp.h" #if CC_GetSessionAuditDigest // Conditional expansion of this file TPM_RC TPM2_GetSessionAuditDigest( GetSessionAuditDigest_In *in, // IN: input parameter list GetSessionAuditDigest_Out *out // OUT: output parameter list ) { SESSION *session = SessionGet(in->sessionHandle); TPMS_ATTEST auditInfo; OBJECT *signObject = HandleToObject(in->signHandle); // Input Validation if(!IsSigningObject(signObject)) return TPM_RCS_KEY + RC_GetSessionAuditDigest_signHandle; if(!CryptSelectSignScheme(signObject, &in->inScheme)) return TPM_RCS_SCHEME + RC_GetSessionAuditDigest_inScheme; // session must be an audit session if(session->attributes.isAudit == CLEAR) return TPM_RCS_TYPE + RC_GetSessionAuditDigest_sessionHandle; // Command Output // Fill in attest information common fields FillInAttestInfo(in->signHandle, &in->inScheme, &in->qualifyingData, &auditInfo); // SessionAuditDigest specific fields auditInfo.type = TPM_ST_ATTEST_SESSION_AUDIT; auditInfo.attested.sessionAudit.sessionDigest = session->u2.auditDigest; // Exclusive audit session auditInfo.attested.sessionAudit.exclusiveSession = (g_exclusiveAuditSession == in->sessionHandle); // Sign attestation structure. A NULL signature will be returned if // signObject is NULL. return SignAttestInfo(signObject, &in->inScheme, &auditInfo, &in->qualifyingData, &out->auditInfo, &out->signature); } #endif // CC_GetSessionAuditDigest #include "Tpm.h" #include "Attest_spt_fp.h" #include "GetCommandAuditDigest_fp.h" #if CC_GetCommandAuditDigest // Conditional expansion of this file TPM_RC TPM2_GetCommandAuditDigest( GetCommandAuditDigest_In *in, // IN: input parameter list GetCommandAuditDigest_Out *out // OUT: output parameter list ) { TPM_RC result; TPMS_ATTEST auditInfo; OBJECT *signObject = HandleToObject(in->signHandle); // Input validation if(!IsSigningObject(signObject)) return TPM_RCS_KEY + RC_GetCommandAuditDigest_signHandle; if(!CryptSelectSignScheme(signObject, &in->inScheme)) return TPM_RCS_SCHEME + RC_GetCommandAuditDigest_inScheme; // Command Output // Fill in attest information common fields FillInAttestInfo(in->signHandle, &in->inScheme, &in->qualifyingData, &auditInfo); // CommandAuditDigest specific fields auditInfo.type = TPM_ST_ATTEST_COMMAND_AUDIT; auditInfo.attested.commandAudit.digestAlg = gp.auditHashAlg; auditInfo.attested.commandAudit.auditCounter = gp.auditCounter; // Copy command audit log auditInfo.attested.commandAudit.auditDigest = gr.commandAuditDigest; CommandAuditGetDigest(&auditInfo.attested.commandAudit.commandDigest); // Sign attestation structure. A NULL signature will be returned if // signHandle is TPM_RH_NULL. A TPM_RC_NV_UNAVAILABLE, TPM_RC_NV_RATE, // TPM_RC_VALUE, TPM_RC_SCHEME or TPM_RC_ATTRIBUTES error may be returned at // this point result = SignAttestInfo(signObject, &in->inScheme, &auditInfo, &in->qualifyingData, &out->auditInfo, &out->signature); // Internal Data Update if(result == TPM_RC_SUCCESS && in->signHandle != TPM_RH_NULL) // Reset log gr.commandAuditDigest.t.size = 0; return result; } #endif // CC_GetCommandAuditDigest #include "Tpm.h" #include "Attest_spt_fp.h" #include "GetTime_fp.h" #if CC_GetTime // Conditional expansion of this file TPM_RC TPM2_GetTime( GetTime_In *in, // IN: input parameter list GetTime_Out *out // OUT: output parameter list ) { TPMS_ATTEST timeInfo; OBJECT *signObject = HandleToObject(in->signHandle); // Input Validation if(!IsSigningObject(signObject)) return TPM_RCS_KEY + RC_GetTime_signHandle; if(!CryptSelectSignScheme(signObject, &in->inScheme)) return TPM_RCS_SCHEME + RC_GetTime_inScheme; // Command Output // Fill in attest common fields FillInAttestInfo(in->signHandle, &in->inScheme, &in->qualifyingData, &timeInfo); // GetClock specific fields timeInfo.type = TPM_ST_ATTEST_TIME; timeInfo.attested.time.time.time = g_time; TimeFillInfo(&timeInfo.attested.time.time.clockInfo); // Firmware version in plain text timeInfo.attested.time.firmwareVersion = (((UINT64)gp.firmwareV1) << 32) + gp.firmwareV2; // Sign attestation structure. A NULL signature will be returned if // signObject is NULL. return SignAttestInfo(signObject, &in->inScheme, &timeInfo, &in->qualifyingData, &out->timeInfo, &out->signature); } #endif // CC_GetTime #include "Tpm.h" #include "CertifyX509_fp.h" #include "X509.h" #include "TpmAsn1_fp.h" #include "X509_spt_fp.h" #include "Attest_spt_fp.h" #include "Platform_fp.h" #if CC_CertifyX509 // Conditional expansion of this file #if CERTIFYX509_DEBUG #include "DebugHelpers_fp.h" #endif /* Error Returns Meaning*/ /* TPM_RC_ATTRIBUTES the attributes of objectHandle are not compatible with the KeyUsage() or TPMA_OBJECT values in the extensions fields */ /* TPM_RC_BINDING the public and private portions of the key are not properly bound. */ /* TPM_RC_HASH the hash algorithm in the scheme is not supported */ /* TPM_RC_KEY signHandle does not reference a signing key; */ /* TPM_RC_SCHEME the scheme is not compatible with sign key type, or input scheme is not compatible with default scheme, or the chosen scheme is not a valid sign scheme */ /* TPM_RC_VALUE most likely a problem with the format of partialCertificate */ TPM_RC TPM2_CertifyX509( CertifyX509_In *in, // IN: input parameter list CertifyX509_Out *out // OUT: output parameter list ) { TPM_RC result; OBJECT *signKey = HandleToObject(in->signHandle); OBJECT *object = HandleToObject(in->objectHandle); HASH_STATE hash; INT16 length; // length for a tagged element ASN1UnmarshalContext ctx; ASN1MarshalContext ctxOut; // certTBS holds an array of pointers and lengths. Each entry references the // corresponding value in a TBSCertificate structure. For example, the 1th // element references the version number stringRef certTBS[REF_COUNT] = {{0}}; #define ALLOWED_SEQUENCES (SUBJECT_PUBLIC_KEY_REF - SIGNATURE_REF) stringRef partial[ALLOWED_SEQUENCES] = {{0}}; INT16 countOfSequences = 0; INT16 i; // #if CERTIFYX509_DEBUG DebugFileInit(); DebugDumpBuffer(in->partialCertificate.t.size, in->partialCertificate.t.buffer, "partialCertificate"); #endif // Input Validation if(in->reserved.b.size != 0) return TPM_RC_SIZE + RC_CertifyX509_reserved; // signing key must be able to sign if(!IsSigningObject(signKey)) return TPM_RCS_KEY + RC_CertifyX509_signHandle; // Pick a scheme for sign. If the input sign scheme is not compatible with // the default scheme, return an error. if(!CryptSelectSignScheme(signKey, &in->inScheme)) return TPM_RCS_SCHEME + RC_CertifyX509_inScheme; // Make sure that the public Key encoding is known if(X509AddPublicKey(NULL, object) == 0) return TPM_RCS_ASYMMETRIC + RC_CertifyX509_objectHandle; // Unbundle 'partialCertificate'. // Initialize the unmarshaling context if(!ASN1UnmarshalContextInitialize(&ctx, in->partialCertificate.t.size, in->partialCertificate.t.buffer)) return TPM_RCS_VALUE + RC_CertifyX509_partialCertificate; // Make sure that this is a constructed SEQUENCE length = ASN1NextTag(&ctx); // Must be a constructed SEQUENCE that uses all of the input parameter if((ctx.tag != (ASN1_CONSTRUCTED_SEQUENCE)) || ((ctx.offset + length) != in->partialCertificate.t.size)) return TPM_RCS_SIZE + RC_CertifyX509_partialCertificate; // This scans through the contents of the outermost SEQUENCE. This would be the // 'issuer', 'validity', 'subject', 'issuerUniqueID' (optional), // 'subjectUniqueID' (optional), and 'extensions.' while(ctx.offset < ctx.size) { INT16 startOfElement = ctx.offset; // // Read the next tag and length field. length = ASN1NextTag(&ctx); if(length < 0) break; if(ctx.tag == ASN1_CONSTRUCTED_SEQUENCE) { partial[countOfSequences].buf = &ctx.buffer[startOfElement]; ctx.offset += length; partial[countOfSequences].len = (INT16)ctx.offset - startOfElement; if(++countOfSequences > ALLOWED_SEQUENCES) break; } else if(ctx.tag == X509_EXTENSIONS) { if(certTBS[EXTENSIONS_REF].len != 0) return TPM_RCS_VALUE + RC_CertifyX509_partialCertificate; certTBS[EXTENSIONS_REF].buf = &ctx.buffer[startOfElement]; ctx.offset += length; certTBS[EXTENSIONS_REF].len = (INT16)ctx.offset - startOfElement; } else return TPM_RCS_VALUE + RC_CertifyX509_partialCertificate; } // Make sure that we used all of the data and found at least the required // number of elements. if((ctx.offset != ctx.size) || (countOfSequences < 3) || (countOfSequences > 4) || (certTBS[EXTENSIONS_REF].buf == NULL)) return TPM_RCS_VALUE + RC_CertifyX509_partialCertificate; // Now that we know how many sequences there were, we can put them where they // belong for(i = 0; i < countOfSequences; i++) certTBS[SUBJECT_KEY_REF - i] = partial[countOfSequences - 1 - i]; // If only three SEQUENCES, then the TPM needs to produce the signature algorithm. // See if it can if((countOfSequences == 3) && (X509AddSigningAlgorithm(NULL, signKey, &in->inScheme) == 0)) return TPM_RCS_SCHEME + RC_CertifyX509_signHandle; // Process the extensions result = X509ProcessExtensions(object, &certTBS[EXTENSIONS_REF]); if(result != TPM_RC_SUCCESS) // If the extension has the TPMA_OBJECT extension and the attributes don't // match, then the error code will be TPM_RCS_ATTRIBUTES. Otherwise, the error // indicates a malformed partialCertificate. return result + ((result == TPM_RCS_ATTRIBUTES) ? RC_CertifyX509_objectHandle : RC_CertifyX509_partialCertificate); // Command Output // Create the addedToCertificate values // Build the addedToCertificate from the bottom up. // Initialize the context structure ASN1InitialializeMarshalContext(&ctxOut, sizeof(out->addedToCertificate.t.buffer), out->addedToCertificate.t.buffer); // Place a marker for the overall context ASN1StartMarshalContext(&ctxOut); // SEQUENCE for addedToCertificate // Add the subject public key descriptor certTBS[SUBJECT_PUBLIC_KEY_REF].len = X509AddPublicKey(&ctxOut, object); certTBS[SUBJECT_PUBLIC_KEY_REF].buf = ctxOut.buffer + ctxOut.offset; // If the caller didn't provide the algorithm identifier, create it if(certTBS[SIGNATURE_REF].len == 0) { certTBS[SIGNATURE_REF].len = X509AddSigningAlgorithm(&ctxOut, signKey, &in->inScheme); certTBS[SIGNATURE_REF].buf = ctxOut.buffer + ctxOut.offset; } // Create the serial number value. Use the out->tbsDigest as scratch. { TPM2B *digest = &out->tbsDigest.b; // digest->size = (INT16)CryptHashStart(&hash, signKey->publicArea.nameAlg); pAssert(digest->size != 0); // The serial number size is the smaller of the digest and the vendor-defined // value digest->size = MIN(digest->size, SIZE_OF_X509_SERIAL_NUMBER); // Add all the parts of the certificate other than the serial number // and version number for(i = SIGNATURE_REF; i < REF_COUNT; i++) CryptDigestUpdate(&hash, certTBS[i].len, certTBS[i].buf); // throw in the Name of the signing key... CryptDigestUpdate2B(&hash, &signKey->name.b); // ...and the Name of the signed key. CryptDigestUpdate2B(&hash, &object->name.b); // Done CryptHashEnd2B(&hash, digest); } // Add the serial number certTBS[SERIAL_NUMBER_REF].len = ASN1PushInteger(&ctxOut, out->tbsDigest.t.size, out->tbsDigest.t.buffer); certTBS[SERIAL_NUMBER_REF].buf = ctxOut.buffer + ctxOut.offset; // Add the static version number ASN1StartMarshalContext(&ctxOut); ASN1PushUINT(&ctxOut, 2); certTBS[VERSION_REF].len = ASN1EndEncapsulation(&ctxOut, ASN1_APPLICAIION_SPECIFIC); certTBS[VERSION_REF].buf = ctxOut.buffer + ctxOut.offset; // Create a fake tag and length for the TBS in the space used for // 'addedToCertificate' { for(length = 0, i = 0; i < REF_COUNT; i++) length += certTBS[i].len; // Put a fake tag and length into the buffer for use in the tbsDigest certTBS[ENCODED_SIZE_REF].len = ASN1PushTagAndLength(&ctxOut, ASN1_CONSTRUCTED_SEQUENCE, length); certTBS[ENCODED_SIZE_REF].buf = ctxOut.buffer + ctxOut.offset; // Restore the buffer pointer to add back the number of octets used for the // tag and length ctxOut.offset += certTBS[ENCODED_SIZE_REF].len; } // sanity check if(ctxOut.offset < 0) return TPM_RC_FAILURE; // Create the tbsDigest to sign out->tbsDigest.t.size = CryptHashStart(&hash, in->inScheme.details.any.hashAlg); for(i = 0; i < REF_COUNT; i++) CryptDigestUpdate(&hash, certTBS[i].len, certTBS[i].buf); CryptHashEnd2B(&hash, &out->tbsDigest.b); #if CERTIFYX509_DEBUG { BYTE fullTBS[4096]; BYTE *fill = fullTBS; int j; for (j = 0; j < REF_COUNT; j++) { MemoryCopy(fill, certTBS[j].buf, certTBS[j].len); fill += certTBS[j].len; } DebugDumpBuffer((int)(fill - &fullTBS[0]), fullTBS, "\nfull TBS"); } #endif // Finish up the processing of addedToCertificate // Create the actual tag and length for the addedToCertificate structure out->addedToCertificate.t.size = ASN1EndEncapsulation(&ctxOut, ASN1_CONSTRUCTED_SEQUENCE); // Now move all the addedToContext to the start of the buffer MemoryCopy(out->addedToCertificate.t.buffer, ctxOut.buffer + ctxOut.offset, out->addedToCertificate.t.size); #if CERTIFYX509_DEBUG DebugDumpBuffer(out->addedToCertificate.t.size, out->addedToCertificate.t.buffer, "\naddedToCertificate"); #endif // only thing missing is the signature result = CryptSign(signKey, &in->inScheme, &out->tbsDigest, &out->signature); return result; } #endif // CC_CertifyX509 libtpms-0.9.3/src/tpm2/AuditCommands.c000066400000000000000000000124131421143571500175460ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Command Audit */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: AuditCommands.c 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2018 */ /* */ /********************************************************************************/ #include "Tpm.h" #include "SetCommandCodeAuditStatus_fp.h" #if CC_SetCommandCodeAuditStatus // Conditional expansion of this file TPM_RC TPM2_SetCommandCodeAuditStatus( SetCommandCodeAuditStatus_In *in // IN: input parameter list ) { // The command needs NV update. Check if NV is available. // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at // this point RETURN_IF_NV_IS_NOT_AVAILABLE; // Internal Data Update // Update hash algorithm if(in->auditAlg != TPM_ALG_NULL && in->auditAlg != gp.auditHashAlg) { // Can't change the algorithm and command list at the same time if(in->setList.count != 0 || in->clearList.count != 0) return TPM_RCS_VALUE + RC_SetCommandCodeAuditStatus_auditAlg; // Change the hash algorithm for audit gp.auditHashAlg = in->auditAlg; // Set the digest size to a unique value that indicates that the digest // algorithm has been changed. The size will be cleared to zero in the // command audit processing on exit. gr.commandAuditDigest.t.size = 1; // Save the change of command audit data (this sets g_updateNV so that NV // will be updated on exit.) NV_SYNC_PERSISTENT(auditHashAlg); } else { UINT32 i; BOOL changed = FALSE; // Process set list for(i = 0; i < in->setList.count; i++) // If change is made in CommandAuditSet, set changed flag if(CommandAuditSet(in->setList.commandCodes[i])) changed = TRUE; // Process clear list for(i = 0; i < in->clearList.count; i++) // If change is made in CommandAuditClear, set changed flag if(CommandAuditClear(in->clearList.commandCodes[i])) changed = TRUE; // if change was made to command list, update NV if(changed) // this sets g_updateNV so that NV will be updated on exit. NV_SYNC_PERSISTENT(auditCommands); } return TPM_RC_SUCCESS; } #endif // CC_SetCommandCodeAuditStatus libtpms-0.9.3/src/tpm2/BackwardsCompatibility.h000066400000000000000000000046541421143571500214660ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Backwards compatibility related stuff */ /* Written by Stefan Berger */ /* IBM Thomas J. Watson Research Center */ /* */ /* (c) Copyright IBM Corporation 2017,2018. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef BACKWARDS_COMPATIBILITY_H #define BACKWARDS_COMPATIBILITY_H typedef UINT8 SEED_COMPAT_LEVEL; enum { SEED_COMPAT_LEVEL_ORIGINAL = 0, /* original TPM 2 code up to rev155 */ SEED_COMPAT_LEVEL_RSA_PRIME_ADJUST_FIX = 1, /* RsaAdjustPrimeCandidate was fixed */ SEED_COMPAT_LEVEL_LAST = SEED_COMPAT_LEVEL_RSA_PRIME_ADJUST_FIX }; #endif /* BACKWARDS_COMPATIBILITY_H */ libtpms-0.9.3/src/tpm2/BackwardsCompatibilityObject.c000066400000000000000000000215361421143571500226060ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Backwards compatibility stuff related to OBJECT */ /* Written by Stefan Berger */ /* IBM Thomas J. Watson Research Center */ /* */ /* (c) Copyright IBM Corporation 2017,2018. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include #include "BackwardsCompatibilityObject.h" #ifndef static_assert #define static_assert(test, msg) #endif /* The following are data structure from libtpms 0.7.x with RSA 2048 support * that help to resume key and hash contexts (TPM2_ContextSave/Load) from this * earlier version. All structures that have different sizes in 0.8 are found * here. */ typedef union { struct { UINT16 size; BYTE buffer[2048/8]; } t; TPM2B b; } OLD_TPM2B_PUBLIC_KEY_RSA; typedef union { TPM2B_DIGEST keyedHash; TPM2B_DIGEST sym; OLD_TPM2B_PUBLIC_KEY_RSA rsa; TPMS_ECC_POINT ecc; // TPMS_DERIVE derive; } OLD_TPMU_PUBLIC_ID; typedef struct { TPMI_ALG_PUBLIC type; TPMI_ALG_HASH nameAlg; TPMA_OBJECT objectAttributes; TPM2B_DIGEST authPolicy; TPMU_PUBLIC_PARMS parameters; OLD_TPMU_PUBLIC_ID unique; } OLD_TPMT_PUBLIC; static_assert(sizeof(OLD_TPMT_PUBLIC) == 356, "OLD_TPMT_PUBLIC has wrong size"); typedef union { struct { UINT16 size; BYTE buffer[((2048/8)/2)*5]; } t; TPM2B b; } OLD_TPM2B_PRIVATE_KEY_RSA; static_assert(sizeof(OLD_TPM2B_PRIVATE_KEY_RSA) == 642, "OLD_TPM2B_PRIVATE_KEY_RSA has wrong size"); typedef union { struct { UINT16 size; BYTE buffer[((2048/8)/2)*5]; } t; TPM2B b; } OLD_TPM2B_PRIVATE_VENDOR_SPECIFIC; typedef union { OLD_TPM2B_PRIVATE_KEY_RSA rsa; TPM2B_ECC_PARAMETER ecc; TPM2B_SENSITIVE_DATA bits; TPM2B_SYM_KEY sym; OLD_TPM2B_PRIVATE_VENDOR_SPECIFIC any; } OLD_TPMU_SENSITIVE_COMPOSITE; typedef struct { TPMI_ALG_PUBLIC sensitiveType; TPM2B_AUTH authValue; TPM2B_DIGEST seedValue; OLD_TPMU_SENSITIVE_COMPOSITE sensitive; } OLD_TPMT_SENSITIVE; static_assert(sizeof(OLD_TPMT_SENSITIVE) == 776, "OLD_TPMT_SENSITIVE has wrong size"); BN_TYPE(old_prime, (2048 / 2)); typedef struct OLD_privateExponent { bn_old_prime_t Q; bn_old_prime_t dP; bn_old_prime_t dQ; bn_old_prime_t qInv; } OLD_privateExponent_t; static inline void CopyFromOldPrimeT(bn_prime_t *dst, const bn_old_prime_t *src) { dst->allocated = src->allocated; dst->size = src->size; memcpy(dst->d, src->d, sizeof(src->d)); } static_assert(sizeof(OLD_privateExponent_t) == 608, "OLD_privateExponent_t has wrong size"); typedef struct OLD_OBJECT { // The attributes field is required to be first followed by the publicArea. // This allows the overlay of the object structure and a sequence structure OBJECT_ATTRIBUTES attributes; // object attributes OLD_TPMT_PUBLIC publicArea; // public area of an object OLD_TPMT_SENSITIVE sensitive; // sensitive area of an object OLD_privateExponent_t privateExponent; // Additional field for the private TPM2B_NAME qualifiedName; // object qualified name TPMI_DH_OBJECT evictHandle; // if the object is an evict object, // the original handle is kept here. // The 'working' handle will be the // handle of an object slot. TPM2B_NAME name; // Name of the object name. Kept here // to avoid repeatedly computing it. // libtpms added: OBJECT lies in NVRAM; to avoid that it needs different number // of bytes on 32 bit and 64 bit architectures, we need to make sure it's the // same size; simple padding at the end works here UINT32 _pad; } OLD_OBJECT; static_assert(sizeof(OLD_OBJECT) == 1896, "OLD_OBJECT has wrong size"); // Convert an OLD_OBJECT that was copied into buffer using MemoryCopy TPM_RC OLD_OBJECTToOBJECT(OBJECT *newObject, BYTE *buffer, INT32 size) { OLD_OBJECT oldObject; TPM_RC rc = 0; // get the attributes MemoryCopy(newObject, buffer, sizeof(newObject->attributes)); if (ObjectIsSequence(newObject)) { /* resuming old hash contexts is not supported */ rc = TPM_RC_DISABLED; } else { if (size != sizeof(OLD_OBJECT)) return TPM_RC_SIZE; MemoryCopy(&oldObject, buffer, sizeof(OLD_OBJECT)); /* fill the newObject with the contents of the oldObject */ newObject->attributes = oldObject.attributes; newObject->publicArea.type = oldObject.publicArea.type; newObject->publicArea.nameAlg = oldObject.publicArea.nameAlg; newObject->publicArea.objectAttributes = oldObject.publicArea.objectAttributes; newObject->publicArea.authPolicy = oldObject.publicArea.authPolicy; newObject->publicArea.parameters = oldObject.publicArea.parameters; /* the unique part can be one or two TPM2B's */ switch (newObject->publicArea.type) { case TPM_ALG_KEYEDHASH: MemoryCopy2B(&newObject->publicArea.unique.keyedHash.b, &oldObject.publicArea.unique.keyedHash.b, sizeof(oldObject.publicArea.unique.keyedHash.t.buffer)); break; case TPM_ALG_SYMCIPHER: MemoryCopy2B(&newObject->publicArea.unique.sym.b, &oldObject.publicArea.unique.sym.b, sizeof(oldObject.publicArea.unique.sym.t.buffer)); break; case TPM_ALG_RSA: MemoryCopy2B(&newObject->publicArea.unique.rsa.b, &oldObject.publicArea.unique.rsa.b, sizeof(oldObject.publicArea.unique.rsa.t.buffer)); break; case TPM_ALG_ECC: MemoryCopy2B(&newObject->publicArea.unique.ecc.x.b, &oldObject.publicArea.unique.ecc.x.b, sizeof(oldObject.publicArea.unique.ecc.x.t.buffer)); MemoryCopy2B(&newObject->publicArea.unique.ecc.y.b, &oldObject.publicArea.unique.ecc.y.b, sizeof(oldObject.publicArea.unique.ecc.y.t.buffer)); break; } newObject->sensitive.sensitiveType = oldObject.sensitive.sensitiveType; newObject->sensitive.authValue = oldObject.sensitive.authValue; newObject->sensitive.seedValue = oldObject.sensitive.seedValue; /* The OLD_TPMU_SENSITIVE_COMPOSITE is always a TPM2B */ MemoryCopy2B(&newObject->sensitive.sensitive.any.b, &oldObject.sensitive.sensitive.any.b, sizeof(oldObject.sensitive.sensitive.any.t.buffer)); CopyFromOldPrimeT(&newObject->privateExponent.Q, &oldObject.privateExponent.Q); CopyFromOldPrimeT(&newObject->privateExponent.dP, &oldObject.privateExponent.dP); CopyFromOldPrimeT(&newObject->privateExponent.dQ, &oldObject.privateExponent.dQ); CopyFromOldPrimeT(&newObject->privateExponent.qInv, &oldObject.privateExponent.qInv); newObject->qualifiedName = oldObject.qualifiedName; newObject->evictHandle = oldObject.evictHandle; newObject->name = oldObject.name; } return rc; } libtpms-0.9.3/src/tpm2/BackwardsCompatibilityObject.h000066400000000000000000000044151421143571500226100ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Backwards compatibility stuff related to OBJECT */ /* Written by Stefan Berger */ /* IBM Thomas J. Watson Research Center */ /* */ /* (c) Copyright IBM Corporation 2017,2018. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef BACKWARDS_COMPATIBILITY_OBJECT_H #define BACKWARDS_COMPATIBILITY_OBJECT_H #include "Tpm.h" TPM_RC OLD_OBJECTToOBJECT(OBJECT *object, BYTE *buffer, INT32 size); #endif /* BACKWARDS_COMPATIBILITY_OBJECT_H */ libtpms-0.9.3/src/tpm2/BaseTypes.h000066400000000000000000000075261421143571500167330ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Basic Typedefs */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: BaseTypes.h 1531 2019-11-21 23:54:38Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ /* 5.2 BaseTypes.h */ #ifndef BASETYPES_H #define BASETYPES_H #include /* NULL definition */ #ifndef NULL #define NULL (0) #endif typedef uint8_t UINT8; typedef uint8_t BYTE; typedef int8_t INT8; typedef int BOOL; typedef uint16_t UINT16; typedef int16_t INT16; typedef uint32_t UINT32; typedef int32_t INT32; typedef uint64_t UINT64; typedef int64_t INT64; #endif libtpms-0.9.3/src/tpm2/Bits.c000066400000000000000000000121111421143571500157120ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Bit Manipulation Routines */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Bits.c 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2018 */ /* */ /********************************************************************************/ /* 9.2 Bits.c */ /* 9.2.1 Introduction */ /* This file contains bit manipulation routines. They operate on bit arrays. */ /* The 0th bit in the array is the right-most bit in the 0th octet in the array. */ /* NOTE: If pAssert() is defined, the functions will assert if the indicated bit number is outside of the range of bArray. How the assert is handled is implementation dependent. */ /* 9.2.2 Includes */ #include "Tpm.h" /* 9.2.3 Functions */ /* 9.2.3.1 TestBit() */ /* This function is used to check the setting of a bit in an array of bits. */ /* Return Values Meaning */ /* TRUE bit is set */ /* FALSE bit is not set */ BOOL TestBit( unsigned int bitNum, // IN: number of the bit in 'bArray' BYTE *bArray, // IN: array containing the bits unsigned int bytesInArray // IN: size in bytes of 'bArray' ) { pAssert(bytesInArray > (bitNum >> 3)); return((bArray[bitNum >> 3] & (1 << (bitNum & 7))) != 0); } /* 9.2.3.2 SetBit() */ /* This function will set the indicated bit in bArray. */ void SetBit( unsigned int bitNum, // IN: number of the bit in 'bArray' BYTE *bArray, // IN: array containing the bits unsigned int bytesInArray // IN: size in bytes of 'bArray' ) { pAssert(bytesInArray > (bitNum >> 3)); bArray[bitNum >> 3] |= (1 << (bitNum & 7)); } /* 9.2.3.3 ClearBit() */ /* This function will clear the indicated bit in bArray. */ void ClearBit( unsigned int bitNum, // IN: number of the bit in 'bArray'. BYTE *bArray, // IN: array containing the bits unsigned int bytesInArray // IN: size in bytes of 'bArray' ) { pAssert(bytesInArray > (bitNum >> 3)); bArray[bitNum >> 3] &= ~(1 << (bitNum & 7)); } libtpms-0.9.3/src/tpm2/Bits_fp.h000066400000000000000000000105701421143571500164130ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Bit Handling */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Bits_fp.h 803 2016-11-15 20:19:26Z kgoldman */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2018 */ /* */ /********************************************************************************/ #ifndef BITS_FP_H #define BITS_FP_H /* 5.3.1 TestBit() */ /* This function is used to check the setting of a bit in an array of bits. */ /* Return Value Meaning */ /* TRUE bit is set */ /* FALSE bit is not set */ BOOL TestBit( unsigned int bitNum, // IN: number of the bit in 'bArray' BYTE *bArray, // IN: array containing the bits unsigned int bytesInArray // IN: size in bytes of 'bArray' ); /* 5.3.2 SetBit() */ /* This function will set the indicated bit in bArray. */ void SetBit( unsigned int bitNum, // IN: number of the bit in 'bArray' BYTE *bArray, // IN: array containing the bits unsigned int bytesInArray // IN: size in bytes of 'bArray' ); /* 5.3.3 ClearBit() */ /* This function will clear the indicated bit in bArray. */ void ClearBit( unsigned int bitNum, // IN: number of the bit in 'bArray'. BYTE *bArray, // IN: array containing the bits unsigned int bytesInArray // IN: size in bytes of 'bArray' ); #endif libtpms-0.9.3/src/tpm2/BnConvert.c000066400000000000000000000266441421143571500167310ustar00rootroot00000000000000/********************************************************************************/ /* */ /* conversion functions that will convert TPM2B to/from internal format */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: BnConvert.c 1519 2019-11-15 20:43:51Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ /* 10.2.2 BnConvert.c */ /* 10.2.2.1 Introduction */ /* This file contains the basic conversion functions that will convert TPM2B to/from the internal format. The internal format is a bigNum, */ /* 10.2.2.2 Includes */ #include "Tpm.h" /* 10.2.2.3 Functions */ /* 10.2.2.3.1 BnFromBytes() */ /* This function will convert a big-endian byte array to the internal number format. If bn is NULL, then the output is NULL. If bytes is null or the required size is 0, then the output is set to zero */ LIB_EXPORT bigNum BnFromBytes( bigNum bn, const BYTE *bytes, NUMBYTES nBytes ) { const BYTE *pFrom; // 'p' points to the least significant bytes of source BYTE *pTo; // points to least significant bytes of destination crypt_uword_t size; // size = (bytes != NULL) ? BYTES_TO_CRYPT_WORDS(nBytes) : 0; // If nothing in, nothing out if(bn == NULL) return NULL; // make sure things fit pAssert(BnGetAllocated(bn) >= size); if(size > 0) { // Clear the topmost word in case it is not filled with data bn->d[size - 1] = 0; // Moving the input bytes from the end of the list (LSB) end pFrom = bytes + nBytes - 1; // To the LS0 of the LSW of the bigNum. pTo = (BYTE *)bn->d; for(; nBytes != 0; nBytes--) *pTo++ = *pFrom--; // For a little-endian machine, the conversion is a straight byte // reversal. For a big-endian machine, we have to put the words in // big-endian byte order #if BIG_ENDIAN_TPM { crypt_word_t t; for(t = (crypt_word_t)size - 1; t >= 0; t--) bn->d[t] = SWAP_CRYPT_WORD(bn->d[t]); } #endif } BnSetTop(bn, size); return bn; } /* 10.2.2.3.2 BnFrom2B() */ /* Convert an TPM2B to a BIG_NUM. If the input value does not exist, or the output does not exist, or the input will not fit into the output the function returns NULL */ LIB_EXPORT bigNum BnFrom2B( bigNum bn, // OUT: const TPM2B *a2B // IN: number to convert ) { if(a2B != NULL) return BnFromBytes(bn, a2B->buffer, a2B->size); // Make sure that the number has an initialized value rather than whatever // was there before BnSetTop(bn, 0); // Function accepts NULL return NULL; } /* 10.2.2.3.3 BnFromHex() */ /* Convert a hex string into a bigNum. This is primarily used in debugging. */ #ifdef _SM2_SIGN_DEBUG // libtpms added LIB_EXPORT bigNum BnFromHex( bigNum bn, // OUT: const char *hex // IN: ) { #define FromHex(a) ((a) - (((a) > 'a') ? ('a' + 10) \ : ((a) > 'A') ? ('A' - 10) : '0')) unsigned i; unsigned wordCount; const char *p; BYTE *d = (BYTE *)&(bn->d[0]); // pAssert(bn && hex); i = (unsigned)strlen(hex); wordCount = BYTES_TO_CRYPT_WORDS((i + 1) / 2); if((i == 0) || (wordCount >= BnGetAllocated(bn))) BnSetWord(bn, 0); else { bn->d[wordCount - 1] = 0; p = hex + i - 1; for(;i > 1; i -= 2) { BYTE a; a = FromHex(*p); p--; *d++ = a + (FromHex(*p) << 4); p--; } if(i == 1) *d = FromHex(*p); } #if !BIG_ENDIAN_TPM for(i = 0; i < wordCount; i++) bn->d[i] = SWAP_CRYPT_WORD(bn->d[i]); #endif // BIG_ENDIAN_TPM BnSetTop(bn, wordCount); return bn; } #endif // libtpms added /* 10.2.2.3.4 BnToBytes() */ /* This function converts a BIG_NUM to a byte array. It converts the bigNum to a big-endian byte string and sets size to the normalized value. If size is an input 0, then the receiving buffer is guaranteed to be large enough for the result and the size will be set to the size required for bigNum (leading zeros suppressed). */ /* The conversion for a little-endian machine simply requires that all significant bytes of the bigNum be reversed. For a big-endian machine, rather than unpack each word individually, the bigNum is converted to little-endian words, copied, and then converted back to big-endian. */ LIB_EXPORT BOOL BnToBytes( bigConst bn, BYTE *buffer, NUMBYTES *size // This the number of bytes that are // available in the buffer. The result // should be this big. ) { crypt_uword_t requiredSize; BYTE *pFrom; BYTE *pTo; crypt_uword_t count; // // validate inputs pAssert(bn && buffer && size); requiredSize = (BnSizeInBits(bn) + 7) / 8; if(requiredSize == 0) { // If the input value is 0, return a byte of zero *size = 1; *buffer = 0; } else { #if BIG_ENDIAN_TPM // Copy the constant input value into a modifiable value BN_VAR(bnL, LARGEST_NUMBER_BITS * 2); BnCopy(bnL, bn); // byte swap the words in the local value to make them little-endian for(count = 0; count < bnL->size; count++) bnL->d[count] = SWAP_CRYPT_WORD(bnL->d[count]); bn = (bigConst)bnL; #endif if(*size == 0) *size = (NUMBYTES)requiredSize; pAssert(requiredSize <= *size); // Byte swap the number (not words but the whole value) count = *size; // Start from the least significant word and offset to the most significant // byte which is in some high word pFrom = (BYTE *)(&bn->d[0]) + requiredSize - 1; pTo = buffer; // If the number of output bytes is larger than the number bytes required // for the input number, pad with zeros for(count = *size; count > requiredSize; count--) *pTo++ = 0; // Move the most significant byte at the end of the BigNum to the next most // significant byte position of the 2B and repeat for all significant bytes. for(; requiredSize > 0; requiredSize--) *pTo++ = *pFrom--; } return TRUE; } /* 10.2.2.3.5 BnTo2B() */ /* Function to convert a BIG_NUM to TPM2B. The TPM2B size is set to the requested size which may require padding. If size is non-zero and less than required by the value in bn then an error is returned. If size is zero, then the TPM2B is assumed to be large enough for the data and a2b->size will be adjusted accordingly. */ LIB_EXPORT BOOL BnTo2B( bigConst bn, // IN: TPM2B *a2B, // OUT: NUMBYTES size // IN: the desired size ) { // Set the output size if(bn && a2B) { a2B->size = size; return BnToBytes(bn, a2B->buffer, &a2B->size); } return FALSE; } #if ALG_ECC /* 10.2.2.3.6 BnPointFrom2B() */ /* Function to create a BIG_POINT structure from a 2B point. A point is going to be two ECC values in the same buffer. The values are going to be the size of the modulus. They are in modular form. */ LIB_EXPORT bn_point_t * BnPointFrom2B( bigPoint ecP, // OUT: the preallocated point structure TPMS_ECC_POINT *p // IN: the number to convert ) { if(p == NULL) return NULL; if(NULL != ecP) { BnFrom2B(ecP->x, &p->x.b); BnFrom2B(ecP->y, &p->y.b); BnSetWord(ecP->z, 1); } return ecP; } /* 10.2.2.3.7 BnPointTo2B() */ /* This function converts a BIG_POINT into a TPMS_ECC_POINT. A TPMS_ECC_POINT contains two TPM2B_ECC_PARAMETER values. The maximum size of the parameters is dependent on the maximum EC key size used in an implementation. The presumption is that the TPMS_ECC_POINT is large enough to hold 2 TPM2B values, each as large as a MAX_ECC_PARAMETER_BYTES */ LIB_EXPORT BOOL BnPointTo2B( TPMS_ECC_POINT *p, // OUT: the converted 2B structure bigPoint ecP, // IN: the values to be converted bigCurve E // IN: curve descriptor for the point ) { UINT16 size; // pAssert(p && ecP && E); pAssert(BnEqualWord(ecP->z, 1)); // BnMsb is the bit number of the MSB. This is one less than the number of bits size = (UINT16)BITS_TO_BYTES(BnSizeInBits(CurveGetOrder(AccessCurveData(E)))); BnTo2B(ecP->x, &p->x.b, size); BnTo2B(ecP->y, &p->y.b, size); return TRUE; } #endif // TPM_ALG_ECC libtpms-0.9.3/src/tpm2/BnMath.c000066400000000000000000000515161421143571500161760ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Simple Operations on Big Numbers */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: BnMath.c 1529 2019-11-21 23:29:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ /* 10.2.3 BnMath.c */ /* 10.2.3.1 Introduction */ /* The simulator code uses the canonical form whenever possible in order to make the code in Part 3 more accessible. The canonical data formats are simple and not well suited for complex big number computations. When operating on big numbers, the data format is changed for easier manipulation. The format is native words in little-endian format. As the magnitude of the number decreases, the length of the array containing the number decreases but the starting address doesn't change. */ /* The functions in this file perform simple operations on these big numbers. Only the more complex operations are passed to the underlying support library. Although the support library would have most of these functions, the interface code to convert the format for the values is greater than the size of the code to implement the functions here. So, rather than incur the overhead of conversion, they are done here. */ /* If an implementer would prefer, the underlying library can be used simply by making code substitutions here. */ /* NOTE: There is an intention to continue to augment these functions so that there would be no need to use an external big number library. */ /* Many of these functions have no error returns and will always return TRUE. This is to allow them to be used in guarded sequences. That is: OK = OK || BnSomething(s); where the BnSomething() function should not be called if OK isn't true. */ /* 10.2.3.2 Includes */ #include "Tpm.h" /* A constant value of zero as a stand in for NULL bigNum values */ const bignum_t BnConstZero = {1, 0, {0}}; /* 10.2.3.3 Functions */ /* 10.2.3.3.1 AddSame() */ /* Adds two values that are the same size. This function allows result to be the same as either of the addends. This is a nice function to put into assembly because handling the carry for multi-precision stuff is not as easy in C (unless there is a REALLY smart compiler). It would be nice if there were idioms in a language that a compiler could recognize what is going on and optimize loops like this. */ /* Return Values Meaning */ /* 0 no carry out */ /* 1 carry out */ static BOOL AddSame( crypt_uword_t *result, const crypt_uword_t *op1, const crypt_uword_t *op2, int count ) { int carry = 0; int i; for(i = 0; i < count; i++) { crypt_uword_t a = op1[i]; crypt_uword_t sum = a + op2[i]; result[i] = sum + carry; // generate a carry if the sum is less than either of the inputs // propagate a carry if there was a carry and the sum + carry is zero // do this using bit operations rather than logical operations so that // the time is about the same. // propagate term | generate term carry = ((result[i] == 0) & carry) | (sum < a); } return carry; } /* 10.2.3.3.2 CarryProp() */ /* Propagate a carry */ static int CarryProp( crypt_uword_t *result, const crypt_uword_t *op, int count, int carry ) { for(; count; count--) carry = ((*result++ = *op++ + carry) == 0) & carry; return carry; } static void CarryResolve( bigNum result, int stop, int carry ) { if(carry) { pAssert((unsigned)stop < result->allocated); result->d[stop++] = 1; } BnSetTop(result, stop); } /* 10.2.3.3.3 BnAdd() */ /* This function adds two bigNum values. Always returns TRUE */ LIB_EXPORT BOOL BnAdd( bigNum result, bigConst op1, bigConst op2 ) { crypt_uword_t stop; int carry; const bignum_t *n1 = op1; const bignum_t *n2 = op2; // if(n2->size > n1->size) { n1 = op2; n2 = op1; } pAssert(result->allocated >= n1->size); stop = MIN(n1->size, n2->allocated); carry = (int)AddSame(result->d, n1->d, n2->d, (int)stop); if(n1->size > stop) carry = CarryProp(&result->d[stop], &n1->d[stop], (int)(n1->size - stop), carry); CarryResolve(result, (int)n1->size, carry); return TRUE; } /* 10.2.3.3.4 BnAddWord() */ /* Adds a word value to a bigNum. */ LIB_EXPORT BOOL BnAddWord( bigNum result, bigConst op, crypt_uword_t word ) { int carry; // carry = (result->d[0] = op->d[0] + word) < word; carry = CarryProp(&result->d[1], &op->d[1], (int)(op->size - 1), carry); CarryResolve(result, (int)op->size, carry); return TRUE; } /* 10.2.3.3.5 SubSame() */ /* Subtract two values that have the same size. */ static int SubSame( crypt_uword_t *result, const crypt_uword_t *op1, const crypt_uword_t *op2, int count ) { int borrow = 0; int i; for(i = 0; i < count; i++) { crypt_uword_t a = op1[i]; crypt_uword_t diff = a - op2[i]; result[i] = diff - borrow; // generate | propagate borrow = (diff > a) | ((diff == 0) & borrow); } return borrow; } /* 10.2.3.3.6 BorrowProp() */ /* This propagates a borrow. If borrow is true when the end of the array is reached, then it means that op2 was larger than op1 and we don't handle that case so an assert is generated. This design choice was made because our only bigNum computations are on large positive numbers (primes) or on fields. Propagate a borrow. */ static int BorrowProp( crypt_uword_t *result, const crypt_uword_t *op, int size, int borrow ) { for(; size > 0; size--) borrow = ((*result++ = *op++ - borrow) == MAX_CRYPT_UWORD) && borrow; return borrow; } /* 10.2.3.3.7 BnSub() */ /* This function does subtraction of two bigNum values and returns result = op1 - op2 when op1 is greater than op2. If op2 is greater than op1, then a fault is generated. This function always returns TRUE. */ LIB_EXPORT BOOL BnSub( bigNum result, bigConst op1, bigConst op2 ) { int borrow; int stop = (int)MIN(op1->size, op2->allocated); // // Make sure that op2 is not obviously larger than op1 pAssert(op1->size >= op2->size); borrow = SubSame(result->d, op1->d, op2->d, stop); if(op1->size > (crypt_uword_t)stop) borrow = BorrowProp(&result->d[stop], &op1->d[stop], (int)(op1->size - stop), borrow); pAssert(!borrow); BnSetTop(result, op1->size); return TRUE; } /* 10.2.3.3.8 BnSubWord() */ /* This function subtracts a word value from a bigNum. This function always returns TRUE. */ LIB_EXPORT BOOL BnSubWord( bigNum result, bigConst op, crypt_uword_t word ) { int borrow; // pAssert(op->size > 1 || word <= op->d[0]); borrow = word > op->d[0]; result->d[0] = op->d[0] - word; borrow = BorrowProp(&result->d[1], &op->d[1], (int)(op->size - 1), borrow); pAssert(!borrow); BnSetTop(result, op->size); return TRUE; } /* 10.2.3.3.9 BnUnsignedCmp() */ /* This function performs a comparison of op1 to op2. The compare is approximately constant time if the size of the values used in the compare is consistent across calls (from the same line in the calling code). */ /* Return Values Meaning */ /* < 0 op1 is less than op2 */ /* 0 op1 is equal to op2 */ /* > 0 op1 is greater than op2 */ LIB_EXPORT int BnUnsignedCmp( bigConst op1, bigConst op2 ) { int retVal; int diff; int i; // pAssert((op1 != NULL) && (op2 != NULL)); retVal = (int)(op1->size - op2->size); if(retVal == 0) { for(i = (int)(op1->size - 1); i >= 0; i--) { diff = (op1->d[i] < op2->d[i]) ? -1 : (op1->d[i] != op2->d[i]); retVal = retVal == 0 ? diff : retVal; } } else retVal = (retVal < 0) ? -1 : 1; return retVal; } /* 10.2.3.3.10 BnUnsignedCmpWord() */ /* Compare a bigNum to a crypt_uword_t. */ /* Return Value Meaning */ /* -1 op1 is less that word */ /* 0 op1 is equal to word */ /* 1 op1 is greater than word */ LIB_EXPORT int BnUnsignedCmpWord( bigConst op1, crypt_uword_t word ) { if(op1->size > 1) return 1; else if(op1->size == 1) return (op1->d[0] < word) ? -1 : (op1->d[0] > word); else // op1 is zero // equal if word is zero return (word == 0) ? 0 : -1; } /* 10.2.3.3.11 BnModWord() */ /* This function does modular division of a big number when the modulus is a word value. */ LIB_EXPORT crypt_word_t BnModWord( bigConst numerator, crypt_word_t modulus ) { BN_MAX(remainder); BN_VAR(mod, RADIX_BITS); // mod->d[0] = modulus; mod->size = (modulus != 0); BnDiv(NULL, remainder, numerator, mod); return remainder->d[0]; } /* 10.2.3.3.12 Msb() */ /* Returns the bit number of the most significant bit of a crypt_uword_t. The number for the least significant bit of any bigNum value is 0. The maximum return value is RADIX_BITS - 1, */ /* Return Values Meaning */ /* -1 the word was zero */ /* n the bit number of the most significant bit in the word */ LIB_EXPORT int Msb( crypt_uword_t word ) { int retVal = -1; // #if RADIX_BITS == 64 if(word & 0xffffffff00000000) { retVal += 32; word >>= 32; } #endif if(word & 0xffff0000) { retVal += 16; word >>= 16; } if(word & 0x0000ff00) { retVal += 8; word >>= 8; } if(word & 0x000000f0) { retVal += 4; word >>= 4; } if(word & 0x0000000c) { retVal += 2; word >>= 2; } if(word & 0x00000002) { retVal += 1; word >>= 1; } return retVal + (int)word; } /* 10.2.3.3.13 BnMsb() */ /* This function returns the number of the MSb() of a bigNum value. */ /* Return Value Meaning */ /* -1 the word was zero or bn was NULL */ /* n the bit number of the most significant bit in the word */ LIB_EXPORT int BnMsb( bigConst bn ) { // If the value is NULL, or the size is zero then treat as zero and return -1 if(bn != NULL && bn->size > 0) { int retVal = Msb(bn->d[bn->size - 1]); retVal += (int)(bn->size - 1) * RADIX_BITS; return retVal; } else return -1; } /* 10.2.3.3.14 BnSizeInBits() */ /* Returns the number of bits required to hold a number. It is one greater than the Msb. */ LIB_EXPORT unsigned BnSizeInBits( bigConst n ) { int bits = BnMsb(n) + 1; // return bits < 0 ? 0 : (unsigned)bits; } /* 10.2.3.3.15 BnSetWord() */ /* Change the value of a bignum_t to a word value. */ LIB_EXPORT bigNum BnSetWord( bigNum n, crypt_uword_t w ) { if(n != NULL) { pAssert(n->allocated > 1); n->d[0] = w; BnSetTop(n, (w != 0) ? 1 : 0); } return n; } /* 10.2.3.3.16 BnSetBit() */ /* SET a bit in a bigNum. Bit 0 is the least-significant bit in the 0th digit_t. The function always return TRUE */ LIB_EXPORT BOOL BnSetBit( bigNum bn, // IN/OUT: big number to modify unsigned int bitNum // IN: Bit number to SET ) { crypt_uword_t offset = bitNum / RADIX_BITS; pAssert(bn->allocated * RADIX_BITS >= bitNum); // Grow the number if necessary to set the bit. while(bn->size <= offset) bn->d[bn->size++] = 0; bn->d[offset] |= (crypt_uword_t)(1 << RADIX_MOD(bitNum)); return TRUE; } /* 10.2.3.3.17 BnTestBit() */ /* Check to see if a bit is SET in a bignum_t. The 0th bit is the LSb() of d[0]. */ /* Return Values Meaning */ /* TRUE the bit is set */ /* FALSE the bit is not set or the number is out of range */ LIB_EXPORT BOOL BnTestBit( bigNum bn, // IN: number to check unsigned int bitNum // IN: bit to test ) { crypt_uword_t offset = RADIX_DIV(bitNum); // if(bn->size > offset) return ((bn->d[offset] & (((crypt_uword_t)1) << RADIX_MOD(bitNum))) != 0); else return FALSE; } /* 10.2.3.3.18 BnMaskBits() */ /* Function to mask off high order bits of a big number. The returned value will have no more than maskBit bits set. */ /* NOTE: There is a requirement that unused words of a bignum_t are set to zero. */ /* Return Values Meaning */ /* TRUE result masked */ /* FALSE the input was not as large as the mask */ LIB_EXPORT BOOL BnMaskBits( bigNum bn, // IN/OUT: number to mask crypt_uword_t maskBit // IN: the bit number for the mask. ) { crypt_uword_t finalSize; BOOL retVal; finalSize = BITS_TO_CRYPT_WORDS(maskBit); retVal = (finalSize <= bn->allocated); if(retVal && (finalSize > 0)) { crypt_uword_t mask; mask = ~((crypt_uword_t)0) >> RADIX_MOD(maskBit); bn->d[finalSize - 1] &= mask; } BnSetTop(bn, finalSize); return retVal; } /* 10.2.3.3.19 BnShiftRight() */ /* Function will shift a bigNum to the right by the shiftAmount. This function always returns TRUE. */ LIB_EXPORT BOOL BnShiftRight( bigNum result, bigConst toShift, uint32_t shiftAmount ) { uint32_t offset = (shiftAmount >> RADIX_LOG2); uint32_t i; uint32_t shiftIn; crypt_uword_t finalSize; // shiftAmount = shiftAmount & RADIX_MASK; shiftIn = RADIX_BITS - shiftAmount; // The end size is toShift->size - offset less one additional // word if the shiftAmount would make the upper word == 0 if(toShift->size > offset) { finalSize = toShift->size - offset; finalSize -= (toShift->d[toShift->size - 1] >> shiftAmount) == 0 ? 1 : 0; } else finalSize = 0; pAssert(finalSize <= result->allocated); if(finalSize != 0) { for(i = 0; i < finalSize; i++) { result->d[i] = (toShift->d[i + offset] >> shiftAmount) | (toShift->d[i + offset + 1] << shiftIn); } if(offset == 0) result->d[i] = toShift->d[i] >> shiftAmount; } BnSetTop(result, finalSize); return TRUE; } /* 10.2.3.3.20 BnGetRandomBits() */ /* Return Value Meaning */ /* TRUE(1) success */ /* FALSE(0) failure */ LIB_EXPORT BOOL BnGetRandomBits( bigNum n, size_t bits, RAND_STATE *rand ) { // Since this could be used for ECC key generation using the extra bits method, // make sure that the value is large enough TPM2B_TYPE(LARGEST, LARGEST_NUMBER + 8); TPM2B_LARGEST large; // large.b.size = (UINT16)BITS_TO_BYTES(bits); if(DRBG_Generate(rand, large.t.buffer, large.t.size) == large.t.size) { if(BnFrom2B(n, &large.b) != NULL) { if(BnMaskBits(n, (crypt_uword_t)bits)) return TRUE; } } return FALSE; } /* 10.2.3.3.21 BnGenerateRandomInRange() */ /* Function to generate a random number r in the range 1 <= r < limit. The function gets a random number of bits that is the size of limit. There is some some probability that the returned number is going to be greater than or equal to the limit. If it is, try again. There is no more than 50% chance that the next number is also greater, so try again. We keep trying until we get a value that meets the criteria. Since limit is very often a number with a LOT of high order ones, this rarely would need a second try. */ /* Return Value Meaning */ /* TRUE(1) success */ /* FALSE(0) failure */ LIB_EXPORT BOOL BnGenerateRandomInRange( bigNum dest, bigConst limit, RAND_STATE *rand ) { size_t bits = BnSizeInBits(limit); // if(bits < 2) { BnSetWord(dest, 0); return FALSE; } else { while(BnGetRandomBits(dest, bits, rand) && (BnEqualZero(dest) || (BnUnsignedCmp(dest, limit) >= 0))); } return !g_inFailureMode; } // libtpms added begin // This version of BnSizeInBits skips any leading zero bytes in bigConst // and thus calculates the bits that OpenSSL will work with after truncating // the leading zeros static LIB_EXPORT unsigned BnSizeInBitsSkipLeadingZeros( bigConst n ) { int firstByte; unsigned bitSize = BnSizeInBits(n); crypt_uword_t i; if (bitSize <= 8) return bitSize; // search for the first limb that is non-zero for (i = 0; i < n->size; i++) { if (n->d[i] != 0) break; } if (i >= n->size) return 0; // should never happen // get the first byte in this limb that is non-zero firstByte = (RADIX_BITS - 1 - Msb(n->d[i])) >> 3; return bitSize - i * sizeof(n->d[0]) - (firstByte << 3); } /* This is a version of BnGenerateRandomInRange that ensures that the upper most byte is non-zero, so that the number will not be shortened and subsequent operations will not have a timing-sidechannel */ LIB_EXPORT BOOL BnGenerateRandomInRangeAllBytes( bigNum dest, bigConst limit, RAND_STATE *rand ) { BOOL OK; int repeats = 0; int maxRepeats; unsigned requestedBits; unsigned requestedBytes; unsigned numBytes; if (rand) return BnGenerateRandomInRange(dest, limit, rand); // a 'limit' like 'BN_P638_n' has leading zeros and we only need 73 bytes not 80 requestedBits = BnSizeInBitsSkipLeadingZeros(limit); requestedBytes = BITS_TO_BYTES(requestedBits); maxRepeats = 8; if (requestedBits & 7) maxRepeats += (9 - (requestedBits & 7)); while (true) { OK = BnGenerateRandomInRange(dest, limit, rand); if (!OK) break; if (repeats < maxRepeats) { numBytes = BITS_TO_BYTES(BnSizeInBitsSkipLeadingZeros(dest)); if (numBytes < requestedBytes) { repeats++; continue; } } break; } return OK; } // libtpms added end libtpms-0.9.3/src/tpm2/BnMemory.c000066400000000000000000000157741421143571500165630ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: BnMemory.c 1262 2018-07-11 21:03:43Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 */ /* */ /********************************************************************************/ /* 10.2.5 BnMemory.c */ /* 10.2.5.1 Introduction */ /* This file contains the memory setup functions used by the bigNum functions in CryptoEngine() */ /* 10.2.5.2 Includes */ #include "Tpm.h" /* 10.2.5.3 Functions */ /* 10.2.5.3.1 BnSetTop() */ /* This function is used when the size of a bignum_t is changed. It makes sure that the unused words are set to zero and that any significant words of zeros are eliminated from the used size indicator. */ LIB_EXPORT bigNum BnSetTop( bigNum bn, // IN/OUT: number to clean crypt_uword_t top // IN: the new top ) { if(bn != NULL) { pAssert(top <= bn->allocated); // If forcing the size to be decreased, make sure that the words being // discarded are being set to 0 while(bn->size > top) bn->d[--bn->size] = 0; bn->size = top; // Now make sure that the words that are left are 'normalized' (no high-order // words of zero. while((bn->size > 0) && (bn->d[bn->size - 1] == 0)) bn->size -= 1; } return bn; } #if 0 /* libtpms added */ /* 10.2.5.3.2 BnClearTop() */ /* This function will make sure that all unused words are zero. */ LIB_EXPORT bigNum BnClearTop( bigNum bn ) { crypt_uword_t i; // if(bn != NULL) { for(i = bn->size; i < bn->allocated; i++) bn->d[i] = 0; while((bn->size > 0) && (bn->d[bn->size] == 0)) bn->size -= 1; } return bn; } #endif /* libtpms added */ /* 10.2.5.3.3 BnInitializeWord() */ /* This function is used to initialize an allocated bigNum with a word value. The bigNum does not have to be allocated with a single word. */ LIB_EXPORT bigNum BnInitializeWord( bigNum bn, // IN: crypt_uword_t allocated, // IN: crypt_uword_t word // IN: ) { bn->allocated = allocated; bn->size = (word != 0); bn->d[0] = word; while(allocated > 1) bn->d[--allocated] = 0; return bn; } /* 10.2.5.3.4 BnInit() */ /* This function initializes a stack allocated bignum_t. It initializes allocated and size and zeros the words of d. */ LIB_EXPORT bigNum BnInit( bigNum bn, crypt_uword_t allocated ) { if(bn != NULL) { bn->allocated = allocated; bn->size = 0; while(allocated != 0) bn->d[--allocated] = 0; } return bn; } /* 10.2.5.3.5 BnCopy() */ /* Function to copy a bignum_t. If the output is NULL, then nothing happens. If the input is NULL, the output is set to zero. */ LIB_EXPORT BOOL BnCopy( bigNum out, bigConst in ) { if(in == out) BnSetTop(out, BnGetSize(out)); else if(out != NULL) { if(in != NULL) { unsigned int i; pAssert(BnGetAllocated(out) >= BnGetSize(in)); for(i = 0; i < BnGetSize(in); i++) out->d[i] = in->d[i]; BnSetTop(out, BnGetSize(in)); } else BnSetTop(out, 0); } return TRUE; } #if ALG_ECC #if 0 /* libtpms added */ /* 10.2.5.3.6 BnPointCopy() */ /* Function to copy a bn point. */ LIB_EXPORT BOOL BnPointCopy( bigPoint pOut, pointConst pIn ) { return BnCopy(pOut->x, pIn->x) && BnCopy(pOut->y, pIn->y) && BnCopy(pOut->z, pIn->z); } #endif /* libtpms added */ /* 10.2.5.3.7 BnInitializePoint() */ /* This function is used to initialize a point structure with the addresses of the coordinates. */ LIB_EXPORT bn_point_t * BnInitializePoint( bigPoint p, // OUT: structure to receive pointers bigNum x, // IN: x coordinate bigNum y, // IN: y coordinate bigNum z // IN: x coordinate ) { p->x = x; p->y = y; p->z = z; BnSetWord(z, 1); return p; } #endif // TPM_ALG_ECC libtpms-0.9.3/src/tpm2/Cancel.c000066400000000000000000000101451421143571500162030ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Simulates the cancel pins on the TPM. */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Cancel.c 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ /* C.2 Cancel.c */ /* C.2.1. Description */ /* This module simulates the cancel pins on the TPM. */ /* C.2.2. Includes, Typedefs, Structures, and Defines */ #include "Platform.h" /* C.2.3. Functions */ /* C.2.3.1. _plat__IsCanceled() */ /* Check if the cancel flag is set */ /* Return Values Meaning */ /* TRUE(1) if cancel flag is set */ /* FALSE(0) if cancel flag is not set */ LIB_EXPORT int _plat__IsCanceled( void ) { // return cancel flag return s_isCanceled; } /* C.2.3.2. _plat__SetCancel() */ /* Set cancel flag. */ LIB_EXPORT void _plat__SetCancel( void ) { s_isCanceled = TRUE; return; } /* C.2.3.3. _plat__ClearCancel() */ /* Clear cancel flag */ LIB_EXPORT void _plat__ClearCancel( void ) { s_isCanceled = FALSE; return; } libtpms-0.9.3/src/tpm2/Capabilities.h000066400000000000000000000102221421143571500174100ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Number of capability values that will fit into the largest data buffer */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Capabilities.h 1519 2019-11-15 20:43:51Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ #ifndef _CAPABILITIES_H #define _CAPABILITIES_H #define MAX_CAP_DATA (MAX_CAP_BUFFER - sizeof(TPM_CAP)-sizeof(UINT32)) #define MAX_CAP_ALGS (MAX_CAP_DATA / sizeof(TPMS_ALG_PROPERTY)) #define MAX_CAP_HANDLES (MAX_CAP_DATA / sizeof(TPM_HANDLE)) #define MAX_CAP_CC (MAX_CAP_DATA / sizeof(TPM_CC)) #define MAX_TPM_PROPERTIES (MAX_CAP_DATA / sizeof(TPMS_TAGGED_PROPERTY)) #define MAX_PCR_PROPERTIES (MAX_CAP_DATA / sizeof(TPMS_TAGGED_PCR_SELECT)) #define MAX_ECC_CURVES (MAX_CAP_DATA / sizeof(TPM_ECC_CURVE)) #define MAX_TAGGED_POLICIES (MAX_CAP_DATA / sizeof(TPMS_TAGGED_POLICY)) #define MAX_ACT_DATA (MAX_CAP_DATA / sizeof(TPMS_ACT_DATA)) #define MAX_AC_CAPABILITIES (MAX_CAP_DATA / sizeof(TPMS_AC_OUTPUT)) #endif libtpms-0.9.3/src/tpm2/CapabilityCommands.c000066400000000000000000000202571421143571500205660ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Capability Commands */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CapabilityCommands.c 1519 2019-11-15 20:43:51Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ #include "Tpm.h" #include "GetCapability_fp.h" #if CC_GetCapability // Conditional expansion of this file TPM_RC TPM2_GetCapability( GetCapability_In *in, // IN: input parameter list GetCapability_Out *out // OUT: output parameter list ) { TPMU_CAPABILITIES *data = &out->capabilityData.data; // Command Output // Set output capability type the same as input type out->capabilityData.capability = in->capability; switch(in->capability) { case TPM_CAP_ALGS: out->moreData = AlgorithmCapGetImplemented((TPM_ALG_ID)in->property, in->propertyCount, &data->algorithms); break; case TPM_CAP_HANDLES: switch(HandleGetType((TPM_HANDLE)in->property)) { case TPM_HT_TRANSIENT: // Get list of handles of loaded transient objects out->moreData = ObjectCapGetLoaded((TPM_HANDLE)in->property, in->propertyCount, &data->handles); break; case TPM_HT_PERSISTENT: // Get list of handles of persistent objects out->moreData = NvCapGetPersistent((TPM_HANDLE)in->property, in->propertyCount, &data->handles); break; case TPM_HT_NV_INDEX: // Get list of defined NV index out->moreData = NvCapGetIndex((TPM_HANDLE)in->property, in->propertyCount, &data->handles); break; case TPM_HT_LOADED_SESSION: // Get list of handles of loaded sessions out->moreData = SessionCapGetLoaded((TPM_HANDLE)in->property, in->propertyCount, &data->handles); break; #ifdef TPM_HT_SAVED_SESSION case TPM_HT_SAVED_SESSION: #else case TPM_HT_ACTIVE_SESSION: #endif // Get list of handles of out->moreData = SessionCapGetSaved((TPM_HANDLE)in->property, in->propertyCount, &data->handles); break; case TPM_HT_PCR: // Get list of handles of PCR out->moreData = PCRCapGetHandles((TPM_HANDLE)in->property, in->propertyCount, &data->handles); break; case TPM_HT_PERMANENT: // Get list of permanent handles out->moreData = PermanentCapGetHandles((TPM_HANDLE)in->property, in->propertyCount, &data->handles); break; default: // Unsupported input handle type return TPM_RCS_HANDLE + RC_GetCapability_property; break; } break; case TPM_CAP_COMMANDS: out->moreData = CommandCapGetCCList((TPM_CC)in->property, in->propertyCount, &data->command); break; case TPM_CAP_PP_COMMANDS: out->moreData = PhysicalPresenceCapGetCCList((TPM_CC)in->property, in->propertyCount, &data->ppCommands); break; case TPM_CAP_AUDIT_COMMANDS: out->moreData = CommandAuditCapGetCCList((TPM_CC)in->property, in->propertyCount, &data->auditCommands); break; case TPM_CAP_PCRS: // Input property must be 0 if(in->property != 0) return TPM_RCS_VALUE + RC_GetCapability_property; out->moreData = PCRCapGetAllocation(in->propertyCount, &data->assignedPCR); break; case TPM_CAP_PCR_PROPERTIES: out->moreData = PCRCapGetProperties((TPM_PT_PCR)in->property, in->propertyCount, &data->pcrProperties); break; case TPM_CAP_TPM_PROPERTIES: out->moreData = TPMCapGetProperties((TPM_PT)in->property, in->propertyCount, &data->tpmProperties); break; #if ALG_ECC case TPM_CAP_ECC_CURVES: out->moreData = CryptCapGetECCCurve((TPM_ECC_CURVE)in->property, in->propertyCount, &data->eccCurves); break; #endif // TPM_ALG_ECC case TPM_CAP_AUTH_POLICIES: if(HandleGetType((TPM_HANDLE)in->property) != TPM_HT_PERMANENT) return TPM_RCS_VALUE + RC_GetCapability_property; out->moreData = PermanentHandleGetPolicy((TPM_HANDLE)in->property, in->propertyCount, &data->authPolicies); break; case TPM_CAP_ACT: if(((TPM_RH)in->property < TPM_RH_ACT_0) || ((TPM_RH)in->property > TPM_RH_ACT_F)) return TPM_RCS_VALUE + RC_GetCapability_property; out->moreData = ActGetCapabilityData((TPM_HANDLE)in->property, in->propertyCount, &data->actData); break; case TPM_CAP_VENDOR_PROPERTY: // vendor property is not implemented default: // Unsupported TPM_CAP value return TPM_RCS_VALUE + RC_GetCapability_capability; break; } return TPM_RC_SUCCESS; } #endif // CC_GetCapability #include "Tpm.h" #include "TestParms_fp.h" #if CC_TestParms // Conditional expansion of this file TPM_RC TPM2_TestParms( TestParms_In *in // IN: input parameter list ) { // Input parameter is not reference in command action NOT_REFERENCED(in); // The parameters are tested at unmarshal process. We do nothing in command // action return TPM_RC_SUCCESS; } #endif // CC_TestParms libtpms-0.9.3/src/tpm2/CertifyCreation_fp.h000066400000000000000000000104301421143571500205770ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CertifyCreation_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef CERTIFYCREATION_FP_H #define CERTIFYCREATION_FP_H typedef struct { TPMI_DH_OBJECT signHandle; TPMI_DH_OBJECT objectHandle; TPM2B_DATA qualifyingData; TPM2B_DIGEST creationHash; TPMT_SIG_SCHEME inScheme; TPMT_TK_CREATION creationTicket; } CertifyCreation_In; #define RC_CertifyCreation_signHandle (TPM_RC_H + TPM_RC_1) #define RC_CertifyCreation_objectHandle (TPM_RC_H + TPM_RC_2) #define RC_CertifyCreation_qualifyingData (TPM_RC_P + TPM_RC_1) #define RC_CertifyCreation_creationHash (TPM_RC_P + TPM_RC_2) #define RC_CertifyCreation_inScheme (TPM_RC_P + TPM_RC_3) #define RC_CertifyCreation_creationTicket (TPM_RC_P + TPM_RC_4) typedef struct { TPM2B_ATTEST certifyInfo; TPMT_SIGNATURE signature; } CertifyCreation_Out; TPM_RC TPM2_CertifyCreation( CertifyCreation_In *in, // IN: input parameter list CertifyCreation_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/CertifyX509_fp.h000066400000000000000000000103021421143571500174760ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM2_CertifyX509 Command Header */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CertifyX509_fp.h 1519 2019-11-15 20:43:51Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2019 */ /* */ /********************************************************************************/ /* rev 155 */ #ifndef CERTIFYX509_FP_H #define CERTIFYX509_FP_H typedef struct { TPMI_DH_OBJECT objectHandle; TPMI_DH_OBJECT signHandle; TPM2B_DATA reserved; TPMT_SIG_SCHEME inScheme; TPM2B_MAX_BUFFER partialCertificate; } CertifyX509_In; #define RC_CertifyX509_signHandle (TPM_RC_H + TPM_RC_1) #define RC_CertifyX509_objectHandle (TPM_RC_H + TPM_RC_2) #define RC_CertifyX509_reserved (TPM_RC_P + TPM_RC_1) #define RC_CertifyX509_inScheme (TPM_RC_P + TPM_RC_2) #define RC_CertifyX509_partialCertificate (TPM_RC_P + TPM_RC_3) typedef struct { TPM2B_MAX_BUFFER addedToCertificate; TPM2B_DIGEST tbsDigest; TPMT_SIGNATURE signature; } CertifyX509_Out; TPM_RC TPM2_CertifyX509( CertifyX509_In *in, // IN: input parameter list CertifyX509_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/Certify_fp.h000066400000000000000000000077641421143571500171320ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Certify_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef CERTIFY_FP_H #define CERTIFY_FP_H typedef struct { TPMI_DH_OBJECT objectHandle; TPMI_DH_OBJECT signHandle; TPM2B_DATA qualifyingData; TPMT_SIG_SCHEME inScheme; } Certify_In; #define RC_Certify_objectHandle (TPM_RC_H + TPM_RC_1) #define RC_Certify_signHandle (TPM_RC_H + TPM_RC_2) #define RC_Certify_qualifyingData (TPM_RC_P + TPM_RC_1) #define RC_Certify_inScheme (TPM_RC_P + TPM_RC_2) typedef struct { TPM2B_ATTEST certifyInfo; TPMT_SIGNATURE signature; } Certify_Out; TPM_RC TPM2_Certify( Certify_In *in, // IN: input parameter list Certify_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/ChangeEPS_fp.h000066400000000000000000000071371421143571500172540ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: ChangeEPS_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef CHANGEEPS_FP_H #define CHANGEEPS_FP_H typedef struct { TPMI_RH_PLATFORM authHandle; } ChangeEPS_In; #define RC_ChangeEPS_authHandle (TPM_RC_H + TPM_RC_1) TPM_RC TPM2_ChangeEPS( ChangeEPS_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/ChangePPS_fp.h000066400000000000000000000071371421143571500172670ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: ChangePPS_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef CHANGEPPS_FP_H #define CHANGEPPS_FP_H typedef struct { TPMI_RH_PLATFORM authHandle; } ChangePPS_In; #define RC_ChangePPS_authHandle (TPM_RC_P + TPM_RC_1) TPM_RC TPM2_ChangePPS( ChangePPS_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/ClearControl_fp.h000066400000000000000000000072541421143571500201060ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: ClearControl_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef CLEARCONTROL_FP_H #define CLEARCONTROL_FP_H typedef struct { TPMI_RH_CLEAR auth; TPMI_YES_NO disable; } ClearControl_In; #define RC_ClearControl_auth (TPM_RC_H + TPM_RC_1) #define RC_ClearControl_disable (TPM_RC_P + TPM_RC_1) TPM_RC TPM2_ClearControl( ClearControl_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/Clear_fp.h000066400000000000000000000070731421143571500165440ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Clear_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef CLEAR_FP_H #define CLEAR_FP_H typedef struct { TPMI_RH_CLEAR authHandle; } Clear_In; #define RC_Clear_authHandle (TPM_RC_H + TPM_RC_1) TPM_RC TPM2_Clear( Clear_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/Clock.c000066400000000000000000000324631421143571500160600ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Used by the simulator to mimic a hardware clock */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Clock.c 1529 2019-11-21 23:29:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ /* added for portability because Linux clock is 32 bits */ #include #include #include /* C.3 Clock.c */ /* C.3.1. Description */ /* This file contains the routines that are used by the simulator to mimic a hardware clock on a TPM. In this implementation, all the time values are measured in millisecond. However, the precision of the clock functions may be implementation dependent. */ /* C.3.2. Includes and Data Definitions */ #include #include "Platform.h" #include "TpmFail_fp.h" /* libtpms added begin */ /* ClockGetTime -- get time given a specified clock type */ uint64_t ClockGetTime( clockid_t clk_id ) { uint64_t time; #ifdef TPM_WINDOWS #error Not supported for TPM_WINDOWS #else struct timespec systime; clock_gettime(clk_id, &systime); time = (uint64_t)systime.tv_sec * 1000 + (systime.tv_nsec / 1000000); #endif return time; } /* ClockAdjustPostResume -- adjust time parameters post resume */ #include "Tpm.h" void ClockAdjustPostResume(UINT64 backthen, BOOL timesAreRealtime) { UINT64 now = ClockGetTime(CLOCK_REALTIME); INT64 timediff = now - backthen; if (timesAreRealtime) { /* g_time, s_realTimePrevious, s_tpmTime are all in real time */ s_suspendedElapsedTime = now; s_hostMonotonicAdjustTime = -ClockGetTime(CLOCK_MONOTONIC); /* s_lastSystemTime & s_lastReportTime need to be set as well */ s_lastSystemTime = now; s_lastReportedTime = now; } else if (timediff >= 0) { s_suspendedElapsedTime += timediff; } } /* libtpms added end */ /* C.3.3. Simulator Functions */ /* C.3.3.1. Introduction */ /* This set of functions is intended to be called by the simulator environment in order to simulate hardware events. */ /* C.3.3.2. _plat__TimerReset() */ /* This function sets current system clock time as t0 for counting TPM time. This function is called at a power on event to reset the clock. When the clock is reset, the indication that the clock was stopped is also set. */ LIB_EXPORT void _plat__TimerReset( void ) { s_lastSystemTime = 0; s_tpmTime = 0; s_adjustRate = CLOCK_NOMINAL; s_timerReset = TRUE; s_timerStopped = TRUE; s_hostMonotonicAdjustTime = 0; /* libtpms added */ s_suspendedElapsedTime = 0; /* libtpms added */ return; } /* C.3.3.3. _plat__TimerRestart() */ /* This function should be called in order to simulate the restart of the timer should it be stopped while power is still applied. */ LIB_EXPORT void _plat__TimerRestart( void ) { s_timerStopped = TRUE; return; } /* C.3.4. Functions Used by TPM */ /* C.3.4.1. Introduction */ /* These functions are called by the TPM code. They should be replaced by appropriated hardware functions. */ clock_t debugTime; /* C.3.4.2. _plat__Time() */ /* This is another, probably futile, attempt to define a portable function that will return a 64-bit clock value that has mSec resolution. */ LIB_EXPORT uint64_t _plat__RealTime( void ) { clock64_t time; //#ifdef _MSC_VER kgold #ifdef TPM_WINDOWS #include struct _timeb sysTime; // _ftime(&sysTime); /* kgold, mingw doesn't have _ftime_s */ time = (clock64_t)(sysTime.time) * 1000 + sysTime.millitm; // set the time back by one hour if daylight savings if(sysTime.dstflag) time -= 1000 * 60 * 60; // mSec/sec * sec/min * min/hour = ms/hour #else // hopefully, this will work with most UNIX systems struct timespec systime; // clock_gettime(CLOCK_MONOTONIC, &systime); time = (clock64_t)systime.tv_sec * 1000 + (systime.tv_nsec / 1000000); #endif /* libtpms added begin */ /* We have to make sure that this function returns monotonically increasing time also when a vTPM has been suspended and the host has been rebooted. Example: - The vTPM is suspended at systime '5' - The vTPM is resumed at systime '1' after a host reboot -> we now need to add '4' to the time Besides this we want to account for the time a vTPM was suspended. If it was suspended for 10 time units, we need to add '10' here. */ time += s_hostMonotonicAdjustTime + s_suspendedElapsedTime; /* libtpms added end */ return time; } /* C.3.4.3. _plat__TimerRead() */ /* This function provides access to the tick timer of the platform. The TPM code uses this value to drive the TPM Clock. */ /* The tick timer is supposed to run when power is applied to the device. This timer should not be reset by time events including _TPM_Init(). It should only be reset when TPM power is re-applied. */ /* If the TPM is run in a protected environment, that environment may provide the tick time to the TPM as long as the time provided by the environment is not allowed to go backwards. If the time provided by the system can go backwards during a power discontinuity, then the _plat__Signal_PowerOn() should call _plat__TimerReset(). */ LIB_EXPORT uint64_t _plat__TimerRead( void ) { #ifdef HARDWARE_CLOCK #error "need a definition for reading the hardware clock" return HARDWARE_CLOCK #else clock64_t timeDiff; clock64_t adjustedTimeDiff; clock64_t timeNow; clock64_t readjustedTimeDiff; // This produces a timeNow that is basically locked to the system clock. timeNow = _plat__RealTime(); // if this hasn't been initialized, initialize it if(s_lastSystemTime == 0) { s_lastSystemTime = timeNow; debugTime = clock(); s_lastReportedTime = 0; s_realTimePrevious = 0; } // The system time can bounce around and that's OK as long as we don't allow // time to go backwards. When the time does appear to go backwards, set // lastSystemTime to be the new value and then update the reported time. if(timeNow < s_lastReportedTime) s_lastSystemTime = timeNow; s_lastReportedTime = s_lastReportedTime + timeNow - s_lastSystemTime; s_lastSystemTime = timeNow; timeNow = s_lastReportedTime; // The code above produces a timeNow that is similar to the value returned // by Clock(). The difference is that timeNow does not max out, and it is // at a ms. rate rather than at a CLOCKS_PER_SEC rate. The code below // uses that value and does the rate adjustment on the time value. // If there is no difference in time, then skip all the computations if(s_realTimePrevious >= timeNow) return s_tpmTime; // Compute the amount of time since the last update of the system clock timeDiff = timeNow - s_realTimePrevious; // Do the time rate adjustment and conversion from CLOCKS_PER_SEC to mSec adjustedTimeDiff = (timeDiff * CLOCK_NOMINAL) / ((uint64_t)s_adjustRate); // update the TPM time with the adjusted timeDiff s_tpmTime += (clock64_t)adjustedTimeDiff; // Might have some rounding error that would loose CLOCKS. See what is not // being used. As mentioned above, this could result in putting back more than // is taken out. Here, we are trying to recreate timeDiff. readjustedTimeDiff = (adjustedTimeDiff * (uint64_t)s_adjustRate ) / CLOCK_NOMINAL; // adjusted is now converted back to being the amount we should advance the // previous sampled time. It should always be less than or equal to timeDiff. // That is, we could not have use more time than we started with. s_realTimePrevious = s_realTimePrevious + readjustedTimeDiff; #ifdef DEBUGGING_TIME // Put this in so that TPM time will pass much faster than real time when // doing debug. // A value of 1000 for DEBUG_TIME_MULTIPLER will make each ms into a second // A good value might be 100 return (s_tpmTime * DEBUG_TIME_MULTIPLIER); #endif return s_tpmTime; #endif } /* C.3.4.3. _plat__TimerWasReset() */ /* This function is used to interrogate the flag indicating if the tick timer has been reset. */ /* If the resetFlag parameter is SET, then the flag will be CLEAR before the function returns. */ LIB_EXPORT int _plat__TimerWasReset( void ) { int retVal = s_timerReset; s_timerReset = FALSE; return retVal; } /* C.3.4.4. _plat__TimerWasStopped() */ /* This function is used to interrogate the flag indicating if the tick timer has been stopped. If so, this is typically a reason to roll the nonce. */ /* This function will CLEAR the s_timerStopped flag before returning. This provides functionality that is similar to status register that is cleared when read. This is the model used here because it is the one that has the most impact on the TPM code as the flag can only be accessed by one entity in the TPM. Any other implementation of the hardware can be made to look like a read-once register. */ LIB_EXPORT int _plat__TimerWasStopped( void ) { BOOL retVal = s_timerStopped; s_timerStopped = FALSE; return retVal; } /* C.3.4.5. _plat__ClockAdjustRate() */ /* Adjust the clock rate */ LIB_EXPORT void _plat__ClockAdjustRate( int adjust // IN: the adjust number. It could be positive // or negative ) { // We expect the caller should only use a fixed set of constant values to // adjust the rate switch(adjust) { case CLOCK_ADJUST_COARSE: s_adjustRate += CLOCK_ADJUST_COARSE; break; case -CLOCK_ADJUST_COARSE: s_adjustRate -= CLOCK_ADJUST_COARSE; break; case CLOCK_ADJUST_MEDIUM: s_adjustRate += CLOCK_ADJUST_MEDIUM; break; case -CLOCK_ADJUST_MEDIUM: s_adjustRate -= CLOCK_ADJUST_MEDIUM; break; case CLOCK_ADJUST_FINE: s_adjustRate += CLOCK_ADJUST_FINE; break; case -CLOCK_ADJUST_FINE: s_adjustRate -= CLOCK_ADJUST_FINE; break; default: // ignore any other values; break; } if(s_adjustRate > (CLOCK_NOMINAL + CLOCK_ADJUST_LIMIT)) s_adjustRate = CLOCK_NOMINAL + CLOCK_ADJUST_LIMIT; if(s_adjustRate < (CLOCK_NOMINAL - CLOCK_ADJUST_LIMIT)) s_adjustRate = CLOCK_NOMINAL - CLOCK_ADJUST_LIMIT; return; } libtpms-0.9.3/src/tpm2/ClockCommands.c000066400000000000000000000112221421143571500175300ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Clocks and Timers */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: ClockCommands.c 1519 2019-11-15 20:43:51Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2018 */ /* */ /********************************************************************************/ #include "Tpm.h" #include "ReadClock_fp.h" #if CC_ReadClock // Conditional expansion of this file TPM_RC TPM2_ReadClock( ReadClock_Out *out // OUT: output parameter list ) { // Command Output out->currentTime.time = g_time; TimeFillInfo(&out->currentTime.clockInfo); return TPM_RC_SUCCESS; } #endif // CC_ReadClock #include "Tpm.h" #include "ClockSet_fp.h" #if CC_ClockSet // Conditional expansion of this file TPM_RC TPM2_ClockSet( ClockSet_In *in // IN: input parameter list ) { // Input Validation // new time can not be bigger than 0xFFFF000000000000 or smaller than // current clock if(in->newTime > 0xFFFF000000000000ULL || in->newTime < go.clock) return TPM_RCS_VALUE + RC_ClockSet_newTime; // Internal Data Update // Can't modify the clock if NV is not available. RETURN_IF_NV_IS_NOT_AVAILABLE; TimeClockUpdate(in->newTime); return TPM_RC_SUCCESS; } #endif // CC_ClockSet #include "Tpm.h" #include "ClockRateAdjust_fp.h" #if CC_ClockRateAdjust // Conditional expansion of this file TPM_RC TPM2_ClockRateAdjust( ClockRateAdjust_In *in // IN: input parameter list ) { // Internal Data Update TimeSetAdjustRate(in->rateAdjust); return TPM_RC_SUCCESS; } #endif // CC_ClockRateAdjust libtpms-0.9.3/src/tpm2/ClockRateAdjust_fp.h000066400000000000000000000073271421143571500205420ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: ClockRateAdjust_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef CLOCKRATEADJUST_FP_H #define CLOCKRATEADJUST_FP_H typedef struct { TPMI_RH_PROVISION auth; TPM_CLOCK_ADJUST rateAdjust; } ClockRateAdjust_In; #define RC_ClockRateAdjust_auth (TPM_RC_H + TPM_RC_1) #define RC_ClockRateAdjust_rateAdjust (TPM_RC_P + TPM_RC_1) TPM_RC TPM2_ClockRateAdjust( ClockRateAdjust_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/ClockSet_fp.h000066400000000000000000000072231421143571500172220ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: ClockSet_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef CLOCKSET_FP_H #define CLOCKSET_FP_H typedef struct { TPMI_RH_PROVISION auth; UINT64 newTime; } ClockSet_In; #define RC_ClockSet_auth (TPM_RC_H + TPM_RC_1) #define RC_ClockSet_newTime (TPM_RC_P + TPM_RC_1) TPM_RC TPM2_ClockSet( ClockSet_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/CommandAttributeData.h000066400000000000000000001061341421143571500210630ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Command code attribute array for GetCapability */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CommandAttributeData.h 1594 2020-03-26 22:15:48Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2020 */ /* */ /********************************************************************************/ /* 5.6 CommandAttributeData.h */ /* This file should only be included by CommandCodeAttibutes.c */ #ifdef _COMMAND_CODE_ATTRIBUTES_ #include "CommandAttributes.h" #if COMPRESSED_LISTS # define PAD_LIST 0 #else # define PAD_LIST 1 #endif /* This is the command code attribute array for GetCapability(). Both this array and s_commandAttributes provides command code attributes, but tuned for different purpose */ const TPMA_CC s_ccAttr [] = { #if (PAD_LIST || CC_NV_UndefineSpaceSpecial) TPMA_CC_INITIALIZER(0x011f, 0, 1, 0, 0, 2, 0, 0, 0), #endif #if (PAD_LIST || CC_EvictControl) TPMA_CC_INITIALIZER(0x0120, 0, 1, 0, 0, 2, 0, 0, 0), #endif #if (PAD_LIST || CC_HierarchyControl) TPMA_CC_INITIALIZER(0x0121, 0, 1, 1, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_NV_UndefineSpace) TPMA_CC_INITIALIZER(0x0122, 0, 1, 0, 0, 2, 0, 0, 0), #endif #if (PAD_LIST ) TPMA_CC_INITIALIZER(0x0123, 0, 0, 0, 0, 0, 0, 0, 0), #endif #if (PAD_LIST || CC_ChangeEPS) TPMA_CC_INITIALIZER(0x0124, 0, 1, 1, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_ChangePPS) TPMA_CC_INITIALIZER(0x0125, 0, 1, 1, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_Clear) TPMA_CC_INITIALIZER(0x0126, 0, 1, 1, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_ClearControl) TPMA_CC_INITIALIZER(0x0127, 0, 1, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_ClockSet) TPMA_CC_INITIALIZER(0x0128, 0, 1, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_HierarchyChangeAuth) TPMA_CC_INITIALIZER(0x0129, 0, 1, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_NV_DefineSpace) TPMA_CC_INITIALIZER(0x012a, 0, 1, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_PCR_Allocate) TPMA_CC_INITIALIZER(0x012b, 0, 1, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_PCR_SetAuthPolicy) TPMA_CC_INITIALIZER(0x012c, 0, 1, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_PP_Commands) TPMA_CC_INITIALIZER(0x012d, 0, 1, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_SetPrimaryPolicy) TPMA_CC_INITIALIZER(0x012e, 0, 1, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_FieldUpgradeStart) TPMA_CC_INITIALIZER(0x012f, 0, 0, 0, 0, 2, 0, 0, 0), #endif #if (PAD_LIST || CC_ClockRateAdjust) TPMA_CC_INITIALIZER(0x0130, 0, 0, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_CreatePrimary) TPMA_CC_INITIALIZER(0x0131, 0, 0, 0, 0, 1, 1, 0, 0), #endif #if (PAD_LIST || CC_NV_GlobalWriteLock) TPMA_CC_INITIALIZER(0x0132, 0, 1, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_GetCommandAuditDigest) TPMA_CC_INITIALIZER(0x0133, 0, 1, 0, 0, 2, 0, 0, 0), #endif #if (PAD_LIST || CC_NV_Increment) TPMA_CC_INITIALIZER(0x0134, 0, 1, 0, 0, 2, 0, 0, 0), #endif #if (PAD_LIST || CC_NV_SetBits) TPMA_CC_INITIALIZER(0x0135, 0, 1, 0, 0, 2, 0, 0, 0), #endif #if (PAD_LIST || CC_NV_Extend) TPMA_CC_INITIALIZER(0x0136, 0, 1, 0, 0, 2, 0, 0, 0), #endif #if (PAD_LIST || CC_NV_Write) TPMA_CC_INITIALIZER(0x0137, 0, 1, 0, 0, 2, 0, 0, 0), #endif #if (PAD_LIST || CC_NV_WriteLock) TPMA_CC_INITIALIZER(0x0138, 0, 1, 0, 0, 2, 0, 0, 0), #endif #if (PAD_LIST || CC_DictionaryAttackLockReset) TPMA_CC_INITIALIZER(0x0139, 0, 1, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_DictionaryAttackParameters) TPMA_CC_INITIALIZER(0x013a, 0, 1, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_NV_ChangeAuth) TPMA_CC_INITIALIZER(0x013b, 0, 1, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_PCR_Event) TPMA_CC_INITIALIZER(0x013c, 0, 1, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_PCR_Reset) TPMA_CC_INITIALIZER(0x013d, 0, 1, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_SequenceComplete) TPMA_CC_INITIALIZER(0x013e, 0, 0, 0, 1, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_SetAlgorithmSet) TPMA_CC_INITIALIZER(0x013f, 0, 1, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_SetCommandCodeAuditStatus) TPMA_CC_INITIALIZER(0x0140, 0, 1, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_FieldUpgradeData) TPMA_CC_INITIALIZER(0x0141, 0, 1, 0, 0, 0, 0, 0, 0), #endif #if (PAD_LIST || CC_IncrementalSelfTest) TPMA_CC_INITIALIZER(0x0142, 0, 1, 0, 0, 0, 0, 0, 0), #endif #if (PAD_LIST || CC_SelfTest) TPMA_CC_INITIALIZER(0x0143, 0, 1, 0, 0, 0, 0, 0, 0), #endif #if (PAD_LIST || CC_Startup) TPMA_CC_INITIALIZER(0x0144, 0, 1, 0, 0, 0, 0, 0, 0), #endif #if (PAD_LIST || CC_Shutdown) TPMA_CC_INITIALIZER(0x0145, 0, 1, 0, 0, 0, 0, 0, 0), #endif #if (PAD_LIST || CC_StirRandom) TPMA_CC_INITIALIZER(0x0146, 0, 1, 0, 0, 0, 0, 0, 0), #endif #if (PAD_LIST || CC_ActivateCredential) TPMA_CC_INITIALIZER(0x0147, 0, 0, 0, 0, 2, 0, 0, 0), #endif #if (PAD_LIST || CC_Certify) TPMA_CC_INITIALIZER(0x0148, 0, 0, 0, 0, 2, 0, 0, 0), #endif #if (PAD_LIST || CC_PolicyNV) TPMA_CC_INITIALIZER(0x0149, 0, 0, 0, 0, 3, 0, 0, 0), #endif #if (PAD_LIST || CC_CertifyCreation) TPMA_CC_INITIALIZER(0x014a, 0, 0, 0, 0, 2, 0, 0, 0), #endif #if (PAD_LIST || CC_Duplicate) TPMA_CC_INITIALIZER(0x014b, 0, 0, 0, 0, 2, 0, 0, 0), #endif #if (PAD_LIST || CC_GetTime) TPMA_CC_INITIALIZER(0x014c, 0, 0, 0, 0, 2, 0, 0, 0), #endif #if (PAD_LIST || CC_GetSessionAuditDigest) TPMA_CC_INITIALIZER(0x014d, 0, 0, 0, 0, 3, 0, 0, 0), #endif #if (PAD_LIST || CC_NV_Read) TPMA_CC_INITIALIZER(0x014e, 0, 0, 0, 0, 2, 0, 0, 0), #endif #if (PAD_LIST || CC_NV_ReadLock) TPMA_CC_INITIALIZER(0x014f, 0, 1, 0, 0, 2, 0, 0, 0), #endif #if (PAD_LIST || CC_ObjectChangeAuth) TPMA_CC_INITIALIZER(0x0150, 0, 0, 0, 0, 2, 0, 0, 0), #endif #if (PAD_LIST || CC_PolicySecret) TPMA_CC_INITIALIZER(0x0151, 0, 0, 0, 0, 2, 0, 0, 0), #endif #if (PAD_LIST || CC_Rewrap) TPMA_CC_INITIALIZER(0x0152, 0, 0, 0, 0, 2, 0, 0, 0), #endif #if (PAD_LIST || CC_Create) TPMA_CC_INITIALIZER(0x0153, 0, 0, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_ECDH_ZGen) TPMA_CC_INITIALIZER(0x0154, 0, 0, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || (CC_HMAC || CC_MAC)) TPMA_CC_INITIALIZER(0x0155, 0, 0, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_Import) TPMA_CC_INITIALIZER(0x0156, 0, 0, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_Load) TPMA_CC_INITIALIZER(0x0157, 0, 0, 0, 0, 1, 1, 0, 0), #endif #if (PAD_LIST || CC_Quote) TPMA_CC_INITIALIZER(0x0158, 0, 0, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_RSA_Decrypt) TPMA_CC_INITIALIZER(0x0159, 0, 0, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST ) TPMA_CC_INITIALIZER(0x015a, 0, 0, 0, 0, 0, 0, 0, 0), #endif #if (PAD_LIST || (CC_HMAC_Start || CC_MAC_Start)) TPMA_CC_INITIALIZER(0x015b, 0, 0, 0, 0, 1, 1, 0, 0), #endif #if (PAD_LIST || CC_SequenceUpdate) TPMA_CC_INITIALIZER(0x015c, 0, 0, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_Sign) TPMA_CC_INITIALIZER(0x015d, 0, 0, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_Unseal) TPMA_CC_INITIALIZER(0x015e, 0, 0, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST ) TPMA_CC_INITIALIZER(0x015f, 0, 0, 0, 0, 0, 0, 0, 0), #endif #if (PAD_LIST || CC_PolicySigned) TPMA_CC_INITIALIZER(0x0160, 0, 0, 0, 0, 2, 0, 0, 0), #endif #if (PAD_LIST || CC_ContextLoad) TPMA_CC_INITIALIZER(0x0161, 0, 0, 0, 0, 0, 1, 0, 0), #endif #if (PAD_LIST || CC_ContextSave) TPMA_CC_INITIALIZER(0x0162, 0, 0, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_ECDH_KeyGen) TPMA_CC_INITIALIZER(0x0163, 0, 0, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_EncryptDecrypt) TPMA_CC_INITIALIZER(0x0164, 0, 0, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_FlushContext) TPMA_CC_INITIALIZER(0x0165, 0, 0, 0, 0, 0, 0, 0, 0), #endif #if (PAD_LIST ) TPMA_CC_INITIALIZER(0x0166, 0, 0, 0, 0, 0, 0, 0, 0), #endif #if (PAD_LIST || CC_LoadExternal) TPMA_CC_INITIALIZER(0x0167, 0, 0, 0, 0, 0, 1, 0, 0), #endif #if (PAD_LIST || CC_MakeCredential) TPMA_CC_INITIALIZER(0x0168, 0, 0, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_NV_ReadPublic) TPMA_CC_INITIALIZER(0x0169, 0, 0, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_PolicyAuthorize) TPMA_CC_INITIALIZER(0x016a, 0, 0, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_PolicyAuthValue) TPMA_CC_INITIALIZER(0x016b, 0, 0, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_PolicyCommandCode) TPMA_CC_INITIALIZER(0x016c, 0, 0, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_PolicyCounterTimer) TPMA_CC_INITIALIZER(0x016d, 0, 0, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_PolicyCpHash) TPMA_CC_INITIALIZER(0x016e, 0, 0, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_PolicyLocality) TPMA_CC_INITIALIZER(0x016f, 0, 0, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_PolicyNameHash) TPMA_CC_INITIALIZER(0x0170, 0, 0, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_PolicyOR) TPMA_CC_INITIALIZER(0x0171, 0, 0, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_PolicyTicket) TPMA_CC_INITIALIZER(0x0172, 0, 0, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_ReadPublic) TPMA_CC_INITIALIZER(0x0173, 0, 0, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_RSA_Encrypt) TPMA_CC_INITIALIZER(0x0174, 0, 0, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST ) TPMA_CC_INITIALIZER(0x0175, 0, 0, 0, 0, 0, 0, 0, 0), #endif #if (PAD_LIST || CC_StartAuthSession) TPMA_CC_INITIALIZER(0x0176, 0, 0, 0, 0, 2, 1, 0, 0), #endif #if (PAD_LIST || CC_VerifySignature) TPMA_CC_INITIALIZER(0x0177, 0, 0, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_ECC_Parameters) TPMA_CC_INITIALIZER(0x0178, 0, 0, 0, 0, 0, 0, 0, 0), #endif #if (PAD_LIST || CC_FirmwareRead) TPMA_CC_INITIALIZER(0x0179, 0, 0, 0, 0, 0, 0, 0, 0), #endif #if (PAD_LIST || CC_GetCapability) TPMA_CC_INITIALIZER(0x017a, 0, 0, 0, 0, 0, 0, 0, 0), #endif #if (PAD_LIST || CC_GetRandom) TPMA_CC_INITIALIZER(0x017b, 0, 0, 0, 0, 0, 0, 0, 0), #endif #if (PAD_LIST || CC_GetTestResult) TPMA_CC_INITIALIZER(0x017c, 0, 0, 0, 0, 0, 0, 0, 0), #endif #if (PAD_LIST || CC_Hash) TPMA_CC_INITIALIZER(0x017d, 0, 0, 0, 0, 0, 0, 0, 0), #endif #if (PAD_LIST || CC_PCR_Read) TPMA_CC_INITIALIZER(0x017e, 0, 0, 0, 0, 0, 0, 0, 0), #endif #if (PAD_LIST || CC_PolicyPCR) TPMA_CC_INITIALIZER(0x017f, 0, 0, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_PolicyRestart) TPMA_CC_INITIALIZER(0x0180, 0, 0, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_ReadClock) TPMA_CC_INITIALIZER(0x0181, 0, 0, 0, 0, 0, 0, 0, 0), #endif #if (PAD_LIST || CC_PCR_Extend) TPMA_CC_INITIALIZER(0x0182, 0, 1, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_PCR_SetAuthValue) TPMA_CC_INITIALIZER(0x0183, 0, 0, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_NV_Certify) TPMA_CC_INITIALIZER(0x0184, 0, 0, 0, 0, 3, 0, 0, 0), #endif #if (PAD_LIST || CC_EventSequenceComplete) TPMA_CC_INITIALIZER(0x0185, 0, 1, 0, 1, 2, 0, 0, 0), #endif #if (PAD_LIST || CC_HashSequenceStart) TPMA_CC_INITIALIZER(0x0186, 0, 0, 0, 0, 0, 1, 0, 0), #endif #if (PAD_LIST || CC_PolicyPhysicalPresence) TPMA_CC_INITIALIZER(0x0187, 0, 0, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_PolicyDuplicationSelect) TPMA_CC_INITIALIZER(0x0188, 0, 0, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_PolicyGetDigest) TPMA_CC_INITIALIZER(0x0189, 0, 0, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_TestParms) TPMA_CC_INITIALIZER(0x018a, 0, 0, 0, 0, 0, 0, 0, 0), #endif #if (PAD_LIST || CC_Commit) TPMA_CC_INITIALIZER(0x018b, 0, 0, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_PolicyPassword) TPMA_CC_INITIALIZER(0x018c, 0, 0, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_ZGen_2Phase) TPMA_CC_INITIALIZER(0x018d, 0, 0, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_EC_Ephemeral) TPMA_CC_INITIALIZER(0x018e, 0, 0, 0, 0, 0, 0, 0, 0), #endif #if (PAD_LIST || CC_PolicyNvWritten) TPMA_CC_INITIALIZER(0x018f, 0, 0, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_PolicyTemplate) TPMA_CC_INITIALIZER(0x0190, 0, 0, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_CreateLoaded) TPMA_CC_INITIALIZER(0x0191, 0, 0, 0, 0, 1, 1, 0, 0), #endif #if (PAD_LIST || CC_PolicyAuthorizeNV) TPMA_CC_INITIALIZER(0x0192, 0, 0, 0, 0, 3, 0, 0, 0), #endif #if (PAD_LIST || CC_EncryptDecrypt2) TPMA_CC_INITIALIZER(0x0193, 0, 0, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_AC_GetCapability) TPMA_CC_INITIALIZER(0x0194, 0, 0, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_AC_Send) TPMA_CC_INITIALIZER(0x0195, 0, 0, 0, 0, 3, 0, 0, 0), #endif #if (PAD_LIST || CC_Policy_AC_SendSelect) TPMA_CC_INITIALIZER(0x0196, 0, 0, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_CertifyX509) TPMA_CC_INITIALIZER(0x0197, 0, 0, 0, 0, 2, 0, 0, 0), #endif #if (PAD_LIST || CC_ACT_SetTimeout) TPMA_CC_INITIALIZER(0x0198, 0, 0, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_ECC_Encrypt) TPMA_CC_INITIALIZER(0x0199, 0, 0, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_ECC_Decrypt) TPMA_CC_INITIALIZER(0x019A, 0, 0, 0, 0, 1, 0, 0, 0), #endif #if (PAD_LIST || CC_Vendor_TCG_Test) TPMA_CC_INITIALIZER(0x0000, 0, 0, 0, 0, 0, 0, 1, 0), #endif TPMA_ZERO_INITIALIZER() }; /* This is the command code attribute structure. */ const COMMAND_ATTRIBUTES s_commandAttributes [] = { #if (PAD_LIST || CC_NV_UndefineSpaceSpecial) (COMMAND_ATTRIBUTES)(CC_NV_UndefineSpaceSpecial * // 0x011f (IS_IMPLEMENTED+HANDLE_1_ADMIN+HANDLE_2_USER+PP_COMMAND)), #endif #if (PAD_LIST || CC_EvictControl) (COMMAND_ATTRIBUTES)(CC_EvictControl * // 0x0120 (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)), #endif #if (PAD_LIST || CC_HierarchyControl) (COMMAND_ATTRIBUTES)(CC_HierarchyControl * // 0x0121 (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)), #endif #if (PAD_LIST || CC_NV_UndefineSpace) (COMMAND_ATTRIBUTES)(CC_NV_UndefineSpace * // 0x0122 (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)), #endif #if (PAD_LIST ) (COMMAND_ATTRIBUTES)(0), // 0x0123 #endif #if (PAD_LIST || CC_ChangeEPS) (COMMAND_ATTRIBUTES)(CC_ChangeEPS * // 0x0124 (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)), #endif #if (PAD_LIST || CC_ChangePPS) (COMMAND_ATTRIBUTES)(CC_ChangePPS * // 0x0125 (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)), #endif #if (PAD_LIST || CC_Clear) (COMMAND_ATTRIBUTES)(CC_Clear * // 0x0126 (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)), #endif #if (PAD_LIST || CC_ClearControl) (COMMAND_ATTRIBUTES)(CC_ClearControl * // 0x0127 (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)), #endif #if (PAD_LIST || CC_ClockSet) (COMMAND_ATTRIBUTES)(CC_ClockSet * // 0x0128 (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)), #endif #if (PAD_LIST || CC_HierarchyChangeAuth) (COMMAND_ATTRIBUTES)(CC_HierarchyChangeAuth * // 0x0129 (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+PP_COMMAND)), #endif #if (PAD_LIST || CC_NV_DefineSpace) (COMMAND_ATTRIBUTES)(CC_NV_DefineSpace * // 0x012a (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+PP_COMMAND)), #endif #if (PAD_LIST || CC_PCR_Allocate) (COMMAND_ATTRIBUTES)(CC_PCR_Allocate * // 0x012b (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)), #endif #if (PAD_LIST || CC_PCR_SetAuthPolicy) (COMMAND_ATTRIBUTES)(CC_PCR_SetAuthPolicy * // 0x012c (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+PP_COMMAND)), #endif #if (PAD_LIST || CC_PP_Commands) (COMMAND_ATTRIBUTES)(CC_PP_Commands * // 0x012d (IS_IMPLEMENTED+HANDLE_1_USER+PP_REQUIRED)), #endif #if (PAD_LIST || CC_SetPrimaryPolicy) (COMMAND_ATTRIBUTES)(CC_SetPrimaryPolicy * // 0x012e (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+PP_COMMAND)), #endif #if (PAD_LIST || CC_FieldUpgradeStart) (COMMAND_ATTRIBUTES)(CC_FieldUpgradeStart * // 0x012f (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_ADMIN+PP_COMMAND)), #endif #if (PAD_LIST || CC_ClockRateAdjust) (COMMAND_ATTRIBUTES)(CC_ClockRateAdjust * // 0x0130 (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)), #endif #if (PAD_LIST || CC_CreatePrimary) (COMMAND_ATTRIBUTES)(CC_CreatePrimary * // 0x0131 (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+PP_COMMAND+ENCRYPT_2+R_HANDLE)), #endif #if (PAD_LIST || CC_NV_GlobalWriteLock) (COMMAND_ATTRIBUTES)(CC_NV_GlobalWriteLock * // 0x0132 (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)), #endif #if (PAD_LIST || CC_GetCommandAuditDigest) (COMMAND_ATTRIBUTES)(CC_GetCommandAuditDigest * // 0x0133 (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+HANDLE_2_USER+ENCRYPT_2)), #endif #if (PAD_LIST || CC_NV_Increment) (COMMAND_ATTRIBUTES)(CC_NV_Increment * // 0x0134 (IS_IMPLEMENTED+HANDLE_1_USER)), #endif #if (PAD_LIST || CC_NV_SetBits) (COMMAND_ATTRIBUTES)(CC_NV_SetBits * // 0x0135 (IS_IMPLEMENTED+HANDLE_1_USER)), #endif #if (PAD_LIST || CC_NV_Extend) (COMMAND_ATTRIBUTES)(CC_NV_Extend * // 0x0136 (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER)), #endif #if (PAD_LIST || CC_NV_Write) (COMMAND_ATTRIBUTES)(CC_NV_Write * // 0x0137 (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER)), #endif #if (PAD_LIST || CC_NV_WriteLock) (COMMAND_ATTRIBUTES)(CC_NV_WriteLock * // 0x0138 (IS_IMPLEMENTED+HANDLE_1_USER)), #endif #if (PAD_LIST || CC_DictionaryAttackLockReset) (COMMAND_ATTRIBUTES)(CC_DictionaryAttackLockReset * // 0x0139 (IS_IMPLEMENTED+HANDLE_1_USER)), #endif #if (PAD_LIST || CC_DictionaryAttackParameters) (COMMAND_ATTRIBUTES)(CC_DictionaryAttackParameters * // 0x013a (IS_IMPLEMENTED+HANDLE_1_USER)), #endif #if (PAD_LIST || CC_NV_ChangeAuth) (COMMAND_ATTRIBUTES)(CC_NV_ChangeAuth * // 0x013b (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_ADMIN)), #endif #if (PAD_LIST || CC_PCR_Event) (COMMAND_ATTRIBUTES)(CC_PCR_Event * // 0x013c (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER)), #endif #if (PAD_LIST || CC_PCR_Reset) (COMMAND_ATTRIBUTES)(CC_PCR_Reset * // 0x013d (IS_IMPLEMENTED+HANDLE_1_USER)), #endif #if (PAD_LIST || CC_SequenceComplete) (COMMAND_ATTRIBUTES)(CC_SequenceComplete * // 0x013e (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)), #endif #if (PAD_LIST || CC_SetAlgorithmSet) (COMMAND_ATTRIBUTES)(CC_SetAlgorithmSet * // 0x013f (IS_IMPLEMENTED+HANDLE_1_USER)), #endif #if (PAD_LIST || CC_SetCommandCodeAuditStatus) (COMMAND_ATTRIBUTES)(CC_SetCommandCodeAuditStatus * // 0x0140 (IS_IMPLEMENTED+HANDLE_1_USER+PP_COMMAND)), #endif #if (PAD_LIST || CC_FieldUpgradeData) (COMMAND_ATTRIBUTES)(CC_FieldUpgradeData * // 0x0141 (IS_IMPLEMENTED+DECRYPT_2)), #endif #if (PAD_LIST || CC_IncrementalSelfTest) (COMMAND_ATTRIBUTES)(CC_IncrementalSelfTest * // 0x0142 (IS_IMPLEMENTED)), #endif #if (PAD_LIST || CC_SelfTest) (COMMAND_ATTRIBUTES)(CC_SelfTest * // 0x0143 (IS_IMPLEMENTED)), #endif #if (PAD_LIST || CC_Startup) (COMMAND_ATTRIBUTES)(CC_Startup * // 0x0144 (IS_IMPLEMENTED+NO_SESSIONS)), #endif #if (PAD_LIST || CC_Shutdown) (COMMAND_ATTRIBUTES)(CC_Shutdown * // 0x0145 (IS_IMPLEMENTED)), #endif #if (PAD_LIST || CC_StirRandom) (COMMAND_ATTRIBUTES)(CC_StirRandom * // 0x0146 (IS_IMPLEMENTED+DECRYPT_2)), #endif #if (PAD_LIST || CC_ActivateCredential) (COMMAND_ATTRIBUTES)(CC_ActivateCredential * // 0x0147 (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_ADMIN+HANDLE_2_USER+ENCRYPT_2)), #endif #if (PAD_LIST || CC_Certify) (COMMAND_ATTRIBUTES)(CC_Certify * // 0x0148 (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_ADMIN+HANDLE_2_USER+ENCRYPT_2)), #endif #if (PAD_LIST || CC_PolicyNV) (COMMAND_ATTRIBUTES)(CC_PolicyNV * // 0x0149 (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ALLOW_TRIAL)), #endif #if (PAD_LIST || CC_CertifyCreation) (COMMAND_ATTRIBUTES)(CC_CertifyCreation * // 0x014a (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)), #endif #if (PAD_LIST || CC_Duplicate) (COMMAND_ATTRIBUTES)(CC_Duplicate * // 0x014b (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_DUP+ENCRYPT_2)), #endif #if (PAD_LIST || CC_GetTime) (COMMAND_ATTRIBUTES)(CC_GetTime * // 0x014c (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+HANDLE_2_USER+ENCRYPT_2)), #endif #if (PAD_LIST || CC_GetSessionAuditDigest) (COMMAND_ATTRIBUTES)(CC_GetSessionAuditDigest * // 0x014d (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+HANDLE_2_USER+ENCRYPT_2)), #endif #if (PAD_LIST || CC_NV_Read) (COMMAND_ATTRIBUTES)(CC_NV_Read * // 0x014e (IS_IMPLEMENTED+HANDLE_1_USER+ENCRYPT_2)), #endif #if (PAD_LIST || CC_NV_ReadLock) (COMMAND_ATTRIBUTES)(CC_NV_ReadLock * // 0x014f (IS_IMPLEMENTED+HANDLE_1_USER)), #endif #if (PAD_LIST || CC_ObjectChangeAuth) (COMMAND_ATTRIBUTES)(CC_ObjectChangeAuth * // 0x0150 (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_ADMIN+ENCRYPT_2)), #endif #if (PAD_LIST || CC_PolicySecret) (COMMAND_ATTRIBUTES)(CC_PolicySecret * // 0x0151 (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ALLOW_TRIAL+ENCRYPT_2)), #endif #if (PAD_LIST || CC_Rewrap) (COMMAND_ATTRIBUTES)(CC_Rewrap * // 0x0152 (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)), #endif #if (PAD_LIST || CC_Create) (COMMAND_ATTRIBUTES)(CC_Create * // 0x0153 (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)), #endif #if (PAD_LIST || CC_ECDH_ZGen) (COMMAND_ATTRIBUTES)(CC_ECDH_ZGen * // 0x0154 (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)), #endif #if (PAD_LIST || (CC_HMAC || CC_MAC)) (COMMAND_ATTRIBUTES)((CC_HMAC || CC_MAC) * // 0x0155 (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)), #endif #if (PAD_LIST || CC_Import) (COMMAND_ATTRIBUTES)(CC_Import * // 0x0156 (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)), #endif #if (PAD_LIST || CC_Load) (COMMAND_ATTRIBUTES)(CC_Load * // 0x0157 (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2+R_HANDLE)), #endif #if (PAD_LIST || CC_Quote) (COMMAND_ATTRIBUTES)(CC_Quote * // 0x0158 (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)), #endif #if (PAD_LIST || CC_RSA_Decrypt) (COMMAND_ATTRIBUTES)(CC_RSA_Decrypt * // 0x0159 (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)), #endif #if (PAD_LIST ) (COMMAND_ATTRIBUTES)(0), // 0x015a #endif #if (PAD_LIST || (CC_HMAC_Start || CC_MAC_Start)) (COMMAND_ATTRIBUTES)((CC_HMAC_Start || CC_MAC_Start) * // 0x015b (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+R_HANDLE)), #endif #if (PAD_LIST || CC_SequenceUpdate) (COMMAND_ATTRIBUTES)(CC_SequenceUpdate * // 0x015c (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER)), #endif #if (PAD_LIST || CC_Sign) (COMMAND_ATTRIBUTES)(CC_Sign * // 0x015d (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER)), #endif #if (PAD_LIST || CC_Unseal) (COMMAND_ATTRIBUTES)(CC_Unseal * // 0x015e (IS_IMPLEMENTED+HANDLE_1_USER+ENCRYPT_2)), #endif #if (PAD_LIST ) (COMMAND_ATTRIBUTES)(0), // 0x015f #endif #if (PAD_LIST || CC_PolicySigned) (COMMAND_ATTRIBUTES)(CC_PolicySigned * // 0x0160 (IS_IMPLEMENTED+DECRYPT_2+ALLOW_TRIAL+ENCRYPT_2)), #endif #if (PAD_LIST || CC_ContextLoad) (COMMAND_ATTRIBUTES)(CC_ContextLoad * // 0x0161 (IS_IMPLEMENTED+NO_SESSIONS+R_HANDLE)), #endif #if (PAD_LIST || CC_ContextSave) (COMMAND_ATTRIBUTES)(CC_ContextSave * // 0x0162 (IS_IMPLEMENTED+NO_SESSIONS)), #endif #if (PAD_LIST || CC_ECDH_KeyGen) (COMMAND_ATTRIBUTES)(CC_ECDH_KeyGen * // 0x0163 (IS_IMPLEMENTED+ENCRYPT_2)), #endif #if (PAD_LIST || CC_EncryptDecrypt) (COMMAND_ATTRIBUTES)(CC_EncryptDecrypt * // 0x0164 (IS_IMPLEMENTED+HANDLE_1_USER+ENCRYPT_2)), #endif #if (PAD_LIST || CC_FlushContext) (COMMAND_ATTRIBUTES)(CC_FlushContext * // 0x0165 (IS_IMPLEMENTED+NO_SESSIONS)), #endif #if (PAD_LIST ) (COMMAND_ATTRIBUTES)(0), // 0x0166 #endif #if (PAD_LIST || CC_LoadExternal) (COMMAND_ATTRIBUTES)(CC_LoadExternal * // 0x0167 (IS_IMPLEMENTED+DECRYPT_2+ENCRYPT_2+R_HANDLE)), #endif #if (PAD_LIST || CC_MakeCredential) (COMMAND_ATTRIBUTES)(CC_MakeCredential * // 0x0168 (IS_IMPLEMENTED+DECRYPT_2+ENCRYPT_2)), #endif #if (PAD_LIST || CC_NV_ReadPublic) (COMMAND_ATTRIBUTES)(CC_NV_ReadPublic * // 0x0169 (IS_IMPLEMENTED+ENCRYPT_2)), #endif #if (PAD_LIST || CC_PolicyAuthorize) (COMMAND_ATTRIBUTES)(CC_PolicyAuthorize * // 0x016a (IS_IMPLEMENTED+DECRYPT_2+ALLOW_TRIAL)), #endif #if (PAD_LIST || CC_PolicyAuthValue) (COMMAND_ATTRIBUTES)(CC_PolicyAuthValue * // 0x016b (IS_IMPLEMENTED+ALLOW_TRIAL)), #endif #if (PAD_LIST || CC_PolicyCommandCode) (COMMAND_ATTRIBUTES)(CC_PolicyCommandCode * // 0x016c (IS_IMPLEMENTED+ALLOW_TRIAL)), #endif #if (PAD_LIST || CC_PolicyCounterTimer) (COMMAND_ATTRIBUTES)(CC_PolicyCounterTimer * // 0x016d (IS_IMPLEMENTED+DECRYPT_2+ALLOW_TRIAL)), #endif #if (PAD_LIST || CC_PolicyCpHash) (COMMAND_ATTRIBUTES)(CC_PolicyCpHash * // 0x016e (IS_IMPLEMENTED+DECRYPT_2+ALLOW_TRIAL)), #endif #if (PAD_LIST || CC_PolicyLocality) (COMMAND_ATTRIBUTES)(CC_PolicyLocality * // 0x016f (IS_IMPLEMENTED+ALLOW_TRIAL)), #endif #if (PAD_LIST || CC_PolicyNameHash) (COMMAND_ATTRIBUTES)(CC_PolicyNameHash * // 0x0170 (IS_IMPLEMENTED+DECRYPT_2+ALLOW_TRIAL)), #endif #if (PAD_LIST || CC_PolicyOR) (COMMAND_ATTRIBUTES)(CC_PolicyOR * // 0x0171 (IS_IMPLEMENTED+ALLOW_TRIAL)), #endif #if (PAD_LIST || CC_PolicyTicket) (COMMAND_ATTRIBUTES)(CC_PolicyTicket * // 0x0172 (IS_IMPLEMENTED+DECRYPT_2+ALLOW_TRIAL)), #endif #if (PAD_LIST || CC_ReadPublic) (COMMAND_ATTRIBUTES)(CC_ReadPublic * // 0x0173 (IS_IMPLEMENTED+ENCRYPT_2)), #endif #if (PAD_LIST || CC_RSA_Encrypt) (COMMAND_ATTRIBUTES)(CC_RSA_Encrypt * // 0x0174 (IS_IMPLEMENTED+DECRYPT_2+ENCRYPT_2)), #endif #if (PAD_LIST ) (COMMAND_ATTRIBUTES)(0), // 0x0175 #endif #if (PAD_LIST || CC_StartAuthSession) (COMMAND_ATTRIBUTES)(CC_StartAuthSession * // 0x0176 (IS_IMPLEMENTED+DECRYPT_2+ENCRYPT_2+R_HANDLE)), #endif #if (PAD_LIST || CC_VerifySignature) (COMMAND_ATTRIBUTES)(CC_VerifySignature * // 0x0177 (IS_IMPLEMENTED+DECRYPT_2)), #endif #if (PAD_LIST || CC_ECC_Parameters) (COMMAND_ATTRIBUTES)(CC_ECC_Parameters * // 0x0178 (IS_IMPLEMENTED)), #endif #if (PAD_LIST || CC_FirmwareRead) (COMMAND_ATTRIBUTES)(CC_FirmwareRead * // 0x0179 (IS_IMPLEMENTED+ENCRYPT_2)), #endif #if (PAD_LIST || CC_GetCapability) (COMMAND_ATTRIBUTES)(CC_GetCapability * // 0x017a (IS_IMPLEMENTED)), #endif #if (PAD_LIST || CC_GetRandom) (COMMAND_ATTRIBUTES)(CC_GetRandom * // 0x017b (IS_IMPLEMENTED+ENCRYPT_2)), #endif #if (PAD_LIST || CC_GetTestResult) (COMMAND_ATTRIBUTES)(CC_GetTestResult * // 0x017c (IS_IMPLEMENTED+ENCRYPT_2)), #endif #if (PAD_LIST || CC_Hash) (COMMAND_ATTRIBUTES)(CC_Hash * // 0x017d (IS_IMPLEMENTED+DECRYPT_2+ENCRYPT_2)), #endif #if (PAD_LIST || CC_PCR_Read) (COMMAND_ATTRIBUTES)(CC_PCR_Read * // 0x017e (IS_IMPLEMENTED)), #endif #if (PAD_LIST || CC_PolicyPCR) (COMMAND_ATTRIBUTES)(CC_PolicyPCR * // 0x017f (IS_IMPLEMENTED+DECRYPT_2+ALLOW_TRIAL)), #endif #if (PAD_LIST || CC_PolicyRestart) (COMMAND_ATTRIBUTES)(CC_PolicyRestart * // 0x0180 (IS_IMPLEMENTED+ALLOW_TRIAL)), #endif #if (PAD_LIST || CC_ReadClock) (COMMAND_ATTRIBUTES)(CC_ReadClock * // 0x0181 (IS_IMPLEMENTED)), #endif #if (PAD_LIST || CC_PCR_Extend) (COMMAND_ATTRIBUTES)(CC_PCR_Extend * // 0x0182 (IS_IMPLEMENTED+HANDLE_1_USER)), #endif #if (PAD_LIST || CC_PCR_SetAuthValue) (COMMAND_ATTRIBUTES)(CC_PCR_SetAuthValue * // 0x0183 (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER)), #endif #if (PAD_LIST || CC_NV_Certify) (COMMAND_ATTRIBUTES)(CC_NV_Certify * // 0x0184 (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+HANDLE_2_USER+ENCRYPT_2)), #endif #if (PAD_LIST || CC_EventSequenceComplete) (COMMAND_ATTRIBUTES)(CC_EventSequenceComplete * // 0x0185 (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+HANDLE_2_USER)), #endif #if (PAD_LIST || CC_HashSequenceStart) (COMMAND_ATTRIBUTES)(CC_HashSequenceStart * // 0x0186 (IS_IMPLEMENTED+DECRYPT_2+R_HANDLE)), #endif #if (PAD_LIST || CC_PolicyPhysicalPresence) (COMMAND_ATTRIBUTES)(CC_PolicyPhysicalPresence * // 0x0187 (IS_IMPLEMENTED+ALLOW_TRIAL)), #endif #if (PAD_LIST || CC_PolicyDuplicationSelect) (COMMAND_ATTRIBUTES)(CC_PolicyDuplicationSelect * // 0x0188 (IS_IMPLEMENTED+DECRYPT_2+ALLOW_TRIAL)), #endif #if (PAD_LIST || CC_PolicyGetDigest) (COMMAND_ATTRIBUTES)(CC_PolicyGetDigest * // 0x0189 (IS_IMPLEMENTED+ALLOW_TRIAL+ENCRYPT_2)), #endif #if (PAD_LIST || CC_TestParms) (COMMAND_ATTRIBUTES)(CC_TestParms * // 0x018a (IS_IMPLEMENTED)), #endif #if (PAD_LIST || CC_Commit) (COMMAND_ATTRIBUTES)(CC_Commit * // 0x018b (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)), #endif #if (PAD_LIST || CC_PolicyPassword) (COMMAND_ATTRIBUTES)(CC_PolicyPassword * // 0x018c (IS_IMPLEMENTED+ALLOW_TRIAL)), #endif #if (PAD_LIST || CC_ZGen_2Phase) (COMMAND_ATTRIBUTES)(CC_ZGen_2Phase * // 0x018d (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)), #endif #if (PAD_LIST || CC_EC_Ephemeral) (COMMAND_ATTRIBUTES)(CC_EC_Ephemeral * // 0x018e (IS_IMPLEMENTED+ENCRYPT_2)), #endif #if (PAD_LIST || CC_PolicyNvWritten) (COMMAND_ATTRIBUTES)(CC_PolicyNvWritten * // 0x018f (IS_IMPLEMENTED+ALLOW_TRIAL)), #endif #if (PAD_LIST || CC_PolicyTemplate) (COMMAND_ATTRIBUTES)(CC_PolicyTemplate * // 0x0190 (IS_IMPLEMENTED+DECRYPT_2+ALLOW_TRIAL)), #endif #if (PAD_LIST || CC_CreateLoaded) (COMMAND_ATTRIBUTES)(CC_CreateLoaded * // 0x0191 (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+PP_COMMAND+ENCRYPT_2+R_HANDLE)), #endif #if (PAD_LIST || CC_PolicyAuthorizeNV) (COMMAND_ATTRIBUTES)(CC_PolicyAuthorizeNV * // 0x0192 (IS_IMPLEMENTED+HANDLE_1_USER+ALLOW_TRIAL)), #endif #if (PAD_LIST || CC_EncryptDecrypt2) (COMMAND_ATTRIBUTES)(CC_EncryptDecrypt2 * // 0x0193 (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)), #endif #if (PAD_LIST || CC_AC_GetCapability) (COMMAND_ATTRIBUTES)(CC_AC_GetCapability * // 0x0194 (IS_IMPLEMENTED)), #endif #if (PAD_LIST || CC_AC_Send) (COMMAND_ATTRIBUTES)(CC_AC_Send * // 0x0195 (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_DUP+HANDLE_2_USER)), #endif #if (PAD_LIST || CC_Policy_AC_SendSelect) (COMMAND_ATTRIBUTES)(CC_Policy_AC_SendSelect * // 0x0196 (IS_IMPLEMENTED+DECRYPT_2+ALLOW_TRIAL)), #endif #if (PAD_LIST || CC_CertifyX509) (COMMAND_ATTRIBUTES)(CC_CertifyX509 * // 0x0197 (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_ADMIN+HANDLE_2_USER+ENCRYPT_2)), #endif #if (PAD_LIST || CC_ACT_SetTimeout) (COMMAND_ATTRIBUTES)(CC_ACT_SetTimeout * // 0x0198 (IS_IMPLEMENTED+HANDLE_1_USER)), #endif #if (PAD_LIST || CC_ECC_Encrypt) (COMMAND_ATTRIBUTES)(CC_ECC_Encrypt * // 0x0199 (IS_IMPLEMENTED+DECRYPT_2+ENCRYPT_2)), #endif #if (PAD_LIST || CC_ECC_Decrypt) (COMMAND_ATTRIBUTES)(CC_ECC_Decrypt * // 0x019A (IS_IMPLEMENTED+DECRYPT_2+HANDLE_1_USER+ENCRYPT_2)), #endif #if (PAD_LIST || CC_Vendor_TCG_Test) (COMMAND_ATTRIBUTES)(CC_Vendor_TCG_Test * // 0x0000 (IS_IMPLEMENTED+DECRYPT_2+ENCRYPT_2)), #endif 0 }; #endif // _COMMAND_CODE_ATTRIBUTES_ libtpms-0.9.3/src/tpm2/CommandAttributes.h000066400000000000000000000113611421143571500204510ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Command Attributes */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CommandAttributes.h 1594 2020-03-26 22:15:48Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2020 */ /* */ /********************************************************************************/ #ifndef COMMANDATTRIBUTES_H #define COMMANDATTRIBUTES_H /* 5.7 CommandAttributes.h */ /* The attributes defined in this file are produced by the parser that creates the structure definitions from Part 3. The attributes are defined in that parser and should track the attributes being tested in CommandCodeAttributes.c. Generally, when an attribute is added to this list, new code will be needed in CommandCodeAttributes.c to test it. */ typedef UINT16 COMMAND_ATTRIBUTES; #define NOT_IMPLEMENTED (COMMAND_ATTRIBUTES)(0) #define ENCRYPT_2 ((COMMAND_ATTRIBUTES)1 << 0) #define ENCRYPT_4 ((COMMAND_ATTRIBUTES)1 << 1) #define DECRYPT_2 ((COMMAND_ATTRIBUTES)1 << 2) #define DECRYPT_4 ((COMMAND_ATTRIBUTES)1 << 3) #define HANDLE_1_USER ((COMMAND_ATTRIBUTES)1 << 4) #define HANDLE_1_ADMIN ((COMMAND_ATTRIBUTES)1 << 5) #define HANDLE_1_DUP ((COMMAND_ATTRIBUTES)1 << 6) #define HANDLE_2_USER ((COMMAND_ATTRIBUTES)1 << 7) #define PP_COMMAND ((COMMAND_ATTRIBUTES)1 << 8) #define IS_IMPLEMENTED ((COMMAND_ATTRIBUTES)1 << 9) #define NO_SESSIONS ((COMMAND_ATTRIBUTES)1 << 10) #define NV_COMMAND ((COMMAND_ATTRIBUTES)1 << 11) #define PP_REQUIRED ((COMMAND_ATTRIBUTES)1 << 12) #define R_HANDLE ((COMMAND_ATTRIBUTES)1 << 13) #define ALLOW_TRIAL ((COMMAND_ATTRIBUTES)1 << 14) #endif // COMMAND_ATTRIBUTES_H libtpms-0.9.3/src/tpm2/CommandAudit.c000066400000000000000000000244351421143571500173720ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Functions That Support Command Audit */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CommandAudit.c 1519 2019-11-15 20:43:51Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ /* 8.1 CommandAudit.c */ /* 8.1.1 Introduction */ /* This file contains the functions that support command audit. */ /* 8.1.2 Includes */ #include "Tpm.h" /* 8.1.3 Functions */ /* 8.1.3.1 CommandAuditPreInstall_Init() */ /* This function initializes the command audit list. This function simulates the behavior of manufacturing. A function is used instead of a structure definition because this is easier than figuring out the initialization value for a bit array. */ /* This function would not be implemented outside of a manufacturing or simulation environment. */ void CommandAuditPreInstall_Init( void ) { // Clear all the audit commands MemorySet(gp.auditCommands, 0x00, sizeof(gp.auditCommands)); // TPM_CC_SetCommandCodeAuditStatus always being audited CommandAuditSet(TPM_CC_SetCommandCodeAuditStatus); // Set initial command audit hash algorithm to be context integrity hash // algorithm gp.auditHashAlg = CONTEXT_INTEGRITY_HASH_ALG; // Set up audit counter to be 0 gp.auditCounter = 0; // Write command audit persistent data to NV NV_SYNC_PERSISTENT(auditCommands); NV_SYNC_PERSISTENT(auditHashAlg); NV_SYNC_PERSISTENT(auditCounter); return; } /* 8.1.3.2 CommandAuditStartup() */ /* This function clears the command audit digest on a TPM Reset. */ BOOL CommandAuditStartup( STARTUP_TYPE type // IN: start up type ) { if((type != SU_RESTART) && (type != SU_RESUME)) { // Reset the digest size to initialize the digest gr.commandAuditDigest.t.size = 0; } return TRUE; } /* 8.1.3.3 CommandAuditSet() */ /* This function will SET the audit flag for a command. This function will not SET the audit flag for a command that is not implemented. This ensures that the audit status is not SET when TPM2_GetCapability() is used to read the list of audited commands. */ /* This function is only used by TPM2_SetCommandCodeAuditStatus(). */ /* The actions in TPM2_SetCommandCodeAuditStatus() are expected to cause the changes to be saved to NV after it is setting and clearing bits. */ /* Return Values Meaning */ /* TRUE the command code audit status was changed */ /* FALSE the command code audit status was not changed */ BOOL CommandAuditSet( TPM_CC commandCode // IN: command code ) { COMMAND_INDEX commandIndex = CommandCodeToCommandIndex(commandCode); // Only SET a bit if the corresponding command is implemented if(commandIndex != UNIMPLEMENTED_COMMAND_INDEX) { // Can't audit shutdown if(commandCode != TPM_CC_Shutdown) { if(!TEST_BIT(commandIndex, gp.auditCommands)) { // Set bit SET_BIT(commandIndex, gp.auditCommands); return TRUE; } } } // No change return FALSE; } /* 8.1.3.4 CommandAuditClear() */ /* This function will CLEAR the audit flag for a command. It will not CLEAR the audit flag for TPM_CC_SetCommandCodeAuditStatus(). */ /* This function is only used by TPM2_SetCommandCodeAuditStatus(). */ /* The actions in TPM2_SetCommandCodeAuditStatus() are expected to cause the changes to be saved to NV after it is setting and clearing bits. */ /* Return Values Meaning */ /* TRUE the command code audit status was changed */ /* FALSE the command code audit status was not changed */ BOOL CommandAuditClear( TPM_CC commandCode // IN: command code ) { COMMAND_INDEX commandIndex = CommandCodeToCommandIndex(commandCode); // Do nothing if the command is not implemented if(commandIndex != UNIMPLEMENTED_COMMAND_INDEX) { // The bit associated with TPM_CC_SetCommandCodeAuditStatus() cannot be // cleared if(commandCode != TPM_CC_SetCommandCodeAuditStatus) { if(TEST_BIT(commandIndex, gp.auditCommands)) { // Clear bit CLEAR_BIT(commandIndex, gp.auditCommands); return TRUE; } } } // No change return FALSE; } /* 8.1.3.5 CommandAuditIsRequired() */ /* This function indicates if the audit flag is SET for a command. */ /* Return Values Meaning */ /* TRUE if command is audited */ /* FALSE if command is not audited */ BOOL CommandAuditIsRequired( COMMAND_INDEX commandIndex // IN: command index ) { // Check the bit map. If the bit is SET, command audit is required return(TEST_BIT(commandIndex, gp.auditCommands)); } /* 8.1.3.6 CommandAuditCapGetCCList() */ /* This function returns a list of commands that have their audit bit SET. */ /* The list starts at the input commandCode. */ /* Return Values Meaning */ /* YES if there are more command code available */ /* NO all the available command code has been returned */ TPMI_YES_NO CommandAuditCapGetCCList( TPM_CC commandCode, // IN: start command code UINT32 count, // IN: count of returned TPM_CC TPML_CC *commandList // OUT: list of TPM_CC ) { TPMI_YES_NO more = NO; COMMAND_INDEX commandIndex; // Initialize output handle list commandList->count = 0; // The maximum count of command we may return is MAX_CAP_CC if(count > MAX_CAP_CC) count = MAX_CAP_CC; // Find the implemented command that has a command code that is the same or // higher than the input // Collect audit commands for(commandIndex = GetClosestCommandIndex(commandCode); commandIndex != UNIMPLEMENTED_COMMAND_INDEX; commandIndex = GetNextCommandIndex(commandIndex)) { if(CommandAuditIsRequired(commandIndex)) { if(commandList->count < count) { // If we have not filled up the return list, add this command // code to its TPM_CC cc = GET_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, commandIndex); if(IS_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, V)) cc += (1 << 29); commandList->commandCodes[commandList->count] = cc; commandList->count++; } else { // If the return list is full but we still have command // available, report this and stop iterating more = YES; break; } } } return more; } /* 8.1.3.7 CommandAuditGetDigest */ /* This command is used to create a digest of the commands being audited. The commands are processed in ascending numeric order with a list of TPM_CC being added to a hash. This operates as if all the audited command codes were concatenated and then hashed. */ void CommandAuditGetDigest( TPM2B_DIGEST *digest // OUT: command digest ) { TPM_CC commandCode; COMMAND_INDEX commandIndex; HASH_STATE hashState; // Start hash digest->t.size = CryptHashStart(&hashState, gp.auditHashAlg); // Add command code for(commandIndex = 0; commandIndex < COMMAND_COUNT; commandIndex++) { if(CommandAuditIsRequired(commandIndex)) { commandCode = GetCommandCode(commandIndex); CryptDigestUpdateInt(&hashState, sizeof(commandCode), commandCode); } } // Complete hash CryptHashEnd2B(&hashState, &digest->b); return; } libtpms-0.9.3/src/tpm2/CommandAudit_fp.h000066400000000000000000000101601421143571500200520ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CommandAudit_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ #ifndef COMMANDAUDIT_FP_H #define COMMANDAUDIT_FP_H void CommandAuditPreInstall_Init( void ); BOOL CommandAuditStartup( STARTUP_TYPE type // IN: start up type ); BOOL CommandAuditSet( TPM_CC commandCode // IN: command code ); BOOL CommandAuditClear( TPM_CC commandCode // IN: command code ); BOOL CommandAuditIsRequired( COMMAND_INDEX commandIndex // IN: command index ); TPMI_YES_NO CommandAuditCapGetCCList( TPM_CC commandCode, // IN: start command code UINT32 count, // IN: count of returned TPM_CC TPML_CC *commandList // OUT: list of TPM_CC ); void CommandAuditGetDigest( TPM2B_DIGEST *digest // OUT: command digest ); #endif libtpms-0.9.3/src/tpm2/CommandCodeAttributes.c000066400000000000000000000511271421143571500212430ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Functions for testing various command properties */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CommandCodeAttributes.c 1594 2020-03-26 22:15:48Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2020 */ /* */ /********************************************************************************/ /* 9.3 CommandCodeAttributes.c */ /* 9.3.1 Introduction */ /* This file contains the functions for testing various command properties. */ /* 9.3.2 Includes and Defines */ #include "Tpm.h" #include "CommandCodeAttributes_fp.h" /* Set the default value for CC_VEND if not already set */ #ifndef CC_VEND #define CC_VEND (TPM_CC)(0x20000000) #endif typedef UINT16 ATTRIBUTE_TYPE; /* The following file is produced from the command tables in part 3 of the specification. It defines the attributes for each of the commands. */ /* NOTE: This file is currently produced by an automated process. Files produced from Part 2 or Part 3 tables through automated processes are not included in the specification so that there is no ambiguity about the table containing the information being the normative definition. */ #define _COMMAND_CODE_ATTRIBUTES_ #include "CommandAttributeData.h" /* 9.3.3 Command Attribute Functions */ /* 9.3.3.1 NextImplementedIndex() */ /* This function is used when the lists are not compressed. In a compressed list, only the implemented commands are present. So, a search might find a value but that value may not be implemented. This function checks to see if the input commandIndex points to an implemented command and, if not, it searches upwards until it finds one. When the list is compressed, this function gets defined as a no-op. */ /* Return Value Meaning */ /* UNIMPLEMENTED_COMMAND_INDEX command is not implemented */ /* other index of the command */ #if !COMPRESSED_LISTS static COMMAND_INDEX NextImplementedIndex( COMMAND_INDEX commandIndex ) { for(;commandIndex < COMMAND_COUNT; commandIndex++) { if(s_commandAttributes[commandIndex] & IS_IMPLEMENTED) return commandIndex; } return UNIMPLEMENTED_COMMAND_INDEX; } #else #define NextImplementedIndex(x) (x) #endif /* 9.3.3.2 GetClosestCommandIndex() */ /* This function returns the command index for the command with a value that is equal to or greater than the input value */ /* Return Value Meaning */ /* UNIMPLEMENTED_COMMAND_INDEX command is not implemented */ /* other index of the command */ COMMAND_INDEX GetClosestCommandIndex( TPM_CC commandCode // IN: the command code to start at ) { BOOL vendor = (commandCode & CC_VEND) != 0; COMMAND_INDEX searchIndex = (COMMAND_INDEX)commandCode; // The commandCode is a UINT32 and the search index is UINT16. We are going to // search for a match but need to make sure that the commandCode value is not // out of range. To do this, need to clear the vendor bit of the commandCode // (if set) and compare the result to the 16-bit searchIndex value. If it is // out of range, indicate that the command is not implemented if((commandCode & ~CC_VEND) != searchIndex) return UNIMPLEMENTED_COMMAND_INDEX; // if there is at least one vendor command, the last entry in the array will // have the v bit set. If the input commandCode is larger than the last // vendor-command, then it is out of range. if(vendor) { #if VENDOR_COMMAND_ARRAY_SIZE > 0 COMMAND_INDEX commandIndex; COMMAND_INDEX min; COMMAND_INDEX max; int diff; #if LIBRARY_COMMAND_ARRAY_SIZE == COMMAND_COUNT #error "Constants are not consistent." #endif // Check to see if the value is equal to or below the minimum // entry. // Note: Put this check first so that the typical case of only one vendor- // specific command doesn't waste any more time. if(GET_ATTRIBUTE(s_ccAttr[LIBRARY_COMMAND_ARRAY_SIZE], TPMA_CC, commandIndex) >= searchIndex) { // the vendor array is always assumed to be packed so there is // no need to check to see if the command is implemented return LIBRARY_COMMAND_ARRAY_SIZE; } // See if this is out of range on the top if(GET_ATTRIBUTE(s_ccAttr[COMMAND_COUNT - 1], TPMA_CC, commandIndex) < searchIndex) { return UNIMPLEMENTED_COMMAND_INDEX; } commandIndex = UNIMPLEMENTED_COMMAND_INDEX; // Needs initialization to keep // compiler happy min = LIBRARY_COMMAND_ARRAY_SIZE; // first vendor command max = COMMAND_COUNT - 1; // last vendor command diff = 1; // needs initialization to keep // compiler happy while(min <= max) { commandIndex = (min + max + 1) / 2; diff = GET_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, commandIndex) - searchIndex; if(diff == 0) return commandIndex; if(diff > 0) max = commandIndex - 1; else min = commandIndex + 1; } // didn't find and exact match. commandIndex will be pointing at the last // item tested. If 'diff' is positive, then the last item tested was // larger index of the command code so it is the smallest value // larger than the requested value. if(diff > 0) return commandIndex; // if 'diff' is negative, then the value tested was smaller than // the commandCode index and the next higher value is the correct one. // Note: this will necessarily be in range because of the earlier check // that the index was within range. return commandIndex + 1; #else // If there are no vendor commands so anything with the vendor bit set is out // of range return UNIMPLEMENTED_COMMAND_INDEX; #endif } // Get here if the V-Bit was not set in 'commandCode' if(GET_ATTRIBUTE(s_ccAttr[LIBRARY_COMMAND_ARRAY_SIZE - 1], TPMA_CC, commandIndex) < searchIndex) { // requested index is out of the range to the top #if VENDOR_COMMAND_ARRAY_SIZE > 0 // If there are vendor commands, then the first vendor command // is the next value greater than the commandCode. // NOTE: we got here if the starting index did not have the V bit but we // reached the end of the array of library commands (non-vendor). Since // there is at least one vendor command, and vendor commands are always // in a compressed list that starts after the library list, the next // index value contains a valid vendor command. return LIBRARY_COMMAND_ARRAY_SIZE; #else // if there are no vendor commands, then this is out of range return UNIMPLEMENTED_COMMAND_INDEX; #endif } // If the request is lower than any value in the array, then return // the lowest value (needs to be an index for an implemented command if(GET_ATTRIBUTE(s_ccAttr[0], TPMA_CC, commandIndex) >= searchIndex) { return NextImplementedIndex(0); } else { #if COMPRESSED_LISTS COMMAND_INDEX commandIndex = UNIMPLEMENTED_COMMAND_INDEX; COMMAND_INDEX min = 0; COMMAND_INDEX max = LIBRARY_COMMAND_ARRAY_SIZE - 1; int diff = 1; #if LIBRARY_COMMAND_ARRAY_SIZE == 0 #error "Something is terribly wrong" #endif // The s_ccAttr array contains an extra entry at the end (a zero value). // Don't count this as an array entry. This means that max should start // out pointing to the last valid entry in the array which is - 2 pAssert(max == (sizeof(s_ccAttr) / sizeof(TPMA_CC) - VENDOR_COMMAND_ARRAY_SIZE - 2)); while(min <= max) { commandIndex = (min + max + 1) / 2; diff = GET_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, commandIndex) - searchIndex; if(diff == 0) return commandIndex; if(diff > 0) max = commandIndex - 1; else min = commandIndex + 1; } // didn't find and exact match. commandIndex will be pointing at the // last item tested. If diff is positive, then the last item tested was // larger index of the command code so it is the smallest value // larger than the requested value. if(diff > 0) return commandIndex; // if diff is negative, then the value tested was smaller than // the commandCode index and the next higher value is the correct one. // Note: this will necessarily be in range because of the earlier check // that the index was within range. return commandIndex + 1; #else // The list is not compressed so offset into the array by the command // code value of the first entry in the list. Then go find the first // implemented command. return NextImplementedIndex(searchIndex - (COMMAND_INDEX)s_ccAttr[0].commandIndex); #endif } } /* 9.3.3.3 CommandCodeToComandIndex() */ /* This function returns the index in the various attributes arrays of the command. */ /* Return Values Meaning */ /* UNIMPLEMENTED_COMMAND_INDEX command is not implemented */ /* other index of the command */ COMMAND_INDEX CommandCodeToCommandIndex( TPM_CC commandCode // IN: the command code to look up ) { // Extract the low 16-bits of the command code to get the starting search index COMMAND_INDEX searchIndex = (COMMAND_INDEX)commandCode; BOOL vendor = (commandCode & CC_VEND) != 0; COMMAND_INDEX commandIndex; #if !COMPRESSED_LISTS if(!vendor) { commandIndex = searchIndex - (COMMAND_INDEX)s_ccAttr[0].commandIndex; // Check for out of range or unimplemented. // Note, since a COMMAND_INDEX is unsigned, if searchIndex is smaller than // the lowest value of command, it will become a 'negative' number making // it look like a large unsigned number, this will cause it to fail // the unsigned check below. if(commandIndex >= LIBRARY_COMMAND_ARRAY_SIZE || (s_commandAttributes[commandIndex] & IS_IMPLEMENTED) == 0) return UNIMPLEMENTED_COMMAND_INDEX; return commandIndex; } #endif // Need this code for any vendor code lookup or for compressed lists commandIndex = GetClosestCommandIndex(commandCode); // Look at the returned value from get closest. If it isn't the one that was // requested, then the command is not implemented. if(commandIndex != UNIMPLEMENTED_COMMAND_INDEX) { if((GET_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, commandIndex) != searchIndex) || (IS_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, V)) != vendor) commandIndex = UNIMPLEMENTED_COMMAND_INDEX; } return commandIndex; } /* 9.3.3.4 GetNextCommandIndex() */ /* This function returns the index of the next implemented command. */ /* Return Values Meaning */ /* UNIMPLEMENTED_COMMAND_INDEX no more implemented commands */ /* other the index of the next implemented command */ COMMAND_INDEX GetNextCommandIndex( COMMAND_INDEX commandIndex // IN: the starting index ) { while(++commandIndex < COMMAND_COUNT) { #if !COMPRESSED_LISTS if(s_commandAttributes[commandIndex] & IS_IMPLEMENTED) #endif return commandIndex; } return UNIMPLEMENTED_COMMAND_INDEX; } /* 9.3.3.5 GetCommandCode() */ /* This function returns the commandCode associated with the command index */ TPM_CC GetCommandCode( COMMAND_INDEX commandIndex // IN: the command index ) { TPM_CC commandCode = GET_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, commandIndex); if(IS_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, V)) commandCode += CC_VEND; return commandCode; } /* 9.3.3.6 CommandAuthRole() */ /* This function returns the authorization role required of a handle. */ /* Return Values Meaning */ /* AUTH_NONE no authorization is required */ /* AUTH_USER user role authorization is required */ /* AUTH_ADMIN admin role authorization is required */ /* AUTH_DUP duplication role authorization is required */ AUTH_ROLE CommandAuthRole( COMMAND_INDEX commandIndex, // IN: command index UINT32 handleIndex // IN: handle index (zero based) ) { if(0 == handleIndex) { // Any authorization role set? COMMAND_ATTRIBUTES properties = s_commandAttributes[commandIndex]; if(properties & HANDLE_1_USER) return AUTH_USER; if(properties & HANDLE_1_ADMIN) return AUTH_ADMIN; if(properties & HANDLE_1_DUP) return AUTH_DUP; } else if(1 == handleIndex) { if(s_commandAttributes[commandIndex] & HANDLE_2_USER) return AUTH_USER; } return AUTH_NONE; } /* 9.3.3.7 EncryptSize() */ /* This function returns the size of the decrypt size field. This function returns 0 if encryption is not allowed */ /* Return Values Meaning */ /* 0 encryption not allowed */ /* 2 size field is two bytes */ /* 4 size field is four bytes */ int EncryptSize( COMMAND_INDEX commandIndex // IN: command index ) { return ((s_commandAttributes[commandIndex] & ENCRYPT_2) ? 2 : (s_commandAttributes[commandIndex] & ENCRYPT_4) ? 4 : 0); } /* 9.3.3.8 DecryptSize() */ /* This function returns the size of the decrypt size field. This function returns 0 if decryption is not allowed */ /* Return Values Meaning */ /* 0 encryption not allowed */ /* 2 size field is two bytes */ /* 4 size field is four bytes */ int DecryptSize( COMMAND_INDEX commandIndex // IN: command index ) { return ((s_commandAttributes[commandIndex] & DECRYPT_2) ? 2 : (s_commandAttributes[commandIndex] & DECRYPT_4) ? 4 : 0); } /* 9.3.3.9 IsSessionAllowed() */ /* This function indicates if the command is allowed to have sessions. */ /* This function must not be called if the command is not known to be implemented. */ /* Return Values Meaning */ /* TRUE session is allowed with this command */ /* FALSE session is not allowed with this command */ BOOL IsSessionAllowed( COMMAND_INDEX commandIndex // IN: the command to be checked ) { return ((s_commandAttributes[commandIndex] & NO_SESSIONS) == 0); } /* 9.3.3.10 IsHandleInResponse() */ /* This function determines if a command has a handle in the response */ BOOL IsHandleInResponse( COMMAND_INDEX commandIndex ) { return ((s_commandAttributes[commandIndex] & R_HANDLE) != 0); } /* 9.3.3.11 IsWriteOperation() */ /* Checks to see if an operation will write to an NV Index and is subject to being blocked by read-lock */ BOOL IsWriteOperation( COMMAND_INDEX commandIndex // IN: Command to check ) { #ifdef WRITE_LOCK return ((s_commandAttributes[commandIndex] & WRITE_LOCK) != 0); #else if(!IS_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, V)) { switch(GET_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, commandIndex)) { case TPM_CC_NV_Write: #if CC_NV_Increment case TPM_CC_NV_Increment: #endif #if CC_NV_SetBits case TPM_CC_NV_SetBits: #endif #if CC_NV_Extend case TPM_CC_NV_Extend: #endif #if CC_AC_Send case TPM_CC_AC_Send: #endif // NV write lock counts as a write operation for authorization purposes. // We check to see if the NV is write locked before we do the // authorization. If it is locked, we fail the command early. case TPM_CC_NV_WriteLock: return TRUE; default: break; } } return FALSE; #endif } /* 9.3.3.12 IsReadOperation() */ /* Checks to see if an operation will write to an NV Index and is subject to being blocked by write-lock. */ BOOL IsReadOperation( COMMAND_INDEX commandIndex // IN: Command to check ) { #ifdef READ_LOCK return ((s_commandAttributes[commandIndex] & READ_LOCK) != 0); #else if(!IS_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, V)) { switch(GET_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, commandIndex)) { case TPM_CC_NV_Read: case TPM_CC_PolicyNV: case TPM_CC_NV_Certify: // NV read lock counts as a read operation for authorization purposes. // We check to see if the NV is read locked before we do the // authorization. If it is locked, we fail the command early. case TPM_CC_NV_ReadLock: return TRUE; default: break; } } return FALSE; #endif } /* 9.3.3.13 CommandCapGetCCList() */ /* This function returns a list of implemented commands and command attributes starting from the command in commandCode. */ /* Return Values Meaning */ /* YES more command attributes are available */ /* NO no more command attributes are available */ TPMI_YES_NO CommandCapGetCCList( TPM_CC commandCode, // IN: start command code UINT32 count, // IN: maximum count for number of entries in // 'commandList' TPML_CCA *commandList // OUT: list of TPMA_CC ) { TPMI_YES_NO more = NO; COMMAND_INDEX commandIndex; // initialize output handle list count commandList->count = 0; for(commandIndex = GetClosestCommandIndex(commandCode); commandIndex != UNIMPLEMENTED_COMMAND_INDEX; commandIndex = GetNextCommandIndex(commandIndex)) { #if !COMPRESSED_LISTS // this check isn't needed for compressed lists. if(!(s_commandAttributes[commandIndex] & IS_IMPLEMENTED)) continue; #endif if(commandList->count < count) { // If the list is not full, add the attributes for this command. commandList->commandAttributes[commandList->count] = s_ccAttr[commandIndex]; commandList->count++; } else { // If the list is full but there are more commands to report, // indicate this and return. more = YES; break; } } return more; } #if 0 /* libtpms added */ /* 9.3.3.14 IsVendorCommand() */ /* Function indicates if a command index references a vendor command. */ /* Return Values Meaning */ /* TRUE command is a vendor command */ /* FALSE command is not a vendor command */ BOOL IsVendorCommand( COMMAND_INDEX commandIndex // IN: command index to check ) { return (IS_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, V)); } #endif /* libtpms added */ libtpms-0.9.3/src/tpm2/CommandCodeAttributes_fp.h000066400000000000000000000116231421143571500217320ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CommandCodeAttributes_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 */ /* */ /********************************************************************************/ #ifndef COMMANDCODEATTRIBUTES_FP_H #define COMMANDCODEATTRIBUTES_FP_H COMMAND_INDEX GetClosestCommandIndex( TPM_CC commandCode // IN: the command code to start at ); COMMAND_INDEX CommandCodeToCommandIndex( TPM_CC commandCode // IN: the command code to look up ); COMMAND_INDEX GetNextCommandIndex( COMMAND_INDEX commandIndex // IN: the starting index ); TPM_CC GetCommandCode( COMMAND_INDEX commandIndex // IN: the command index ); AUTH_ROLE CommandAuthRole( COMMAND_INDEX commandIndex, // IN: command index UINT32 handleIndex // IN: handle index (zero based) ); int EncryptSize( COMMAND_INDEX commandIndex // IN: command index ); int DecryptSize( COMMAND_INDEX commandIndex // IN: command index ); BOOL IsSessionAllowed( COMMAND_INDEX commandIndex // IN: the command to be checked ); BOOL IsHandleInResponse( COMMAND_INDEX commandIndex ); BOOL IsWriteOperation( COMMAND_INDEX commandIndex // IN: Command to check ); BOOL IsReadOperation( COMMAND_INDEX commandIndex // IN: Command to check ); TPMI_YES_NO CommandCapGetCCList( TPM_CC commandCode, // IN: start command code UINT32 count, // IN: maximum count for number of entries in // 'commandList' TPML_CCA *commandList // OUT: list of TPMA_CC ); #if 0 /* libtpms added */ BOOL IsVendorCommand( COMMAND_INDEX commandIndex // IN: command index to check ); #endif /* libtpms added */ #endif libtpms-0.9.3/src/tpm2/CommandDispatchData.h000066400000000000000000005221241421143571500206600ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Command DIspatch Data */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CommandDispatchData.h 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2021 */ /* */ /********************************************************************************/ /* This file should only be included by CommandCodeAttibutes.c */ #ifdef _COMMAND_TABLE_DISPATCH_ #define END_OF_LIST 0xff #define ADD_FLAG 0x80 /* These macros provide some variability in how the data is encoded. They also make the lines a little shorter. ;-) */ #if TABLE_DRIVEN_MARSHAL # define UNMARSHAL_DISPATCH(name) (marshalIndex_t)name##_MARSHAL_REF # define MARSHAL_DISPATCH(name) (marshalIndex_t)name##_MARSHAL_REF # define _UNMARSHAL_T_ marshalIndex_t # define _MARSHAL_T_ marshalIndex_t # #else # define UNMARSHAL_DISPATCH(name) (UNMARSHAL_t)name##_Unmarshal # define MARSHAL_DISPATCH(name) (MARSHAL_t)name##_Marshal # define _UNMARSHAL_T_ UNMARSHAL_t # define _MARSHAL_T_ MARSHAL_t #endif const _UNMARSHAL_T_ unmarshalArray[] = { #define TPMI_DH_CONTEXT_H_UNMARSHAL 0 UNMARSHAL_DISPATCH(TPMI_DH_CONTEXT), #define TPMI_RH_AC_H_UNMARSHAL (TPMI_DH_CONTEXT_H_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPMI_RH_AC), #define TPMI_RH_ACT_H_UNMARSHAL (TPMI_RH_AC_H_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPMI_RH_ACT), #define TPMI_RH_CLEAR_H_UNMARSHAL (TPMI_RH_ACT_H_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPMI_RH_CLEAR), #define TPMI_RH_HIERARCHY_AUTH_H_UNMARSHAL (TPMI_RH_CLEAR_H_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPMI_RH_HIERARCHY_AUTH), #define TPMI_RH_HIERARCHY_POLICY_H_UNMARSHAL \ (TPMI_RH_HIERARCHY_AUTH_H_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPMI_RH_HIERARCHY_POLICY), #define TPMI_RH_LOCKOUT_H_UNMARSHAL \ (TPMI_RH_HIERARCHY_POLICY_H_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPMI_RH_LOCKOUT), #define TPMI_RH_NV_AUTH_H_UNMARSHAL (TPMI_RH_LOCKOUT_H_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPMI_RH_NV_AUTH), #define TPMI_RH_NV_INDEX_H_UNMARSHAL (TPMI_RH_NV_AUTH_H_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPMI_RH_NV_INDEX), #define TPMI_RH_PLATFORM_H_UNMARSHAL (TPMI_RH_NV_INDEX_H_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPMI_RH_PLATFORM), #define TPMI_RH_PROVISION_H_UNMARSHAL (TPMI_RH_PLATFORM_H_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPMI_RH_PROVISION), #define TPMI_SH_HMAC_H_UNMARSHAL (TPMI_RH_PROVISION_H_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPMI_SH_HMAC), #define TPMI_SH_POLICY_H_UNMARSHAL (TPMI_SH_HMAC_H_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPMI_SH_POLICY), // HANDLE_FIRST_FLAG_TYPE is the first handle that needs a flag when called. #define HANDLE_FIRST_FLAG_TYPE (TPMI_SH_POLICY_H_UNMARSHAL + 1) #define TPMI_DH_ENTITY_H_UNMARSHAL (TPMI_SH_POLICY_H_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPMI_DH_ENTITY), #define TPMI_DH_OBJECT_H_UNMARSHAL (TPMI_DH_ENTITY_H_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPMI_DH_OBJECT), #define TPMI_DH_PARENT_H_UNMARSHAL (TPMI_DH_OBJECT_H_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPMI_DH_PARENT), #define TPMI_DH_PCR_H_UNMARSHAL (TPMI_DH_PARENT_H_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPMI_DH_PCR), #define TPMI_RH_ENDORSEMENT_H_UNMARSHAL (TPMI_DH_PCR_H_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPMI_RH_ENDORSEMENT), #define TPMI_RH_HIERARCHY_H_UNMARSHAL \ (TPMI_RH_ENDORSEMENT_H_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPMI_RH_HIERARCHY), // PARAMETER_FIRST_TYPE marks the end of the handle list. #define PARAMETER_FIRST_TYPE (TPMI_RH_HIERARCHY_H_UNMARSHAL + 1) #define TPM2B_DATA_P_UNMARSHAL (TPMI_RH_HIERARCHY_H_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPM2B_DATA), #define TPM2B_DIGEST_P_UNMARSHAL (TPM2B_DATA_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPM2B_DIGEST), #define TPM2B_ECC_PARAMETER_P_UNMARSHAL (TPM2B_DIGEST_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPM2B_ECC_PARAMETER), #define TPM2B_ECC_POINT_P_UNMARSHAL \ (TPM2B_ECC_PARAMETER_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPM2B_ECC_POINT), #define TPM2B_ENCRYPTED_SECRET_P_UNMARSHAL (TPM2B_ECC_POINT_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPM2B_ENCRYPTED_SECRET), #define TPM2B_EVENT_P_UNMARSHAL \ (TPM2B_ENCRYPTED_SECRET_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPM2B_EVENT), #define TPM2B_ID_OBJECT_P_UNMARSHAL (TPM2B_EVENT_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPM2B_ID_OBJECT), #define TPM2B_IV_P_UNMARSHAL (TPM2B_ID_OBJECT_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPM2B_IV), #define TPM2B_MAX_BUFFER_P_UNMARSHAL (TPM2B_IV_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPM2B_MAX_BUFFER), #define TPM2B_MAX_NV_BUFFER_P_UNMARSHAL (TPM2B_MAX_BUFFER_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPM2B_MAX_NV_BUFFER), #define TPM2B_NAME_P_UNMARSHAL \ (TPM2B_MAX_NV_BUFFER_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPM2B_NAME), #define TPM2B_NV_PUBLIC_P_UNMARSHAL (TPM2B_NAME_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPM2B_NV_PUBLIC), #define TPM2B_PRIVATE_P_UNMARSHAL (TPM2B_NV_PUBLIC_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPM2B_PRIVATE), #define TPM2B_PUBLIC_KEY_RSA_P_UNMARSHAL (TPM2B_PRIVATE_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPM2B_PUBLIC_KEY_RSA), #define TPM2B_SENSITIVE_P_UNMARSHAL \ (TPM2B_PUBLIC_KEY_RSA_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPM2B_SENSITIVE), #define TPM2B_SENSITIVE_CREATE_P_UNMARSHAL (TPM2B_SENSITIVE_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPM2B_SENSITIVE_CREATE), #define TPM2B_SENSITIVE_DATA_P_UNMARSHAL \ (TPM2B_SENSITIVE_CREATE_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPM2B_SENSITIVE_DATA), #define TPM2B_TEMPLATE_P_UNMARSHAL \ (TPM2B_SENSITIVE_DATA_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPM2B_TEMPLATE), #define TPM2B_TIMEOUT_P_UNMARSHAL (TPM2B_TEMPLATE_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPM2B_TIMEOUT), #define TPMI_DH_CONTEXT_P_UNMARSHAL (TPM2B_TIMEOUT_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPMI_DH_CONTEXT), #define TPMI_DH_PERSISTENT_P_UNMARSHAL (TPMI_DH_CONTEXT_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPMI_DH_PERSISTENT), #define TPMI_ECC_CURVE_P_UNMARSHAL (TPMI_DH_PERSISTENT_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPMI_ECC_CURVE), #define TPMI_YES_NO_P_UNMARSHAL (TPMI_ECC_CURVE_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPMI_YES_NO), #define TPML_ALG_P_UNMARSHAL (TPMI_YES_NO_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPML_ALG), #define TPML_CC_P_UNMARSHAL (TPML_ALG_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPML_CC), #define TPML_DIGEST_P_UNMARSHAL (TPML_CC_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPML_DIGEST), #define TPML_DIGEST_VALUES_P_UNMARSHAL (TPML_DIGEST_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPML_DIGEST_VALUES), #define TPML_PCR_SELECTION_P_UNMARSHAL (TPML_DIGEST_VALUES_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPML_PCR_SELECTION), #define TPMS_CONTEXT_P_UNMARSHAL (TPML_PCR_SELECTION_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPMS_CONTEXT), #define TPMT_PUBLIC_PARMS_P_UNMARSHAL (TPMS_CONTEXT_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPMT_PUBLIC_PARMS), #define TPMT_TK_AUTH_P_UNMARSHAL (TPMT_PUBLIC_PARMS_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPMT_TK_AUTH), #define TPMT_TK_CREATION_P_UNMARSHAL (TPMT_TK_AUTH_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPMT_TK_CREATION), #define TPMT_TK_HASHCHECK_P_UNMARSHAL (TPMT_TK_CREATION_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPMT_TK_HASHCHECK), #define TPMT_TK_VERIFIED_P_UNMARSHAL (TPMT_TK_HASHCHECK_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPMT_TK_VERIFIED), #define TPM_AT_P_UNMARSHAL (TPMT_TK_VERIFIED_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPM_AT), #define TPM_CAP_P_UNMARSHAL (TPM_AT_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPM_CAP), #define TPM_CLOCK_ADJUST_P_UNMARSHAL (TPM_CAP_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPM_CLOCK_ADJUST), #define TPM_EO_P_UNMARSHAL (TPM_CLOCK_ADJUST_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPM_EO), #define TPM_SE_P_UNMARSHAL (TPM_EO_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPM_SE), #define TPM_SU_P_UNMARSHAL (TPM_SE_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPM_SU), #define UINT16_P_UNMARSHAL (TPM_SU_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(UINT16), #define UINT32_P_UNMARSHAL (UINT16_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(UINT32), #define UINT64_P_UNMARSHAL (UINT32_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(UINT64), #define UINT8_P_UNMARSHAL (UINT64_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(UINT8), // PARAMETER_FIRST_FLAG_TYPE is the first parameter to need a flag. #define PARAMETER_FIRST_FLAG_TYPE (UINT8_P_UNMARSHAL + 1) #define TPM2B_PUBLIC_P_UNMARSHAL (UINT8_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPM2B_PUBLIC), #define TPMI_ALG_CIPHER_MODE_P_UNMARSHAL (TPM2B_PUBLIC_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPMI_ALG_CIPHER_MODE), #define TPMI_ALG_HASH_P_UNMARSHAL \ (TPMI_ALG_CIPHER_MODE_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPMI_ALG_HASH), #define TPMI_ALG_MAC_SCHEME_P_UNMARSHAL (TPMI_ALG_HASH_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPMI_ALG_MAC_SCHEME), #define TPMI_DH_PCR_P_UNMARSHAL \ (TPMI_ALG_MAC_SCHEME_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPMI_DH_PCR), #define TPMI_ECC_KEY_EXCHANGE_P_UNMARSHAL (TPMI_DH_PCR_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPMI_ECC_KEY_EXCHANGE), #define TPMI_RH_ENABLES_P_UNMARSHAL \ (TPMI_ECC_KEY_EXCHANGE_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPMI_RH_ENABLES), #define TPMI_RH_HIERARCHY_P_UNMARSHAL (TPMI_RH_ENABLES_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPMI_RH_HIERARCHY), #define TPMT_KDF_SCHEME_P_UNMARSHAL (TPMI_RH_HIERARCHY_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPMT_KDF_SCHEME), #define TPMT_RSA_DECRYPT_P_UNMARSHAL (TPMT_KDF_SCHEME_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPMT_RSA_DECRYPT), #define TPMT_SIGNATURE_P_UNMARSHAL (TPMT_RSA_DECRYPT_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPMT_SIGNATURE), #define TPMT_SIG_SCHEME_P_UNMARSHAL (TPMT_SIGNATURE_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPMT_SIG_SCHEME), #define TPMT_SYM_DEF_P_UNMARSHAL (TPMT_SIG_SCHEME_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPMT_SYM_DEF), #define TPMT_SYM_DEF_OBJECT_P_UNMARSHAL (TPMT_SYM_DEF_P_UNMARSHAL + 1) UNMARSHAL_DISPATCH(TPMT_SYM_DEF_OBJECT) // PARAMETER_LAST_TYPE is the end of the command parameter list. // PARAMETER_LAST_TYPE is the end of the command parameter list. #define PARAMETER_LAST_TYPE (TPMT_SYM_DEF_OBJECT_P_UNMARSHAL) }; const _MARSHAL_T_ marshalArray[] = { #define UINT32_H_MARSHAL 0 MARSHAL_DISPATCH(UINT32), // RESPONSE_PARAMETER_FIRST_TYPE marks the end of the response handles. #define RESPONSE_PARAMETER_FIRST_TYPE (UINT32_H_MARSHAL + 1) #define TPM2B_ATTEST_P_MARSHAL (UINT32_H_MARSHAL + 1) MARSHAL_DISPATCH(TPM2B_ATTEST), #define TPM2B_CREATION_DATA_P_MARSHAL (TPM2B_ATTEST_P_MARSHAL + 1) MARSHAL_DISPATCH(TPM2B_CREATION_DATA), #define TPM2B_DATA_P_MARSHAL (TPM2B_CREATION_DATA_P_MARSHAL + 1) MARSHAL_DISPATCH(TPM2B_DATA), #define TPM2B_DIGEST_P_MARSHAL (TPM2B_DATA_P_MARSHAL + 1) MARSHAL_DISPATCH(TPM2B_DIGEST), #define TPM2B_ECC_POINT_P_MARSHAL (TPM2B_DIGEST_P_MARSHAL + 1) MARSHAL_DISPATCH(TPM2B_ECC_POINT), #define TPM2B_ENCRYPTED_SECRET_P_MARSHAL (TPM2B_ECC_POINT_P_MARSHAL + 1) MARSHAL_DISPATCH(TPM2B_ENCRYPTED_SECRET), #define TPM2B_ID_OBJECT_P_MARSHAL \ (TPM2B_ENCRYPTED_SECRET_P_MARSHAL + 1) MARSHAL_DISPATCH(TPM2B_ID_OBJECT), #define TPM2B_IV_P_MARSHAL (TPM2B_ID_OBJECT_P_MARSHAL + 1) MARSHAL_DISPATCH(TPM2B_IV), #define TPM2B_MAX_BUFFER_P_MARSHAL (TPM2B_IV_P_MARSHAL + 1) MARSHAL_DISPATCH(TPM2B_MAX_BUFFER), #define TPM2B_MAX_NV_BUFFER_P_MARSHAL (TPM2B_MAX_BUFFER_P_MARSHAL + 1) MARSHAL_DISPATCH(TPM2B_MAX_NV_BUFFER), #define TPM2B_NAME_P_MARSHAL (TPM2B_MAX_NV_BUFFER_P_MARSHAL + 1) MARSHAL_DISPATCH(TPM2B_NAME), #define TPM2B_NV_PUBLIC_P_MARSHAL (TPM2B_NAME_P_MARSHAL + 1) MARSHAL_DISPATCH(TPM2B_NV_PUBLIC), #define TPM2B_PRIVATE_P_MARSHAL (TPM2B_NV_PUBLIC_P_MARSHAL + 1) MARSHAL_DISPATCH(TPM2B_PRIVATE), #define TPM2B_PUBLIC_P_MARSHAL (TPM2B_PRIVATE_P_MARSHAL + 1) MARSHAL_DISPATCH(TPM2B_PUBLIC), #define TPM2B_PUBLIC_KEY_RSA_P_MARSHAL (TPM2B_PUBLIC_P_MARSHAL + 1) MARSHAL_DISPATCH(TPM2B_PUBLIC_KEY_RSA), #define TPM2B_SENSITIVE_DATA_P_MARSHAL (TPM2B_PUBLIC_KEY_RSA_P_MARSHAL + 1) MARSHAL_DISPATCH(TPM2B_SENSITIVE_DATA), #define TPM2B_TIMEOUT_P_MARSHAL (TPM2B_SENSITIVE_DATA_P_MARSHAL + 1) MARSHAL_DISPATCH(TPM2B_TIMEOUT), #define UINT8_P_MARSHAL (TPM2B_TIMEOUT_P_MARSHAL + 1) MARSHAL_DISPATCH(UINT8), #define TPML_AC_CAPABILITIES_P_MARSHAL (UINT8_P_MARSHAL + 1) MARSHAL_DISPATCH(TPML_AC_CAPABILITIES), #define TPML_ALG_P_MARSHAL (TPML_AC_CAPABILITIES_P_MARSHAL + 1) MARSHAL_DISPATCH(TPML_ALG), #define TPML_DIGEST_P_MARSHAL (TPML_ALG_P_MARSHAL + 1) MARSHAL_DISPATCH(TPML_DIGEST), #define TPML_DIGEST_VALUES_P_MARSHAL (TPML_DIGEST_P_MARSHAL + 1) MARSHAL_DISPATCH(TPML_DIGEST_VALUES), #define TPML_PCR_SELECTION_P_MARSHAL (TPML_DIGEST_VALUES_P_MARSHAL + 1) MARSHAL_DISPATCH(TPML_PCR_SELECTION), #define TPMS_AC_OUTPUT_P_MARSHAL (TPML_PCR_SELECTION_P_MARSHAL + 1) MARSHAL_DISPATCH(TPMS_AC_OUTPUT), #define TPMS_ALGORITHM_DETAIL_ECC_P_MARSHAL (TPMS_AC_OUTPUT_P_MARSHAL + 1) MARSHAL_DISPATCH(TPMS_ALGORITHM_DETAIL_ECC), #define TPMS_CAPABILITY_DATA_P_MARSHAL \ (TPMS_ALGORITHM_DETAIL_ECC_P_MARSHAL + 1) MARSHAL_DISPATCH(TPMS_CAPABILITY_DATA), #define TPMS_CONTEXT_P_MARSHAL (TPMS_CAPABILITY_DATA_P_MARSHAL + 1) MARSHAL_DISPATCH(TPMS_CONTEXT), #define TPMS_TIME_INFO_P_MARSHAL (TPMS_CONTEXT_P_MARSHAL + 1) MARSHAL_DISPATCH(TPMS_TIME_INFO), #define TPMT_HA_P_MARSHAL (TPMS_TIME_INFO_P_MARSHAL + 1) MARSHAL_DISPATCH(TPMT_HA), #define TPMT_SIGNATURE_P_MARSHAL (TPMT_HA_P_MARSHAL + 1) MARSHAL_DISPATCH(TPMT_SIGNATURE), #define TPMT_TK_AUTH_P_MARSHAL (TPMT_SIGNATURE_P_MARSHAL + 1) MARSHAL_DISPATCH(TPMT_TK_AUTH), #define TPMT_TK_CREATION_P_MARSHAL (TPMT_TK_AUTH_P_MARSHAL + 1) MARSHAL_DISPATCH(TPMT_TK_CREATION), #define TPMT_TK_HASHCHECK_P_MARSHAL (TPMT_TK_CREATION_P_MARSHAL + 1) MARSHAL_DISPATCH(TPMT_TK_HASHCHECK), #define TPMT_TK_VERIFIED_P_MARSHAL (TPMT_TK_HASHCHECK_P_MARSHAL + 1) MARSHAL_DISPATCH(TPMT_TK_VERIFIED), #define UINT32_P_MARSHAL (TPMT_TK_VERIFIED_P_MARSHAL + 1) MARSHAL_DISPATCH(UINT32), #define UINT16_P_MARSHAL (UINT32_P_MARSHAL + 1) MARSHAL_DISPATCH(UINT16) #define RESPONSE_PARAMETER_LAST_TYPE (UINT16_P_MARSHAL) }; /* This list of aliases allows the types in the _COMMAND_DESCRIPTOR_T to match the types in the command/response templates of part 3. */ #define INT32_P_UNMARSHAL UINT32_P_UNMARSHAL #define TPM2B_AUTH_P_UNMARSHAL TPM2B_DIGEST_P_UNMARSHAL #define TPM2B_NONCE_P_UNMARSHAL TPM2B_DIGEST_P_UNMARSHAL #define TPM2B_OPERAND_P_UNMARSHAL TPM2B_DIGEST_P_UNMARSHAL #define TPMA_LOCALITY_P_UNMARSHAL UINT8_P_UNMARSHAL #define TPM_CC_P_UNMARSHAL UINT32_P_UNMARSHAL #define TPMI_DH_CONTEXT_H_MARSHAL UINT32_H_MARSHAL #define TPMI_DH_OBJECT_H_MARSHAL UINT32_H_MARSHAL #define TPMI_SH_AUTH_SESSION_H_MARSHAL UINT32_H_MARSHAL #define TPM_HANDLE_H_MARSHAL UINT32_H_MARSHAL #define TPM2B_NONCE_P_MARSHAL TPM2B_DIGEST_P_MARSHAL #define TPMI_YES_NO_P_MARSHAL UINT8_P_MARSHAL #define TPM_RC_P_MARSHAL UINT32_P_MARSHAL #if CC_Startup #include "Startup_fp.h" typedef TPM_RC (Startup_Entry)( Startup_In *in ); typedef const struct { Startup_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; BYTE types[3]; } Startup_COMMAND_DESCRIPTOR_t; Startup_COMMAND_DESCRIPTOR_t _StartupData = { /* entry */ &TPM2_Startup, /* inSize */ (UINT16)(sizeof(Startup_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(Startup_COMMAND_DESCRIPTOR_t, types), /* offsets */ // No parameter offsets /* types */ {TPM_SU_P_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _StartupDataAddress (&_StartupData) #else #define _StartupDataAddress 0 #endif #if CC_Shutdown #include "Shutdown_fp.h" typedef TPM_RC (Shutdown_Entry)( Shutdown_In *in ); typedef const struct { Shutdown_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; BYTE types[3]; } Shutdown_COMMAND_DESCRIPTOR_t; Shutdown_COMMAND_DESCRIPTOR_t _ShutdownData = { /* entry */ &TPM2_Shutdown, /* inSize */ (UINT16)(sizeof(Shutdown_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(Shutdown_COMMAND_DESCRIPTOR_t, types), /* offsets */ // No parameter offsets /* types */ {TPM_SU_P_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _ShutdownDataAddress (&_ShutdownData) #else #define _ShutdownDataAddress 0 #endif #if CC_SelfTest #include "SelfTest_fp.h" typedef TPM_RC (SelfTest_Entry)( SelfTest_In *in ); typedef const struct { SelfTest_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; BYTE types[3]; } SelfTest_COMMAND_DESCRIPTOR_t; SelfTest_COMMAND_DESCRIPTOR_t _SelfTestData = { /* entry */ &TPM2_SelfTest, /* inSize */ (UINT16)(sizeof(SelfTest_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(SelfTest_COMMAND_DESCRIPTOR_t, types), /* offsets */ // No parameter offsets /* types */ {TPMI_YES_NO_P_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _SelfTestDataAddress (&_SelfTestData) #else #define _SelfTestDataAddress 0 #endif #if CC_IncrementalSelfTest #include "IncrementalSelfTest_fp.h" typedef TPM_RC (IncrementalSelfTest_Entry)( IncrementalSelfTest_In *in, IncrementalSelfTest_Out *out ); typedef const struct { IncrementalSelfTest_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; BYTE types[4]; } IncrementalSelfTest_COMMAND_DESCRIPTOR_t; IncrementalSelfTest_COMMAND_DESCRIPTOR_t _IncrementalSelfTestData = { /* entry */ &TPM2_IncrementalSelfTest, /* inSize */ (UINT16)(sizeof(IncrementalSelfTest_In)), /* outSize */ (UINT16)(sizeof(IncrementalSelfTest_Out)), /* offsetOfTypes */ offsetof(IncrementalSelfTest_COMMAND_DESCRIPTOR_t, types), /* offsets */ // No parameter offsets /* types */ {TPML_ALG_P_UNMARSHAL, END_OF_LIST, TPML_ALG_P_MARSHAL, END_OF_LIST} }; #define _IncrementalSelfTestDataAddress (&_IncrementalSelfTestData) #else #define _IncrementalSelfTestDataAddress 0 #endif #if CC_GetTestResult #include "GetTestResult_fp.h" typedef TPM_RC (GetTestResult_Entry)( GetTestResult_Out *out ); typedef const struct { GetTestResult_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[1]; BYTE types[4]; } GetTestResult_COMMAND_DESCRIPTOR_t; GetTestResult_COMMAND_DESCRIPTOR_t _GetTestResultData = { /* entry */ &TPM2_GetTestResult, /* inSize */ 0, /* outSize */ (UINT16)(sizeof(GetTestResult_Out)), /* offsetOfTypes */ offsetof(GetTestResult_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(GetTestResult_Out, testResult))}, /* types */ {END_OF_LIST, TPM2B_MAX_BUFFER_P_MARSHAL, TPM_RC_P_MARSHAL, END_OF_LIST} }; #define _GetTestResultDataAddress (&_GetTestResultData) #else #define _GetTestResultDataAddress 0 #endif #if CC_StartAuthSession #include "StartAuthSession_fp.h" typedef TPM_RC (StartAuthSession_Entry)( StartAuthSession_In *in, StartAuthSession_Out *out ); typedef const struct { StartAuthSession_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[7]; BYTE types[11]; } StartAuthSession_COMMAND_DESCRIPTOR_t; StartAuthSession_COMMAND_DESCRIPTOR_t _StartAuthSessionData = { /* entry */ &TPM2_StartAuthSession, /* inSize */ (UINT16)(sizeof(StartAuthSession_In)), /* outSize */ (UINT16)(sizeof(StartAuthSession_Out)), /* offsetOfTypes */ offsetof(StartAuthSession_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(StartAuthSession_In, bind)), (UINT16)(offsetof(StartAuthSession_In, nonceCaller)), (UINT16)(offsetof(StartAuthSession_In, encryptedSalt)), (UINT16)(offsetof(StartAuthSession_In, sessionType)), (UINT16)(offsetof(StartAuthSession_In, symmetric)), (UINT16)(offsetof(StartAuthSession_In, authHash)), (UINT16)(offsetof(StartAuthSession_Out, nonceTPM))}, /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG, TPMI_DH_ENTITY_H_UNMARSHAL + ADD_FLAG, TPM2B_NONCE_P_UNMARSHAL, TPM2B_ENCRYPTED_SECRET_P_UNMARSHAL, TPM_SE_P_UNMARSHAL, TPMT_SYM_DEF_P_UNMARSHAL + ADD_FLAG, TPMI_ALG_HASH_P_UNMARSHAL, END_OF_LIST, TPMI_SH_AUTH_SESSION_H_MARSHAL, TPM2B_NONCE_P_MARSHAL, END_OF_LIST} }; #define _StartAuthSessionDataAddress (&_StartAuthSessionData) #else #define _StartAuthSessionDataAddress 0 #endif #if CC_PolicyRestart #include "PolicyRestart_fp.h" typedef TPM_RC (PolicyRestart_Entry)( PolicyRestart_In *in ); typedef const struct { PolicyRestart_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; BYTE types[3]; } PolicyRestart_COMMAND_DESCRIPTOR_t; PolicyRestart_COMMAND_DESCRIPTOR_t _PolicyRestartData = { /* entry */ &TPM2_PolicyRestart, /* inSize */ (UINT16)(sizeof(PolicyRestart_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(PolicyRestart_COMMAND_DESCRIPTOR_t, types), /* offsets */ // No parameter offsets /* types */ {TPMI_SH_POLICY_H_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _PolicyRestartDataAddress (&_PolicyRestartData) #else #define _PolicyRestartDataAddress 0 #endif #if CC_Create #include "Create_fp.h" typedef TPM_RC (Create_Entry)( Create_In *in, Create_Out *out ); typedef const struct { Create_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[8]; BYTE types[12]; } Create_COMMAND_DESCRIPTOR_t; Create_COMMAND_DESCRIPTOR_t _CreateData = { /* entry */ &TPM2_Create, /* inSize */ (UINT16)(sizeof(Create_In)), /* outSize */ (UINT16)(sizeof(Create_Out)), /* offsetOfTypes */ offsetof(Create_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(Create_In, inSensitive)), (UINT16)(offsetof(Create_In, inPublic)), (UINT16)(offsetof(Create_In, outsideInfo)), (UINT16)(offsetof(Create_In, creationPCR)), (UINT16)(offsetof(Create_Out, outPublic)), (UINT16)(offsetof(Create_Out, creationData)), (UINT16)(offsetof(Create_Out, creationHash)), (UINT16)(offsetof(Create_Out, creationTicket))}, /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, TPM2B_SENSITIVE_CREATE_P_UNMARSHAL, TPM2B_PUBLIC_P_UNMARSHAL, TPM2B_DATA_P_UNMARSHAL, TPML_PCR_SELECTION_P_UNMARSHAL, END_OF_LIST, TPM2B_PRIVATE_P_MARSHAL, TPM2B_PUBLIC_P_MARSHAL, TPM2B_CREATION_DATA_P_MARSHAL, TPM2B_DIGEST_P_MARSHAL, TPMT_TK_CREATION_P_MARSHAL, END_OF_LIST} }; #define _CreateDataAddress (&_CreateData) #else #define _CreateDataAddress 0 #endif #if CC_Load #include "Load_fp.h" typedef TPM_RC (Load_Entry)( Load_In *in, Load_Out *out ); typedef const struct { Load_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[3]; BYTE types[7]; } Load_COMMAND_DESCRIPTOR_t; Load_COMMAND_DESCRIPTOR_t _LoadData = { /* entry */ &TPM2_Load, /* inSize */ (UINT16)(sizeof(Load_In)), /* outSize */ (UINT16)(sizeof(Load_Out)), /* offsetOfTypes */ offsetof(Load_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(Load_In, inPrivate)), (UINT16)(offsetof(Load_In, inPublic)), (UINT16)(offsetof(Load_Out, name))}, /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, TPM2B_PRIVATE_P_UNMARSHAL, TPM2B_PUBLIC_P_UNMARSHAL, END_OF_LIST, TPM_HANDLE_H_MARSHAL, TPM2B_NAME_P_MARSHAL, END_OF_LIST} }; #define _LoadDataAddress (&_LoadData) #else #define _LoadDataAddress 0 #endif #if CC_LoadExternal #include "LoadExternal_fp.h" typedef TPM_RC (LoadExternal_Entry)( LoadExternal_In *in, LoadExternal_Out *out ); typedef const struct { LoadExternal_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[3]; BYTE types[7]; } LoadExternal_COMMAND_DESCRIPTOR_t; LoadExternal_COMMAND_DESCRIPTOR_t _LoadExternalData = { /* entry */ &TPM2_LoadExternal, /* inSize */ (UINT16)(sizeof(LoadExternal_In)), /* outSize */ (UINT16)(sizeof(LoadExternal_Out)), /* offsetOfTypes */ offsetof(LoadExternal_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(LoadExternal_In, inPublic)), (UINT16)(offsetof(LoadExternal_In, hierarchy)), (UINT16)(offsetof(LoadExternal_Out, name))}, /* types */ {TPM2B_SENSITIVE_P_UNMARSHAL, TPM2B_PUBLIC_P_UNMARSHAL + ADD_FLAG, TPMI_RH_HIERARCHY_P_UNMARSHAL + ADD_FLAG, END_OF_LIST, TPM_HANDLE_H_MARSHAL, TPM2B_NAME_P_MARSHAL, END_OF_LIST} }; #define _LoadExternalDataAddress (&_LoadExternalData) #else #define _LoadExternalDataAddress 0 #endif #if CC_ReadPublic #include "ReadPublic_fp.h" typedef TPM_RC (ReadPublic_Entry)( ReadPublic_In *in, ReadPublic_Out *out ); typedef const struct { ReadPublic_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[2]; BYTE types[6]; } ReadPublic_COMMAND_DESCRIPTOR_t; ReadPublic_COMMAND_DESCRIPTOR_t _ReadPublicData = { /* entry */ &TPM2_ReadPublic, /* inSize */ (UINT16)(sizeof(ReadPublic_In)), /* outSize */ (UINT16)(sizeof(ReadPublic_Out)), /* offsetOfTypes */ offsetof(ReadPublic_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(ReadPublic_Out, name)), (UINT16)(offsetof(ReadPublic_Out, qualifiedName))}, /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, END_OF_LIST, TPM2B_PUBLIC_P_MARSHAL, TPM2B_NAME_P_MARSHAL, TPM2B_NAME_P_MARSHAL, END_OF_LIST} }; #define _ReadPublicDataAddress (&_ReadPublicData) #else #define _ReadPublicDataAddress 0 #endif #if CC_ActivateCredential #include "ActivateCredential_fp.h" typedef TPM_RC (ActivateCredential_Entry)( ActivateCredential_In *in, ActivateCredential_Out *out ); typedef const struct { ActivateCredential_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[3]; BYTE types[7]; } ActivateCredential_COMMAND_DESCRIPTOR_t; ActivateCredential_COMMAND_DESCRIPTOR_t _ActivateCredentialData = { /* entry */ &TPM2_ActivateCredential, /* inSize */ (UINT16)(sizeof(ActivateCredential_In)), /* outSize */ (UINT16)(sizeof(ActivateCredential_Out)), /* offsetOfTypes */ offsetof(ActivateCredential_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(ActivateCredential_In, keyHandle)), (UINT16)(offsetof(ActivateCredential_In, credentialBlob)), (UINT16)(offsetof(ActivateCredential_In, secret))}, /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, TPMI_DH_OBJECT_H_UNMARSHAL, TPM2B_ID_OBJECT_P_UNMARSHAL, TPM2B_ENCRYPTED_SECRET_P_UNMARSHAL, END_OF_LIST, TPM2B_DIGEST_P_MARSHAL, END_OF_LIST} }; #define _ActivateCredentialDataAddress (&_ActivateCredentialData) #else #define _ActivateCredentialDataAddress 0 #endif #if CC_MakeCredential #include "MakeCredential_fp.h" typedef TPM_RC (MakeCredential_Entry)( MakeCredential_In *in, MakeCredential_Out *out ); typedef const struct { MakeCredential_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[3]; BYTE types[7]; } MakeCredential_COMMAND_DESCRIPTOR_t; MakeCredential_COMMAND_DESCRIPTOR_t _MakeCredentialData = { /* entry */ &TPM2_MakeCredential, /* inSize */ (UINT16)(sizeof(MakeCredential_In)), /* outSize */ (UINT16)(sizeof(MakeCredential_Out)), /* offsetOfTypes */ offsetof(MakeCredential_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(MakeCredential_In, credential)), (UINT16)(offsetof(MakeCredential_In, objectName)), (UINT16)(offsetof(MakeCredential_Out, secret))}, /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, TPM2B_DIGEST_P_UNMARSHAL, TPM2B_NAME_P_UNMARSHAL, END_OF_LIST, TPM2B_ID_OBJECT_P_MARSHAL, TPM2B_ENCRYPTED_SECRET_P_MARSHAL, END_OF_LIST} }; #define _MakeCredentialDataAddress (&_MakeCredentialData) #else #define _MakeCredentialDataAddress 0 #endif #if CC_Unseal #include "Unseal_fp.h" typedef TPM_RC (Unseal_Entry)( Unseal_In *in, Unseal_Out *out ); typedef const struct { Unseal_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; BYTE types[4]; } Unseal_COMMAND_DESCRIPTOR_t; Unseal_COMMAND_DESCRIPTOR_t _UnsealData = { /* entry */ &TPM2_Unseal, /* inSize */ (UINT16)(sizeof(Unseal_In)), /* outSize */ (UINT16)(sizeof(Unseal_Out)), /* offsetOfTypes */ offsetof(Unseal_COMMAND_DESCRIPTOR_t, types), /* offsets */ // No parameter offsets /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, END_OF_LIST, TPM2B_SENSITIVE_DATA_P_MARSHAL, END_OF_LIST} }; #define _UnsealDataAddress (&_UnsealData) #else #define _UnsealDataAddress 0 #endif #if CC_ObjectChangeAuth #include "ObjectChangeAuth_fp.h" typedef TPM_RC (ObjectChangeAuth_Entry)( ObjectChangeAuth_In *in, ObjectChangeAuth_Out *out ); typedef const struct { ObjectChangeAuth_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[2]; BYTE types[6]; } ObjectChangeAuth_COMMAND_DESCRIPTOR_t; ObjectChangeAuth_COMMAND_DESCRIPTOR_t _ObjectChangeAuthData = { /* entry */ &TPM2_ObjectChangeAuth, /* inSize */ (UINT16)(sizeof(ObjectChangeAuth_In)), /* outSize */ (UINT16)(sizeof(ObjectChangeAuth_Out)), /* offsetOfTypes */ offsetof(ObjectChangeAuth_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(ObjectChangeAuth_In, parentHandle)), (UINT16)(offsetof(ObjectChangeAuth_In, newAuth))}, /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, TPMI_DH_OBJECT_H_UNMARSHAL, TPM2B_AUTH_P_UNMARSHAL, END_OF_LIST, TPM2B_PRIVATE_P_MARSHAL, END_OF_LIST} }; #define _ObjectChangeAuthDataAddress (&_ObjectChangeAuthData) #else #define _ObjectChangeAuthDataAddress 0 #endif #if CC_CreateLoaded #include "CreateLoaded_fp.h" typedef TPM_RC (CreateLoaded_Entry)( CreateLoaded_In *in, CreateLoaded_Out *out ); typedef const struct { CreateLoaded_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[5]; BYTE types[9]; } CreateLoaded_COMMAND_DESCRIPTOR_t; CreateLoaded_COMMAND_DESCRIPTOR_t _CreateLoadedData = { /* entry */ &TPM2_CreateLoaded, /* inSize */ (UINT16)(sizeof(CreateLoaded_In)), /* outSize */ (UINT16)(sizeof(CreateLoaded_Out)), /* offsetOfTypes */ offsetof(CreateLoaded_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(CreateLoaded_In, inSensitive)), (UINT16)(offsetof(CreateLoaded_In, inPublic)), (UINT16)(offsetof(CreateLoaded_Out, outPrivate)), (UINT16)(offsetof(CreateLoaded_Out, outPublic)), (UINT16)(offsetof(CreateLoaded_Out, name))}, /* types */ {TPMI_DH_PARENT_H_UNMARSHAL + ADD_FLAG, TPM2B_SENSITIVE_CREATE_P_UNMARSHAL, TPM2B_TEMPLATE_P_UNMARSHAL, END_OF_LIST, TPM_HANDLE_H_MARSHAL, TPM2B_PRIVATE_P_MARSHAL, TPM2B_PUBLIC_P_MARSHAL, TPM2B_NAME_P_MARSHAL, END_OF_LIST} }; #define _CreateLoadedDataAddress (&_CreateLoadedData) #else #define _CreateLoadedDataAddress 0 #endif #if CC_Duplicate #include "Duplicate_fp.h" typedef TPM_RC (Duplicate_Entry)( Duplicate_In *in, Duplicate_Out *out ); typedef const struct { Duplicate_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[5]; BYTE types[9]; } Duplicate_COMMAND_DESCRIPTOR_t; Duplicate_COMMAND_DESCRIPTOR_t _DuplicateData = { /* entry */ &TPM2_Duplicate, /* inSize */ (UINT16)(sizeof(Duplicate_In)), /* outSize */ (UINT16)(sizeof(Duplicate_Out)), /* offsetOfTypes */ offsetof(Duplicate_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(Duplicate_In, newParentHandle)), (UINT16)(offsetof(Duplicate_In, encryptionKeyIn)), (UINT16)(offsetof(Duplicate_In, symmetricAlg)), (UINT16)(offsetof(Duplicate_Out, duplicate)), (UINT16)(offsetof(Duplicate_Out, outSymSeed))}, /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG, TPM2B_DATA_P_UNMARSHAL, TPMT_SYM_DEF_OBJECT_P_UNMARSHAL + ADD_FLAG, END_OF_LIST, TPM2B_DATA_P_MARSHAL, TPM2B_PRIVATE_P_MARSHAL, TPM2B_ENCRYPTED_SECRET_P_MARSHAL, END_OF_LIST} }; #define _DuplicateDataAddress (&_DuplicateData) #else #define _DuplicateDataAddress 0 #endif #if CC_Rewrap #include "Rewrap_fp.h" typedef TPM_RC (Rewrap_Entry)( Rewrap_In *in, Rewrap_Out *out ); typedef const struct { Rewrap_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[5]; BYTE types[9]; } Rewrap_COMMAND_DESCRIPTOR_t; Rewrap_COMMAND_DESCRIPTOR_t _RewrapData = { /* entry */ &TPM2_Rewrap, /* inSize */ (UINT16)(sizeof(Rewrap_In)), /* outSize */ (UINT16)(sizeof(Rewrap_Out)), /* offsetOfTypes */ offsetof(Rewrap_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(Rewrap_In, newParent)), (UINT16)(offsetof(Rewrap_In, inDuplicate)), (UINT16)(offsetof(Rewrap_In, name)), (UINT16)(offsetof(Rewrap_In, inSymSeed)), (UINT16)(offsetof(Rewrap_Out, outSymSeed))}, /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG, TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG, TPM2B_PRIVATE_P_UNMARSHAL, TPM2B_NAME_P_UNMARSHAL, TPM2B_ENCRYPTED_SECRET_P_UNMARSHAL, END_OF_LIST, TPM2B_PRIVATE_P_MARSHAL, TPM2B_ENCRYPTED_SECRET_P_MARSHAL, END_OF_LIST} }; #define _RewrapDataAddress (&_RewrapData) #else #define _RewrapDataAddress 0 #endif #if CC_Import #include "Import_fp.h" typedef TPM_RC (Import_Entry)( Import_In *in, Import_Out *out ); typedef const struct { Import_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[5]; BYTE types[9]; } Import_COMMAND_DESCRIPTOR_t; Import_COMMAND_DESCRIPTOR_t _ImportData = { /* entry */ &TPM2_Import, /* inSize */ (UINT16)(sizeof(Import_In)), /* outSize */ (UINT16)(sizeof(Import_Out)), /* offsetOfTypes */ offsetof(Import_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(Import_In, encryptionKey)), (UINT16)(offsetof(Import_In, objectPublic)), (UINT16)(offsetof(Import_In, duplicate)), (UINT16)(offsetof(Import_In, inSymSeed)), (UINT16)(offsetof(Import_In, symmetricAlg))}, /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, TPM2B_DATA_P_UNMARSHAL, TPM2B_PUBLIC_P_UNMARSHAL, TPM2B_PRIVATE_P_UNMARSHAL, TPM2B_ENCRYPTED_SECRET_P_UNMARSHAL, TPMT_SYM_DEF_OBJECT_P_UNMARSHAL + ADD_FLAG, END_OF_LIST, TPM2B_PRIVATE_P_MARSHAL, END_OF_LIST} }; #define _ImportDataAddress (&_ImportData) #else #define _ImportDataAddress 0 #endif #if CC_RSA_Encrypt #include "RSA_Encrypt_fp.h" typedef TPM_RC (RSA_Encrypt_Entry)( RSA_Encrypt_In *in, RSA_Encrypt_Out *out ); typedef const struct { RSA_Encrypt_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[3]; BYTE types[7]; } RSA_Encrypt_COMMAND_DESCRIPTOR_t; RSA_Encrypt_COMMAND_DESCRIPTOR_t _RSA_EncryptData = { /* entry */ &TPM2_RSA_Encrypt, /* inSize */ (UINT16)(sizeof(RSA_Encrypt_In)), /* outSize */ (UINT16)(sizeof(RSA_Encrypt_Out)), /* offsetOfTypes */ offsetof(RSA_Encrypt_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(RSA_Encrypt_In, message)), (UINT16)(offsetof(RSA_Encrypt_In, inScheme)), (UINT16)(offsetof(RSA_Encrypt_In, label))}, /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, TPM2B_PUBLIC_KEY_RSA_P_UNMARSHAL, TPMT_RSA_DECRYPT_P_UNMARSHAL + ADD_FLAG, TPM2B_DATA_P_UNMARSHAL, END_OF_LIST, TPM2B_PUBLIC_KEY_RSA_P_MARSHAL, END_OF_LIST} }; #define _RSA_EncryptDataAddress (&_RSA_EncryptData) #else #define _RSA_EncryptDataAddress 0 #endif #if CC_RSA_Decrypt #include "RSA_Decrypt_fp.h" typedef TPM_RC (RSA_Decrypt_Entry)( RSA_Decrypt_In *in, RSA_Decrypt_Out *out ); typedef const struct { RSA_Decrypt_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[3]; BYTE types[7]; } RSA_Decrypt_COMMAND_DESCRIPTOR_t; RSA_Decrypt_COMMAND_DESCRIPTOR_t _RSA_DecryptData = { /* entry */ &TPM2_RSA_Decrypt, /* inSize */ (UINT16)(sizeof(RSA_Decrypt_In)), /* outSize */ (UINT16)(sizeof(RSA_Decrypt_Out)), /* offsetOfTypes */ offsetof(RSA_Decrypt_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(RSA_Decrypt_In, cipherText)), (UINT16)(offsetof(RSA_Decrypt_In, inScheme)), (UINT16)(offsetof(RSA_Decrypt_In, label))}, /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, TPM2B_PUBLIC_KEY_RSA_P_UNMARSHAL, TPMT_RSA_DECRYPT_P_UNMARSHAL + ADD_FLAG, TPM2B_DATA_P_UNMARSHAL, END_OF_LIST, TPM2B_PUBLIC_KEY_RSA_P_MARSHAL, END_OF_LIST} }; #define _RSA_DecryptDataAddress (&_RSA_DecryptData) #else #define _RSA_DecryptDataAddress 0 #endif #if CC_ECDH_KeyGen #include "ECDH_KeyGen_fp.h" typedef TPM_RC (ECDH_KeyGen_Entry)( ECDH_KeyGen_In *in, ECDH_KeyGen_Out *out ); typedef const struct { ECDH_KeyGen_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[1]; BYTE types[5]; } ECDH_KeyGen_COMMAND_DESCRIPTOR_t; ECDH_KeyGen_COMMAND_DESCRIPTOR_t _ECDH_KeyGenData = { /* entry */ &TPM2_ECDH_KeyGen, /* inSize */ (UINT16)(sizeof(ECDH_KeyGen_In)), /* outSize */ (UINT16)(sizeof(ECDH_KeyGen_Out)), /* offsetOfTypes */ offsetof(ECDH_KeyGen_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(ECDH_KeyGen_Out, pubPoint))}, /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, END_OF_LIST, TPM2B_ECC_POINT_P_MARSHAL, TPM2B_ECC_POINT_P_MARSHAL, END_OF_LIST} }; #define _ECDH_KeyGenDataAddress (&_ECDH_KeyGenData) #else #define _ECDH_KeyGenDataAddress 0 #endif #if CC_ECDH_ZGen #include "ECDH_ZGen_fp.h" typedef TPM_RC (ECDH_ZGen_Entry)( ECDH_ZGen_In *in, ECDH_ZGen_Out *out ); typedef const struct { ECDH_ZGen_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[1]; BYTE types[5]; } ECDH_ZGen_COMMAND_DESCRIPTOR_t; ECDH_ZGen_COMMAND_DESCRIPTOR_t _ECDH_ZGenData = { /* entry */ &TPM2_ECDH_ZGen, /* inSize */ (UINT16)(sizeof(ECDH_ZGen_In)), /* outSize */ (UINT16)(sizeof(ECDH_ZGen_Out)), /* offsetOfTypes */ offsetof(ECDH_ZGen_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(ECDH_ZGen_In, inPoint))}, /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, TPM2B_ECC_POINT_P_UNMARSHAL, END_OF_LIST, TPM2B_ECC_POINT_P_MARSHAL, END_OF_LIST} }; #define _ECDH_ZGenDataAddress (&_ECDH_ZGenData) #else #define _ECDH_ZGenDataAddress 0 #endif #if CC_ECC_Encrypt #include "ECC_Encrypt_fp.h" typedef TPM_RC (ECC_Encrypt_Entry)( ECC_Encrypt_In *in, ECC_Encrypt_Out *out ); typedef const struct { ECC_Encrypt_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[4]; BYTE types[8]; } ECC_Encrypt_COMMAND_DESCRIPTOR_t; ECC_Encrypt_COMMAND_DESCRIPTOR_t _ECC_EncryptData = { /* entry */ &TPM2_ECC_Encrypt, /* inSize */ (UINT16)(sizeof(ECC_Encrypt_In)), /* outSize */ (UINT16)(sizeof(ECC_Encrypt_Out)), /* offsetOfTypes */ offsetof(ECC_Encrypt_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(ECC_Encrypt_In, plainText)), (UINT16)(offsetof(ECC_Encrypt_In, inScheme)), (UINT16)(offsetof(ECC_Encrypt_Out, C2)), (UINT16)(offsetof(ECC_Encrypt_Out, C3))}, /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, TPM2B_MAX_BUFFER_P_UNMARSHAL, TPMT_KDF_SCHEME_P_UNMARSHAL + ADD_FLAG, END_OF_LIST, TPM2B_ECC_POINT_P_MARSHAL, TPM2B_MAX_BUFFER_P_MARSHAL, TPM2B_DIGEST_P_MARSHAL, END_OF_LIST} }; #define _ECC_EncryptDataAddress (&_ECC_EncryptData) #else #define _ECC_EncryptDataAddress 0 #endif // CC_ECC_Encrypt #if CC_ECC_Decrypt #include "ECC_Decrypt_fp.h" typedef TPM_RC (ECC_Decrypt_Entry)( ECC_Decrypt_In *in, ECC_Decrypt_Out *out ); typedef const struct { ECC_Decrypt_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[4]; BYTE types[8]; } ECC_Decrypt_COMMAND_DESCRIPTOR_t; ECC_Decrypt_COMMAND_DESCRIPTOR_t _ECC_DecryptData = { /* entry */ &TPM2_ECC_Decrypt, /* inSize */ (UINT16)(sizeof(ECC_Decrypt_In)), /* outSize */ (UINT16)(sizeof(ECC_Decrypt_Out)), /* offsetOfTypes */ offsetof(ECC_Decrypt_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(ECC_Decrypt_In, C1)), (UINT16)(offsetof(ECC_Decrypt_In, C2)), (UINT16)(offsetof(ECC_Decrypt_In, C3)), (UINT16)(offsetof(ECC_Decrypt_In, inScheme))}, /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, TPM2B_ECC_POINT_P_UNMARSHAL, TPM2B_MAX_BUFFER_P_UNMARSHAL, TPM2B_DIGEST_P_UNMARSHAL, TPMT_KDF_SCHEME_P_UNMARSHAL + ADD_FLAG, END_OF_LIST, TPM2B_MAX_BUFFER_P_MARSHAL, END_OF_LIST} }; #define _ECC_DecryptDataAddress (&_ECC_DecryptData) #else #define _ECC_DecryptDataAddress 0 #endif // CC_ECC_Decrypt #if CC_ECC_Parameters #include "ECC_Parameters_fp.h" typedef TPM_RC (ECC_Parameters_Entry)( ECC_Parameters_In *in, ECC_Parameters_Out *out ); typedef const struct { ECC_Parameters_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; BYTE types[4]; } ECC_Parameters_COMMAND_DESCRIPTOR_t; ECC_Parameters_COMMAND_DESCRIPTOR_t _ECC_ParametersData = { /* entry */ &TPM2_ECC_Parameters, /* inSize */ (UINT16)(sizeof(ECC_Parameters_In)), /* outSize */ (UINT16)(sizeof(ECC_Parameters_Out)), /* offsetOfTypes */ offsetof(ECC_Parameters_COMMAND_DESCRIPTOR_t, types), /* offsets */ // No parameter offsets /* types */ {TPMI_ECC_CURVE_P_UNMARSHAL, END_OF_LIST, TPMS_ALGORITHM_DETAIL_ECC_P_MARSHAL, END_OF_LIST} }; #define _ECC_ParametersDataAddress (&_ECC_ParametersData) #else #define _ECC_ParametersDataAddress 0 #endif #if CC_ZGen_2Phase #include "ZGen_2Phase_fp.h" typedef TPM_RC (ZGen_2Phase_Entry)( ZGen_2Phase_In *in, ZGen_2Phase_Out *out ); typedef const struct { ZGen_2Phase_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[5]; BYTE types[9]; } ZGen_2Phase_COMMAND_DESCRIPTOR_t; ZGen_2Phase_COMMAND_DESCRIPTOR_t _ZGen_2PhaseData = { /* entry */ &TPM2_ZGen_2Phase, /* inSize */ (UINT16)(sizeof(ZGen_2Phase_In)), /* outSize */ (UINT16)(sizeof(ZGen_2Phase_Out)), /* offsetOfTypes */ offsetof(ZGen_2Phase_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(ZGen_2Phase_In, inQsB)), (UINT16)(offsetof(ZGen_2Phase_In, inQeB)), (UINT16)(offsetof(ZGen_2Phase_In, inScheme)), (UINT16)(offsetof(ZGen_2Phase_In, counter)), (UINT16)(offsetof(ZGen_2Phase_Out, outZ2))}, /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, TPM2B_ECC_POINT_P_UNMARSHAL, TPM2B_ECC_POINT_P_UNMARSHAL, TPMI_ECC_KEY_EXCHANGE_P_UNMARSHAL, UINT16_P_UNMARSHAL, END_OF_LIST, TPM2B_ECC_POINT_P_MARSHAL, TPM2B_ECC_POINT_P_MARSHAL, END_OF_LIST} }; #define _ZGen_2PhaseDataAddress (&_ZGen_2PhaseData) #else #define _ZGen_2PhaseDataAddress 0 #endif #if CC_EncryptDecrypt #include "EncryptDecrypt_fp.h" typedef TPM_RC (EncryptDecrypt_Entry)( EncryptDecrypt_In *in, EncryptDecrypt_Out *out ); typedef const struct { EncryptDecrypt_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[5]; BYTE types[9]; } EncryptDecrypt_COMMAND_DESCRIPTOR_t; EncryptDecrypt_COMMAND_DESCRIPTOR_t _EncryptDecryptData = { /* entry */ &TPM2_EncryptDecrypt, /* inSize */ (UINT16)(sizeof(EncryptDecrypt_In)), /* outSize */ (UINT16)(sizeof(EncryptDecrypt_Out)), /* offsetOfTypes */ offsetof(EncryptDecrypt_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(EncryptDecrypt_In, decrypt)), (UINT16)(offsetof(EncryptDecrypt_In, mode)), (UINT16)(offsetof(EncryptDecrypt_In, ivIn)), (UINT16)(offsetof(EncryptDecrypt_In, inData)), (UINT16)(offsetof(EncryptDecrypt_Out, ivOut))}, /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, TPMI_YES_NO_P_UNMARSHAL, TPMI_ALG_CIPHER_MODE_P_UNMARSHAL + ADD_FLAG, TPM2B_IV_P_UNMARSHAL, TPM2B_MAX_BUFFER_P_UNMARSHAL, END_OF_LIST, TPM2B_MAX_BUFFER_P_MARSHAL, TPM2B_IV_P_MARSHAL, END_OF_LIST} }; #define _EncryptDecryptDataAddress (&_EncryptDecryptData) #else #define _EncryptDecryptDataAddress 0 #endif #if CC_EncryptDecrypt2 #include "EncryptDecrypt2_fp.h" typedef TPM_RC (EncryptDecrypt2_Entry)( EncryptDecrypt2_In *in, EncryptDecrypt2_Out *out ); typedef const struct { EncryptDecrypt2_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[5]; BYTE types[9]; } EncryptDecrypt2_COMMAND_DESCRIPTOR_t; EncryptDecrypt2_COMMAND_DESCRIPTOR_t _EncryptDecrypt2Data = { /* entry */ &TPM2_EncryptDecrypt2, /* inSize */ (UINT16)(sizeof(EncryptDecrypt2_In)), /* outSize */ (UINT16)(sizeof(EncryptDecrypt2_Out)), /* offsetOfTypes */ offsetof(EncryptDecrypt2_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(EncryptDecrypt2_In, inData)), (UINT16)(offsetof(EncryptDecrypt2_In, decrypt)), (UINT16)(offsetof(EncryptDecrypt2_In, mode)), (UINT16)(offsetof(EncryptDecrypt2_In, ivIn)), (UINT16)(offsetof(EncryptDecrypt2_Out, ivOut))}, /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, TPM2B_MAX_BUFFER_P_UNMARSHAL, TPMI_YES_NO_P_UNMARSHAL, TPMI_ALG_CIPHER_MODE_P_UNMARSHAL + ADD_FLAG, TPM2B_IV_P_UNMARSHAL, END_OF_LIST, TPM2B_MAX_BUFFER_P_MARSHAL, TPM2B_IV_P_MARSHAL, END_OF_LIST} }; #define _EncryptDecrypt2DataAddress (&_EncryptDecrypt2Data) #else #define _EncryptDecrypt2DataAddress 0 #endif #if CC_Hash #include "Hash_fp.h" typedef TPM_RC (Hash_Entry)( Hash_In *in, Hash_Out *out ); typedef const struct { Hash_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[3]; BYTE types[7]; } Hash_COMMAND_DESCRIPTOR_t; Hash_COMMAND_DESCRIPTOR_t _HashData = { /* entry */ &TPM2_Hash, /* inSize */ (UINT16)(sizeof(Hash_In)), /* outSize */ (UINT16)(sizeof(Hash_Out)), /* offsetOfTypes */ offsetof(Hash_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(Hash_In, hashAlg)), (UINT16)(offsetof(Hash_In, hierarchy)), (UINT16)(offsetof(Hash_Out, validation))}, /* types */ {TPM2B_MAX_BUFFER_P_UNMARSHAL, TPMI_ALG_HASH_P_UNMARSHAL, TPMI_RH_HIERARCHY_P_UNMARSHAL + ADD_FLAG, END_OF_LIST, TPM2B_DIGEST_P_MARSHAL, TPMT_TK_HASHCHECK_P_MARSHAL, END_OF_LIST} }; #define _HashDataAddress (&_HashData) #else #define _HashDataAddress 0 #endif #if CC_HMAC #include "HMAC_fp.h" typedef TPM_RC (HMAC_Entry)( HMAC_In *in, HMAC_Out *out ); typedef const struct { HMAC_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[2]; BYTE types[6]; } HMAC_COMMAND_DESCRIPTOR_t; HMAC_COMMAND_DESCRIPTOR_t _HMACData = { /* entry */ &TPM2_HMAC, /* inSize */ (UINT16)(sizeof(HMAC_In)), /* outSize */ (UINT16)(sizeof(HMAC_Out)), /* offsetOfTypes */ offsetof(HMAC_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(HMAC_In, buffer)), (UINT16)(offsetof(HMAC_In, hashAlg))}, /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, TPM2B_MAX_BUFFER_P_UNMARSHAL, TPMI_ALG_HASH_P_UNMARSHAL + ADD_FLAG, END_OF_LIST, TPM2B_DIGEST_P_MARSHAL, END_OF_LIST} }; #define _HMACDataAddress (&_HMACData) #else #define _HMACDataAddress 0 #endif #if CC_MAC #include "MAC_fp.h" typedef TPM_RC (MAC_Entry)( MAC_In *in, MAC_Out *out ); typedef const struct { MAC_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[2]; BYTE types[6]; } MAC_COMMAND_DESCRIPTOR_t; MAC_COMMAND_DESCRIPTOR_t _MACData = { /* entry */ &TPM2_MAC, /* inSize */ (UINT16)(sizeof(MAC_In)), /* outSize */ (UINT16)(sizeof(MAC_Out)), /* offsetOfTypes */ offsetof(MAC_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(MAC_In, buffer)), (UINT16)(offsetof(MAC_In, inScheme))}, /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, TPM2B_MAX_BUFFER_P_UNMARSHAL, TPMI_ALG_MAC_SCHEME_P_UNMARSHAL + ADD_FLAG, END_OF_LIST, TPM2B_DIGEST_P_MARSHAL, END_OF_LIST} }; #define _MACDataAddress (&_MACData) #else #define _MACDataAddress 0 #endif #if CC_GetRandom #include "GetRandom_fp.h" typedef TPM_RC (GetRandom_Entry)( GetRandom_In *in, GetRandom_Out *out ); typedef const struct { GetRandom_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; BYTE types[4]; } GetRandom_COMMAND_DESCRIPTOR_t; GetRandom_COMMAND_DESCRIPTOR_t _GetRandomData = { /* entry */ &TPM2_GetRandom, /* inSize */ (UINT16)(sizeof(GetRandom_In)), /* outSize */ (UINT16)(sizeof(GetRandom_Out)), /* offsetOfTypes */ offsetof(GetRandom_COMMAND_DESCRIPTOR_t, types), /* offsets */ // No parameter offsets /* types */ {UINT16_P_UNMARSHAL, END_OF_LIST, TPM2B_DIGEST_P_MARSHAL, END_OF_LIST} }; #define _GetRandomDataAddress (&_GetRandomData) #else #define _GetRandomDataAddress 0 #endif #if CC_StirRandom #include "StirRandom_fp.h" typedef TPM_RC (StirRandom_Entry)( StirRandom_In *in ); typedef const struct { StirRandom_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; BYTE types[3]; } StirRandom_COMMAND_DESCRIPTOR_t; StirRandom_COMMAND_DESCRIPTOR_t _StirRandomData = { /* entry */ &TPM2_StirRandom, /* inSize */ (UINT16)(sizeof(StirRandom_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(StirRandom_COMMAND_DESCRIPTOR_t, types), /* offsets */ // No parameter offsets /* types */ {TPM2B_SENSITIVE_DATA_P_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _StirRandomDataAddress (&_StirRandomData) #else #define _StirRandomDataAddress 0 #endif #if CC_HMAC_Start #include "HMAC_Start_fp.h" typedef TPM_RC (HMAC_Start_Entry)( HMAC_Start_In *in, HMAC_Start_Out *out ); typedef const struct { HMAC_Start_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[2]; BYTE types[6]; } HMAC_Start_COMMAND_DESCRIPTOR_t; HMAC_Start_COMMAND_DESCRIPTOR_t _HMAC_StartData = { /* entry */ &TPM2_HMAC_Start, /* inSize */ (UINT16)(sizeof(HMAC_Start_In)), /* outSize */ (UINT16)(sizeof(HMAC_Start_Out)), /* offsetOfTypes */ offsetof(HMAC_Start_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(HMAC_Start_In, auth)), (UINT16)(offsetof(HMAC_Start_In, hashAlg))}, /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, TPM2B_AUTH_P_UNMARSHAL, TPMI_ALG_HASH_P_UNMARSHAL + ADD_FLAG, END_OF_LIST, TPMI_DH_OBJECT_H_MARSHAL, END_OF_LIST} }; #define _HMAC_StartDataAddress (&_HMAC_StartData) #else #define _HMAC_StartDataAddress 0 #endif #if CC_MAC_Start #include "MAC_Start_fp.h" typedef TPM_RC (MAC_Start_Entry)( MAC_Start_In *in, MAC_Start_Out *out ); typedef const struct { MAC_Start_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[2]; BYTE types[6]; } MAC_Start_COMMAND_DESCRIPTOR_t; MAC_Start_COMMAND_DESCRIPTOR_t _MAC_StartData = { /* entry */ &TPM2_MAC_Start, /* inSize */ (UINT16)(sizeof(MAC_Start_In)), /* outSize */ (UINT16)(sizeof(MAC_Start_Out)), /* offsetOfTypes */ offsetof(MAC_Start_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(MAC_Start_In, auth)), (UINT16)(offsetof(MAC_Start_In, inScheme))}, /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, TPM2B_AUTH_P_UNMARSHAL, TPMI_ALG_MAC_SCHEME_P_UNMARSHAL + ADD_FLAG, END_OF_LIST, TPMI_DH_OBJECT_H_MARSHAL, END_OF_LIST} }; #define _MAC_StartDataAddress (&_MAC_StartData) #else #define _MAC_StartDataAddress 0 #endif #if CC_HashSequenceStart #include "HashSequenceStart_fp.h" typedef TPM_RC (HashSequenceStart_Entry)( HashSequenceStart_In *in, HashSequenceStart_Out *out ); typedef const struct { HashSequenceStart_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[1]; BYTE types[5]; } HashSequenceStart_COMMAND_DESCRIPTOR_t; HashSequenceStart_COMMAND_DESCRIPTOR_t _HashSequenceStartData = { /* entry */ &TPM2_HashSequenceStart, /* inSize */ (UINT16)(sizeof(HashSequenceStart_In)), /* outSize */ (UINT16)(sizeof(HashSequenceStart_Out)), /* offsetOfTypes */ offsetof(HashSequenceStart_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(HashSequenceStart_In, hashAlg))}, /* types */ {TPM2B_AUTH_P_UNMARSHAL, TPMI_ALG_HASH_P_UNMARSHAL + ADD_FLAG, END_OF_LIST, TPMI_DH_OBJECT_H_MARSHAL, END_OF_LIST} }; #define _HashSequenceStartDataAddress (&_HashSequenceStartData) #else #define _HashSequenceStartDataAddress 0 #endif #if CC_SequenceUpdate #include "SequenceUpdate_fp.h" typedef TPM_RC (SequenceUpdate_Entry)( SequenceUpdate_In *in ); typedef const struct { SequenceUpdate_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[1]; BYTE types[4]; } SequenceUpdate_COMMAND_DESCRIPTOR_t; SequenceUpdate_COMMAND_DESCRIPTOR_t _SequenceUpdateData = { /* entry */ &TPM2_SequenceUpdate, /* inSize */ (UINT16)(sizeof(SequenceUpdate_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(SequenceUpdate_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(SequenceUpdate_In, buffer))}, /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, TPM2B_MAX_BUFFER_P_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _SequenceUpdateDataAddress (&_SequenceUpdateData) #else #define _SequenceUpdateDataAddress 0 #endif #if CC_SequenceComplete #include "SequenceComplete_fp.h" typedef TPM_RC (SequenceComplete_Entry)( SequenceComplete_In *in, SequenceComplete_Out *out ); typedef const struct { SequenceComplete_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[3]; BYTE types[7]; } SequenceComplete_COMMAND_DESCRIPTOR_t; SequenceComplete_COMMAND_DESCRIPTOR_t _SequenceCompleteData = { /* entry */ &TPM2_SequenceComplete, /* inSize */ (UINT16)(sizeof(SequenceComplete_In)), /* outSize */ (UINT16)(sizeof(SequenceComplete_Out)), /* offsetOfTypes */ offsetof(SequenceComplete_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(SequenceComplete_In, buffer)), (UINT16)(offsetof(SequenceComplete_In, hierarchy)), (UINT16)(offsetof(SequenceComplete_Out, validation))}, /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, TPM2B_MAX_BUFFER_P_UNMARSHAL, TPMI_RH_HIERARCHY_P_UNMARSHAL + ADD_FLAG, END_OF_LIST, TPM2B_DIGEST_P_MARSHAL, TPMT_TK_HASHCHECK_P_MARSHAL, END_OF_LIST} }; #define _SequenceCompleteDataAddress (&_SequenceCompleteData) #else #define _SequenceCompleteDataAddress 0 #endif #if CC_EventSequenceComplete #include "EventSequenceComplete_fp.h" typedef TPM_RC (EventSequenceComplete_Entry)( EventSequenceComplete_In *in, EventSequenceComplete_Out *out ); typedef const struct { EventSequenceComplete_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[2]; BYTE types[6]; } EventSequenceComplete_COMMAND_DESCRIPTOR_t; EventSequenceComplete_COMMAND_DESCRIPTOR_t _EventSequenceCompleteData = { /* entry */ &TPM2_EventSequenceComplete, /* inSize */ (UINT16)(sizeof(EventSequenceComplete_In)), /* outSize */ (UINT16)(sizeof(EventSequenceComplete_Out)), /* offsetOfTypes */ offsetof(EventSequenceComplete_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(EventSequenceComplete_In, sequenceHandle)), (UINT16)(offsetof(EventSequenceComplete_In, buffer))}, /* types */ {TPMI_DH_PCR_H_UNMARSHAL + ADD_FLAG, TPMI_DH_OBJECT_H_UNMARSHAL, TPM2B_MAX_BUFFER_P_UNMARSHAL, END_OF_LIST, TPML_DIGEST_VALUES_P_MARSHAL, END_OF_LIST} }; #define _EventSequenceCompleteDataAddress (&_EventSequenceCompleteData) #else #define _EventSequenceCompleteDataAddress 0 #endif #if CC_Certify #include "Certify_fp.h" typedef TPM_RC (Certify_Entry)( Certify_In *in, Certify_Out *out ); typedef const struct { Certify_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[4]; BYTE types[8]; } Certify_COMMAND_DESCRIPTOR_t; Certify_COMMAND_DESCRIPTOR_t _CertifyData = { /* entry */ &TPM2_Certify, /* inSize */ (UINT16)(sizeof(Certify_In)), /* outSize */ (UINT16)(sizeof(Certify_Out)), /* offsetOfTypes */ offsetof(Certify_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(Certify_In, signHandle)), (UINT16)(offsetof(Certify_In, qualifyingData)), (UINT16)(offsetof(Certify_In, inScheme)), (UINT16)(offsetof(Certify_Out, signature))}, /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG, TPM2B_DATA_P_UNMARSHAL, TPMT_SIG_SCHEME_P_UNMARSHAL + ADD_FLAG, END_OF_LIST, TPM2B_ATTEST_P_MARSHAL, TPMT_SIGNATURE_P_MARSHAL, END_OF_LIST} }; #define _CertifyDataAddress (&_CertifyData) #else #define _CertifyDataAddress 0 #endif #if CC_CertifyCreation #include "CertifyCreation_fp.h" typedef TPM_RC (CertifyCreation_Entry)( CertifyCreation_In *in, CertifyCreation_Out *out ); typedef const struct { CertifyCreation_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[6]; BYTE types[10]; } CertifyCreation_COMMAND_DESCRIPTOR_t; CertifyCreation_COMMAND_DESCRIPTOR_t _CertifyCreationData = { /* entry */ &TPM2_CertifyCreation, /* inSize */ (UINT16)(sizeof(CertifyCreation_In)), /* outSize */ (UINT16)(sizeof(CertifyCreation_Out)), /* offsetOfTypes */ offsetof(CertifyCreation_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(CertifyCreation_In, objectHandle)), (UINT16)(offsetof(CertifyCreation_In, qualifyingData)), (UINT16)(offsetof(CertifyCreation_In, creationHash)), (UINT16)(offsetof(CertifyCreation_In, inScheme)), (UINT16)(offsetof(CertifyCreation_In, creationTicket)), (UINT16)(offsetof(CertifyCreation_Out, signature))}, /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG, TPMI_DH_OBJECT_H_UNMARSHAL, TPM2B_DATA_P_UNMARSHAL, TPM2B_DIGEST_P_UNMARSHAL, TPMT_SIG_SCHEME_P_UNMARSHAL + ADD_FLAG, TPMT_TK_CREATION_P_UNMARSHAL, END_OF_LIST, TPM2B_ATTEST_P_MARSHAL, TPMT_SIGNATURE_P_MARSHAL, END_OF_LIST} }; #define _CertifyCreationDataAddress (&_CertifyCreationData) #else #define _CertifyCreationDataAddress 0 #endif #if CC_Quote #include "Quote_fp.h" typedef TPM_RC (Quote_Entry)( Quote_In *in, Quote_Out *out ); typedef const struct { Quote_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[4]; BYTE types[8]; } Quote_COMMAND_DESCRIPTOR_t; Quote_COMMAND_DESCRIPTOR_t _QuoteData = { /* entry */ &TPM2_Quote, /* inSize */ (UINT16)(sizeof(Quote_In)), /* outSize */ (UINT16)(sizeof(Quote_Out)), /* offsetOfTypes */ offsetof(Quote_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(Quote_In, qualifyingData)), (UINT16)(offsetof(Quote_In, inScheme)), (UINT16)(offsetof(Quote_In, PCRselect)), (UINT16)(offsetof(Quote_Out, signature))}, /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG, TPM2B_DATA_P_UNMARSHAL, TPMT_SIG_SCHEME_P_UNMARSHAL + ADD_FLAG, TPML_PCR_SELECTION_P_UNMARSHAL, END_OF_LIST, TPM2B_ATTEST_P_MARSHAL, TPMT_SIGNATURE_P_MARSHAL, END_OF_LIST} }; #define _QuoteDataAddress (&_QuoteData) #else #define _QuoteDataAddress 0 #endif #if CC_GetSessionAuditDigest #include "GetSessionAuditDigest_fp.h" typedef TPM_RC (GetSessionAuditDigest_Entry)( GetSessionAuditDigest_In *in, GetSessionAuditDigest_Out *out ); typedef const struct { GetSessionAuditDigest_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[5]; BYTE types[9]; } GetSessionAuditDigest_COMMAND_DESCRIPTOR_t; GetSessionAuditDigest_COMMAND_DESCRIPTOR_t _GetSessionAuditDigestData = { /* entry */ &TPM2_GetSessionAuditDigest, /* inSize */ (UINT16)(sizeof(GetSessionAuditDigest_In)), /* outSize */ (UINT16)(sizeof(GetSessionAuditDigest_Out)), /* offsetOfTypes */ offsetof(GetSessionAuditDigest_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(GetSessionAuditDigest_In, signHandle)), (UINT16)(offsetof(GetSessionAuditDigest_In, sessionHandle)), (UINT16)(offsetof(GetSessionAuditDigest_In, qualifyingData)), (UINT16)(offsetof(GetSessionAuditDigest_In, inScheme)), (UINT16)(offsetof(GetSessionAuditDigest_Out, signature))}, /* types */ {TPMI_RH_ENDORSEMENT_H_UNMARSHAL, TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG, TPMI_SH_HMAC_H_UNMARSHAL, TPM2B_DATA_P_UNMARSHAL, TPMT_SIG_SCHEME_P_UNMARSHAL + ADD_FLAG, END_OF_LIST, TPM2B_ATTEST_P_MARSHAL, TPMT_SIGNATURE_P_MARSHAL, END_OF_LIST} }; #define _GetSessionAuditDigestDataAddress (&_GetSessionAuditDigestData) #else #define _GetSessionAuditDigestDataAddress 0 #endif #if CC_GetCommandAuditDigest #include "GetCommandAuditDigest_fp.h" typedef TPM_RC (GetCommandAuditDigest_Entry)( GetCommandAuditDigest_In *in, GetCommandAuditDigest_Out *out ); typedef const struct { GetCommandAuditDigest_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[4]; BYTE types[8]; } GetCommandAuditDigest_COMMAND_DESCRIPTOR_t; GetCommandAuditDigest_COMMAND_DESCRIPTOR_t _GetCommandAuditDigestData = { /* entry */ &TPM2_GetCommandAuditDigest, /* inSize */ (UINT16)(sizeof(GetCommandAuditDigest_In)), /* outSize */ (UINT16)(sizeof(GetCommandAuditDigest_Out)), /* offsetOfTypes */ offsetof(GetCommandAuditDigest_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(GetCommandAuditDigest_In, signHandle)), (UINT16)(offsetof(GetCommandAuditDigest_In, qualifyingData)), (UINT16)(offsetof(GetCommandAuditDigest_In, inScheme)), (UINT16)(offsetof(GetCommandAuditDigest_Out, signature))}, /* types */ {TPMI_RH_ENDORSEMENT_H_UNMARSHAL, TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG, TPM2B_DATA_P_UNMARSHAL, TPMT_SIG_SCHEME_P_UNMARSHAL + ADD_FLAG, END_OF_LIST, TPM2B_ATTEST_P_MARSHAL, TPMT_SIGNATURE_P_MARSHAL, END_OF_LIST} }; #define _GetCommandAuditDigestDataAddress (&_GetCommandAuditDigestData) #else #define _GetCommandAuditDigestDataAddress 0 #endif #if CC_GetTime #include "GetTime_fp.h" typedef TPM_RC (GetTime_Entry)( GetTime_In *in, GetTime_Out *out ); typedef const struct { GetTime_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[4]; BYTE types[8]; } GetTime_COMMAND_DESCRIPTOR_t; GetTime_COMMAND_DESCRIPTOR_t _GetTimeData = { /* entry */ &TPM2_GetTime, /* inSize */ (UINT16)(sizeof(GetTime_In)), /* outSize */ (UINT16)(sizeof(GetTime_Out)), /* offsetOfTypes */ offsetof(GetTime_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(GetTime_In, signHandle)), (UINT16)(offsetof(GetTime_In, qualifyingData)), (UINT16)(offsetof(GetTime_In, inScheme)), (UINT16)(offsetof(GetTime_Out, signature))}, /* types */ {TPMI_RH_ENDORSEMENT_H_UNMARSHAL, TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG, TPM2B_DATA_P_UNMARSHAL, TPMT_SIG_SCHEME_P_UNMARSHAL + ADD_FLAG, END_OF_LIST, TPM2B_ATTEST_P_MARSHAL, TPMT_SIGNATURE_P_MARSHAL, END_OF_LIST} }; #define _GetTimeDataAddress (&_GetTimeData) #else #define _GetTimeDataAddress 0 #endif #if CC_CertifyX509 #include "CertifyX509_fp.h" typedef TPM_RC (CertifyX509_Entry)( CertifyX509_In *in, CertifyX509_Out *out ); typedef const struct { CertifyX509_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[6]; BYTE types[10]; } CertifyX509_COMMAND_DESCRIPTOR_t; CertifyX509_COMMAND_DESCRIPTOR_t _CertifyX509Data = { /* entry */ &TPM2_CertifyX509, /* inSize */ (UINT16)(sizeof(CertifyX509_In)), /* outSize */ (UINT16)(sizeof(CertifyX509_Out)), /* offsetOfTypes */ offsetof(CertifyX509_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(CertifyX509_In, signHandle)), (UINT16)(offsetof(CertifyX509_In, reserved)), (UINT16)(offsetof(CertifyX509_In, inScheme)), (UINT16)(offsetof(CertifyX509_In, partialCertificate)), (UINT16)(offsetof(CertifyX509_Out, tbsDigest)), (UINT16)(offsetof(CertifyX509_Out, signature))}, /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG, TPM2B_DATA_P_UNMARSHAL, TPMT_SIG_SCHEME_P_UNMARSHAL + ADD_FLAG, TPM2B_MAX_BUFFER_P_UNMARSHAL, END_OF_LIST, TPM2B_MAX_BUFFER_P_MARSHAL, TPM2B_DIGEST_P_MARSHAL, TPMT_SIGNATURE_P_MARSHAL, END_OF_LIST} }; #define _CertifyX509DataAddress (&_CertifyX509Data) #else #define _CertifyX509DataAddress 0 #endif // CC_CertifyX509 #if CC_Commit #include "Commit_fp.h" typedef TPM_RC (Commit_Entry)( Commit_In *in, Commit_Out *out ); typedef const struct { Commit_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[6]; BYTE types[10]; } Commit_COMMAND_DESCRIPTOR_t; Commit_COMMAND_DESCRIPTOR_t _CommitData = { /* entry */ &TPM2_Commit, /* inSize */ (UINT16)(sizeof(Commit_In)), /* outSize */ (UINT16)(sizeof(Commit_Out)), /* offsetOfTypes */ offsetof(Commit_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(Commit_In, P1)), (UINT16)(offsetof(Commit_In, s2)), (UINT16)(offsetof(Commit_In, y2)), (UINT16)(offsetof(Commit_Out, L)), (UINT16)(offsetof(Commit_Out, E)), (UINT16)(offsetof(Commit_Out, counter))}, /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, TPM2B_ECC_POINT_P_UNMARSHAL, TPM2B_SENSITIVE_DATA_P_UNMARSHAL, TPM2B_ECC_PARAMETER_P_UNMARSHAL, END_OF_LIST, TPM2B_ECC_POINT_P_MARSHAL, TPM2B_ECC_POINT_P_MARSHAL, TPM2B_ECC_POINT_P_MARSHAL, UINT16_P_MARSHAL, END_OF_LIST} }; #define _CommitDataAddress (&_CommitData) #else #define _CommitDataAddress 0 #endif #if CC_EC_Ephemeral #include "EC_Ephemeral_fp.h" typedef TPM_RC (EC_Ephemeral_Entry)( EC_Ephemeral_In *in, EC_Ephemeral_Out *out ); typedef const struct { EC_Ephemeral_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[1]; BYTE types[5]; } EC_Ephemeral_COMMAND_DESCRIPTOR_t; EC_Ephemeral_COMMAND_DESCRIPTOR_t _EC_EphemeralData = { /* entry */ &TPM2_EC_Ephemeral, /* inSize */ (UINT16)(sizeof(EC_Ephemeral_In)), /* outSize */ (UINT16)(sizeof(EC_Ephemeral_Out)), /* offsetOfTypes */ offsetof(EC_Ephemeral_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(EC_Ephemeral_Out, counter))}, /* types */ {TPMI_ECC_CURVE_P_UNMARSHAL, END_OF_LIST, TPM2B_ECC_POINT_P_MARSHAL, UINT16_P_MARSHAL, END_OF_LIST} }; #define _EC_EphemeralDataAddress (&_EC_EphemeralData) #else #define _EC_EphemeralDataAddress 0 #endif #if CC_VerifySignature #include "VerifySignature_fp.h" typedef TPM_RC (VerifySignature_Entry)( VerifySignature_In *in, VerifySignature_Out *out ); typedef const struct { VerifySignature_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[2]; BYTE types[6]; } VerifySignature_COMMAND_DESCRIPTOR_t; VerifySignature_COMMAND_DESCRIPTOR_t _VerifySignatureData = { /* entry */ &TPM2_VerifySignature, /* inSize */ (UINT16)(sizeof(VerifySignature_In)), /* outSize */ (UINT16)(sizeof(VerifySignature_Out)), /* offsetOfTypes */ offsetof(VerifySignature_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(VerifySignature_In, digest)), (UINT16)(offsetof(VerifySignature_In, signature))}, /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, TPM2B_DIGEST_P_UNMARSHAL, TPMT_SIGNATURE_P_UNMARSHAL, END_OF_LIST, TPMT_TK_VERIFIED_P_MARSHAL, END_OF_LIST} }; #define _VerifySignatureDataAddress (&_VerifySignatureData) #else #define _VerifySignatureDataAddress 0 #endif #if CC_Sign #include "Sign_fp.h" typedef TPM_RC (Sign_Entry)( Sign_In *in, Sign_Out *out ); typedef const struct { Sign_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[3]; BYTE types[7]; } Sign_COMMAND_DESCRIPTOR_t; Sign_COMMAND_DESCRIPTOR_t _SignData = { /* entry */ &TPM2_Sign, /* inSize */ (UINT16)(sizeof(Sign_In)), /* outSize */ (UINT16)(sizeof(Sign_Out)), /* offsetOfTypes */ offsetof(Sign_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(Sign_In, digest)), (UINT16)(offsetof(Sign_In, inScheme)), (UINT16)(offsetof(Sign_In, validation))}, /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, TPM2B_DIGEST_P_UNMARSHAL, TPMT_SIG_SCHEME_P_UNMARSHAL + ADD_FLAG, TPMT_TK_HASHCHECK_P_UNMARSHAL, END_OF_LIST, TPMT_SIGNATURE_P_MARSHAL, END_OF_LIST} }; #define _SignDataAddress (&_SignData) #else #define _SignDataAddress 0 #endif #if CC_SetCommandCodeAuditStatus #include "SetCommandCodeAuditStatus_fp.h" typedef TPM_RC (SetCommandCodeAuditStatus_Entry)( SetCommandCodeAuditStatus_In *in ); typedef const struct { SetCommandCodeAuditStatus_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[3]; BYTE types[6]; } SetCommandCodeAuditStatus_COMMAND_DESCRIPTOR_t; SetCommandCodeAuditStatus_COMMAND_DESCRIPTOR_t _SetCommandCodeAuditStatusData = { /* entry */ &TPM2_SetCommandCodeAuditStatus, /* inSize */ (UINT16)(sizeof(SetCommandCodeAuditStatus_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(SetCommandCodeAuditStatus_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(SetCommandCodeAuditStatus_In, auditAlg)), (UINT16)(offsetof(SetCommandCodeAuditStatus_In, setList)), (UINT16)(offsetof(SetCommandCodeAuditStatus_In, clearList))}, /* types */ {TPMI_RH_PROVISION_H_UNMARSHAL, TPMI_ALG_HASH_P_UNMARSHAL + ADD_FLAG, TPML_CC_P_UNMARSHAL, TPML_CC_P_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _SetCommandCodeAuditStatusDataAddress (&_SetCommandCodeAuditStatusData) #else #define _SetCommandCodeAuditStatusDataAddress 0 #endif #if CC_PCR_Extend #include "PCR_Extend_fp.h" typedef TPM_RC (PCR_Extend_Entry)( PCR_Extend_In *in ); typedef const struct { PCR_Extend_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[1]; BYTE types[4]; } PCR_Extend_COMMAND_DESCRIPTOR_t; PCR_Extend_COMMAND_DESCRIPTOR_t _PCR_ExtendData = { /* entry */ &TPM2_PCR_Extend, /* inSize */ (UINT16)(sizeof(PCR_Extend_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(PCR_Extend_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(PCR_Extend_In, digests))}, /* types */ {TPMI_DH_PCR_H_UNMARSHAL + ADD_FLAG, TPML_DIGEST_VALUES_P_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _PCR_ExtendDataAddress (&_PCR_ExtendData) #else #define _PCR_ExtendDataAddress 0 #endif #if CC_PCR_Event #include "PCR_Event_fp.h" typedef TPM_RC (PCR_Event_Entry)( PCR_Event_In *in, PCR_Event_Out *out ); typedef const struct { PCR_Event_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[1]; BYTE types[5]; } PCR_Event_COMMAND_DESCRIPTOR_t; PCR_Event_COMMAND_DESCRIPTOR_t _PCR_EventData = { /* entry */ &TPM2_PCR_Event, /* inSize */ (UINT16)(sizeof(PCR_Event_In)), /* outSize */ (UINT16)(sizeof(PCR_Event_Out)), /* offsetOfTypes */ offsetof(PCR_Event_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(PCR_Event_In, eventData))}, /* types */ {TPMI_DH_PCR_H_UNMARSHAL + ADD_FLAG, TPM2B_EVENT_P_UNMARSHAL, END_OF_LIST, TPML_DIGEST_VALUES_P_MARSHAL, END_OF_LIST} }; #define _PCR_EventDataAddress (&_PCR_EventData) #else #define _PCR_EventDataAddress 0 #endif #if CC_PCR_Read #include "PCR_Read_fp.h" typedef TPM_RC (PCR_Read_Entry)( PCR_Read_In *in, PCR_Read_Out *out ); typedef const struct { PCR_Read_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[2]; BYTE types[6]; } PCR_Read_COMMAND_DESCRIPTOR_t; PCR_Read_COMMAND_DESCRIPTOR_t _PCR_ReadData = { /* entry */ &TPM2_PCR_Read, /* inSize */ (UINT16)(sizeof(PCR_Read_In)), /* outSize */ (UINT16)(sizeof(PCR_Read_Out)), /* offsetOfTypes */ offsetof(PCR_Read_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(PCR_Read_Out, pcrSelectionOut)), (UINT16)(offsetof(PCR_Read_Out, pcrValues))}, /* types */ {TPML_PCR_SELECTION_P_UNMARSHAL, END_OF_LIST, UINT32_P_MARSHAL, TPML_PCR_SELECTION_P_MARSHAL, TPML_DIGEST_P_MARSHAL, END_OF_LIST} }; #define _PCR_ReadDataAddress (&_PCR_ReadData) #else #define _PCR_ReadDataAddress 0 #endif #if CC_PCR_Allocate #include "PCR_Allocate_fp.h" typedef TPM_RC (PCR_Allocate_Entry)( PCR_Allocate_In *in, PCR_Allocate_Out *out ); typedef const struct { PCR_Allocate_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[4]; BYTE types[8]; } PCR_Allocate_COMMAND_DESCRIPTOR_t; PCR_Allocate_COMMAND_DESCRIPTOR_t _PCR_AllocateData = { /* entry */ &TPM2_PCR_Allocate, /* inSize */ (UINT16)(sizeof(PCR_Allocate_In)), /* outSize */ (UINT16)(sizeof(PCR_Allocate_Out)), /* offsetOfTypes */ offsetof(PCR_Allocate_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(PCR_Allocate_In, pcrAllocation)), (UINT16)(offsetof(PCR_Allocate_Out, maxPCR)), (UINT16)(offsetof(PCR_Allocate_Out, sizeNeeded)), (UINT16)(offsetof(PCR_Allocate_Out, sizeAvailable))}, /* types */ {TPMI_RH_PLATFORM_H_UNMARSHAL, TPML_PCR_SELECTION_P_UNMARSHAL, END_OF_LIST, TPMI_YES_NO_P_MARSHAL, UINT32_P_MARSHAL, UINT32_P_MARSHAL, UINT32_P_MARSHAL, END_OF_LIST} }; #define _PCR_AllocateDataAddress (&_PCR_AllocateData) #else #define _PCR_AllocateDataAddress 0 #endif #if CC_PCR_SetAuthPolicy #include "PCR_SetAuthPolicy_fp.h" typedef TPM_RC (PCR_SetAuthPolicy_Entry)( PCR_SetAuthPolicy_In *in ); typedef const struct { PCR_SetAuthPolicy_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[3]; BYTE types[6]; } PCR_SetAuthPolicy_COMMAND_DESCRIPTOR_t; PCR_SetAuthPolicy_COMMAND_DESCRIPTOR_t _PCR_SetAuthPolicyData = { /* entry */ &TPM2_PCR_SetAuthPolicy, /* inSize */ (UINT16)(sizeof(PCR_SetAuthPolicy_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(PCR_SetAuthPolicy_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(PCR_SetAuthPolicy_In, authPolicy)), (UINT16)(offsetof(PCR_SetAuthPolicy_In, hashAlg)), (UINT16)(offsetof(PCR_SetAuthPolicy_In, pcrNum))}, /* types */ {TPMI_RH_PLATFORM_H_UNMARSHAL, TPM2B_DIGEST_P_UNMARSHAL, TPMI_ALG_HASH_P_UNMARSHAL + ADD_FLAG, TPMI_DH_PCR_P_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _PCR_SetAuthPolicyDataAddress (&_PCR_SetAuthPolicyData) #else #define _PCR_SetAuthPolicyDataAddress 0 #endif #if CC_PCR_SetAuthValue #include "PCR_SetAuthValue_fp.h" typedef TPM_RC (PCR_SetAuthValue_Entry)( PCR_SetAuthValue_In *in ); typedef const struct { PCR_SetAuthValue_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[1]; BYTE types[4]; } PCR_SetAuthValue_COMMAND_DESCRIPTOR_t; PCR_SetAuthValue_COMMAND_DESCRIPTOR_t _PCR_SetAuthValueData = { /* entry */ &TPM2_PCR_SetAuthValue, /* inSize */ (UINT16)(sizeof(PCR_SetAuthValue_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(PCR_SetAuthValue_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(PCR_SetAuthValue_In, auth))}, /* types */ {TPMI_DH_PCR_H_UNMARSHAL, TPM2B_DIGEST_P_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _PCR_SetAuthValueDataAddress (&_PCR_SetAuthValueData) #else #define _PCR_SetAuthValueDataAddress 0 #endif #if CC_PCR_Reset #include "PCR_Reset_fp.h" typedef TPM_RC (PCR_Reset_Entry)( PCR_Reset_In *in ); typedef const struct { PCR_Reset_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; BYTE types[3]; } PCR_Reset_COMMAND_DESCRIPTOR_t; PCR_Reset_COMMAND_DESCRIPTOR_t _PCR_ResetData = { /* entry */ &TPM2_PCR_Reset, /* inSize */ (UINT16)(sizeof(PCR_Reset_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(PCR_Reset_COMMAND_DESCRIPTOR_t, types), /* offsets */ // No parameter offsets /* types */ {TPMI_DH_PCR_H_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _PCR_ResetDataAddress (&_PCR_ResetData) #else #define _PCR_ResetDataAddress 0 #endif #if CC_PolicySigned #include "PolicySigned_fp.h" typedef TPM_RC (PolicySigned_Entry)( PolicySigned_In *in, PolicySigned_Out *out ); typedef const struct { PolicySigned_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[7]; BYTE types[11]; } PolicySigned_COMMAND_DESCRIPTOR_t; PolicySigned_COMMAND_DESCRIPTOR_t _PolicySignedData = { /* entry */ &TPM2_PolicySigned, /* inSize */ (UINT16)(sizeof(PolicySigned_In)), /* outSize */ (UINT16)(sizeof(PolicySigned_Out)), /* offsetOfTypes */ offsetof(PolicySigned_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(PolicySigned_In, policySession)), (UINT16)(offsetof(PolicySigned_In, nonceTPM)), (UINT16)(offsetof(PolicySigned_In, cpHashA)), (UINT16)(offsetof(PolicySigned_In, policyRef)), (UINT16)(offsetof(PolicySigned_In, expiration)), (UINT16)(offsetof(PolicySigned_In, auth)), (UINT16)(offsetof(PolicySigned_Out, policyTicket))}, /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, TPMI_SH_POLICY_H_UNMARSHAL, TPM2B_NONCE_P_UNMARSHAL, TPM2B_DIGEST_P_UNMARSHAL, TPM2B_NONCE_P_UNMARSHAL, INT32_P_UNMARSHAL, TPMT_SIGNATURE_P_UNMARSHAL, END_OF_LIST, TPM2B_TIMEOUT_P_MARSHAL, TPMT_TK_AUTH_P_MARSHAL, END_OF_LIST} }; #define _PolicySignedDataAddress (&_PolicySignedData) #else #define _PolicySignedDataAddress 0 #endif #if CC_PolicySecret #include "PolicySecret_fp.h" typedef TPM_RC (PolicySecret_Entry)( PolicySecret_In *in, PolicySecret_Out *out ); typedef const struct { PolicySecret_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[6]; BYTE types[10]; } PolicySecret_COMMAND_DESCRIPTOR_t; PolicySecret_COMMAND_DESCRIPTOR_t _PolicySecretData = { /* entry */ &TPM2_PolicySecret, /* inSize */ (UINT16)(sizeof(PolicySecret_In)), /* outSize */ (UINT16)(sizeof(PolicySecret_Out)), /* offsetOfTypes */ offsetof(PolicySecret_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(PolicySecret_In, policySession)), (UINT16)(offsetof(PolicySecret_In, nonceTPM)), (UINT16)(offsetof(PolicySecret_In, cpHashA)), (UINT16)(offsetof(PolicySecret_In, policyRef)), (UINT16)(offsetof(PolicySecret_In, expiration)), (UINT16)(offsetof(PolicySecret_Out, policyTicket))}, /* types */ {TPMI_DH_ENTITY_H_UNMARSHAL, TPMI_SH_POLICY_H_UNMARSHAL, TPM2B_NONCE_P_UNMARSHAL, TPM2B_DIGEST_P_UNMARSHAL, TPM2B_NONCE_P_UNMARSHAL, INT32_P_UNMARSHAL, END_OF_LIST, TPM2B_TIMEOUT_P_MARSHAL, TPMT_TK_AUTH_P_MARSHAL, END_OF_LIST} }; #define _PolicySecretDataAddress (&_PolicySecretData) #else #define _PolicySecretDataAddress 0 #endif #if CC_PolicyTicket #include "PolicyTicket_fp.h" typedef TPM_RC (PolicyTicket_Entry)( PolicyTicket_In *in ); typedef const struct { PolicyTicket_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[5]; BYTE types[8]; } PolicyTicket_COMMAND_DESCRIPTOR_t; PolicyTicket_COMMAND_DESCRIPTOR_t _PolicyTicketData = { /* entry */ &TPM2_PolicyTicket, /* inSize */ (UINT16)(sizeof(PolicyTicket_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(PolicyTicket_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(PolicyTicket_In, timeout)), (UINT16)(offsetof(PolicyTicket_In, cpHashA)), (UINT16)(offsetof(PolicyTicket_In, policyRef)), (UINT16)(offsetof(PolicyTicket_In, authName)), (UINT16)(offsetof(PolicyTicket_In, ticket))}, /* types */ {TPMI_SH_POLICY_H_UNMARSHAL, TPM2B_TIMEOUT_P_UNMARSHAL, TPM2B_DIGEST_P_UNMARSHAL, TPM2B_NONCE_P_UNMARSHAL, TPM2B_NAME_P_UNMARSHAL, TPMT_TK_AUTH_P_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _PolicyTicketDataAddress (&_PolicyTicketData) #else #define _PolicyTicketDataAddress 0 #endif #if CC_PolicyOR #include "PolicyOR_fp.h" typedef TPM_RC (PolicyOR_Entry)( PolicyOR_In *in ); typedef const struct { PolicyOR_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[1]; BYTE types[4]; } PolicyOR_COMMAND_DESCRIPTOR_t; PolicyOR_COMMAND_DESCRIPTOR_t _PolicyORData = { /* entry */ &TPM2_PolicyOR, /* inSize */ (UINT16)(sizeof(PolicyOR_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(PolicyOR_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(PolicyOR_In, pHashList))}, /* types */ {TPMI_SH_POLICY_H_UNMARSHAL, TPML_DIGEST_P_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _PolicyORDataAddress (&_PolicyORData) #else #define _PolicyORDataAddress 0 #endif #if CC_PolicyPCR #include "PolicyPCR_fp.h" typedef TPM_RC (PolicyPCR_Entry)( PolicyPCR_In *in ); typedef const struct { PolicyPCR_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[2]; BYTE types[5]; } PolicyPCR_COMMAND_DESCRIPTOR_t; PolicyPCR_COMMAND_DESCRIPTOR_t _PolicyPCRData = { /* entry */ &TPM2_PolicyPCR, /* inSize */ (UINT16)(sizeof(PolicyPCR_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(PolicyPCR_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(PolicyPCR_In, pcrDigest)), (UINT16)(offsetof(PolicyPCR_In, pcrs))}, /* types */ {TPMI_SH_POLICY_H_UNMARSHAL, TPM2B_DIGEST_P_UNMARSHAL, TPML_PCR_SELECTION_P_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _PolicyPCRDataAddress (&_PolicyPCRData) #else #define _PolicyPCRDataAddress 0 #endif #if CC_PolicyLocality #include "PolicyLocality_fp.h" typedef TPM_RC (PolicyLocality_Entry)( PolicyLocality_In *in ); typedef const struct { PolicyLocality_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[1]; BYTE types[4]; } PolicyLocality_COMMAND_DESCRIPTOR_t; PolicyLocality_COMMAND_DESCRIPTOR_t _PolicyLocalityData = { /* entry */ &TPM2_PolicyLocality, /* inSize */ (UINT16)(sizeof(PolicyLocality_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(PolicyLocality_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(PolicyLocality_In, locality))}, /* types */ {TPMI_SH_POLICY_H_UNMARSHAL, TPMA_LOCALITY_P_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _PolicyLocalityDataAddress (&_PolicyLocalityData) #else #define _PolicyLocalityDataAddress 0 #endif #if CC_PolicyNV #include "PolicyNV_fp.h" typedef TPM_RC (PolicyNV_Entry)( PolicyNV_In *in ); typedef const struct { PolicyNV_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[5]; BYTE types[8]; } PolicyNV_COMMAND_DESCRIPTOR_t; PolicyNV_COMMAND_DESCRIPTOR_t _PolicyNVData = { /* entry */ &TPM2_PolicyNV, /* inSize */ (UINT16)(sizeof(PolicyNV_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(PolicyNV_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(PolicyNV_In, nvIndex)), (UINT16)(offsetof(PolicyNV_In, policySession)), (UINT16)(offsetof(PolicyNV_In, operandB)), (UINT16)(offsetof(PolicyNV_In, offset)), (UINT16)(offsetof(PolicyNV_In, operation))}, /* types */ {TPMI_RH_NV_AUTH_H_UNMARSHAL, TPMI_RH_NV_INDEX_H_UNMARSHAL, TPMI_SH_POLICY_H_UNMARSHAL, TPM2B_OPERAND_P_UNMARSHAL, UINT16_P_UNMARSHAL, TPM_EO_P_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _PolicyNVDataAddress (&_PolicyNVData) #else #define _PolicyNVDataAddress 0 #endif #if CC_PolicyCounterTimer #include "PolicyCounterTimer_fp.h" typedef TPM_RC (PolicyCounterTimer_Entry)( PolicyCounterTimer_In *in ); typedef const struct { PolicyCounterTimer_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[3]; BYTE types[6]; } PolicyCounterTimer_COMMAND_DESCRIPTOR_t; PolicyCounterTimer_COMMAND_DESCRIPTOR_t _PolicyCounterTimerData = { /* entry */ &TPM2_PolicyCounterTimer, /* inSize */ (UINT16)(sizeof(PolicyCounterTimer_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(PolicyCounterTimer_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(PolicyCounterTimer_In, operandB)), (UINT16)(offsetof(PolicyCounterTimer_In, offset)), (UINT16)(offsetof(PolicyCounterTimer_In, operation))}, /* types */ {TPMI_SH_POLICY_H_UNMARSHAL, TPM2B_OPERAND_P_UNMARSHAL, UINT16_P_UNMARSHAL, TPM_EO_P_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _PolicyCounterTimerDataAddress (&_PolicyCounterTimerData) #else #define _PolicyCounterTimerDataAddress 0 #endif #if CC_PolicyCommandCode #include "PolicyCommandCode_fp.h" typedef TPM_RC (PolicyCommandCode_Entry)( PolicyCommandCode_In *in ); typedef const struct { PolicyCommandCode_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[1]; BYTE types[4]; } PolicyCommandCode_COMMAND_DESCRIPTOR_t; PolicyCommandCode_COMMAND_DESCRIPTOR_t _PolicyCommandCodeData = { /* entry */ &TPM2_PolicyCommandCode, /* inSize */ (UINT16)(sizeof(PolicyCommandCode_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(PolicyCommandCode_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(PolicyCommandCode_In, code))}, /* types */ {TPMI_SH_POLICY_H_UNMARSHAL, TPM_CC_P_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _PolicyCommandCodeDataAddress (&_PolicyCommandCodeData) #else #define _PolicyCommandCodeDataAddress 0 #endif #if CC_PolicyPhysicalPresence #include "PolicyPhysicalPresence_fp.h" typedef TPM_RC (PolicyPhysicalPresence_Entry)( PolicyPhysicalPresence_In *in ); typedef const struct { PolicyPhysicalPresence_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; BYTE types[3]; } PolicyPhysicalPresence_COMMAND_DESCRIPTOR_t; PolicyPhysicalPresence_COMMAND_DESCRIPTOR_t _PolicyPhysicalPresenceData = { /* entry */ &TPM2_PolicyPhysicalPresence, /* inSize */ (UINT16)(sizeof(PolicyPhysicalPresence_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(PolicyPhysicalPresence_COMMAND_DESCRIPTOR_t, types), /* offsets */ // No parameter offsets /* types */ {TPMI_SH_POLICY_H_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _PolicyPhysicalPresenceDataAddress (&_PolicyPhysicalPresenceData) #else #define _PolicyPhysicalPresenceDataAddress 0 #endif #if CC_PolicyCpHash #include "PolicyCpHash_fp.h" typedef TPM_RC (PolicyCpHash_Entry)( PolicyCpHash_In *in ); typedef const struct { PolicyCpHash_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[1]; BYTE types[4]; } PolicyCpHash_COMMAND_DESCRIPTOR_t; PolicyCpHash_COMMAND_DESCRIPTOR_t _PolicyCpHashData = { /* entry */ &TPM2_PolicyCpHash, /* inSize */ (UINT16)(sizeof(PolicyCpHash_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(PolicyCpHash_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(PolicyCpHash_In, cpHashA))}, /* types */ {TPMI_SH_POLICY_H_UNMARSHAL, TPM2B_DIGEST_P_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _PolicyCpHashDataAddress (&_PolicyCpHashData) #else #define _PolicyCpHashDataAddress 0 #endif #if CC_PolicyNameHash #include "PolicyNameHash_fp.h" typedef TPM_RC (PolicyNameHash_Entry)( PolicyNameHash_In *in ); typedef const struct { PolicyNameHash_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[1]; BYTE types[4]; } PolicyNameHash_COMMAND_DESCRIPTOR_t; PolicyNameHash_COMMAND_DESCRIPTOR_t _PolicyNameHashData = { /* entry */ &TPM2_PolicyNameHash, /* inSize */ (UINT16)(sizeof(PolicyNameHash_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(PolicyNameHash_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(PolicyNameHash_In, nameHash))}, /* types */ {TPMI_SH_POLICY_H_UNMARSHAL, TPM2B_DIGEST_P_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _PolicyNameHashDataAddress (&_PolicyNameHashData) #else #define _PolicyNameHashDataAddress 0 #endif #if CC_PolicyDuplicationSelect #include "PolicyDuplicationSelect_fp.h" typedef TPM_RC (PolicyDuplicationSelect_Entry)( PolicyDuplicationSelect_In *in ); typedef const struct { PolicyDuplicationSelect_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[3]; BYTE types[6]; } PolicyDuplicationSelect_COMMAND_DESCRIPTOR_t; PolicyDuplicationSelect_COMMAND_DESCRIPTOR_t _PolicyDuplicationSelectData = { /* entry */ &TPM2_PolicyDuplicationSelect, /* inSize */ (UINT16)(sizeof(PolicyDuplicationSelect_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(PolicyDuplicationSelect_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(PolicyDuplicationSelect_In, objectName)), (UINT16)(offsetof(PolicyDuplicationSelect_In, newParentName)), (UINT16)(offsetof(PolicyDuplicationSelect_In, includeObject))}, /* types */ {TPMI_SH_POLICY_H_UNMARSHAL, TPM2B_NAME_P_UNMARSHAL, TPM2B_NAME_P_UNMARSHAL, TPMI_YES_NO_P_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _PolicyDuplicationSelectDataAddress (&_PolicyDuplicationSelectData) #else #define _PolicyDuplicationSelectDataAddress 0 #endif #if CC_PolicyAuthorize #include "PolicyAuthorize_fp.h" typedef TPM_RC (PolicyAuthorize_Entry)( PolicyAuthorize_In *in ); typedef const struct { PolicyAuthorize_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[4]; BYTE types[7]; } PolicyAuthorize_COMMAND_DESCRIPTOR_t; PolicyAuthorize_COMMAND_DESCRIPTOR_t _PolicyAuthorizeData = { /* entry */ &TPM2_PolicyAuthorize, /* inSize */ (UINT16)(sizeof(PolicyAuthorize_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(PolicyAuthorize_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(PolicyAuthorize_In, approvedPolicy)), (UINT16)(offsetof(PolicyAuthorize_In, policyRef)), (UINT16)(offsetof(PolicyAuthorize_In, keySign)), (UINT16)(offsetof(PolicyAuthorize_In, checkTicket))}, /* types */ {TPMI_SH_POLICY_H_UNMARSHAL, TPM2B_DIGEST_P_UNMARSHAL, TPM2B_NONCE_P_UNMARSHAL, TPM2B_NAME_P_UNMARSHAL, TPMT_TK_VERIFIED_P_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _PolicyAuthorizeDataAddress (&_PolicyAuthorizeData) #else #define _PolicyAuthorizeDataAddress 0 #endif #if CC_PolicyAuthValue #include "PolicyAuthValue_fp.h" typedef TPM_RC (PolicyAuthValue_Entry)( PolicyAuthValue_In *in ); typedef const struct { PolicyAuthValue_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; BYTE types[3]; } PolicyAuthValue_COMMAND_DESCRIPTOR_t; PolicyAuthValue_COMMAND_DESCRIPTOR_t _PolicyAuthValueData = { /* entry */ &TPM2_PolicyAuthValue, /* inSize */ (UINT16)(sizeof(PolicyAuthValue_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(PolicyAuthValue_COMMAND_DESCRIPTOR_t, types), /* offsets */ // No parameter offsets /* types */ {TPMI_SH_POLICY_H_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _PolicyAuthValueDataAddress (&_PolicyAuthValueData) #else #define _PolicyAuthValueDataAddress 0 #endif #if CC_PolicyPassword #include "PolicyPassword_fp.h" typedef TPM_RC (PolicyPassword_Entry)( PolicyPassword_In *in ); typedef const struct { PolicyPassword_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; BYTE types[3]; } PolicyPassword_COMMAND_DESCRIPTOR_t; PolicyPassword_COMMAND_DESCRIPTOR_t _PolicyPasswordData = { /* entry */ &TPM2_PolicyPassword, /* inSize */ (UINT16)(sizeof(PolicyPassword_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(PolicyPassword_COMMAND_DESCRIPTOR_t, types), /* offsets */ // No parameter offsets /* types */ {TPMI_SH_POLICY_H_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _PolicyPasswordDataAddress (&_PolicyPasswordData) #else #define _PolicyPasswordDataAddress 0 #endif #if CC_PolicyGetDigest #include "PolicyGetDigest_fp.h" typedef TPM_RC (PolicyGetDigest_Entry)( PolicyGetDigest_In *in, PolicyGetDigest_Out *out ); typedef const struct { PolicyGetDigest_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; BYTE types[4]; } PolicyGetDigest_COMMAND_DESCRIPTOR_t; PolicyGetDigest_COMMAND_DESCRIPTOR_t _PolicyGetDigestData = { /* entry */ &TPM2_PolicyGetDigest, /* inSize */ (UINT16)(sizeof(PolicyGetDigest_In)), /* outSize */ (UINT16)(sizeof(PolicyGetDigest_Out)), /* offsetOfTypes */ offsetof(PolicyGetDigest_COMMAND_DESCRIPTOR_t, types), /* offsets */ // No parameter offsets /* types */ {TPMI_SH_POLICY_H_UNMARSHAL, END_OF_LIST, TPM2B_DIGEST_P_MARSHAL, END_OF_LIST} }; #define _PolicyGetDigestDataAddress (&_PolicyGetDigestData) #else #define _PolicyGetDigestDataAddress 0 #endif #if CC_PolicyNvWritten #include "PolicyNvWritten_fp.h" typedef TPM_RC (PolicyNvWritten_Entry)( PolicyNvWritten_In *in ); typedef const struct { PolicyNvWritten_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[1]; BYTE types[4]; } PolicyNvWritten_COMMAND_DESCRIPTOR_t; PolicyNvWritten_COMMAND_DESCRIPTOR_t _PolicyNvWrittenData = { /* entry */ &TPM2_PolicyNvWritten, /* inSize */ (UINT16)(sizeof(PolicyNvWritten_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(PolicyNvWritten_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(PolicyNvWritten_In, writtenSet))}, /* types */ {TPMI_SH_POLICY_H_UNMARSHAL, TPMI_YES_NO_P_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _PolicyNvWrittenDataAddress (&_PolicyNvWrittenData) #else #define _PolicyNvWrittenDataAddress 0 #endif #if CC_PolicyTemplate #include "PolicyTemplate_fp.h" typedef TPM_RC (PolicyTemplate_Entry)( PolicyTemplate_In *in ); typedef const struct { PolicyTemplate_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[1]; BYTE types[4]; } PolicyTemplate_COMMAND_DESCRIPTOR_t; PolicyTemplate_COMMAND_DESCRIPTOR_t _PolicyTemplateData = { /* entry */ &TPM2_PolicyTemplate, /* inSize */ (UINT16)(sizeof(PolicyTemplate_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(PolicyTemplate_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(PolicyTemplate_In, templateHash))}, /* types */ {TPMI_SH_POLICY_H_UNMARSHAL, TPM2B_DIGEST_P_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _PolicyTemplateDataAddress (&_PolicyTemplateData) #else #define _PolicyTemplateDataAddress 0 #endif #if CC_PolicyAuthorizeNV #include "PolicyAuthorizeNV_fp.h" typedef TPM_RC (PolicyAuthorizeNV_Entry)( PolicyAuthorizeNV_In *in ); typedef const struct { PolicyAuthorizeNV_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[2]; BYTE types[5]; } PolicyAuthorizeNV_COMMAND_DESCRIPTOR_t; PolicyAuthorizeNV_COMMAND_DESCRIPTOR_t _PolicyAuthorizeNVData = { /* entry */ &TPM2_PolicyAuthorizeNV, /* inSize */ (UINT16)(sizeof(PolicyAuthorizeNV_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(PolicyAuthorizeNV_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(PolicyAuthorizeNV_In, nvIndex)), (UINT16)(offsetof(PolicyAuthorizeNV_In, policySession))}, /* types */ {TPMI_RH_NV_AUTH_H_UNMARSHAL, TPMI_RH_NV_INDEX_H_UNMARSHAL, TPMI_SH_POLICY_H_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _PolicyAuthorizeNVDataAddress (&_PolicyAuthorizeNVData) #else #define _PolicyAuthorizeNVDataAddress 0 #endif #if CC_CreatePrimary #include "CreatePrimary_fp.h" typedef TPM_RC (CreatePrimary_Entry)( CreatePrimary_In *in, CreatePrimary_Out *out ); typedef const struct { CreatePrimary_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[9]; BYTE types[13]; } CreatePrimary_COMMAND_DESCRIPTOR_t; CreatePrimary_COMMAND_DESCRIPTOR_t _CreatePrimaryData = { /* entry */ &TPM2_CreatePrimary, /* inSize */ (UINT16)(sizeof(CreatePrimary_In)), /* outSize */ (UINT16)(sizeof(CreatePrimary_Out)), /* offsetOfTypes */ offsetof(CreatePrimary_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(CreatePrimary_In, inSensitive)), (UINT16)(offsetof(CreatePrimary_In, inPublic)), (UINT16)(offsetof(CreatePrimary_In, outsideInfo)), (UINT16)(offsetof(CreatePrimary_In, creationPCR)), (UINT16)(offsetof(CreatePrimary_Out, outPublic)), (UINT16)(offsetof(CreatePrimary_Out, creationData)), (UINT16)(offsetof(CreatePrimary_Out, creationHash)), (UINT16)(offsetof(CreatePrimary_Out, creationTicket)), (UINT16)(offsetof(CreatePrimary_Out, name))}, /* types */ {TPMI_RH_HIERARCHY_H_UNMARSHAL + ADD_FLAG, TPM2B_SENSITIVE_CREATE_P_UNMARSHAL, TPM2B_PUBLIC_P_UNMARSHAL, TPM2B_DATA_P_UNMARSHAL, TPML_PCR_SELECTION_P_UNMARSHAL, END_OF_LIST, TPM_HANDLE_H_MARSHAL, TPM2B_PUBLIC_P_MARSHAL, TPM2B_CREATION_DATA_P_MARSHAL, TPM2B_DIGEST_P_MARSHAL, TPMT_TK_CREATION_P_MARSHAL, TPM2B_NAME_P_MARSHAL, END_OF_LIST} }; #define _CreatePrimaryDataAddress (&_CreatePrimaryData) #else #define _CreatePrimaryDataAddress 0 #endif #if CC_HierarchyControl #include "HierarchyControl_fp.h" typedef TPM_RC (HierarchyControl_Entry)( HierarchyControl_In *in ); typedef const struct { HierarchyControl_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[2]; BYTE types[5]; } HierarchyControl_COMMAND_DESCRIPTOR_t; HierarchyControl_COMMAND_DESCRIPTOR_t _HierarchyControlData = { /* entry */ &TPM2_HierarchyControl, /* inSize */ (UINT16)(sizeof(HierarchyControl_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(HierarchyControl_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(HierarchyControl_In, enable)), (UINT16)(offsetof(HierarchyControl_In, state))}, /* types */ {TPMI_RH_HIERARCHY_H_UNMARSHAL, TPMI_RH_ENABLES_P_UNMARSHAL, TPMI_YES_NO_P_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _HierarchyControlDataAddress (&_HierarchyControlData) #else #define _HierarchyControlDataAddress 0 #endif #if CC_SetPrimaryPolicy #include "SetPrimaryPolicy_fp.h" typedef TPM_RC (SetPrimaryPolicy_Entry)( SetPrimaryPolicy_In *in ); typedef const struct { SetPrimaryPolicy_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[2]; BYTE types[5]; } SetPrimaryPolicy_COMMAND_DESCRIPTOR_t; SetPrimaryPolicy_COMMAND_DESCRIPTOR_t _SetPrimaryPolicyData = { /* entry */ &TPM2_SetPrimaryPolicy, /* inSize */ (UINT16)(sizeof(SetPrimaryPolicy_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(SetPrimaryPolicy_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(SetPrimaryPolicy_In, authPolicy)), (UINT16)(offsetof(SetPrimaryPolicy_In, hashAlg))}, /* types */ {TPMI_RH_HIERARCHY_POLICY_H_UNMARSHAL, TPM2B_DIGEST_P_UNMARSHAL, TPMI_ALG_HASH_P_UNMARSHAL + ADD_FLAG, END_OF_LIST, END_OF_LIST} }; #define _SetPrimaryPolicyDataAddress (&_SetPrimaryPolicyData) #else #define _SetPrimaryPolicyDataAddress 0 #endif #if CC_ChangePPS #include "ChangePPS_fp.h" typedef TPM_RC (ChangePPS_Entry)( ChangePPS_In *in ); typedef const struct { ChangePPS_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; BYTE types[3]; } ChangePPS_COMMAND_DESCRIPTOR_t; ChangePPS_COMMAND_DESCRIPTOR_t _ChangePPSData = { /* entry */ &TPM2_ChangePPS, /* inSize */ (UINT16)(sizeof(ChangePPS_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(ChangePPS_COMMAND_DESCRIPTOR_t, types), /* offsets */ // No parameter offsets /* types */ {TPMI_RH_PLATFORM_H_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _ChangePPSDataAddress (&_ChangePPSData) #else #define _ChangePPSDataAddress 0 #endif #if CC_ChangeEPS #include "ChangeEPS_fp.h" typedef TPM_RC (ChangeEPS_Entry)( ChangeEPS_In *in ); typedef const struct { ChangeEPS_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; BYTE types[3]; } ChangeEPS_COMMAND_DESCRIPTOR_t; ChangeEPS_COMMAND_DESCRIPTOR_t _ChangeEPSData = { /* entry */ &TPM2_ChangeEPS, /* inSize */ (UINT16)(sizeof(ChangeEPS_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(ChangeEPS_COMMAND_DESCRIPTOR_t, types), /* offsets */ // No parameter offsets /* types */ {TPMI_RH_PLATFORM_H_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _ChangeEPSDataAddress (&_ChangeEPSData) #else #define _ChangeEPSDataAddress 0 #endif #if CC_Clear #include "Clear_fp.h" typedef TPM_RC (Clear_Entry)( Clear_In *in ); typedef const struct { Clear_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; BYTE types[3]; } Clear_COMMAND_DESCRIPTOR_t; Clear_COMMAND_DESCRIPTOR_t _ClearData = { /* entry */ &TPM2_Clear, /* inSize */ (UINT16)(sizeof(Clear_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(Clear_COMMAND_DESCRIPTOR_t, types), /* offsets */ // No parameter offsets /* types */ {TPMI_RH_CLEAR_H_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _ClearDataAddress (&_ClearData) #else #define _ClearDataAddress 0 #endif #if CC_ClearControl #include "ClearControl_fp.h" typedef TPM_RC (ClearControl_Entry)( ClearControl_In *in ); typedef const struct { ClearControl_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[1]; BYTE types[4]; } ClearControl_COMMAND_DESCRIPTOR_t; ClearControl_COMMAND_DESCRIPTOR_t _ClearControlData = { /* entry */ &TPM2_ClearControl, /* inSize */ (UINT16)(sizeof(ClearControl_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(ClearControl_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(ClearControl_In, disable))}, /* types */ {TPMI_RH_CLEAR_H_UNMARSHAL, TPMI_YES_NO_P_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _ClearControlDataAddress (&_ClearControlData) #else #define _ClearControlDataAddress 0 #endif #if CC_HierarchyChangeAuth #include "HierarchyChangeAuth_fp.h" typedef TPM_RC (HierarchyChangeAuth_Entry)( HierarchyChangeAuth_In *in ); typedef const struct { HierarchyChangeAuth_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[1]; BYTE types[4]; } HierarchyChangeAuth_COMMAND_DESCRIPTOR_t; HierarchyChangeAuth_COMMAND_DESCRIPTOR_t _HierarchyChangeAuthData = { /* entry */ &TPM2_HierarchyChangeAuth, /* inSize */ (UINT16)(sizeof(HierarchyChangeAuth_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(HierarchyChangeAuth_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(HierarchyChangeAuth_In, newAuth))}, /* types */ {TPMI_RH_HIERARCHY_AUTH_H_UNMARSHAL, TPM2B_AUTH_P_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _HierarchyChangeAuthDataAddress (&_HierarchyChangeAuthData) #else #define _HierarchyChangeAuthDataAddress 0 #endif #if CC_DictionaryAttackLockReset #include "DictionaryAttackLockReset_fp.h" typedef TPM_RC (DictionaryAttackLockReset_Entry)( DictionaryAttackLockReset_In *in ); typedef const struct { DictionaryAttackLockReset_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; BYTE types[3]; } DictionaryAttackLockReset_COMMAND_DESCRIPTOR_t; DictionaryAttackLockReset_COMMAND_DESCRIPTOR_t _DictionaryAttackLockResetData = { /* entry */ &TPM2_DictionaryAttackLockReset, /* inSize */ (UINT16)(sizeof(DictionaryAttackLockReset_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(DictionaryAttackLockReset_COMMAND_DESCRIPTOR_t, types), /* offsets */ // No parameter offsets /* types */ {TPMI_RH_LOCKOUT_H_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _DictionaryAttackLockResetDataAddress (&_DictionaryAttackLockResetData) #else #define _DictionaryAttackLockResetDataAddress 0 #endif #if CC_DictionaryAttackParameters #include "DictionaryAttackParameters_fp.h" typedef TPM_RC (DictionaryAttackParameters_Entry)( DictionaryAttackParameters_In *in ); typedef const struct { DictionaryAttackParameters_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[3]; BYTE types[6]; } DictionaryAttackParameters_COMMAND_DESCRIPTOR_t; DictionaryAttackParameters_COMMAND_DESCRIPTOR_t _DictionaryAttackParametersData = { /* entry */ &TPM2_DictionaryAttackParameters, /* inSize */ (UINT16)(sizeof(DictionaryAttackParameters_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(DictionaryAttackParameters_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(DictionaryAttackParameters_In, newMaxTries)), (UINT16)(offsetof(DictionaryAttackParameters_In, newRecoveryTime)), (UINT16)(offsetof(DictionaryAttackParameters_In, lockoutRecovery))}, /* types */ {TPMI_RH_LOCKOUT_H_UNMARSHAL, UINT32_P_UNMARSHAL, UINT32_P_UNMARSHAL, UINT32_P_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _DictionaryAttackParametersDataAddress (&_DictionaryAttackParametersData) #else #define _DictionaryAttackParametersDataAddress 0 #endif #if CC_PP_Commands #include "PP_Commands_fp.h" typedef TPM_RC (PP_Commands_Entry)( PP_Commands_In *in ); typedef const struct { PP_Commands_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[2]; BYTE types[5]; } PP_Commands_COMMAND_DESCRIPTOR_t; PP_Commands_COMMAND_DESCRIPTOR_t _PP_CommandsData = { /* entry */ &TPM2_PP_Commands, /* inSize */ (UINT16)(sizeof(PP_Commands_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(PP_Commands_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(PP_Commands_In, setList)), (UINT16)(offsetof(PP_Commands_In, clearList))}, /* types */ {TPMI_RH_PLATFORM_H_UNMARSHAL, TPML_CC_P_UNMARSHAL, TPML_CC_P_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _PP_CommandsDataAddress (&_PP_CommandsData) #else #define _PP_CommandsDataAddress 0 #endif #if CC_SetAlgorithmSet #include "SetAlgorithmSet_fp.h" typedef TPM_RC (SetAlgorithmSet_Entry)( SetAlgorithmSet_In *in ); typedef const struct { SetAlgorithmSet_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[1]; BYTE types[4]; } SetAlgorithmSet_COMMAND_DESCRIPTOR_t; SetAlgorithmSet_COMMAND_DESCRIPTOR_t _SetAlgorithmSetData = { /* entry */ &TPM2_SetAlgorithmSet, /* inSize */ (UINT16)(sizeof(SetAlgorithmSet_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(SetAlgorithmSet_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(SetAlgorithmSet_In, algorithmSet))}, /* types */ {TPMI_RH_PLATFORM_H_UNMARSHAL, UINT32_P_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _SetAlgorithmSetDataAddress (&_SetAlgorithmSetData) #else #define _SetAlgorithmSetDataAddress 0 #endif #if CC_FieldUpgradeStart #include "FieldUpgradeStart_fp.h" typedef TPM_RC (FieldUpgradeStart_Entry)( FieldUpgradeStart_In *in ); typedef const struct { FieldUpgradeStart_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[3]; BYTE types[6]; } FieldUpgradeStart_COMMAND_DESCRIPTOR_t; FieldUpgradeStart_COMMAND_DESCRIPTOR_t _FieldUpgradeStartData = { /* entry */ &TPM2_FieldUpgradeStart, /* inSize */ (UINT16)(sizeof(FieldUpgradeStart_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(FieldUpgradeStart_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(FieldUpgradeStart_In, keyHandle)), (UINT16)(offsetof(FieldUpgradeStart_In, fuDigest)), (UINT16)(offsetof(FieldUpgradeStart_In, manifestSignature))}, /* types */ {TPMI_RH_PLATFORM_H_UNMARSHAL, TPMI_DH_OBJECT_H_UNMARSHAL, TPM2B_DIGEST_P_UNMARSHAL, TPMT_SIGNATURE_P_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _FieldUpgradeStartDataAddress (&_FieldUpgradeStartData) #else #define _FieldUpgradeStartDataAddress 0 #endif #if CC_FieldUpgradeData #include "FieldUpgradeData_fp.h" typedef TPM_RC (FieldUpgradeData_Entry)( FieldUpgradeData_In *in, FieldUpgradeData_Out *out ); typedef const struct { FieldUpgradeData_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[1]; BYTE types[5]; } FieldUpgradeData_COMMAND_DESCRIPTOR_t; FieldUpgradeData_COMMAND_DESCRIPTOR_t _FieldUpgradeDataData = { /* entry */ &TPM2_FieldUpgradeData, /* inSize */ (UINT16)(sizeof(FieldUpgradeData_In)), /* outSize */ (UINT16)(sizeof(FieldUpgradeData_Out)), /* offsetOfTypes */ offsetof(FieldUpgradeData_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(FieldUpgradeData_Out, firstDigest))}, /* types */ {TPM2B_MAX_BUFFER_P_UNMARSHAL, END_OF_LIST, TPMT_HA_P_MARSHAL, TPMT_HA_P_MARSHAL, END_OF_LIST} }; #define _FieldUpgradeDataDataAddress (&_FieldUpgradeDataData) #else #define _FieldUpgradeDataDataAddress 0 #endif #if CC_FirmwareRead #include "FirmwareRead_fp.h" typedef TPM_RC (FirmwareRead_Entry)( FirmwareRead_In *in, FirmwareRead_Out *out ); typedef const struct { FirmwareRead_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; BYTE types[4]; } FirmwareRead_COMMAND_DESCRIPTOR_t; FirmwareRead_COMMAND_DESCRIPTOR_t _FirmwareReadData = { /* entry */ &TPM2_FirmwareRead, /* inSize */ (UINT16)(sizeof(FirmwareRead_In)), /* outSize */ (UINT16)(sizeof(FirmwareRead_Out)), /* offsetOfTypes */ offsetof(FirmwareRead_COMMAND_DESCRIPTOR_t, types), /* offsets */ // No parameter offsets /* types */ {UINT32_P_UNMARSHAL, END_OF_LIST, TPM2B_MAX_BUFFER_P_MARSHAL, END_OF_LIST} }; #define _FirmwareReadDataAddress (&_FirmwareReadData) #else #define _FirmwareReadDataAddress 0 #endif #if CC_ContextSave #include "ContextSave_fp.h" typedef TPM_RC (ContextSave_Entry)( ContextSave_In *in, ContextSave_Out *out ); typedef const struct { ContextSave_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; BYTE types[4]; } ContextSave_COMMAND_DESCRIPTOR_t; ContextSave_COMMAND_DESCRIPTOR_t _ContextSaveData = { /* entry */ &TPM2_ContextSave, /* inSize */ (UINT16)(sizeof(ContextSave_In)), /* outSize */ (UINT16)(sizeof(ContextSave_Out)), /* offsetOfTypes */ offsetof(ContextSave_COMMAND_DESCRIPTOR_t, types), /* offsets */ // No parameter offsets /* types */ {TPMI_DH_CONTEXT_H_UNMARSHAL, END_OF_LIST, TPMS_CONTEXT_P_MARSHAL, END_OF_LIST} }; #define _ContextSaveDataAddress (&_ContextSaveData) #else #define _ContextSaveDataAddress 0 #endif #if CC_ContextLoad #include "ContextLoad_fp.h" typedef TPM_RC (ContextLoad_Entry)( ContextLoad_In *in, ContextLoad_Out *out ); typedef const struct { ContextLoad_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; BYTE types[4]; } ContextLoad_COMMAND_DESCRIPTOR_t; ContextLoad_COMMAND_DESCRIPTOR_t _ContextLoadData = { /* entry */ &TPM2_ContextLoad, /* inSize */ (UINT16)(sizeof(ContextLoad_In)), /* outSize */ (UINT16)(sizeof(ContextLoad_Out)), /* offsetOfTypes */ offsetof(ContextLoad_COMMAND_DESCRIPTOR_t, types), /* offsets */ // No parameter offsets /* types */ {TPMS_CONTEXT_P_UNMARSHAL, END_OF_LIST, TPMI_DH_CONTEXT_H_MARSHAL, END_OF_LIST} }; #define _ContextLoadDataAddress (&_ContextLoadData) #else #define _ContextLoadDataAddress 0 #endif #if CC_FlushContext #include "FlushContext_fp.h" typedef TPM_RC (FlushContext_Entry)( FlushContext_In *in ); typedef const struct { FlushContext_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; BYTE types[3]; } FlushContext_COMMAND_DESCRIPTOR_t; FlushContext_COMMAND_DESCRIPTOR_t _FlushContextData = { /* entry */ &TPM2_FlushContext, /* inSize */ (UINT16)(sizeof(FlushContext_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(FlushContext_COMMAND_DESCRIPTOR_t, types), /* offsets */ // No parameter offsets /* types */ {TPMI_DH_CONTEXT_P_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _FlushContextDataAddress (&_FlushContextData) #else #define _FlushContextDataAddress 0 #endif #if CC_EvictControl #include "EvictControl_fp.h" typedef TPM_RC (EvictControl_Entry)( EvictControl_In *in ); typedef const struct { EvictControl_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[2]; BYTE types[5]; } EvictControl_COMMAND_DESCRIPTOR_t; EvictControl_COMMAND_DESCRIPTOR_t _EvictControlData = { /* entry */ &TPM2_EvictControl, /* inSize */ (UINT16)(sizeof(EvictControl_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(EvictControl_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(EvictControl_In, objectHandle)), (UINT16)(offsetof(EvictControl_In, persistentHandle))}, /* types */ {TPMI_RH_PROVISION_H_UNMARSHAL, TPMI_DH_OBJECT_H_UNMARSHAL, TPMI_DH_PERSISTENT_P_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _EvictControlDataAddress (&_EvictControlData) #else #define _EvictControlDataAddress 0 #endif #if CC_ReadClock #include "ReadClock_fp.h" typedef TPM_RC (ReadClock_Entry)( ReadClock_Out *out ); typedef const struct { ReadClock_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; BYTE types[3]; } ReadClock_COMMAND_DESCRIPTOR_t; ReadClock_COMMAND_DESCRIPTOR_t _ReadClockData = { /* entry */ &TPM2_ReadClock, /* inSize */ 0, /* outSize */ (UINT16)(sizeof(ReadClock_Out)), /* offsetOfTypes */ offsetof(ReadClock_COMMAND_DESCRIPTOR_t, types), /* offsets */ // No parameter offsets /* types */ {END_OF_LIST, TPMS_TIME_INFO_P_MARSHAL, END_OF_LIST} }; #define _ReadClockDataAddress (&_ReadClockData) #else #define _ReadClockDataAddress 0 #endif #if CC_ClockSet #include "ClockSet_fp.h" typedef TPM_RC (ClockSet_Entry)( ClockSet_In *in ); typedef const struct { ClockSet_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[1]; BYTE types[4]; } ClockSet_COMMAND_DESCRIPTOR_t; ClockSet_COMMAND_DESCRIPTOR_t _ClockSetData = { /* entry */ &TPM2_ClockSet, /* inSize */ (UINT16)(sizeof(ClockSet_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(ClockSet_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(ClockSet_In, newTime))}, /* types */ {TPMI_RH_PROVISION_H_UNMARSHAL, UINT64_P_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _ClockSetDataAddress (&_ClockSetData) #else #define _ClockSetDataAddress 0 #endif #if CC_ClockRateAdjust #include "ClockRateAdjust_fp.h" typedef TPM_RC (ClockRateAdjust_Entry)( ClockRateAdjust_In *in ); typedef const struct { ClockRateAdjust_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[1]; BYTE types[4]; } ClockRateAdjust_COMMAND_DESCRIPTOR_t; ClockRateAdjust_COMMAND_DESCRIPTOR_t _ClockRateAdjustData = { /* entry */ &TPM2_ClockRateAdjust, /* inSize */ (UINT16)(sizeof(ClockRateAdjust_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(ClockRateAdjust_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(ClockRateAdjust_In, rateAdjust))}, /* types */ {TPMI_RH_PROVISION_H_UNMARSHAL, TPM_CLOCK_ADJUST_P_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _ClockRateAdjustDataAddress (&_ClockRateAdjustData) #else #define _ClockRateAdjustDataAddress 0 #endif #if CC_GetCapability #include "GetCapability_fp.h" typedef TPM_RC (GetCapability_Entry)( GetCapability_In *in, GetCapability_Out *out ); typedef const struct { GetCapability_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[3]; BYTE types[7]; } GetCapability_COMMAND_DESCRIPTOR_t; GetCapability_COMMAND_DESCRIPTOR_t _GetCapabilityData = { /* entry */ &TPM2_GetCapability, /* inSize */ (UINT16)(sizeof(GetCapability_In)), /* outSize */ (UINT16)(sizeof(GetCapability_Out)), /* offsetOfTypes */ offsetof(GetCapability_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(GetCapability_In, property)), (UINT16)(offsetof(GetCapability_In, propertyCount)), (UINT16)(offsetof(GetCapability_Out, capabilityData))}, /* types */ {TPM_CAP_P_UNMARSHAL, UINT32_P_UNMARSHAL, UINT32_P_UNMARSHAL, END_OF_LIST, TPMI_YES_NO_P_MARSHAL, TPMS_CAPABILITY_DATA_P_MARSHAL, END_OF_LIST} }; #define _GetCapabilityDataAddress (&_GetCapabilityData) #else #define _GetCapabilityDataAddress 0 #endif #if CC_TestParms #include "TestParms_fp.h" typedef TPM_RC (TestParms_Entry)( TestParms_In *in ); typedef const struct { TestParms_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; BYTE types[3]; } TestParms_COMMAND_DESCRIPTOR_t; TestParms_COMMAND_DESCRIPTOR_t _TestParmsData = { /* entry */ &TPM2_TestParms, /* inSize */ (UINT16)(sizeof(TestParms_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(TestParms_COMMAND_DESCRIPTOR_t, types), /* offsets */ // No parameter offsets /* types */ {TPMT_PUBLIC_PARMS_P_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _TestParmsDataAddress (&_TestParmsData) #else #define _TestParmsDataAddress 0 #endif #if CC_NV_DefineSpace #include "NV_DefineSpace_fp.h" typedef TPM_RC (NV_DefineSpace_Entry)( NV_DefineSpace_In *in ); typedef const struct { NV_DefineSpace_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[2]; BYTE types[5]; } NV_DefineSpace_COMMAND_DESCRIPTOR_t; NV_DefineSpace_COMMAND_DESCRIPTOR_t _NV_DefineSpaceData = { /* entry */ &TPM2_NV_DefineSpace, /* inSize */ (UINT16)(sizeof(NV_DefineSpace_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(NV_DefineSpace_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(NV_DefineSpace_In, auth)), (UINT16)(offsetof(NV_DefineSpace_In, publicInfo))}, /* types */ {TPMI_RH_PROVISION_H_UNMARSHAL, TPM2B_AUTH_P_UNMARSHAL, TPM2B_NV_PUBLIC_P_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _NV_DefineSpaceDataAddress (&_NV_DefineSpaceData) #else #define _NV_DefineSpaceDataAddress 0 #endif #if CC_NV_UndefineSpace #include "NV_UndefineSpace_fp.h" typedef TPM_RC (NV_UndefineSpace_Entry)( NV_UndefineSpace_In *in ); typedef const struct { NV_UndefineSpace_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[1]; BYTE types[4]; } NV_UndefineSpace_COMMAND_DESCRIPTOR_t; NV_UndefineSpace_COMMAND_DESCRIPTOR_t _NV_UndefineSpaceData = { /* entry */ &TPM2_NV_UndefineSpace, /* inSize */ (UINT16)(sizeof(NV_UndefineSpace_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(NV_UndefineSpace_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(NV_UndefineSpace_In, nvIndex))}, /* types */ {TPMI_RH_PROVISION_H_UNMARSHAL, TPMI_RH_NV_INDEX_H_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _NV_UndefineSpaceDataAddress (&_NV_UndefineSpaceData) #else #define _NV_UndefineSpaceDataAddress 0 #endif #if CC_NV_UndefineSpaceSpecial #include "NV_UndefineSpaceSpecial_fp.h" typedef TPM_RC (NV_UndefineSpaceSpecial_Entry)( NV_UndefineSpaceSpecial_In *in ); typedef const struct { NV_UndefineSpaceSpecial_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[1]; BYTE types[4]; } NV_UndefineSpaceSpecial_COMMAND_DESCRIPTOR_t; NV_UndefineSpaceSpecial_COMMAND_DESCRIPTOR_t _NV_UndefineSpaceSpecialData = { /* entry */ &TPM2_NV_UndefineSpaceSpecial, /* inSize */ (UINT16)(sizeof(NV_UndefineSpaceSpecial_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(NV_UndefineSpaceSpecial_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(NV_UndefineSpaceSpecial_In, platform))}, /* types */ {TPMI_RH_NV_INDEX_H_UNMARSHAL, TPMI_RH_PLATFORM_H_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _NV_UndefineSpaceSpecialDataAddress (&_NV_UndefineSpaceSpecialData) #else #define _NV_UndefineSpaceSpecialDataAddress 0 #endif #if CC_NV_ReadPublic #include "NV_ReadPublic_fp.h" typedef TPM_RC (NV_ReadPublic_Entry)( NV_ReadPublic_In *in, NV_ReadPublic_Out *out ); typedef const struct { NV_ReadPublic_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[1]; BYTE types[5]; } NV_ReadPublic_COMMAND_DESCRIPTOR_t; NV_ReadPublic_COMMAND_DESCRIPTOR_t _NV_ReadPublicData = { /* entry */ &TPM2_NV_ReadPublic, /* inSize */ (UINT16)(sizeof(NV_ReadPublic_In)), /* outSize */ (UINT16)(sizeof(NV_ReadPublic_Out)), /* offsetOfTypes */ offsetof(NV_ReadPublic_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(NV_ReadPublic_Out, nvName))}, /* types */ {TPMI_RH_NV_INDEX_H_UNMARSHAL, END_OF_LIST, TPM2B_NV_PUBLIC_P_MARSHAL, TPM2B_NAME_P_MARSHAL, END_OF_LIST} }; #define _NV_ReadPublicDataAddress (&_NV_ReadPublicData) #else #define _NV_ReadPublicDataAddress 0 #endif #if CC_NV_Write #include "NV_Write_fp.h" typedef TPM_RC (NV_Write_Entry)( NV_Write_In *in ); typedef const struct { NV_Write_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[3]; BYTE types[6]; } NV_Write_COMMAND_DESCRIPTOR_t; NV_Write_COMMAND_DESCRIPTOR_t _NV_WriteData = { /* entry */ &TPM2_NV_Write, /* inSize */ (UINT16)(sizeof(NV_Write_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(NV_Write_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(NV_Write_In, nvIndex)), (UINT16)(offsetof(NV_Write_In, data)), (UINT16)(offsetof(NV_Write_In, offset))}, /* types */ {TPMI_RH_NV_AUTH_H_UNMARSHAL, TPMI_RH_NV_INDEX_H_UNMARSHAL, TPM2B_MAX_NV_BUFFER_P_UNMARSHAL, UINT16_P_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _NV_WriteDataAddress (&_NV_WriteData) #else #define _NV_WriteDataAddress 0 #endif #if CC_NV_Increment #include "NV_Increment_fp.h" typedef TPM_RC (NV_Increment_Entry)( NV_Increment_In *in ); typedef const struct { NV_Increment_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[1]; BYTE types[4]; } NV_Increment_COMMAND_DESCRIPTOR_t; NV_Increment_COMMAND_DESCRIPTOR_t _NV_IncrementData = { /* entry */ &TPM2_NV_Increment, /* inSize */ (UINT16)(sizeof(NV_Increment_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(NV_Increment_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(NV_Increment_In, nvIndex))}, /* types */ {TPMI_RH_NV_AUTH_H_UNMARSHAL, TPMI_RH_NV_INDEX_H_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _NV_IncrementDataAddress (&_NV_IncrementData) #else #define _NV_IncrementDataAddress 0 #endif #if CC_NV_Extend #include "NV_Extend_fp.h" typedef TPM_RC (NV_Extend_Entry)( NV_Extend_In *in ); typedef const struct { NV_Extend_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[2]; BYTE types[5]; } NV_Extend_COMMAND_DESCRIPTOR_t; NV_Extend_COMMAND_DESCRIPTOR_t _NV_ExtendData = { /* entry */ &TPM2_NV_Extend, /* inSize */ (UINT16)(sizeof(NV_Extend_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(NV_Extend_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(NV_Extend_In, nvIndex)), (UINT16)(offsetof(NV_Extend_In, data))}, /* types */ {TPMI_RH_NV_AUTH_H_UNMARSHAL, TPMI_RH_NV_INDEX_H_UNMARSHAL, TPM2B_MAX_NV_BUFFER_P_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _NV_ExtendDataAddress (&_NV_ExtendData) #else #define _NV_ExtendDataAddress 0 #endif #if CC_NV_SetBits #include "NV_SetBits_fp.h" typedef TPM_RC (NV_SetBits_Entry)( NV_SetBits_In *in ); typedef const struct { NV_SetBits_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[2]; BYTE types[5]; } NV_SetBits_COMMAND_DESCRIPTOR_t; NV_SetBits_COMMAND_DESCRIPTOR_t _NV_SetBitsData = { /* entry */ &TPM2_NV_SetBits, /* inSize */ (UINT16)(sizeof(NV_SetBits_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(NV_SetBits_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(NV_SetBits_In, nvIndex)), (UINT16)(offsetof(NV_SetBits_In, bits))}, /* types */ {TPMI_RH_NV_AUTH_H_UNMARSHAL, TPMI_RH_NV_INDEX_H_UNMARSHAL, UINT64_P_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _NV_SetBitsDataAddress (&_NV_SetBitsData) #else #define _NV_SetBitsDataAddress 0 #endif #if CC_NV_WriteLock #include "NV_WriteLock_fp.h" typedef TPM_RC (NV_WriteLock_Entry)( NV_WriteLock_In *in ); typedef const struct { NV_WriteLock_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[1]; BYTE types[4]; } NV_WriteLock_COMMAND_DESCRIPTOR_t; NV_WriteLock_COMMAND_DESCRIPTOR_t _NV_WriteLockData = { /* entry */ &TPM2_NV_WriteLock, /* inSize */ (UINT16)(sizeof(NV_WriteLock_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(NV_WriteLock_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(NV_WriteLock_In, nvIndex))}, /* types */ {TPMI_RH_NV_AUTH_H_UNMARSHAL, TPMI_RH_NV_INDEX_H_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _NV_WriteLockDataAddress (&_NV_WriteLockData) #else #define _NV_WriteLockDataAddress 0 #endif #if CC_NV_GlobalWriteLock #include "NV_GlobalWriteLock_fp.h" typedef TPM_RC (NV_GlobalWriteLock_Entry)( NV_GlobalWriteLock_In *in ); typedef const struct { NV_GlobalWriteLock_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; BYTE types[3]; } NV_GlobalWriteLock_COMMAND_DESCRIPTOR_t; NV_GlobalWriteLock_COMMAND_DESCRIPTOR_t _NV_GlobalWriteLockData = { /* entry */ &TPM2_NV_GlobalWriteLock, /* inSize */ (UINT16)(sizeof(NV_GlobalWriteLock_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(NV_GlobalWriteLock_COMMAND_DESCRIPTOR_t, types), /* offsets */ // No parameter offsets /* types */ {TPMI_RH_PROVISION_H_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _NV_GlobalWriteLockDataAddress (&_NV_GlobalWriteLockData) #else #define _NV_GlobalWriteLockDataAddress 0 #endif #if CC_NV_Read #include "NV_Read_fp.h" typedef TPM_RC (NV_Read_Entry)( NV_Read_In *in, NV_Read_Out *out ); typedef const struct { NV_Read_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[3]; BYTE types[7]; } NV_Read_COMMAND_DESCRIPTOR_t; NV_Read_COMMAND_DESCRIPTOR_t _NV_ReadData = { /* entry */ &TPM2_NV_Read, /* inSize */ (UINT16)(sizeof(NV_Read_In)), /* outSize */ (UINT16)(sizeof(NV_Read_Out)), /* offsetOfTypes */ offsetof(NV_Read_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(NV_Read_In, nvIndex)), (UINT16)(offsetof(NV_Read_In, size)), (UINT16)(offsetof(NV_Read_In, offset))}, /* types */ {TPMI_RH_NV_AUTH_H_UNMARSHAL, TPMI_RH_NV_INDEX_H_UNMARSHAL, UINT16_P_UNMARSHAL, UINT16_P_UNMARSHAL, END_OF_LIST, TPM2B_MAX_NV_BUFFER_P_MARSHAL, END_OF_LIST} }; #define _NV_ReadDataAddress (&_NV_ReadData) #else #define _NV_ReadDataAddress 0 #endif #if CC_NV_ReadLock #include "NV_ReadLock_fp.h" typedef TPM_RC (NV_ReadLock_Entry)( NV_ReadLock_In *in ); typedef const struct { NV_ReadLock_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[1]; BYTE types[4]; } NV_ReadLock_COMMAND_DESCRIPTOR_t; NV_ReadLock_COMMAND_DESCRIPTOR_t _NV_ReadLockData = { /* entry */ &TPM2_NV_ReadLock, /* inSize */ (UINT16)(sizeof(NV_ReadLock_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(NV_ReadLock_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(NV_ReadLock_In, nvIndex))}, /* types */ {TPMI_RH_NV_AUTH_H_UNMARSHAL, TPMI_RH_NV_INDEX_H_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _NV_ReadLockDataAddress (&_NV_ReadLockData) #else #define _NV_ReadLockDataAddress 0 #endif #if CC_NV_ChangeAuth #include "NV_ChangeAuth_fp.h" typedef TPM_RC (NV_ChangeAuth_Entry)( NV_ChangeAuth_In *in ); typedef const struct { NV_ChangeAuth_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[1]; BYTE types[4]; } NV_ChangeAuth_COMMAND_DESCRIPTOR_t; NV_ChangeAuth_COMMAND_DESCRIPTOR_t _NV_ChangeAuthData = { /* entry */ &TPM2_NV_ChangeAuth, /* inSize */ (UINT16)(sizeof(NV_ChangeAuth_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(NV_ChangeAuth_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(NV_ChangeAuth_In, newAuth))}, /* types */ {TPMI_RH_NV_INDEX_H_UNMARSHAL, TPM2B_AUTH_P_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _NV_ChangeAuthDataAddress (&_NV_ChangeAuthData) #else #define _NV_ChangeAuthDataAddress 0 #endif #if CC_NV_Certify #include "NV_Certify_fp.h" typedef TPM_RC (NV_Certify_Entry)( NV_Certify_In *in, NV_Certify_Out *out ); typedef const struct { NV_Certify_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[7]; BYTE types[11]; } NV_Certify_COMMAND_DESCRIPTOR_t; NV_Certify_COMMAND_DESCRIPTOR_t _NV_CertifyData = { /* entry */ &TPM2_NV_Certify, /* inSize */ (UINT16)(sizeof(NV_Certify_In)), /* outSize */ (UINT16)(sizeof(NV_Certify_Out)), /* offsetOfTypes */ offsetof(NV_Certify_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(NV_Certify_In, authHandle)), (UINT16)(offsetof(NV_Certify_In, nvIndex)), (UINT16)(offsetof(NV_Certify_In, qualifyingData)), (UINT16)(offsetof(NV_Certify_In, inScheme)), (UINT16)(offsetof(NV_Certify_In, size)), (UINT16)(offsetof(NV_Certify_In, offset)), (UINT16)(offsetof(NV_Certify_Out, signature))}, /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL + ADD_FLAG, TPMI_RH_NV_AUTH_H_UNMARSHAL, TPMI_RH_NV_INDEX_H_UNMARSHAL, TPM2B_DATA_P_UNMARSHAL, TPMT_SIG_SCHEME_P_UNMARSHAL + ADD_FLAG, UINT16_P_UNMARSHAL, UINT16_P_UNMARSHAL, END_OF_LIST, TPM2B_ATTEST_P_MARSHAL, TPMT_SIGNATURE_P_MARSHAL, END_OF_LIST} }; #define _NV_CertifyDataAddress (&_NV_CertifyData) #else #define _NV_CertifyDataAddress 0 #endif #if CC_AC_GetCapability #include "AC_GetCapability_fp.h" typedef TPM_RC (AC_GetCapability_Entry)( AC_GetCapability_In *in, AC_GetCapability_Out *out ); typedef const struct { AC_GetCapability_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[3]; BYTE types[7]; } AC_GetCapability_COMMAND_DESCRIPTOR_t; AC_GetCapability_COMMAND_DESCRIPTOR_t _AC_GetCapabilityData = { /* entry */ &TPM2_AC_GetCapability, /* inSize */ (UINT16)(sizeof(AC_GetCapability_In)), /* outSize */ (UINT16)(sizeof(AC_GetCapability_Out)), /* offsetOfTypes */ offsetof(AC_GetCapability_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(AC_GetCapability_In, capability)), (UINT16)(offsetof(AC_GetCapability_In, count)), (UINT16)(offsetof(AC_GetCapability_Out, capabilitiesData))}, /* types */ {TPMI_RH_AC_H_UNMARSHAL, TPM_AT_P_UNMARSHAL, UINT32_P_UNMARSHAL, END_OF_LIST, TPMI_YES_NO_P_MARSHAL, TPML_AC_CAPABILITIES_P_MARSHAL, END_OF_LIST} }; #define _AC_GetCapabilityDataAddress (&_AC_GetCapabilityData) #else #define _AC_GetCapabilityDataAddress 0 #endif #if CC_AC_Send #include "AC_Send_fp.h" typedef TPM_RC (AC_Send_Entry)( AC_Send_In *in, AC_Send_Out *out ); typedef const struct { AC_Send_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[3]; BYTE types[7]; } AC_Send_COMMAND_DESCRIPTOR_t; AC_Send_COMMAND_DESCRIPTOR_t _AC_SendData = { /* entry */ &TPM2_AC_Send, /* inSize */ (UINT16)(sizeof(AC_Send_In)), /* outSize */ (UINT16)(sizeof(AC_Send_Out)), /* offsetOfTypes */ offsetof(AC_Send_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(AC_Send_In, authHandle)), (UINT16)(offsetof(AC_Send_In, ac)), (UINT16)(offsetof(AC_Send_In, acDataIn))}, /* types */ {TPMI_DH_OBJECT_H_UNMARSHAL, TPMI_RH_NV_AUTH_H_UNMARSHAL, TPMI_RH_AC_H_UNMARSHAL, TPM2B_MAX_BUFFER_P_UNMARSHAL, END_OF_LIST, TPMS_AC_OUTPUT_P_MARSHAL, END_OF_LIST} }; #define _AC_SendDataAddress (&_AC_SendData) #else #define _AC_SendDataAddress 0 #endif #if CC_Policy_AC_SendSelect #include "Policy_AC_SendSelect_fp.h" typedef TPM_RC (Policy_AC_SendSelect_Entry)( Policy_AC_SendSelect_In *in ); typedef const struct { Policy_AC_SendSelect_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[4]; BYTE types[7]; } Policy_AC_SendSelect_COMMAND_DESCRIPTOR_t; Policy_AC_SendSelect_COMMAND_DESCRIPTOR_t _Policy_AC_SendSelectData = { /* entry */ &TPM2_Policy_AC_SendSelect, /* inSize */ (UINT16)(sizeof(Policy_AC_SendSelect_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(Policy_AC_SendSelect_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(Policy_AC_SendSelect_In, objectName)), (UINT16)(offsetof(Policy_AC_SendSelect_In, authHandleName)), (UINT16)(offsetof(Policy_AC_SendSelect_In, acName)), (UINT16)(offsetof(Policy_AC_SendSelect_In, includeObject))}, /* types */ {TPMI_SH_POLICY_H_UNMARSHAL, TPM2B_NAME_P_UNMARSHAL, TPM2B_NAME_P_UNMARSHAL, TPM2B_NAME_P_UNMARSHAL, TPMI_YES_NO_P_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _Policy_AC_SendSelectDataAddress (&_Policy_AC_SendSelectData) #else #define _Policy_AC_SendSelectDataAddress 0 #endif #if CC_ACT_SetTimeout #include "ACT_SetTimeout_fp.h" typedef TPM_RC (ACT_SetTimeout_Entry)( ACT_SetTimeout_In *in ); typedef const struct { ACT_SetTimeout_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; UINT16 paramOffsets[1]; BYTE types[4]; } ACT_SetTimeout_COMMAND_DESCRIPTOR_t; ACT_SetTimeout_COMMAND_DESCRIPTOR_t _ACT_SetTimeoutData = { /* entry */ &TPM2_ACT_SetTimeout, /* inSize */ (UINT16)(sizeof(ACT_SetTimeout_In)), /* outSize */ 0, /* offsetOfTypes */ offsetof(ACT_SetTimeout_COMMAND_DESCRIPTOR_t, types), /* offsets */ {(UINT16)(offsetof(ACT_SetTimeout_In, startTimeout))}, /* types */ {TPMI_RH_ACT_H_UNMARSHAL, UINT32_P_UNMARSHAL, END_OF_LIST, END_OF_LIST} }; #define _ACT_SetTimeoutDataAddress (&_ACT_SetTimeoutData) #else #define _ACT_SetTimeoutDataAddress 0 #endif // CC_ACT_SetTimeout #if CC_Vendor_TCG_Test #include "Vendor_TCG_Test_fp.h" typedef TPM_RC (Vendor_TCG_Test_Entry)( Vendor_TCG_Test_In *in, Vendor_TCG_Test_Out *out ); typedef const struct { Vendor_TCG_Test_Entry *entry; UINT16 inSize; UINT16 outSize; UINT16 offsetOfTypes; BYTE types[4]; } Vendor_TCG_Test_COMMAND_DESCRIPTOR_t; Vendor_TCG_Test_COMMAND_DESCRIPTOR_t _Vendor_TCG_TestData = { /* entry */ &TPM2_Vendor_TCG_Test, /* inSize */ (UINT16)(sizeof(Vendor_TCG_Test_In)), /* outSize */ (UINT16)(sizeof(Vendor_TCG_Test_Out)), /* offsetOfTypes */ offsetof(Vendor_TCG_Test_COMMAND_DESCRIPTOR_t, types), /* offsets */ // No parameter offsets /* types */ {TPM2B_DATA_P_UNMARSHAL, END_OF_LIST, TPM2B_DATA_P_MARSHAL, END_OF_LIST} }; #define _Vendor_TCG_TestDataAddress (&_Vendor_TCG_TestData) #else #define _Vendor_TCG_TestDataAddress 0 #endif COMMAND_DESCRIPTOR_t *s_CommandDataArray[] = { #if (PAD_LIST || CC_NV_UndefineSpaceSpecial) (COMMAND_DESCRIPTOR_t *)_NV_UndefineSpaceSpecialDataAddress, #endif #if (PAD_LIST || CC_EvictControl) (COMMAND_DESCRIPTOR_t *)_EvictControlDataAddress, #endif #if (PAD_LIST || CC_HierarchyControl) (COMMAND_DESCRIPTOR_t *)_HierarchyControlDataAddress, #endif #if (PAD_LIST || CC_NV_UndefineSpace) (COMMAND_DESCRIPTOR_t *)_NV_UndefineSpaceDataAddress, #endif #if (PAD_LIST) (COMMAND_DESCRIPTOR_t *)0, #endif #if (PAD_LIST || CC_ChangeEPS) (COMMAND_DESCRIPTOR_t *)_ChangeEPSDataAddress, #endif #if (PAD_LIST || CC_ChangePPS) (COMMAND_DESCRIPTOR_t *)_ChangePPSDataAddress, #endif #if (PAD_LIST || CC_Clear) (COMMAND_DESCRIPTOR_t *)_ClearDataAddress, #endif #if (PAD_LIST || CC_ClearControl) (COMMAND_DESCRIPTOR_t *)_ClearControlDataAddress, #endif #if (PAD_LIST || CC_ClockSet) (COMMAND_DESCRIPTOR_t *)_ClockSetDataAddress, #endif #if (PAD_LIST || CC_HierarchyChangeAuth) (COMMAND_DESCRIPTOR_t *)_HierarchyChangeAuthDataAddress, #endif #if (PAD_LIST || CC_NV_DefineSpace) (COMMAND_DESCRIPTOR_t *)_NV_DefineSpaceDataAddress, #endif #if (PAD_LIST || CC_PCR_Allocate) (COMMAND_DESCRIPTOR_t *)_PCR_AllocateDataAddress, #endif #if (PAD_LIST || CC_PCR_SetAuthPolicy) (COMMAND_DESCRIPTOR_t *)_PCR_SetAuthPolicyDataAddress, #endif #if (PAD_LIST || CC_PP_Commands) (COMMAND_DESCRIPTOR_t *)_PP_CommandsDataAddress, #endif #if (PAD_LIST || CC_SetPrimaryPolicy) (COMMAND_DESCRIPTOR_t *)_SetPrimaryPolicyDataAddress, #endif #if (PAD_LIST || CC_FieldUpgradeStart) (COMMAND_DESCRIPTOR_t *)_FieldUpgradeStartDataAddress, #endif #if (PAD_LIST || CC_ClockRateAdjust) (COMMAND_DESCRIPTOR_t *)_ClockRateAdjustDataAddress, #endif #if (PAD_LIST || CC_CreatePrimary) (COMMAND_DESCRIPTOR_t *)_CreatePrimaryDataAddress, #endif #if (PAD_LIST || CC_NV_GlobalWriteLock) (COMMAND_DESCRIPTOR_t *)_NV_GlobalWriteLockDataAddress, #endif #if (PAD_LIST || CC_GetCommandAuditDigest) (COMMAND_DESCRIPTOR_t *)_GetCommandAuditDigestDataAddress, #endif #if (PAD_LIST || CC_NV_Increment) (COMMAND_DESCRIPTOR_t *)_NV_IncrementDataAddress, #endif #if (PAD_LIST || CC_NV_SetBits) (COMMAND_DESCRIPTOR_t *)_NV_SetBitsDataAddress, #endif #if (PAD_LIST || CC_NV_Extend) (COMMAND_DESCRIPTOR_t *)_NV_ExtendDataAddress, #endif #if (PAD_LIST || CC_NV_Write) (COMMAND_DESCRIPTOR_t *)_NV_WriteDataAddress, #endif #if (PAD_LIST || CC_NV_WriteLock) (COMMAND_DESCRIPTOR_t *)_NV_WriteLockDataAddress, #endif #if (PAD_LIST || CC_DictionaryAttackLockReset) (COMMAND_DESCRIPTOR_t *)_DictionaryAttackLockResetDataAddress, #endif #if (PAD_LIST || CC_DictionaryAttackParameters) (COMMAND_DESCRIPTOR_t *)_DictionaryAttackParametersDataAddress, #endif #if (PAD_LIST || CC_NV_ChangeAuth) (COMMAND_DESCRIPTOR_t *)_NV_ChangeAuthDataAddress, #endif #if (PAD_LIST || CC_PCR_Event) (COMMAND_DESCRIPTOR_t *)_PCR_EventDataAddress, #endif #if (PAD_LIST || CC_PCR_Reset) (COMMAND_DESCRIPTOR_t *)_PCR_ResetDataAddress, #endif #if (PAD_LIST || CC_SequenceComplete) (COMMAND_DESCRIPTOR_t *)_SequenceCompleteDataAddress, #endif #if (PAD_LIST || CC_SetAlgorithmSet) (COMMAND_DESCRIPTOR_t *)_SetAlgorithmSetDataAddress, #endif #if (PAD_LIST || CC_SetCommandCodeAuditStatus) (COMMAND_DESCRIPTOR_t *)_SetCommandCodeAuditStatusDataAddress, #endif #if (PAD_LIST || CC_FieldUpgradeData) (COMMAND_DESCRIPTOR_t *)_FieldUpgradeDataDataAddress, #endif #if (PAD_LIST || CC_IncrementalSelfTest) (COMMAND_DESCRIPTOR_t *)_IncrementalSelfTestDataAddress, #endif #if (PAD_LIST || CC_SelfTest) (COMMAND_DESCRIPTOR_t *)_SelfTestDataAddress, #endif #if (PAD_LIST || CC_Startup) (COMMAND_DESCRIPTOR_t *)_StartupDataAddress, #endif #if (PAD_LIST || CC_Shutdown) (COMMAND_DESCRIPTOR_t *)_ShutdownDataAddress, #endif #if (PAD_LIST || CC_StirRandom) (COMMAND_DESCRIPTOR_t *)_StirRandomDataAddress, #endif #if (PAD_LIST || CC_ActivateCredential) (COMMAND_DESCRIPTOR_t *)_ActivateCredentialDataAddress, #endif #if (PAD_LIST || CC_Certify) (COMMAND_DESCRIPTOR_t *)_CertifyDataAddress, #endif #if (PAD_LIST || CC_PolicyNV) (COMMAND_DESCRIPTOR_t *)_PolicyNVDataAddress, #endif #if (PAD_LIST || CC_CertifyCreation) (COMMAND_DESCRIPTOR_t *)_CertifyCreationDataAddress, #endif #if (PAD_LIST || CC_Duplicate) (COMMAND_DESCRIPTOR_t *)_DuplicateDataAddress, #endif #if (PAD_LIST || CC_GetTime) (COMMAND_DESCRIPTOR_t *)_GetTimeDataAddress, #endif #if (PAD_LIST || CC_GetSessionAuditDigest) (COMMAND_DESCRIPTOR_t *)_GetSessionAuditDigestDataAddress, #endif #if (PAD_LIST || CC_NV_Read) (COMMAND_DESCRIPTOR_t *)_NV_ReadDataAddress, #endif #if (PAD_LIST || CC_NV_ReadLock) (COMMAND_DESCRIPTOR_t *)_NV_ReadLockDataAddress, #endif #if (PAD_LIST || CC_ObjectChangeAuth) (COMMAND_DESCRIPTOR_t *)_ObjectChangeAuthDataAddress, #endif #if (PAD_LIST || CC_PolicySecret) (COMMAND_DESCRIPTOR_t *)_PolicySecretDataAddress, #endif #if (PAD_LIST || CC_Rewrap) (COMMAND_DESCRIPTOR_t *)_RewrapDataAddress, #endif #if (PAD_LIST || CC_Create) (COMMAND_DESCRIPTOR_t *)_CreateDataAddress, #endif #if (PAD_LIST || CC_ECDH_ZGen) (COMMAND_DESCRIPTOR_t *)_ECDH_ZGenDataAddress, #endif #if (PAD_LIST || (CC_HMAC || CC_MAC)) # if CC_HMAC (COMMAND_DESCRIPTOR_t *)_HMACDataAddress, # endif # if CC_MAC (COMMAND_DESCRIPTOR_t *)_MACDataAddress, # endif # if (CC_HMAC || CC_MAC) > 1 # error "More than one aliased command defined" # endif #endif // CC_HMAC CC_MAC #if (PAD_LIST || CC_Import) (COMMAND_DESCRIPTOR_t *)_ImportDataAddress, #endif #if (PAD_LIST || CC_Load) (COMMAND_DESCRIPTOR_t *)_LoadDataAddress, #endif #if (PAD_LIST || CC_Quote) (COMMAND_DESCRIPTOR_t *)_QuoteDataAddress, #endif #if (PAD_LIST || CC_RSA_Decrypt) (COMMAND_DESCRIPTOR_t *)_RSA_DecryptDataAddress, #endif #if (PAD_LIST) (COMMAND_DESCRIPTOR_t *)0, #endif #if (PAD_LIST || (CC_HMAC_Start || CC_MAC_Start)) # if CC_HMAC_Start (COMMAND_DESCRIPTOR_t *)_HMAC_StartDataAddress, # endif # if CC_MAC_Start (COMMAND_DESCRIPTOR_t *)_MAC_StartDataAddress, # endif # if (CC_HMAC_Start || CC_MAC_Start) > 1 # error "More than one aliased command defined" # endif #endif // CC_HMAC_Start CC_MAC_Start #if (PAD_LIST || CC_SequenceUpdate) (COMMAND_DESCRIPTOR_t *)_SequenceUpdateDataAddress, #endif #if (PAD_LIST || CC_Sign) (COMMAND_DESCRIPTOR_t *)_SignDataAddress, #endif #if (PAD_LIST || CC_Unseal) (COMMAND_DESCRIPTOR_t *)_UnsealDataAddress, #endif #if (PAD_LIST) (COMMAND_DESCRIPTOR_t *)0, #endif #if (PAD_LIST || CC_PolicySigned) (COMMAND_DESCRIPTOR_t *)_PolicySignedDataAddress, #endif #if (PAD_LIST || CC_ContextLoad) (COMMAND_DESCRIPTOR_t *)_ContextLoadDataAddress, #endif #if (PAD_LIST || CC_ContextSave) (COMMAND_DESCRIPTOR_t *)_ContextSaveDataAddress, #endif #if (PAD_LIST || CC_ECDH_KeyGen) (COMMAND_DESCRIPTOR_t *)_ECDH_KeyGenDataAddress, #endif #if (PAD_LIST || CC_EncryptDecrypt) (COMMAND_DESCRIPTOR_t *)_EncryptDecryptDataAddress, #endif #if (PAD_LIST || CC_FlushContext) (COMMAND_DESCRIPTOR_t *)_FlushContextDataAddress, #endif #if (PAD_LIST) (COMMAND_DESCRIPTOR_t *)0, #endif #if (PAD_LIST || CC_LoadExternal) (COMMAND_DESCRIPTOR_t *)_LoadExternalDataAddress, #endif #if (PAD_LIST || CC_MakeCredential) (COMMAND_DESCRIPTOR_t *)_MakeCredentialDataAddress, #endif #if (PAD_LIST || CC_NV_ReadPublic) (COMMAND_DESCRIPTOR_t *)_NV_ReadPublicDataAddress, #endif #if (PAD_LIST || CC_PolicyAuthorize) (COMMAND_DESCRIPTOR_t *)_PolicyAuthorizeDataAddress, #endif #if (PAD_LIST || CC_PolicyAuthValue) (COMMAND_DESCRIPTOR_t *)_PolicyAuthValueDataAddress, #endif #if (PAD_LIST || CC_PolicyCommandCode) (COMMAND_DESCRIPTOR_t *)_PolicyCommandCodeDataAddress, #endif #if (PAD_LIST || CC_PolicyCounterTimer) (COMMAND_DESCRIPTOR_t *)_PolicyCounterTimerDataAddress, #endif #if (PAD_LIST || CC_PolicyCpHash) (COMMAND_DESCRIPTOR_t *)_PolicyCpHashDataAddress, #endif #if (PAD_LIST || CC_PolicyLocality) (COMMAND_DESCRIPTOR_t *)_PolicyLocalityDataAddress, #endif #if (PAD_LIST || CC_PolicyNameHash) (COMMAND_DESCRIPTOR_t *)_PolicyNameHashDataAddress, #endif #if (PAD_LIST || CC_PolicyOR) (COMMAND_DESCRIPTOR_t *)_PolicyORDataAddress, #endif #if (PAD_LIST || CC_PolicyTicket) (COMMAND_DESCRIPTOR_t *)_PolicyTicketDataAddress, #endif #if (PAD_LIST || CC_ReadPublic) (COMMAND_DESCRIPTOR_t *)_ReadPublicDataAddress, #endif #if (PAD_LIST || CC_RSA_Encrypt) (COMMAND_DESCRIPTOR_t *)_RSA_EncryptDataAddress, #endif #if (PAD_LIST) (COMMAND_DESCRIPTOR_t *)0, #endif #if (PAD_LIST || CC_StartAuthSession) (COMMAND_DESCRIPTOR_t *)_StartAuthSessionDataAddress, #endif #if (PAD_LIST || CC_VerifySignature) (COMMAND_DESCRIPTOR_t *)_VerifySignatureDataAddress, #endif #if (PAD_LIST || CC_ECC_Parameters) (COMMAND_DESCRIPTOR_t *)_ECC_ParametersDataAddress, #endif #if (PAD_LIST || CC_FirmwareRead) (COMMAND_DESCRIPTOR_t *)_FirmwareReadDataAddress, #endif #if (PAD_LIST || CC_GetCapability) (COMMAND_DESCRIPTOR_t *)_GetCapabilityDataAddress, #endif #if (PAD_LIST || CC_GetRandom) (COMMAND_DESCRIPTOR_t *)_GetRandomDataAddress, #endif #if (PAD_LIST || CC_GetTestResult) (COMMAND_DESCRIPTOR_t *)_GetTestResultDataAddress, #endif #if (PAD_LIST || CC_Hash) (COMMAND_DESCRIPTOR_t *)_HashDataAddress, #endif #if (PAD_LIST || CC_PCR_Read) (COMMAND_DESCRIPTOR_t *)_PCR_ReadDataAddress, #endif #if (PAD_LIST || CC_PolicyPCR) (COMMAND_DESCRIPTOR_t *)_PolicyPCRDataAddress, #endif #if (PAD_LIST || CC_PolicyRestart) (COMMAND_DESCRIPTOR_t *)_PolicyRestartDataAddress, #endif #if (PAD_LIST || CC_ReadClock) (COMMAND_DESCRIPTOR_t *)_ReadClockDataAddress, #endif #if (PAD_LIST || CC_PCR_Extend) (COMMAND_DESCRIPTOR_t *)_PCR_ExtendDataAddress, #endif #if (PAD_LIST || CC_PCR_SetAuthValue) (COMMAND_DESCRIPTOR_t *)_PCR_SetAuthValueDataAddress, #endif #if (PAD_LIST || CC_NV_Certify) (COMMAND_DESCRIPTOR_t *)_NV_CertifyDataAddress, #endif #if (PAD_LIST || CC_EventSequenceComplete) (COMMAND_DESCRIPTOR_t *)_EventSequenceCompleteDataAddress, #endif #if (PAD_LIST || CC_HashSequenceStart) (COMMAND_DESCRIPTOR_t *)_HashSequenceStartDataAddress, #endif #if (PAD_LIST || CC_PolicyPhysicalPresence) (COMMAND_DESCRIPTOR_t *)_PolicyPhysicalPresenceDataAddress, #endif #if (PAD_LIST || CC_PolicyDuplicationSelect) (COMMAND_DESCRIPTOR_t *)_PolicyDuplicationSelectDataAddress, #endif #if (PAD_LIST || CC_PolicyGetDigest) (COMMAND_DESCRIPTOR_t *)_PolicyGetDigestDataAddress, #endif #if (PAD_LIST || CC_TestParms) (COMMAND_DESCRIPTOR_t *)_TestParmsDataAddress, #endif #if (PAD_LIST || CC_Commit) (COMMAND_DESCRIPTOR_t *)_CommitDataAddress, #endif #if (PAD_LIST || CC_PolicyPassword) (COMMAND_DESCRIPTOR_t *)_PolicyPasswordDataAddress, #endif #if (PAD_LIST || CC_ZGen_2Phase) (COMMAND_DESCRIPTOR_t *)_ZGen_2PhaseDataAddress, #endif #if (PAD_LIST || CC_EC_Ephemeral) (COMMAND_DESCRIPTOR_t *)_EC_EphemeralDataAddress, #endif #if (PAD_LIST || CC_PolicyNvWritten) (COMMAND_DESCRIPTOR_t *)_PolicyNvWrittenDataAddress, #endif #if (PAD_LIST || CC_PolicyTemplate) (COMMAND_DESCRIPTOR_t *)_PolicyTemplateDataAddress, #endif #if (PAD_LIST || CC_CreateLoaded) (COMMAND_DESCRIPTOR_t *)_CreateLoadedDataAddress, #endif #if (PAD_LIST || CC_PolicyAuthorizeNV) (COMMAND_DESCRIPTOR_t *)_PolicyAuthorizeNVDataAddress, #endif #if (PAD_LIST || CC_EncryptDecrypt2) (COMMAND_DESCRIPTOR_t *)_EncryptDecrypt2DataAddress, #endif #if (PAD_LIST || CC_AC_GetCapability) (COMMAND_DESCRIPTOR_t *)_AC_GetCapabilityDataAddress, #endif // CC_AC_GetCapability #if (PAD_LIST || CC_AC_Send) (COMMAND_DESCRIPTOR_t *)_AC_SendDataAddress, #endif // CC_AC_Send #if (PAD_LIST || CC_Policy_AC_SendSelect) (COMMAND_DESCRIPTOR_t *)_Policy_AC_SendSelectDataAddress, #endif // CC_Policy_AC_SendSelect #if (PAD_LIST || CC_CertifyX509) (COMMAND_DESCRIPTOR_t *)_CertifyX509DataAddress, #endif // CC_CertifyX509 #if (PAD_LIST || CC_ACT_SetTimeout) (COMMAND_DESCRIPTOR_t *)_ACT_SetTimeoutDataAddress, #endif // CC_ACT_SetTimeout #if (PAD_LIST || CC_ECC_Encrypt) (COMMAND_DESCRIPTOR_t *)_ECC_EncryptDataAddress, #endif // CC_ECC_Encrypt #if (PAD_LIST || CC_ECC_Decrypt) (COMMAND_DESCRIPTOR_t *)_ECC_DecryptDataAddress, #endif // CC_ECC_Decrypt #if (PAD_LIST || CC_Vendor_TCG_Test) (COMMAND_DESCRIPTOR_t *)_Vendor_TCG_TestDataAddress, #endif 0 }; #endif // _COMMAND_TABLE_DISPATCH_ libtpms-0.9.3/src/tpm2/CommandDispatcher.c000066400000000000000000000376501421143571500204150ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Command Dispatcher */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CommandDispatcher.c 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2021 */ /* */ /********************************************************************************/ /* 6.3 CommandDispatcher.c */ /* CommandDispatcher() performs the following operations: */ /* * unmarshals command parameters from the input buffer; */ /* NOTE Unlike other unmarshaling functions, parmBufferStart does not advance. parmBufferSize Is reduced. */ /* * invokes the function that performs the command actions; */ /* * marshals the returned handles, if any; and */ /* * marshals the returned parameters, if any, into the output buffer putting in the * parameterSize field if authorization sessions are present. */ /* NOTE 1 The output buffer is the return from the MemoryGetResponseBuffer() function. It includes the header, handles, response parameters, and authorization area. respParmSize is the response parameter size, and does not include the header, handles, or authorization area. */ /* NOTE 2 The reference implementation is permitted to do compare operations over a union as a byte array. Therefore, the command parameter in structure must be initialized (e.g., zeroed) before unmarshaling so that the compare operation is valid in cases where some bytes are unused. */ /* 6.3.1.1 Includes and Typedefs */ #include "Tpm.h" // #include "Marshal.h" kgold #if TABLE_DRIVEN_DISPATCH typedef TPM_RC(NoFlagFunction)(void *target, BYTE **buffer, INT32 *size); typedef TPM_RC(FlagFunction)(void *target, BYTE **buffer, INT32 *size, BOOL flag); typedef FlagFunction *UNMARSHAL_t; typedef INT16(MarshalFunction)(void *source, BYTE **buffer, INT32 *size); typedef MarshalFunction *MARSHAL_t; typedef TPM_RC(COMMAND_NO_ARGS)(void); typedef TPM_RC(COMMAND_IN_ARG)(void *in); typedef TPM_RC(COMMAND_OUT_ARG)(void *out); typedef TPM_RC(COMMAND_INOUT_ARG)(void *in, void *out); typedef union { COMMAND_NO_ARGS *noArgs; COMMAND_IN_ARG *inArg; COMMAND_OUT_ARG *outArg; COMMAND_INOUT_ARG *inOutArg; } COMMAND_t; typedef struct { COMMAND_t command; // Address of the command UINT16 inSize; // Maximum size of the input structure UINT16 outSize; // Maximum size of the output structure UINT16 typesOffset; // address of the types field UINT16 offsets[1]; } COMMAND_DESCRIPTOR_t; #if COMPRESSED_LISTS # define PAD_LIST 0 #else # define PAD_LIST 1 #endif #define _COMMAND_TABLE_DISPATCH_ #include "CommandDispatchData.h" #define TEST_COMMAND TPM_CC_Startup #define NEW_CC #else #include "Commands.h" #endif /* 6.3.1.2 Marshal/Unmarshal Functions */ /* 6.3.1.2.1 ParseHandleBuffer() */ /* This is the table-driven version of the handle buffer unmarshaling code */ TPM_RC ParseHandleBuffer( COMMAND *command ) { TPM_RC result; #if TABLE_DRIVEN_DISPATCH COMMAND_DESCRIPTOR_t *desc; BYTE *types; BYTE type; BYTE dType; // Make sure that nothing strange has happened pAssert(command->index < sizeof(s_CommandDataArray) / sizeof(COMMAND_DESCRIPTOR_t *)); // Get the address of the descriptor for this command desc = s_CommandDataArray[command->index]; pAssert(desc != NULL); // Get the associated list of unmarshaling data types. types = &((BYTE *)desc)[desc->typesOffset]; // if(s_ccAttr[commandIndex].commandIndex == TEST_COMMAND) // commandIndex = commandIndex; // No handles yet command->handleNum = 0; // Get the first type value for(type = *types++; // check each byte to make sure that we have not hit the start // of the parameters (dType = (type & 0x7F)) < PARAMETER_FIRST_TYPE; // get the next type type = *types++) { #if TABLE_DRIVEN_MARSHAL marshalIndex_t index; index = unmarshalArray[dType] | ((type & 0x80) ? NULL_FLAG : 0); result = Unmarshal(index, &(command->handles[command->handleNum]), &command->parameterBuffer, &command->parameterSize); #else // See if unmarshaling of this handle type requires a flag if(dType < HANDLE_FIRST_FLAG_TYPE) { // Look up the function to do the unmarshaling NoFlagFunction *f = (NoFlagFunction *)unmarshalArray[dType]; // call it result = f(&(command->handles[command->handleNum]), &command->parameterBuffer, &command->parameterSize); } else { // Look up the function FlagFunction *f = unmarshalArray[dType]; // Call it setting the flag to the appropriate value result = f(&(command->handles[command->handleNum]), &command->parameterBuffer, &command->parameterSize, (type & 0x80) != 0); } #endif // Got a handle // We do this first so that the match for the handle offset of the // response code works correctly. command->handleNum += 1; if(result != TPM_RC_SUCCESS) // if the unmarshaling failed, return the response code with the // handle indication set return result + TPM_RC_H + (command->handleNum * TPM_RC_1); } #else BYTE **handleBufferStart = &command->parameterBuffer; INT32 *bufferRemainingSize = &command->parameterSize; TPM_HANDLE *handles = &command->handles[0]; UINT32 *handleCount = &command->handleNum; *handleCount = 0; switch(command->code) { #include "HandleProcess.h" #undef handles default: FAIL(FATAL_ERROR_INTERNAL); break; } #endif return TPM_RC_SUCCESS; } /* 6.3.1.2.2 CommandDispatcher() */ /* Function to unmarshal the command parameters, call the selected action code, and marshal the response parameters. */ TPM_RC CommandDispatcher( COMMAND *command ) { #if !TABLE_DRIVEN_DISPATCH TPM_RC result; BYTE **paramBuffer = &command->parameterBuffer; INT32 *paramBufferSize = &command->parameterSize; BYTE **responseBuffer = &command->responseBuffer; INT32 *respParmSize = &command->parameterSize; INT32 rSize; TPM_HANDLE *handles = &command->handles[0]; command->handleNum = 0; /* The command-specific code knows how many handles there are. This is for cataloging the number of response handles */ MemoryIoBufferAllocationReset(); /* Initialize so that allocation will work properly */ switch(GetCommandCode(command->index)) { #include "CommandDispatcher.h" default: FAIL(FATAL_ERROR_INTERNAL); break; } Exit: MemoryIoBufferZero(); return result; #else COMMAND_DESCRIPTOR_t *desc; BYTE *types; BYTE type; UINT16 *offsets; UINT16 offset = 0; UINT32 maxInSize; BYTE *commandIn; INT32 maxOutSize; BYTE *commandOut; COMMAND_t cmd; TPM_HANDLE *handles; UINT32 hasInParameters = 0; BOOL hasOutParameters = FALSE; UINT32 pNum = 0; BYTE dType; // dispatch type TPM_RC result; // // Get the address of the descriptor for this command pAssert(command->index < sizeof(s_CommandDataArray) / sizeof(COMMAND_DESCRIPTOR_t *)); desc = s_CommandDataArray[command->index]; // Get the list of parameter types for this command pAssert(desc != NULL); types = &((BYTE *)desc)[desc->typesOffset]; // Get a pointer to the list of parameter offsets offsets = &desc->offsets[0]; // pointer to handles handles = command->handles; // Get the size required to hold all the unmarshaled parameters for this command maxInSize = desc->inSize; // and the size of the output parameter structure returned by this command maxOutSize = desc->outSize; MemoryIoBufferAllocationReset(); // Get a buffer for the input parameters commandIn = MemoryGetInBuffer(maxInSize); // And the output parameters commandOut = (BYTE *)MemoryGetOutBuffer((UINT32)maxOutSize); // Get the address of the action code dispatch cmd = desc->command; // Copy any handles into the input buffer for(type = *types++; (type & 0x7F) < PARAMETER_FIRST_TYPE; type = *types++) { // 'offset' was initialized to zero so the first unmarshaling will always // be to the start of the data structure *(TPM_HANDLE *)&(commandIn[offset]) = *handles++; // This check is used so that we don't have to add an additional offset // value to the offsets list to correspond to the stop value in the // command parameter list. if(*types != 0xFF) offset = *offsets++; // maxInSize -= sizeof(TPM_HANDLE); hasInParameters++; } // Exit loop with type containing the last value read from types // maxInSize has the amount of space remaining in the command action input // buffer. Make sure that we don't have more data to unmarshal than is going to // fit. // type contains the last value read from types so it is not necessary to // reload it, which is good because *types now points to the next value for(; (dType = (type & 0x7F)) <= PARAMETER_LAST_TYPE; type = *types++) { pNum++; #if TABLE_DRIVEN_MARSHAL { marshalIndex_t index = unmarshalArray[dType]; index |= (type & 0x80) ? NULL_FLAG : 0; result = Unmarshal(index, &commandIn[offset], &command->parameterBuffer, &command->parameterSize); } #else if(dType < PARAMETER_FIRST_FLAG_TYPE) { NoFlagFunction *f = (NoFlagFunction *)unmarshalArray[dType]; result = f(&commandIn[offset], &command->parameterBuffer, &command->parameterSize); } else { FlagFunction *f = unmarshalArray[dType]; result = f(&commandIn[offset], &command->parameterBuffer, &command->parameterSize, (type & 0x80) != 0); } #endif if(result != TPM_RC_SUCCESS) { result += TPM_RC_P + (TPM_RC_1 * pNum); goto Exit; } // This check is used so that we don't have to add an additional offset // value to the offsets list to correspond to the stop value in the // command parameter list. if(*types != 0xFF) offset = *offsets++; hasInParameters++; } // Should have used all the bytes in the input if(command->parameterSize != 0) { result = TPM_RC_SIZE; goto Exit; } // The command parameter unmarshaling stopped when it hit a value that was out // of range for unmarshaling values and left *types pointing to the first // marshaling type. If that type happens to be the STOP value, then there // are no response parameters. So, set the flag to indicate if there are // output parameters. hasOutParameters = *types != 0xFF; // There are four cases for calling, with and without input parameters and with // and without output parameters. if(hasInParameters > 0) { if(hasOutParameters) result = cmd.inOutArg(commandIn, commandOut); else result = cmd.inArg(commandIn); } else { if(hasOutParameters) result = cmd.outArg(commandOut); else result = cmd.noArgs(); } if(result != TPM_RC_SUCCESS) goto Exit; // Offset in the marshaled output structure offset = 0; // Process the return handles, if any command->handleNum = 0; // Could make this a loop to process output handles but there is only ever // one handle in the outputs (for now). type = *types++; if((dType = (type & 0x7F)) < RESPONSE_PARAMETER_FIRST_TYPE) { // The out->handle value was referenced as TPM_HANDLE in the // action code so it has to be properly aligned. command->handles[command->handleNum++] = *((TPM_HANDLE *)&(commandOut[offset])); maxOutSize -= sizeof(UINT32); type = *types++; offset = *offsets++; } // Use the size of the command action output buffer as the maximum for the // number of bytes that can get marshaled. Since the marshaling code has // no pointers to data, all of the data being returned has to be in the // command action output buffer. If we try to marshal more bytes than // could fit into the output buffer, we need to fail. for(;(dType = (type & 0x7F)) <= RESPONSE_PARAMETER_LAST_TYPE && !g_inFailureMode; type = *types++) { #if TABLE_DRIVEN_MARSHAL marshalIndex_t index = marshalArray[dType]; command->parameterSize += Marshal(index, &commandOut[offset], &command->responseBuffer, &maxOutSize); #else const MARSHAL_t f = marshalArray[dType]; command->parameterSize += f(&commandOut[offset], &command->responseBuffer, &maxOutSize); #endif offset = *offsets++; } result = (maxOutSize < 0) ? TPM_RC_FAILURE : TPM_RC_SUCCESS; Exit: MemoryIoBufferZero(); return result; #endif } libtpms-0.9.3/src/tpm2/CommandDispatcher_fp.h000066400000000000000000000070221421143571500210750ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CommandDispatcher_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 */ /* */ /********************************************************************************/ #ifndef COMMANDDISPATCHER_FP_H #define COMMANDDISPATCHER_FP_H TPM_RC CommandDispatcher( COMMAND *command ); TPM_RC ParseHandleBuffer( COMMAND *command ); #endif libtpms-0.9.3/src/tpm2/Commit_fp.h000066400000000000000000000077371421143571500167550ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Commit_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef COMMIT_FP_H #define COMMIT_FP_H typedef struct { TPMI_DH_OBJECT signHandle; TPM2B_ECC_POINT P1; TPM2B_SENSITIVE_DATA s2; TPM2B_ECC_PARAMETER y2; } Commit_In; #define RC_Commit_signHandle (TPM_RC_H + TPM_RC_1) #define RC_Commit_P1 (TPM_RC_P + TPM_RC_1) #define RC_Commit_s2 (TPM_RC_P + TPM_RC_2) #define RC_Commit_y2 (TPM_RC_P + TPM_RC_3) typedef struct { TPM2B_ECC_POINT K; TPM2B_ECC_POINT L; TPM2B_ECC_POINT E; UINT16 counter; } Commit_Out; TPM_RC TPM2_Commit( Commit_In *in, // IN: input parameter list Commit_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/CompilerDependencies.h000066400000000000000000000163631421143571500211140ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Compiler Dependencies */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CompilerDependencies.h 1453 2019-04-05 16:43:36Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ #ifndef COMPILERDEPEDENCIES_H #define COMPILERDEPEDENCIES_H /* kgold - Not in the original code. A user reported that it was required for a non-Visual Studio environment. */ #ifdef TPM_WINDOWS #include #include #endif /* 5.10 CompilerDependencies.h */ #ifdef GCC # undef _MSC_VER # undef WIN32 #endif #ifdef _MSC_VER // These definitions are for the Microsoft compiler Endian conversion for aligned structures # define REVERSE_ENDIAN_16(_Number) _byteswap_ushort(_Number) # define REVERSE_ENDIAN_32(_Number) _byteswap_ulong(_Number) # define REVERSE_ENDIAN_64(_Number) _byteswap_uint64(_Number) // Avoid compiler warning for in line of stdio (or not) // #define _NO_CRT_STDIO_INLINE // This macro is used to handle LIB_EXPORT of function and variable names in lieu of a .def // file. Visual Studio requires that functions be explicitly exported and imported. # define LIB_EXPORT __declspec(dllexport) // VS compatible version # define LIB_IMPORT __declspec(dllimport) // This is defined to indicate a function that does not return. Microsoft compilers do not // support the _Noretrun() function parameter. # define NORETURN __declspec(noreturn) # if _MSC_VER >= 1400 // SAL processing when needed # include # endif # ifdef _WIN64 # define _INTPTR 2 # else # define _INTPTR 1 # endif # define NOT_REFERENCED(x) (x) // Lower the compiler error warning for system include files. They tend not to be that clean and // there is no reason to sort through all the spurious errors that they generate when the normal // error level is set to /Wall # define _REDUCE_WARNING_LEVEL_(n) \ __pragma(warning(push, n)) // Restore the compiler warning level # define _NORMAL_WARNING_LEVEL_ \ __pragma(warning(pop)) # include #endif // _MSC_VER #ifndef _MSC_VER #ifndef WINAPI # define WINAPI #endif # define __pragma(x) /* libtpms added begin */ # if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR >= 2) # define REVERSE_ENDIAN_16(_Number) __builtin_bswap16(_Number) # define REVERSE_ENDIAN_32(_Number) __builtin_bswap32(_Number) # define REVERSE_ENDIAN_64(_Number) __builtin_bswap64(_Number) # else # if defined __linux__ || defined __CYGWIN__ # include # define REVERSE_ENDIAN_16(_Number) bswap_16(_Number) # define REVERSE_ENDIAN_32(_Number) bswap_32(_Number) # define REVERSE_ENDIAN_64(_Number) bswap_64(_Number) # elif defined __OpenBSD__ # include # define REVERSE_ENDIAN_16(_Number) swap16(_Number) # define REVERSE_ENDIAN_32(_Number) swap32(_Number) # define REVERSE_ENDIAN_64(_Number) swap64(_Number) # elif defined __APPLE__ # include # define REVERSE_ENDIAN_16(_Number) _OSSwapInt16(_Number) # define REVERSE_ENDIAN_32(_Number) _OSSwapInt32(_Number) # define REVERSE_ENDIAN_64(_Number) _OSSwapInt64(_Number) # elif defined __FreeBSD__ # include # define REVERSE_ENDIAN_16(_Number) bswap16(_Number) # define REVERSE_ENDIAN_32(_Number) bswap32(_Number) # define REVERSE_ENDIAN_64(_Number) bswap64(_Number) # else # error Unsupported OS # endif # endif /* libtpms added end */ #endif #if defined(__GNUC__) # define NORETURN __attribute__((noreturn)) # include #endif // Things that are not defined should be defined as NULL #ifndef NORETURN # define NORETURN #endif #ifndef LIB_EXPORT # define LIB_EXPORT #endif #ifndef LIB_IMPORT # define LIB_IMPORT #endif #ifndef _REDUCE_WARNING_LEVEL_ # define _REDUCE_WARNING_LEVEL_(n) #endif #ifndef _NORMAL_WARNING_LEVEL_ # define _NORMAL_WARNING_LEVEL_ #endif #ifndef NOT_REFERENCED # define NOT_REFERENCED(x) (x = x) #endif #ifdef _POSIX_ typedef int SOCKET; #endif // #ifdef TPM_POSIX // typedef int SOCKET; // #endif #endif // _COMPILER_DEPENDENCIES_H_ libtpms-0.9.3/src/tpm2/ContextCommands.c000066400000000000000000000474431421143571500201370ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Context Management */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: ContextCommands.c 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2021 */ /* */ /********************************************************************************/ #include "Tpm.h" #include "ContextSave_fp.h" #include "NVMarshal.h" // libtpms added #if CC_ContextSave // Conditional expansion of this file #include "Context_spt_fp.h" /* Error Returns Meaning */ /* TPM_RC_CONTEXT_GAP a contextID could not be assigned for a session context save */ /* TPM_RC_TOO_MANY_CONTEXTS no more contexts can be saved as the counter has maxed out */ TPM_RC TPM2_ContextSave( ContextSave_In *in, // IN: input parameter list ContextSave_Out *out // OUT: output parameter list ) { TPM_RC result = TPM_RC_SUCCESS; UINT16 fingerprintSize; // The size of fingerprint in context // blob. UINT64 contextID = 0; // session context ID TPM2B_SYM_KEY symKey; TPM2B_IV iv; TPM2B_DIGEST integrity; UINT16 integritySize; BYTE *buffer; // This command may cause the orderlyState to be cleared due to // the update of state reset data. If the state is orderly and // cannot be changed, exit early. RETURN_IF_ORDERLY; // Internal Data Update // This implementation does not do things in quite the same way as described in // Part 2 of the specification. In Part 2, it indicates that the // TPMS_CONTEXT_DATA contains two TPM2B values. That is not how this is // implemented. Rather, the size field of the TPM2B_CONTEXT_DATA is used to // determine the amount of data in the encrypted data. That part is not // independently sized. This makes the actual size 2 bytes smaller than // calculated using Part 2. Since this is opaque to the caller, it is not // necessary to fix. The actual size is returned by TPM2_GetCapabilties(). // Initialize output handle. At the end of command action, the output // handle of an object will be replaced, while the output handle // for a session will be the same as input out->context.savedHandle = in->saveHandle; // Get the size of fingerprint in context blob. The sequence value in // TPMS_CONTEXT structure is used as the fingerprint fingerprintSize = sizeof(out->context.sequence); // Compute the integrity size at the beginning of context blob integritySize = sizeof(integrity.t.size) + CryptHashGetDigestSize(CONTEXT_INTEGRITY_HASH_ALG); // Perform object or session specific context save switch(HandleGetType(in->saveHandle)) { case TPM_HT_TRANSIENT: { OBJECT *object = HandleToObject(in->saveHandle); ANY_OBJECT_BUFFER *outObject; unsigned char buffer[sizeof(OBJECT) * 2]; // libtpms changed begin BYTE *bufptr = &buffer[0]; INT32 size = sizeof(buffer); UINT16 written = ANY_OBJECT_Marshal(object, &bufptr, &size); UINT16 objectSize = written; // libtpms changed end outObject = (ANY_OBJECT_BUFFER *)(out->context.contextBlob.t.buffer + integritySize + fingerprintSize); // Set size of the context data. The contents of context blob is vendor // defined. In this implementation, the size is size of integrity // plus fingerprint plus the whole internal OBJECT structure out->context.contextBlob.t.size = integritySize + fingerprintSize + objectSize; // Make sure things fit pAssert(out->context.contextBlob.t.size <= sizeof(out->context.contextBlob.t.buffer)); // Copy the whole internal OBJECT structure to context blob MemoryCopy(outObject, buffer, written); // libtpms changed // Increment object context ID gr.objectContextID++; // If object context ID overflows, TPM should be put in failure mode if(gr.objectContextID == 0) FAIL(FATAL_ERROR_INTERNAL); // Fill in other return values for an object. out->context.sequence = gr.objectContextID; // For regular object, savedHandle is 0x80000000. For sequence object, // savedHandle is 0x80000001. For object with stClear, savedHandle // is 0x80000002 if(ObjectIsSequence(object)) { out->context.savedHandle = 0x80000001; /* ANY_OBJECT_Marshal already wrote it // libtpms changed begin SequenceDataExport((HASH_OBJECT *)object, (HASH_OBJECT_BUFFER *)outObject); */ // libtpms changed end } else out->context.savedHandle = (object->attributes.stClear == SET) ? 0x80000002 : 0x80000000; // Get object hierarchy out->context.hierarchy = ObjectGetHierarchy(object); break; } case TPM_HT_HMAC_SESSION: case TPM_HT_POLICY_SESSION: { SESSION *session = SessionGet(in->saveHandle); // Set size of the context data. The contents of context blob is vendor // defined. In this implementation, the size of context blob is the // size of a internal session structure plus the size of // fingerprint plus the size of integrity out->context.contextBlob.t.size = integritySize + fingerprintSize + sizeof(*session); // Make sure things fit pAssert(out->context.contextBlob.t.size < sizeof(out->context.contextBlob.t.buffer)); // Copy the whole internal SESSION structure to context blob. // Save space for fingerprint at the beginning of the buffer // This is done before anything else so that the actual context // can be reclaimed after this call pAssert(sizeof(*session) <= sizeof(out->context.contextBlob.t.buffer) - integritySize - fingerprintSize); MemoryCopy(out->context.contextBlob.t.buffer + integritySize + fingerprintSize, session, sizeof(*session)); // Fill in the other return parameters for a session // Get a context ID and set the session tracking values appropriately // TPM_RC_CONTEXT_GAP is a possible error. // SessionContextSave() will flush the in-memory context // so no additional errors may occur after this call. result = SessionContextSave(out->context.savedHandle, &contextID); if(result != TPM_RC_SUCCESS) return result; // sequence number is the current session contextID out->context.sequence = contextID; // use TPM_RH_NULL as hierarchy for session context out->context.hierarchy = TPM_RH_NULL; break; } default: // SaveContext may only take an object handle or a session handle. // All the other handle type should be filtered out at unmarshal FAIL(FATAL_ERROR_INTERNAL); break; } // Save fingerprint at the beginning of encrypted area of context blob. // Reserve the integrity space pAssert(sizeof(out->context.sequence) <= sizeof(out->context.contextBlob.t.buffer) - integritySize); MemoryCopy(out->context.contextBlob.t.buffer + integritySize, &out->context.sequence, sizeof(out->context.sequence)); // Compute context encryption key ComputeContextProtectionKey(&out->context, &symKey, &iv); // Encrypt context blob CryptSymmetricEncrypt(out->context.contextBlob.t.buffer + integritySize, CONTEXT_ENCRYPT_ALG, CONTEXT_ENCRYPT_KEY_BITS, symKey.t.buffer, &iv, TPM_ALG_CFB, out->context.contextBlob.t.size - integritySize, out->context.contextBlob.t.buffer + integritySize); // Compute integrity hash for the object // In this implementation, the same routine is used for both sessions // and objects. ComputeContextIntegrity(&out->context, &integrity); // add integrity at the beginning of context blob buffer = out->context.contextBlob.t.buffer; TPM2B_DIGEST_Marshal(&integrity, &buffer, NULL); // orderly state should be cleared because of the update of state reset and // state clear data g_clearOrderly = TRUE; return result; } #endif // CC_ContextSave #include "Tpm.h" #include "ContextLoad_fp.h" #if CC_ContextLoad // Conditional expansion of this file #include "Context_spt_fp.h" TPM_RC TPM2_ContextLoad( ContextLoad_In *in, // IN: input parameter list ContextLoad_Out *out // OUT: output parameter list ) { TPM_RC result; TPM2B_DIGEST integrityToCompare; TPM2B_DIGEST integrity; BYTE *buffer; // defined to save some typing INT32 size; // defined to save some typing TPM_HT handleType; TPM2B_SYM_KEY symKey; TPM2B_IV iv; // Input Validation // See discussion about the context format in TPM2_ContextSave Detailed Actions // IF this is a session context, make sure that the sequence number is // consistent with the version in the slot // Check context blob size handleType = HandleGetType(in->context.savedHandle); // Get integrity from context blob buffer = in->context.contextBlob.t.buffer; size = (INT32)in->context.contextBlob.t.size; result = TPM2B_DIGEST_Unmarshal(&integrity, &buffer, &size); if(result != TPM_RC_SUCCESS) return result; // the size of the integrity value has to match the size of digest produced // by the integrity hash if(integrity.t.size != CryptHashGetDigestSize(CONTEXT_INTEGRITY_HASH_ALG)) return TPM_RCS_SIZE + RC_ContextLoad_context; // Make sure that the context blob has enough space for the fingerprint. This // is elastic pants to go with the belt and suspenders we already have to make // sure that the context is complete and untampered. if((unsigned)size < sizeof(in->context.sequence)) return TPM_RCS_SIZE + RC_ContextLoad_context; // After unmarshaling the integrity value, 'buffer' is pointing at the first // byte of the integrity protected and encrypted buffer and 'size' is the number // of integrity protected and encrypted bytes. // Compute context integrity ComputeContextIntegrity(&in->context, &integrityToCompare); // Compare integrity if(!MemoryEqual2B(&integrity.b, &integrityToCompare.b)) return TPM_RCS_INTEGRITY + RC_ContextLoad_context; // Compute context encryption key ComputeContextProtectionKey(&in->context, &symKey, &iv); // Decrypt context data in place CryptSymmetricDecrypt(buffer, CONTEXT_ENCRYPT_ALG, CONTEXT_ENCRYPT_KEY_BITS, symKey.t.buffer, &iv, TPM_ALG_CFB, size, buffer); // See if the fingerprint value matches. If not, it is symptomatic of either // a broken TPM or that the TPM is under attack so go into failure mode. if(!MemoryEqual(buffer, &in->context.sequence, sizeof(in->context.sequence))) FAIL(FATAL_ERROR_INTERNAL); // step over fingerprint buffer += sizeof(in->context.sequence); // set the remaining size of the context size -= sizeof(in->context.sequence); // Perform object or session specific input check switch(handleType) { case TPM_HT_TRANSIENT: { OBJECT *outObject; if(size > (INT32)sizeof(OBJECT)) FAIL(FATAL_ERROR_INTERNAL); // Discard any changes to the handle that the TRM might have made in->context.savedHandle = TRANSIENT_FIRST; // If hierarchy is disabled, no object context can be loaded in this // hierarchy if(!HierarchyIsEnabled(in->context.hierarchy)) return TPM_RCS_HIERARCHY + RC_ContextLoad_context; // Restore object. If there is no empty space, indicate as much outObject = ObjectContextLoadLibtpms(buffer, size, // libtpms changed &out->loadedHandle); if(outObject == NULL) return TPM_RC_OBJECT_MEMORY; break; } case TPM_HT_POLICY_SESSION: case TPM_HT_HMAC_SESSION: { if(size != sizeof(SESSION)) FAIL(FATAL_ERROR_INTERNAL); // This command may cause the orderlyState to be cleared due to // the update of state reset data. If this is the case, check if NV is // available first RETURN_IF_ORDERLY; // Check if input handle points to a valid saved session and that the // sequence number makes sense if(!SequenceNumberForSavedContextIsValid(&in->context)) return TPM_RCS_HANDLE + RC_ContextLoad_context; // Restore session. A TPM_RC_SESSION_MEMORY, TPM_RC_CONTEXT_GAP error // may be returned at this point result = SessionContextLoad((SESSION_BUF *)buffer, &in->context.savedHandle); if(result != TPM_RC_SUCCESS) return result; out->loadedHandle = in->context.savedHandle; // orderly state should be cleared because of the update of state // reset and state clear data g_clearOrderly = TRUE; break; } default: // Context blob may only have an object handle or a session handle. // All the other handle type should be filtered out at unmarshal FAIL(FATAL_ERROR_INTERNAL); break; } return TPM_RC_SUCCESS; } #endif // CC_ContextLoad #include "Tpm.h" #include "FlushContext_fp.h" #if CC_FlushContext // Conditional expansion of this file TPM_RC TPM2_FlushContext( FlushContext_In *in // IN: input parameter list ) { // Internal Data Update // Call object or session specific routine to flush switch(HandleGetType(in->flushHandle)) { case TPM_HT_TRANSIENT: if(!IsObjectPresent(in->flushHandle)) return TPM_RCS_HANDLE + RC_FlushContext_flushHandle; // Flush object FlushObject(in->flushHandle); break; case TPM_HT_HMAC_SESSION: case TPM_HT_POLICY_SESSION: if(!SessionIsLoaded(in->flushHandle) && !SessionIsSaved(in->flushHandle) ) return TPM_RCS_HANDLE + RC_FlushContext_flushHandle; // If the session to be flushed is the exclusive audit session, then // indicate that there is no exclusive audit session any longer. if(in->flushHandle == g_exclusiveAuditSession) g_exclusiveAuditSession = TPM_RH_UNASSIGNED; // Flush session SessionFlush(in->flushHandle); break; default: // This command only takes object or session handle. Other handles // should be filtered out at handle unmarshal FAIL(FATAL_ERROR_INTERNAL); break; } return TPM_RC_SUCCESS; } #endif // CC_FlushContext #include "Tpm.h" #include "EvictControl_fp.h" #if CC_EvictControl // Conditional expansion of this file TPM_RC TPM2_EvictControl( EvictControl_In *in // IN: input parameter list ) { TPM_RC result; OBJECT *evictObject; // Input Validation // Get internal object pointer evictObject = HandleToObject(in->objectHandle); // Temporary, stClear or public only objects can not be made persistent if(evictObject->attributes.temporary == SET || evictObject->attributes.stClear == SET || evictObject->attributes.publicOnly == SET) return TPM_RCS_ATTRIBUTES + RC_EvictControl_objectHandle; // If objectHandle refers to a persistent object, it should be the same as // input persistentHandle if(evictObject->attributes.evict == SET && evictObject->evictHandle != in->persistentHandle) return TPM_RCS_HANDLE + RC_EvictControl_objectHandle; // Additional authorization validation if(in->auth == TPM_RH_PLATFORM) { // To make persistent if(evictObject->attributes.evict == CLEAR) { // PlatformAuth can not set evict object in storage or endorsement // hierarchy if(evictObject->attributes.ppsHierarchy == CLEAR) return TPM_RCS_HIERARCHY + RC_EvictControl_objectHandle; // Platform cannot use a handle outside of platform persistent range. if(!NvIsPlatformPersistentHandle(in->persistentHandle)) return TPM_RCS_RANGE + RC_EvictControl_persistentHandle; } // PlatformAuth can delete any persistent object } else if(in->auth == TPM_RH_OWNER) { // OwnerAuth can not set or clear evict object in platform hierarchy if(evictObject->attributes.ppsHierarchy == SET) return TPM_RCS_HIERARCHY + RC_EvictControl_objectHandle; // Owner cannot use a handle outside of owner persistent range. if(evictObject->attributes.evict == CLEAR && !NvIsOwnerPersistentHandle(in->persistentHandle)) return TPM_RCS_RANGE + RC_EvictControl_persistentHandle; } else { // Other authorization is not allowed in this command and should have been // filtered out in unmarshal process FAIL(FATAL_ERROR_INTERNAL); } // Internal Data Update // Change evict state if(evictObject->attributes.evict == CLEAR) { // Make object persistent if(NvFindHandle(in->persistentHandle) != 0) return TPM_RC_NV_DEFINED; // A TPM_RC_NV_HANDLE or TPM_RC_NV_SPACE error may be returned at this // point result = NvAddEvictObject(in->persistentHandle, evictObject); } else { // Delete the persistent object in NV result = NvDeleteEvict(evictObject->evictHandle); } return result; } #endif // CC_EvictControl libtpms-0.9.3/src/tpm2/ContextLoad_fp.h000066400000000000000000000073501421143571500177400ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: ContextLoad_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef CONTEXTLOAD_FP_H #define CONTEXTLOAD_FP_H typedef struct { TPMS_CONTEXT context; } ContextLoad_In; #define RC_ContextLoad_context (TPM_RC_P + TPM_RC_1) typedef struct { TPMI_DH_CONTEXT loadedHandle; } ContextLoad_Out; TPM_RC TPM2_ContextLoad( ContextLoad_In *in, // IN: input parameter list ContextLoad_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/ContextSave_fp.h000066400000000000000000000073501421143571500177570ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: ContextSave_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef CONTEXTSAVE_FP_H #define CONTEXTSAVE_FP_H typedef struct { TPMI_DH_CONTEXT saveHandle; } ContextSave_In; #define RC_ContextSave_saveHandle (TPM_RC_P + TPM_RC_1) typedef struct { TPMS_CONTEXT context; } ContextSave_Out; TPM_RC TPM2_ContextSave( ContextSave_In *in, // IN: input parameter list ContextSave_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/Context_spt.c000066400000000000000000000235271421143571500173400ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Context Management Command Support */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Context_spt.c 1603 2020-04-03 17:48:43Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2020 */ /* */ /********************************************************************************/ /* 7.3.1 Includes */ #include "Tpm.h" #include "Context_spt_fp.h" /* 7.3.2 Functions */ /* 7.3.2.1 ComputeContextProtectionKey() */ /* This function retrieves the symmetric protection key for context encryption It is used by TPM2_ContextSave() and TPM2_ContextLoad() to create the symmetric encryption key and iv */ void ComputeContextProtectionKey( TPMS_CONTEXT *contextBlob, // IN: context blob TPM2B_SYM_KEY *symKey, // OUT: the symmetric key TPM2B_IV *iv // OUT: the IV. ) { UINT16 symKeyBits; // number of bits in the parent's // symmetric key TPM2B_PROOF *proof = NULL; // the proof value to use. Is null for // everything but a primary object in // the Endorsement Hierarchy BYTE kdfResult[sizeof(TPMU_HA) * 2];// Value produced by the KDF TPM2B_DATA sequence2B, handle2B; // Get proof value proof = HierarchyGetProof(contextBlob->hierarchy); // Get sequence value in 2B format sequence2B.t.size = sizeof(contextBlob->sequence); cAssert(sequence2B.t.size <= sizeof(sequence2B.t.buffer)); MemoryCopy(sequence2B.t.buffer, &contextBlob->sequence, sequence2B.t.size); // Get handle value in 2B format handle2B.t.size = sizeof(contextBlob->savedHandle); cAssert(handle2B.t.size <= sizeof(handle2B.t.buffer)); MemoryCopy(handle2B.t.buffer, &contextBlob->savedHandle, handle2B.t.size); // Get the symmetric encryption key size symKey->t.size = CONTEXT_ENCRYPT_KEY_BYTES; symKeyBits = CONTEXT_ENCRYPT_KEY_BITS; // Get the size of the IV for the algorithm iv->t.size = CryptGetSymmetricBlockSize(CONTEXT_ENCRYPT_ALG, symKeyBits); // KDFa to generate symmetric key and IV value CryptKDFa(CONTEXT_INTEGRITY_HASH_ALG, &proof->b, CONTEXT_KEY, &sequence2B.b, &handle2B.b, (symKey->t.size + iv->t.size) * 8, kdfResult, NULL, FALSE); // Copy part of the returned value as the key pAssert(symKey->t.size <= sizeof(symKey->t.buffer)); MemoryCopy(symKey->t.buffer, kdfResult, symKey->t.size); // Copy the rest as the IV pAssert(iv->t.size <= sizeof(iv->t.buffer)); MemoryCopy(iv->t.buffer, &kdfResult[symKey->t.size], iv->t.size); return; } /* 7.3.2.2 ComputeContextIntegrity() */ /* Generate the integrity hash for a context It is used by TPM2_ContextSave() to create an integrity hash and by TPM2_ContextLoad() to compare an integrity hash */ void ComputeContextIntegrity( TPMS_CONTEXT *contextBlob, // IN: context blob TPM2B_DIGEST *integrity // OUT: integrity ) { HMAC_STATE hmacState; TPM2B_PROOF *proof; UINT16 integritySize; // Get proof value proof = HierarchyGetProof(contextBlob->hierarchy); // Start HMAC integrity->t.size = CryptHmacStart2B(&hmacState, CONTEXT_INTEGRITY_HASH_ALG, &proof->b); // Compute integrity size at the beginning of context blob integritySize = sizeof(integrity->t.size) + integrity->t.size; // Adding total reset counter so that the context cannot be // used after a TPM Reset CryptDigestUpdateInt(&hmacState.hashState, sizeof(gp.totalResetCount), gp.totalResetCount); // If this is a ST_CLEAR object, add the clear count // so that this contest cannot be loaded after a TPM Restart if(contextBlob->savedHandle == 0x80000002) CryptDigestUpdateInt(&hmacState.hashState, sizeof(gr.clearCount), gr.clearCount); // Adding sequence number to the HMAC to make sure that it doesn't // get changed CryptDigestUpdateInt(&hmacState.hashState, sizeof(contextBlob->sequence), contextBlob->sequence); // Protect the handle CryptDigestUpdateInt(&hmacState.hashState, sizeof(contextBlob->savedHandle), contextBlob->savedHandle); // Adding sensitive contextData, skip the leading integrity area CryptDigestUpdate(&hmacState.hashState, contextBlob->contextBlob.t.size - integritySize, contextBlob->contextBlob.t.buffer + integritySize); // Complete HMAC CryptHmacEnd2B(&hmacState, &integrity->b); return; } #if 0 /* 7.3.2.3 SequenceDataExport() */ /* This function is used scan through the sequence object and either modify the hash state data for export (contextSave) or to import it into the internal format (contextLoad). This function should only be called after the sequence object has been copied to the context buffer (contextSave) or from the context buffer into the sequence object. The presumption is that the context buffer version of the data is the same size as the internal representation so nothing outsize of the hash context area gets modified. */ void SequenceDataExport( HASH_OBJECT *object, // IN: an internal hash object HASH_OBJECT_BUFFER *exportObject // OUT: a sequence context in a buffer ) { // If the hash object is not an event, then only one hash context is needed int count = (object->attributes.eventSeq) ? HASH_COUNT : 1; for(count--; count >= 0; count--) { HASH_STATE *hash = &object->state.hashState[count]; size_t offset = (BYTE *)hash - (BYTE *)object; BYTE *exportHash = &((BYTE *)exportObject)[offset]; CryptHashExportState(hash, (EXPORT_HASH_STATE *)exportHash); } } /* 7.3.2.4 SequenceDataImport() */ /* This function is used scan through the sequence object and either modify the hash state data for export (contextSave) or to import it into the internal format (contextLoad). This function should only be called after the sequence object has been copied to the context buffer (contextSave) or from the context buffer into the sequence object. The presumption is that the context buffer version of the data is the same size as the internal representation so nothing outsize of the hash context area gets modified. */ void SequenceDataImport( HASH_OBJECT *object, // IN/OUT: an internal hash object HASH_OBJECT_BUFFER *exportObject // IN/OUT: a sequence context in a buffer ) { // If the hash object is not an event, then only one hash context is needed int count = (object->attributes.eventSeq) ? HASH_COUNT : 1; for(count--; count >= 0; count--) { HASH_STATE *hash = &object->state.hashState[count]; size_t offset = (BYTE *)hash - (BYTE *)object; BYTE *importHash = &((BYTE *)exportObject)[offset]; // CryptHashImportState(hash, (EXPORT_HASH_STATE *)importHash); } } #endif libtpms-0.9.3/src/tpm2/Context_spt_fp.h000066400000000000000000000101261421143571500200210ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Context_spt_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 */ /* */ /********************************************************************************/ #ifndef CONTEXT_SPT_H #define CONTEXT_SPT_H void ComputeContextProtectionKey( TPMS_CONTEXT *contextBlob, // IN: context blob TPM2B_SYM_KEY *symKey, // OUT: the symmetric key TPM2B_IV *iv // OUT: the IV. ); void ComputeContextIntegrity( TPMS_CONTEXT *contextBlob, // IN: context blob TPM2B_DIGEST *integrity // OUT: integrity ); void SequenceDataExport( HASH_OBJECT *object, // IN: an internal hash object HASH_OBJECT_BUFFER *exportObject // OUT: a sequence context in a buffer ); void SequenceDataImport( HASH_OBJECT *object, // IN/OUT: an internal hash object HASH_OBJECT_BUFFER *exportObject // IN/OUT: a sequence context in a buffer ); #endif libtpms-0.9.3/src/tpm2/CreateLoaded_fp.h000066400000000000000000000100071421143571500200210ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CreateLoaded_fp.h 1600 2020-03-30 22:08:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ #ifndef CREATELOADED_FP_H #define CREATELOADED_FP_H /* rev 136 */ typedef struct { TPMI_DH_PARENT parentHandle; TPM2B_SENSITIVE_CREATE inSensitive; TPM2B_TEMPLATE inPublic; } CreateLoaded_In; #define RC_CreateLoaded_parentHandle (TPM_RC_H + TPM_RC_1) #define RC_CreateLoaded_inSensitive (TPM_RC_P + TPM_RC_1) #define RC_CreateLoaded_inPublic (TPM_RC_P + TPM_RC_2) typedef struct { TPM_HANDLE objectHandle; TPM2B_PRIVATE outPrivate; TPM2B_PUBLIC outPublic; TPM2B_NAME name; } CreateLoaded_Out; TPM_RC TPM2_CreateLoaded( CreateLoaded_In *in, // IN: input parameter list CreateLoaded_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/CreatePrimary_fp.h000066400000000000000000000104251421143571500202600ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CreatePrimary_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef CREATEPRIMARY_FP_H #define CREATEPRIMARY_FP_H typedef struct { TPMI_RH_HIERARCHY primaryHandle; TPM2B_SENSITIVE_CREATE inSensitive; TPM2B_PUBLIC inPublic; TPM2B_DATA outsideInfo; TPML_PCR_SELECTION creationPCR; } CreatePrimary_In; #define RC_CreatePrimary_primaryHandle (TPM_RC_H + TPM_RC_1) #define RC_CreatePrimary_inSensitive (TPM_RC_P + TPM_RC_1) #define RC_CreatePrimary_inPublic (TPM_RC_P + TPM_RC_2) #define RC_CreatePrimary_outsideInfo (TPM_RC_P + TPM_RC_3) #define RC_CreatePrimary_creationPCR (TPM_RC_P + TPM_RC_4) typedef struct { TPM_HANDLE objectHandle; TPM2B_PUBLIC outPublic; TPM2B_CREATION_DATA creationData; TPM2B_DIGEST creationHash; TPMT_TK_CREATION creationTicket; TPM2B_NAME name; } CreatePrimary_Out; TPM_RC TPM2_CreatePrimary( CreatePrimary_In *in, // IN: input parameter list CreatePrimary_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/Create_fp.h000066400000000000000000000102561421143571500167160ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Create_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 137 */ #ifndef CREATE_FP_H #define CREATE_FP_H typedef struct { TPMI_DH_OBJECT parentHandle; TPM2B_SENSITIVE_CREATE inSensitive; TPM2B_PUBLIC inPublic; TPM2B_DATA outsideInfo; TPML_PCR_SELECTION creationPCR; } Create_In; #define RC_Create_parentHandle (TPM_RC_H + TPM_RC_1) #define RC_Create_inSensitive (TPM_RC_P + TPM_RC_1) #define RC_Create_inPublic (TPM_RC_P + TPM_RC_2) #define RC_Create_outsideInfo (TPM_RC_P + TPM_RC_3) #define RC_Create_creationPCR (TPM_RC_P + TPM_RC_4) typedef struct { TPM2B_PRIVATE outPrivate; TPM2B_PUBLIC outPublic; TPM2B_CREATION_DATA creationData; TPM2B_DIGEST creationHash; TPMT_TK_CREATION creationTicket; } Create_Out; TPM_RC TPM2_Create( Create_In *in, // IN: input parameter list Create_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/CryptEccData.c000066400000000000000000000731571421143571500173400ustar00rootroot00000000000000/********************************************************************************/ /* */ /* ECC curve data */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CryptEccData.c 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2018 - 2021 */ /* */ /********************************************************************************/ /* 10.2.8 CryptEccData.c */ #include "Tpm.h" #include "OIDs.h" /* This file contains the ECC curve data. The format of the data depends on the setting of USE_BN_ECC_DATA. If it is defined, then the TPM's BigNum() format is used. Otherwise, it is kept in TPM2B format. The purpose of having the data in BigNum() format is so that it does not have to be reformatted before being used by the crypto library. */ #if ALG_ECC #if USE_BN_ECC_DATA # define TO_ECC_64 TO_CRYPT_WORD_64 # define TO_ECC_56(a, b, c, d, e, f, g) TO_ECC_64(0, a, b, c, d, e, f, g) # define TO_ECC_48(a, b, c, d, e, f) TO_ECC_64(0, 0, a, b, c, d, e, f) # define TO_ECC_40(a, b, c, d, e) TO_ECC_64(0, 0, 0, a, b, c, d, e) # if RADIX_BITS > 32 # define TO_ECC_32(a, b, c, d) TO_ECC_64(0, 0, 0, 0, a, b, c, d) # define TO_ECC_24(a, b, c) TO_ECC_64(0, 0, 0, 0, 0, a, b, c) # define TO_ECC_16(a, b) TO_ECC_64(0, 0, 0, 0, 0, 0, a, b) # define TO_ECC_8(a) TO_ECC_64(0, 0, 0, 0, 0, 0, 0, a) # else // RADIX_BITS == 32 # define TO_ECC_32 BIG_ENDIAN_BYTES_TO_UINT32 # define TO_ECC_24(a, b, c) TO_ECC_32(0, a, b, c) # define TO_ECC_16(a, b) TO_ECC_32(0, 0, a, b) # define TO_ECC_8(a) TO_ECC_32(0, 0, 0, a) # endif #else // TPM2B_ # define TO_ECC_64(a, b, c, d, e, f, g, h) a, b, c, d, e, f, g, h # define TO_ECC_56(a, b, c, d, e, f, g) a, b, c, d, e, f, g # define TO_ECC_48(a, b, c, d, e, f) a, b, c, d, e, f # define TO_ECC_40(a, b, c, d, e) a, b, c, d, e # define TO_ECC_32(a, b, c, d) a, b, c, d # define TO_ECC_24(a, b, c) a, b, c # define TO_ECC_16(a, b) a, b # define TO_ECC_8(a) a #endif #if USE_BN_ECC_DATA #define BN_MIN_ALLOC(bytes) \ (BYTES_TO_CRYPT_WORDS(bytes) == 0) ? 1 : BYTES_TO_CRYPT_WORDS(bytes) # define ECC_CONST(NAME, bytes, initializer) \ const struct { \ crypt_uword_t allocate, size, d[BN_MIN_ALLOC(bytes)]; \ } NAME = {BN_MIN_ALLOC(bytes), BYTES_TO_CRYPT_WORDS(bytes),{initializer}} ECC_CONST(ECC_ZERO, 0, 0); #else # define ECC_CONST(NAME, bytes, initializer) \ const TPM2B_##bytes##_BYTE_VALUE NAME = {bytes, {initializer}} /* Have to special case ECC_ZERO */ TPM2B_BYTE_VALUE(1); TPM2B_1_BYTE_VALUE ECC_ZERO = {1, {0}}; #endif ECC_CONST(ECC_ONE, 1, 1); #if !USE_BN_ECC_DATA TPM2B_BYTE_VALUE(24); #define TO_ECC_192(a, b, c) a, b, c TPM2B_BYTE_VALUE(28); #define TO_ECC_224(a, b, c, d) a, b, c, d TPM2B_BYTE_VALUE(32); #define TO_ECC_256(a, b, c, d) a, b, c, d TPM2B_BYTE_VALUE(48); #define TO_ECC_384(a, b, c, d, e, f) a, b, c, d, e, f TPM2B_BYTE_VALUE(66); #define TO_ECC_528(a, b, c, d, e, f, g, h, i) a, b, c, d, e, f, g, h, i TPM2B_BYTE_VALUE(80); #define TO_ECC_640(a, b, c, d, e, f, g, h, i, j) a, b, c, d, e, f, g, h, i, j #else #define TO_ECC_192(a, b, c) c, b, a #define TO_ECC_224(a, b, c, d) d, c, b, a #define TO_ECC_256(a, b, c, d) d, c, b, a #define TO_ECC_384(a, b, c, d, e, f) f, e, d, c, b, a #define TO_ECC_528(a, b, c, d, e, f, g, h, i) i, h, g, f, e, d, c, b, a #define TO_ECC_640(a, b, c, d, e, f, g, h, i, j) j, i, h, g, f, e, d, c, b, a #endif // !USE_BN_ECC_DATA #if ECC_NIST_P192 ECC_CONST(NIST_P192_p, 24, TO_ECC_192( TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF))); ECC_CONST(NIST_P192_a, 24, TO_ECC_192( TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC))); ECC_CONST(NIST_P192_b, 24, TO_ECC_192( TO_ECC_64(0x64, 0x21, 0x05, 0x19, 0xE5, 0x9C, 0x80, 0xE7), TO_ECC_64(0x0F, 0xA7, 0xE9, 0xAB, 0x72, 0x24, 0x30, 0x49), TO_ECC_64(0xFE, 0xB8, 0xDE, 0xEC, 0xC1, 0x46, 0xB9, 0xB1))); ECC_CONST(NIST_P192_gX, 24, TO_ECC_192( TO_ECC_64(0x18, 0x8D, 0xA8, 0x0E, 0xB0, 0x30, 0x90, 0xF6), TO_ECC_64(0x7C, 0xBF, 0x20, 0xEB, 0x43, 0xA1, 0x88, 0x00), TO_ECC_64(0xF4, 0xFF, 0x0A, 0xFD, 0x82, 0xFF, 0x10, 0x12))); ECC_CONST(NIST_P192_gY, 24, TO_ECC_192( TO_ECC_64(0x07, 0x19, 0x2B, 0x95, 0xFF, 0xC8, 0xDA, 0x78), TO_ECC_64(0x63, 0x10, 0x11, 0xED, 0x6B, 0x24, 0xCD, 0xD5), TO_ECC_64(0x73, 0xF9, 0x77, 0xA1, 0x1E, 0x79, 0x48, 0x11))); ECC_CONST(NIST_P192_n, 24, TO_ECC_192( TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x99, 0xDE, 0xF8, 0x36), TO_ECC_64(0x14, 0x6B, 0xC9, 0xB1, 0xB4, 0xD2, 0x28, 0x31))); #define NIST_P192_h ECC_ONE #define NIST_P192_gZ ECC_ONE #if USE_BN_ECC_DATA const ECC_CURVE_DATA NIST_P192 = { (bigNum)&NIST_P192_p, (bigNum)&NIST_P192_n, (bigNum)&NIST_P192_h, (bigNum)&NIST_P192_a, (bigNum)&NIST_P192_b, {(bigNum)&NIST_P192_gX, (bigNum)&NIST_P192_gY, (bigNum)&NIST_P192_gZ}}; #else const ECC_CURVE_DATA NIST_P192 = { &NIST_P192_p.b, &NIST_P192_n.b, &NIST_P192_h.b, &NIST_P192_a.b, &NIST_P192_b.b, {&NIST_P192_gX.b, &NIST_P192_gY.b, &NIST_P192_gZ.b}}; #endif // USE_BN_ECC_DATA #endif // ECC_NIST_P192 #if ECC_NIST_P224 ECC_CONST(NIST_P224_p, 28, TO_ECC_224( TO_ECC_32(0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00), TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01))); ECC_CONST(NIST_P224_a, 28, TO_ECC_224( TO_ECC_32(0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE))); ECC_CONST(NIST_P224_b, 28, TO_ECC_224( TO_ECC_32(0xB4, 0x05, 0x0A, 0x85), TO_ECC_64(0x0C, 0x04, 0xB3, 0xAB, 0xF5, 0x41, 0x32, 0x56), TO_ECC_64(0x50, 0x44, 0xB0, 0xB7, 0xD7, 0xBF, 0xD8, 0xBA), TO_ECC_64(0x27, 0x0B, 0x39, 0x43, 0x23, 0x55, 0xFF, 0xB4))); ECC_CONST(NIST_P224_gX, 28, TO_ECC_224( TO_ECC_32(0xB7, 0x0E, 0x0C, 0xBD), TO_ECC_64(0x6B, 0xB4, 0xBF, 0x7F, 0x32, 0x13, 0x90, 0xB9), TO_ECC_64(0x4A, 0x03, 0xC1, 0xD3, 0x56, 0xC2, 0x11, 0x22), TO_ECC_64(0x34, 0x32, 0x80, 0xD6, 0x11, 0x5C, 0x1D, 0x21))); ECC_CONST(NIST_P224_gY, 28, TO_ECC_224( TO_ECC_32(0xBD, 0x37, 0x63, 0x88), TO_ECC_64(0xB5, 0xF7, 0x23, 0xFB, 0x4C, 0x22, 0xDF, 0xE6), TO_ECC_64(0xCD, 0x43, 0x75, 0xA0, 0x5A, 0x07, 0x47, 0x64), TO_ECC_64(0x44, 0xD5, 0x81, 0x99, 0x85, 0x00, 0x7E, 0x34))); ECC_CONST(NIST_P224_n, 28, TO_ECC_224( TO_ECC_32(0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0xFF, 0xFF, 0x16, 0xA2, 0xE0, 0xB8, 0xF0, 0x3E), TO_ECC_64(0x13, 0xDD, 0x29, 0x45, 0x5C, 0x5C, 0x2A, 0x3D))); #define NIST_P224_h ECC_ONE #define NIST_P224_gZ ECC_ONE #if USE_BN_ECC_DATA const ECC_CURVE_DATA NIST_P224 = { (bigNum)&NIST_P224_p, (bigNum)&NIST_P224_n, (bigNum)&NIST_P224_h, (bigNum)&NIST_P224_a, (bigNum)&NIST_P224_b, {(bigNum)&NIST_P224_gX, (bigNum)&NIST_P224_gY, (bigNum)&NIST_P224_gZ}}; #else const ECC_CURVE_DATA NIST_P224 = { &NIST_P224_p.b, &NIST_P224_n.b, &NIST_P224_h.b, &NIST_P224_a.b, &NIST_P224_b.b, {&NIST_P224_gX.b, &NIST_P224_gY.b, &NIST_P224_gZ.b}}; #endif // USE_BN_ECC_DATA #endif // ECC_NIST_P224 #if ECC_NIST_P256 ECC_CONST(NIST_P256_p, 32, TO_ECC_256( TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01), TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF))); ECC_CONST(NIST_P256_a, 32, TO_ECC_256( TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01), TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC))); ECC_CONST(NIST_P256_b, 32, TO_ECC_256( TO_ECC_64(0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7), TO_ECC_64(0xB3, 0xEB, 0xBD, 0x55, 0x76, 0x98, 0x86, 0xBC), TO_ECC_64(0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6), TO_ECC_64(0x3B, 0xCE, 0x3C, 0x3E, 0x27, 0xD2, 0x60, 0x4B))); ECC_CONST(NIST_P256_gX, 32, TO_ECC_256( TO_ECC_64(0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47), TO_ECC_64(0xF8, 0xBC, 0xE6, 0xE5, 0x63, 0xA4, 0x40, 0xF2), TO_ECC_64(0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0), TO_ECC_64(0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96))); ECC_CONST(NIST_P256_gY, 32, TO_ECC_256( TO_ECC_64(0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, 0x9B), TO_ECC_64(0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E, 0x16), TO_ECC_64(0x2B, 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE), TO_ECC_64(0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, 0xF5))); ECC_CONST(NIST_P256_n, 32, TO_ECC_256( TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84), TO_ECC_64(0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51))); #define NIST_P256_h ECC_ONE #define NIST_P256_gZ ECC_ONE #if USE_BN_ECC_DATA const ECC_CURVE_DATA NIST_P256 = { (bigNum)&NIST_P256_p, (bigNum)&NIST_P256_n, (bigNum)&NIST_P256_h, (bigNum)&NIST_P256_a, (bigNum)&NIST_P256_b, {(bigNum)&NIST_P256_gX, (bigNum)&NIST_P256_gY, (bigNum)&NIST_P256_gZ}}; #else const ECC_CURVE_DATA NIST_P256 = { &NIST_P256_p.b, &NIST_P256_n.b, &NIST_P256_h.b, &NIST_P256_a.b, &NIST_P256_b.b, {&NIST_P256_gX.b, &NIST_P256_gY.b, &NIST_P256_gZ.b}}; #endif // USE_BN_ECC_DATA #endif // ECC_NIST_P256 #if ECC_NIST_P384 ECC_CONST(NIST_P384_p, 48, TO_ECC_384( TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00), TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF))); ECC_CONST(NIST_P384_a, 48, TO_ECC_384( TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00), TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFC))); ECC_CONST(NIST_P384_b, 48, TO_ECC_384( TO_ECC_64(0xB3, 0x31, 0x2F, 0xA7, 0xE2, 0x3E, 0xE7, 0xE4), TO_ECC_64(0x98, 0x8E, 0x05, 0x6B, 0xE3, 0xF8, 0x2D, 0x19), TO_ECC_64(0x18, 0x1D, 0x9C, 0x6E, 0xFE, 0x81, 0x41, 0x12), TO_ECC_64(0x03, 0x14, 0x08, 0x8F, 0x50, 0x13, 0x87, 0x5A), TO_ECC_64(0xC6, 0x56, 0x39, 0x8D, 0x8A, 0x2E, 0xD1, 0x9D), TO_ECC_64(0x2A, 0x85, 0xC8, 0xED, 0xD3, 0xEC, 0x2A, 0xEF))); ECC_CONST(NIST_P384_gX, 48, TO_ECC_384( TO_ECC_64(0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37), TO_ECC_64(0x8E, 0xB1, 0xC7, 0x1E, 0xF3, 0x20, 0xAD, 0x74), TO_ECC_64(0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98), TO_ECC_64(0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38), TO_ECC_64(0x55, 0x02, 0xF2, 0x5D, 0xBF, 0x55, 0x29, 0x6C), TO_ECC_64(0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7))); ECC_CONST(NIST_P384_gY, 48, TO_ECC_384( TO_ECC_64(0x36, 0x17, 0xDE, 0x4A, 0x96, 0x26, 0x2C, 0x6F), TO_ECC_64(0x5D, 0x9E, 0x98, 0xBF, 0x92, 0x92, 0xDC, 0x29), TO_ECC_64(0xF8, 0xF4, 0x1D, 0xBD, 0x28, 0x9A, 0x14, 0x7C), TO_ECC_64(0xE9, 0xDA, 0x31, 0x13, 0xB5, 0xF0, 0xB8, 0xC0), TO_ECC_64(0x0A, 0x60, 0xB1, 0xCE, 0x1D, 0x7E, 0x81, 0x9D), TO_ECC_64(0x7A, 0x43, 0x1D, 0x7C, 0x90, 0xEA, 0x0E, 0x5F))); ECC_CONST(NIST_P384_n, 48, TO_ECC_384( TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0xC7, 0x63, 0x4D, 0x81, 0xF4, 0x37, 0x2D, 0xDF), TO_ECC_64(0x58, 0x1A, 0x0D, 0xB2, 0x48, 0xB0, 0xA7, 0x7A), TO_ECC_64(0xEC, 0xEC, 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x73))); #define NIST_P384_h ECC_ONE #define NIST_P384_gZ ECC_ONE #if USE_BN_ECC_DATA const ECC_CURVE_DATA NIST_P384 = { (bigNum)&NIST_P384_p, (bigNum)&NIST_P384_n, (bigNum)&NIST_P384_h, (bigNum)&NIST_P384_a, (bigNum)&NIST_P384_b, {(bigNum)&NIST_P384_gX, (bigNum)&NIST_P384_gY, (bigNum)&NIST_P384_gZ}}; #else const ECC_CURVE_DATA NIST_P384 = { &NIST_P384_p.b, &NIST_P384_n.b, &NIST_P384_h.b, &NIST_P384_a.b, &NIST_P384_b.b, {&NIST_P384_gX.b, &NIST_P384_gY.b, &NIST_P384_gZ.b}}; #endif // USE_BN_ECC_DATA #endif // ECC_NIST_P384 #if ECC_NIST_P521 ECC_CONST(NIST_P521_p, 66, TO_ECC_528( TO_ECC_16(0x01, 0xFF), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF))); ECC_CONST(NIST_P521_a, 66, TO_ECC_528( TO_ECC_16(0x01, 0xFF), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC))); ECC_CONST(NIST_P521_b, 66, TO_ECC_528( TO_ECC_16(0x00, 0x51), TO_ECC_64(0x95, 0x3E, 0xB9, 0x61, 0x8E, 0x1C, 0x9A, 0x1F), TO_ECC_64(0x92, 0x9A, 0x21, 0xA0, 0xB6, 0x85, 0x40, 0xEE), TO_ECC_64(0xA2, 0xDA, 0x72, 0x5B, 0x99, 0xB3, 0x15, 0xF3), TO_ECC_64(0xB8, 0xB4, 0x89, 0x91, 0x8E, 0xF1, 0x09, 0xE1), TO_ECC_64(0x56, 0x19, 0x39, 0x51, 0xEC, 0x7E, 0x93, 0x7B), TO_ECC_64(0x16, 0x52, 0xC0, 0xBD, 0x3B, 0xB1, 0xBF, 0x07), TO_ECC_64(0x35, 0x73, 0xDF, 0x88, 0x3D, 0x2C, 0x34, 0xF1), TO_ECC_64(0xEF, 0x45, 0x1F, 0xD4, 0x6B, 0x50, 0x3F, 0x00))); ECC_CONST(NIST_P521_gX, 66, TO_ECC_528( TO_ECC_16(0x00, 0xC6), TO_ECC_64(0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, 0xE9, 0xCD), TO_ECC_64(0x9E, 0x3E, 0xCB, 0x66, 0x23, 0x95, 0xB4, 0x42), TO_ECC_64(0x9C, 0x64, 0x81, 0x39, 0x05, 0x3F, 0xB5, 0x21), TO_ECC_64(0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D, 0x3D, 0xBA), TO_ECC_64(0xA1, 0x4B, 0x5E, 0x77, 0xEF, 0xE7, 0x59, 0x28), TO_ECC_64(0xFE, 0x1D, 0xC1, 0x27, 0xA2, 0xFF, 0xA8, 0xDE), TO_ECC_64(0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A, 0x42, 0x9B), TO_ECC_64(0xF9, 0x7E, 0x7E, 0x31, 0xC2, 0xE5, 0xBD, 0x66))); ECC_CONST(NIST_P521_gY, 66, TO_ECC_528( TO_ECC_16(0x01, 0x18), TO_ECC_64(0x39, 0x29, 0x6A, 0x78, 0x9A, 0x3B, 0xC0, 0x04), TO_ECC_64(0x5C, 0x8A, 0x5F, 0xB4, 0x2C, 0x7D, 0x1B, 0xD9), TO_ECC_64(0x98, 0xF5, 0x44, 0x49, 0x57, 0x9B, 0x44, 0x68), TO_ECC_64(0x17, 0xAF, 0xBD, 0x17, 0x27, 0x3E, 0x66, 0x2C), TO_ECC_64(0x97, 0xEE, 0x72, 0x99, 0x5E, 0xF4, 0x26, 0x40), TO_ECC_64(0xC5, 0x50, 0xB9, 0x01, 0x3F, 0xAD, 0x07, 0x61), TO_ECC_64(0x35, 0x3C, 0x70, 0x86, 0xA2, 0x72, 0xC2, 0x40), TO_ECC_64(0x88, 0xBE, 0x94, 0x76, 0x9F, 0xD1, 0x66, 0x50))); ECC_CONST(NIST_P521_n, 66, TO_ECC_528( TO_ECC_16(0x01, 0xFF), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA), TO_ECC_64(0x51, 0x86, 0x87, 0x83, 0xBF, 0x2F, 0x96, 0x6B), TO_ECC_64(0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09, 0xA5, 0xD0), TO_ECC_64(0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C, 0x47, 0xAE), TO_ECC_64(0xBB, 0x6F, 0xB7, 0x1E, 0x91, 0x38, 0x64, 0x09))); #define NIST_P521_h ECC_ONE #define NIST_P521_gZ ECC_ONE #if USE_BN_ECC_DATA const ECC_CURVE_DATA NIST_P521 = { (bigNum)&NIST_P521_p, (bigNum)&NIST_P521_n, (bigNum)&NIST_P521_h, (bigNum)&NIST_P521_a, (bigNum)&NIST_P521_b, {(bigNum)&NIST_P521_gX, (bigNum)&NIST_P521_gY, (bigNum)&NIST_P521_gZ}}; #else const ECC_CURVE_DATA NIST_P521 = { &NIST_P521_p.b, &NIST_P521_n.b, &NIST_P521_h.b, &NIST_P521_a.b, &NIST_P521_b.b, {&NIST_P521_gX.b, &NIST_P521_gY.b, &NIST_P521_gZ.b}}; #endif // USE_BN_ECC_DATA #endif // ECC_NIST_P521 #if ECC_BN_P256 ECC_CONST(BN_P256_p, 32, TO_ECC_256( TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF0, 0xCD), TO_ECC_64(0x46, 0xE5, 0xF2, 0x5E, 0xEE, 0x71, 0xA4, 0x9F), TO_ECC_64(0x0C, 0xDC, 0x65, 0xFB, 0x12, 0x98, 0x0A, 0x82), TO_ECC_64(0xD3, 0x29, 0x2D, 0xDB, 0xAE, 0xD3, 0x30, 0x13))); #define BN_P256_a ECC_ZERO ECC_CONST(BN_P256_b, 1, TO_ECC_8(3)); #define BN_P256_gX ECC_ONE ECC_CONST(BN_P256_gY, 1, TO_ECC_8(2)); ECC_CONST(BN_P256_n, 32, TO_ECC_256( TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF0, 0xCD), TO_ECC_64(0x46, 0xE5, 0xF2, 0x5E, 0xEE, 0x71, 0xA4, 0x9E), TO_ECC_64(0x0C, 0xDC, 0x65, 0xFB, 0x12, 0x99, 0x92, 0x1A), TO_ECC_64(0xF6, 0x2D, 0x53, 0x6C, 0xD1, 0x0B, 0x50, 0x0D))); #define BN_P256_h ECC_ONE #define BN_P256_gZ ECC_ONE #if USE_BN_ECC_DATA const ECC_CURVE_DATA BN_P256 = { (bigNum)&BN_P256_p, (bigNum)&BN_P256_n, (bigNum)&BN_P256_h, (bigNum)&BN_P256_a, (bigNum)&BN_P256_b, {(bigNum)&BN_P256_gX, (bigNum)&BN_P256_gY, (bigNum)&BN_P256_gZ}}; #else const ECC_CURVE_DATA BN_P256 = { &BN_P256_p.b, &BN_P256_n.b, &BN_P256_h.b, &BN_P256_a.b, &BN_P256_b.b, {&BN_P256_gX.b, &BN_P256_gY.b, &BN_P256_gZ.b}}; #endif // USE_BN_ECC_DATA #endif // ECC_BN_P256 #if ECC_BN_P638 ECC_CONST(BN_P638_p, 80, TO_ECC_640( TO_ECC_64(0x23, 0xFF, 0xFF, 0xFD, 0xC0, 0x00, 0x00, 0x0D), TO_ECC_64(0x7F, 0xFF, 0xFF, 0xB8, 0x00, 0x00, 0x01, 0xD3), TO_ECC_64(0xFF, 0xFF, 0xF9, 0x42, 0xD0, 0x00, 0x16, 0x5E), TO_ECC_64(0x3F, 0xFF, 0x94, 0x87, 0x00, 0x00, 0xD5, 0x2F), TO_ECC_64(0xFF, 0xFD, 0xD0, 0xE0, 0x00, 0x08, 0xDE, 0x55), TO_ECC_64(0xC0, 0x00, 0x86, 0x52, 0x00, 0x21, 0xE5, 0x5B), TO_ECC_64(0xFF, 0xFF, 0xF5, 0x1F, 0xFF, 0xF4, 0xEB, 0x80), TO_ECC_64(0x00, 0x00, 0x00, 0x4C, 0x80, 0x01, 0x5A, 0xCD), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEC, 0xE0), TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67))); #define BN_P638_a ECC_ZERO ECC_CONST(BN_P638_b, 2, TO_ECC_16(0x01,0x01)); ECC_CONST(BN_P638_gX, 80, TO_ECC_640( TO_ECC_64(0x23, 0xFF, 0xFF, 0xFD, 0xC0, 0x00, 0x00, 0x0D), TO_ECC_64(0x7F, 0xFF, 0xFF, 0xB8, 0x00, 0x00, 0x01, 0xD3), TO_ECC_64(0xFF, 0xFF, 0xF9, 0x42, 0xD0, 0x00, 0x16, 0x5E), TO_ECC_64(0x3F, 0xFF, 0x94, 0x87, 0x00, 0x00, 0xD5, 0x2F), TO_ECC_64(0xFF, 0xFD, 0xD0, 0xE0, 0x00, 0x08, 0xDE, 0x55), TO_ECC_64(0xC0, 0x00, 0x86, 0x52, 0x00, 0x21, 0xE5, 0x5B), TO_ECC_64(0xFF, 0xFF, 0xF5, 0x1F, 0xFF, 0xF4, 0xEB, 0x80), TO_ECC_64(0x00, 0x00, 0x00, 0x4C, 0x80, 0x01, 0x5A, 0xCD), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEC, 0xE0), TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66))); ECC_CONST(BN_P638_gY, 1, TO_ECC_8(0x10)); ECC_CONST(BN_P638_n, 80, TO_ECC_640( TO_ECC_64(0x23, 0xFF, 0xFF, 0xFD, 0xC0, 0x00, 0x00, 0x0D), TO_ECC_64(0x7F, 0xFF, 0xFF, 0xB8, 0x00, 0x00, 0x01, 0xD3), TO_ECC_64(0xFF, 0xFF, 0xF9, 0x42, 0xD0, 0x00, 0x16, 0x5E), TO_ECC_64(0x3F, 0xFF, 0x94, 0x87, 0x00, 0x00, 0xD5, 0x2F), TO_ECC_64(0xFF, 0xFD, 0xD0, 0xE0, 0x00, 0x08, 0xDE, 0x55), TO_ECC_64(0x60, 0x00, 0x86, 0x55, 0x00, 0x21, 0xE5, 0x55), TO_ECC_64(0xFF, 0xFF, 0xF5, 0x4F, 0xFF, 0xF4, 0xEA, 0xC0), TO_ECC_64(0x00, 0x00, 0x00, 0x49, 0x80, 0x01, 0x54, 0xD9), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xED, 0xA0), TO_ECC_64(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61))); #define BN_P638_h ECC_ONE #define BN_P638_gZ ECC_ONE #if USE_BN_ECC_DATA const ECC_CURVE_DATA BN_P638 = { (bigNum)&BN_P638_p, (bigNum)&BN_P638_n, (bigNum)&BN_P638_h, (bigNum)&BN_P638_a, (bigNum)&BN_P638_b, {(bigNum)&BN_P638_gX, (bigNum)&BN_P638_gY, (bigNum)&BN_P638_gZ}}; #else const ECC_CURVE_DATA BN_P638 = { &BN_P638_p.b, &BN_P638_n.b, &BN_P638_h.b, &BN_P638_a.b, &BN_P638_b.b, {&BN_P638_gX.b, &BN_P638_gY.b, &BN_P638_gZ.b}}; #endif // USE_BN_ECC_DATA #endif // ECC_BN_P638 #if ECC_SM2_P256 ECC_CONST(SM2_P256_p, 32, TO_ECC_256( TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF))); ECC_CONST(SM2_P256_a, 32, TO_ECC_256( TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC))); ECC_CONST(SM2_P256_b, 32, TO_ECC_256( TO_ECC_64(0x28, 0xE9, 0xFA, 0x9E, 0x9D, 0x9F, 0x5E, 0x34), TO_ECC_64(0x4D, 0x5A, 0x9E, 0x4B, 0xCF, 0x65, 0x09, 0xA7), TO_ECC_64(0xF3, 0x97, 0x89, 0xF5, 0x15, 0xAB, 0x8F, 0x92), TO_ECC_64(0xDD, 0xBC, 0xBD, 0x41, 0x4D, 0x94, 0x0E, 0x93))); ECC_CONST(SM2_P256_gX, 32, TO_ECC_256( TO_ECC_64(0x32, 0xC4, 0xAE, 0x2C, 0x1F, 0x19, 0x81, 0x19), TO_ECC_64(0x5F, 0x99, 0x04, 0x46, 0x6A, 0x39, 0xC9, 0x94), TO_ECC_64(0x8F, 0xE3, 0x0B, 0xBF, 0xF2, 0x66, 0x0B, 0xE1), TO_ECC_64(0x71, 0x5A, 0x45, 0x89, 0x33, 0x4C, 0x74, 0xC7))); ECC_CONST(SM2_P256_gY, 32, TO_ECC_256( TO_ECC_64(0xBC, 0x37, 0x36, 0xA2, 0xF4, 0xF6, 0x77, 0x9C), TO_ECC_64(0x59, 0xBD, 0xCE, 0xE3, 0x6B, 0x69, 0x21, 0x53), TO_ECC_64(0xD0, 0xA9, 0x87, 0x7C, 0xC6, 0x2A, 0x47, 0x40), TO_ECC_64(0x02, 0xDF, 0x32, 0xE5, 0x21, 0x39, 0xF0, 0xA0))); ECC_CONST(SM2_P256_n, 32, TO_ECC_256( TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF), TO_ECC_64(0x72, 0x03, 0xDF, 0x6B, 0x21, 0xC6, 0x05, 0x2B), TO_ECC_64(0x53, 0xBB, 0xF4, 0x09, 0x39, 0xD5, 0x41, 0x23))); #define SM2_P256_h ECC_ONE #define SM2_P256_gZ ECC_ONE #if USE_BN_ECC_DATA const ECC_CURVE_DATA SM2_P256 = { (bigNum)&SM2_P256_p, (bigNum)&SM2_P256_n, (bigNum)&SM2_P256_h, (bigNum)&SM2_P256_a, (bigNum)&SM2_P256_b, {(bigNum)&SM2_P256_gX, (bigNum)&SM2_P256_gY, (bigNum)&SM2_P256_gZ}}; #else const ECC_CURVE_DATA SM2_P256 = { &SM2_P256_p.b, &SM2_P256_n.b, &SM2_P256_h.b, &SM2_P256_a.b, &SM2_P256_b.b, {&SM2_P256_gX.b, &SM2_P256_gY.b, &SM2_P256_gZ.b}}; #endif // USE_BN_ECC_DATA #endif // ECC_SM2_P256 #define comma const ECC_CURVE eccCurves[] = { #if ECC_NIST_P192 comma {TPM_ECC_NIST_P192, 192, {TPM_ALG_KDF1_SP800_56A, {{TPM_ALG_SHA256}}}, {TPM_ALG_NULL, {{TPM_ALG_NULL}}}, &NIST_P192, OID_ECC_NIST_P192 CURVE_NAME("NIST_P192")} # undef comma # define comma , #endif // ECC_NIST_P192 #if ECC_NIST_P224 comma {TPM_ECC_NIST_P224, 224, {TPM_ALG_KDF1_SP800_56A, {{TPM_ALG_SHA256}}}, {TPM_ALG_NULL, {{TPM_ALG_NULL}}}, &NIST_P224, OID_ECC_NIST_P224 CURVE_NAME("NIST_P224")} # undef comma # define comma , #endif // ECC_NIST_P224 #if ECC_NIST_P256 comma {TPM_ECC_NIST_P256, 256, {TPM_ALG_KDF1_SP800_56A, {{TPM_ALG_SHA256}}}, {TPM_ALG_NULL, {{TPM_ALG_NULL}}}, &NIST_P256, OID_ECC_NIST_P256 CURVE_NAME("NIST_P256")} # undef comma # define comma , #endif // ECC_NIST_P256 #if ECC_NIST_P384 comma {TPM_ECC_NIST_P384, 384, {TPM_ALG_KDF1_SP800_56A, {{TPM_ALG_SHA384}}}, {TPM_ALG_NULL, {{TPM_ALG_NULL}}}, &NIST_P384, OID_ECC_NIST_P384 CURVE_NAME("NIST_P384")} # undef comma # define comma , #endif // ECC_NIST_P384 #if ECC_NIST_P521 comma {TPM_ECC_NIST_P521, 521, {TPM_ALG_KDF1_SP800_56A, {{TPM_ALG_SHA512}}}, {TPM_ALG_NULL, {{TPM_ALG_NULL}}}, &NIST_P521, OID_ECC_NIST_P521 CURVE_NAME("NIST_P521")} # undef comma # define comma , #endif // ECC_NIST_P521 #if ECC_BN_P256 comma {TPM_ECC_BN_P256, 256, {TPM_ALG_NULL, {{TPM_ALG_NULL}}}, {TPM_ALG_NULL, {{TPM_ALG_NULL}}}, &BN_P256, OID_ECC_BN_P256 CURVE_NAME("BN_P256")} # undef comma # define comma , #endif // ECC_BN_P256 #if ECC_BN_P638 comma {TPM_ECC_BN_P638, 638, {TPM_ALG_NULL, {{TPM_ALG_NULL}}}, {TPM_ALG_NULL, {{TPM_ALG_NULL}}}, &BN_P638, OID_ECC_BN_P638 CURVE_NAME("BN_P638")} # undef comma # define comma , #endif // ECC_BN_P638 #if ECC_SM2_P256 comma {TPM_ECC_SM2_P256, 256, {TPM_ALG_KDF1_SP800_56A, {{TPM_ALG_SM3_256}}}, {TPM_ALG_NULL, {{TPM_ALG_NULL}}}, &SM2_P256, OID_ECC_SM2_P256 CURVE_NAME("SM2_P256")} # undef comma # define comma , #endif // ECC_SM2_P256 }; #endif // TPM_ALG_ECC libtpms-0.9.3/src/tpm2/CryptSelfTest.c000066400000000000000000000235011421143571500175710ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Self-Test of Cryptographic Functions */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CryptSelfTest.c 1594 2020-03-26 22:15:48Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2020 */ /* */ /********************************************************************************/ /* 10.2.7 CryptSelfTest.c */ /* 10.2.7.1 Introduction */ /* The functions in this file are designed to support self-test of cryptographic functions in the TPM. The TPM allows the user to decide whether to run self-test on a demand basis or to run all the self-tests before proceeding. */ /* The self-tests are controlled by a set of bit vectors. The g_untestedDecryptionAlgorithms vector has a bit for each decryption algorithm that needs to be tested and g_untestedEncryptionAlgorithms has a bit for each encryption algorithm that needs to be tested. Before an algorithm is used, the appropriate vector is checked (indexed using the algorithm ID). If the bit is 1, then the test function should be called. */ /* For more information, see TpmSelfTests().txt */ #include "Tpm.h" /* 10.2.7.2 Functions */ /* 10.2.7.2.1 RunSelfTest() */ /* Local function to run self-test */ static TPM_RC CryptRunSelfTests( ALGORITHM_VECTOR *toTest // IN: the vector of the algorithms to test ) { TPM_ALG_ID alg; // For each of the algorithms that are in the toTestVecor, need to run a // test for(alg = TPM_ALG_FIRST; alg <= TPM_ALG_LAST; alg++) { if(TEST_BIT(alg, *toTest)) { TPM_RC result = CryptTestAlgorithm(alg, toTest); if(result != TPM_RC_SUCCESS) return result; } } return TPM_RC_SUCCESS; } /* 10.2.7.2.2 CryptSelfTest() */ /* This function is called to start/complete a full self-test. If fullTest is NO, then only the untested algorithms will be run. If fullTest is YES, then g_untestedDecryptionAlgorithms is reinitialized and then all tests are run. This implementation of the reference design does not support processing outside the framework of a TPM command. As a consequence, this command does not complete until all tests are done. Since this can take a long time, the TPM will check after each test to see if the command is canceled. If so, then the TPM will returned TPM_RC_CANCELLED. To continue with the self-tests, call TPM2_SelfTest(fullTest == No) and the TPM will complete the testing. */ /* Error Returns Meaning */ /* TPM_RC_CANCELED if the command is canceled */ LIB_EXPORT TPM_RC CryptSelfTest( TPMI_YES_NO fullTest // IN: if full test is required ) { #if SIMULATION if(g_forceFailureMode) FAIL(FATAL_ERROR_FORCED); #endif // If the caller requested a full test, then reset the to test vector so that // all the tests will be run if(fullTest == YES) { MemoryCopy(g_toTest, g_implementedAlgorithms, sizeof(g_toTest)); } return CryptRunSelfTests(&g_toTest); } /* 10.2.7.2.3 CryptIncrementalSelfTest() */ /* This function is used to perform an incremental self-test. This implementation will perform the toTest values before returning. That is, it assumes that the TPM cannot perform background tasks between commands. */ /* This command may be canceled. If it is, then there is no return result. However, this command can be run again and the incremental progress will not be lost. */ /* Error Returns Meaning */ /* TPM_RC_CANCELED processing of this command was canceled */ /* TPM_RC_TESTING if toTest list is not empty */ /* TPM_RC_VALUE an algorithm in the toTest list is not implemented */ TPM_RC CryptIncrementalSelfTest( TPML_ALG *toTest, // IN: list of algorithms to be tested TPML_ALG *toDoList // OUT: list of algorithms needing test ) { ALGORITHM_VECTOR toTestVector = {0}; TPM_ALG_ID alg; UINT32 i; pAssert(toTest != NULL && toDoList != NULL); if(toTest->count > 0) { // Transcribe the toTest list into the toTestVector for(i = 0; i < toTest->count; i++) { alg = toTest->algorithms[i]; // make sure that the algorithm value is not out of range if((alg > TPM_ALG_LAST) || !TEST_BIT(alg, g_implementedAlgorithms)) return TPM_RC_VALUE; SET_BIT(alg, toTestVector); } // Run the test if(CryptRunSelfTests(&toTestVector) == TPM_RC_CANCELED) return TPM_RC_CANCELED; } // Fill in the toDoList with the algorithms that are still untested toDoList->count = 0; for(alg = TPM_ALG_FIRST; toDoList->count < MAX_ALG_LIST_SIZE && alg <= TPM_ALG_LAST; alg++) { if(TEST_BIT(alg, g_toTest)) toDoList->algorithms[toDoList->count++] = alg; } return TPM_RC_SUCCESS; } /* 10.2.7.2.4 CryptInitializeToTest() */ /* This function will initialize the data structures for testing all the algorithms. This should not be called unless CryptAlgsSetImplemented() has been called */ void CryptInitializeToTest( void ) { // Indicate that nothing has been tested memset(&g_cryptoSelfTestState, 0, sizeof(g_cryptoSelfTestState)); // Copy the implemented algorithm vector MemoryCopy(g_toTest, g_implementedAlgorithms, sizeof(g_toTest)); // Setting the algorithm to null causes the test function to just clear // out any algorithms for which there is no test. CryptTestAlgorithm(TPM_ALG_ERROR, &g_toTest); return; } /* 10.2.7.2.5 CryptTestAlgorithm() */ /* Only point of contact with the actual self tests. If a self-test fails, there is no return and the TPM goes into failure mode. The call to TestAlgorithm() uses an algorithm selector and a bit vector. When the test is run, the corresponding bit in toTest and in g_toTest is CLEAR. If toTest is NULL, then only the bit in g_toTest is CLEAR. There is a special case for the call to TestAlgorithm(). When alg is TPM_ALG_ERROR, TestAlgorithm() will CLEAR any bit in toTest for which it has no test. This allows the knowledge about which algorithms have test to be accessed through the interface that provides the test. */ /* Error Returns Meaning */ /* TPM_RC_CANCELED test was canceled */ LIB_EXPORT TPM_RC CryptTestAlgorithm( TPM_ALG_ID alg, ALGORITHM_VECTOR *toTest ) { TPM_RC result; #if SELF_TEST result = TestAlgorithm(alg, toTest); #else // If this is an attempt to determine the algorithms for which there is a // self test, pretend that all of them do. We do that by not clearing any // of the algorithm bits. When/if this function is called to run tests, it // will over report. This can be changed so that any call to check on which // algorithms have tests, 'toTest' can be cleared. if(alg != TPM_ALG_ERROR) { CLEAR_BIT(alg, g_toTest); if(toTest != NULL) CLEAR_BIT(alg, *toTest); } result = TPM_RC_SUCCESS; #endif return result; } libtpms-0.9.3/src/tpm2/CryptSelfTest_fp.h000066400000000000000000000075251421143571500202730ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CryptSelfTest_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 */ /* */ /********************************************************************************/ #ifndef CRYPTSELFTEST_FP_H #define CRYPTSELFTEST_FP_H LIB_EXPORT TPM_RC CryptSelfTest( TPMI_YES_NO fullTest // IN: if full test is required ); TPM_RC CryptIncrementalSelfTest( TPML_ALG *toTest, // IN: list of algorithms to be tested TPML_ALG *toDoList // OUT: list of algorithms needing test ); void CryptInitializeToTest( void ); LIB_EXPORT TPM_RC CryptTestAlgorithm( TPM_ALG_ID alg, ALGORITHM_VECTOR *toTest ); #endif libtpms-0.9.3/src/tpm2/CryptUtil.c000066400000000000000000002023721421143571500167620ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Interfaces to the Crypto Engine */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CryptUtil.c 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2021 */ /* */ /********************************************************************************/ /* 10.2.6 CryptUtil.c */ /* 10.2.6.1 Introduction */ /* This module contains the interfaces to the CryptoEngine() and provides miscellaneous cryptographic functions in support of the TPM. */ /* 10.2.6.2 Includes */ #include "Tpm.h" /* 10.2.6.3 Hash/HMAC Functions */ /* 10.2.6.3.1 CryptHmacSign() */ /* Sign a digest using an HMAC key. This an HMAC of a digest, not an HMAC of a message. */ /* Error Returns Meaning */ /* TPM_RC_HASH not a valid hash */ static TPM_RC CryptHmacSign( TPMT_SIGNATURE *signature, // OUT: signature OBJECT *signKey, // IN: HMAC key sign the hash TPM2B_DIGEST *hashData // IN: hash to be signed ) { HMAC_STATE hmacState; UINT32 digestSize; digestSize = CryptHmacStart2B(&hmacState, signature->signature.any.hashAlg, &signKey->sensitive.sensitive.bits.b); CryptDigestUpdate2B(&hmacState.hashState, &hashData->b); CryptHmacEnd(&hmacState, digestSize, (BYTE *)&signature->signature.hmac.digest); return TPM_RC_SUCCESS; } /* 10.2.6.3.2 CryptHMACVerifySignature() */ /* This function will verify a signature signed by a HMAC key. Note that a caller needs to prepare signature with the signature algorithm (TPM_ALG_HMAC) and the hash algorithm to use. This function then builds a signature of that type. */ /* Error Returns Meaning */ /* TPM_RC_SCHEME not the proper scheme for this key type */ /* TPM_RC_SIGNATURE if invalid input or signature is not genuine */ static TPM_RC CryptHMACVerifySignature( OBJECT *signKey, // IN: HMAC key signed the hash TPM2B_DIGEST *hashData, // IN: digest being verified TPMT_SIGNATURE *signature // IN: signature to be verified ) { TPMT_SIGNATURE test; TPMT_KEYEDHASH_SCHEME *keyScheme = &signKey->publicArea.parameters.keyedHashDetail.scheme; // if((signature->sigAlg != TPM_ALG_HMAC) || (signature->signature.hmac.hashAlg == TPM_ALG_NULL)) return TPM_RC_SCHEME; // This check is not really needed for verification purposes. However, it does // prevent someone from trying to validate a signature using a weaker hash // algorithm than otherwise allowed by the key. That is, a key with a scheme // other than TMP_ALG_NULL can only be used to validate signatures that have // a matching scheme. if((keyScheme->scheme != TPM_ALG_NULL) && ((keyScheme->scheme != signature->sigAlg) || (keyScheme->details.hmac.hashAlg != signature->signature.any.hashAlg))) return TPM_RC_SIGNATURE; test.sigAlg = signature->sigAlg; test.signature.hmac.hashAlg = signature->signature.hmac.hashAlg; CryptHmacSign(&test, signKey, hashData); // Compare digest if(!MemoryEqual(&test.signature.hmac.digest, &signature->signature.hmac.digest, CryptHashGetDigestSize(signature->signature.any.hashAlg))) return TPM_RC_SIGNATURE; return TPM_RC_SUCCESS; } /* 10.2.6.3.3 CryptGenerateKeyedHash() */ /* This function creates a keyedHash object. */ /* Error Returns Meaning */ /* TPM_RC_NO_RESULT cannot get values from random number generator */ /* TPM_RC_SIZE sensitive data size is larger than allowed for the scheme */ static TPM_RC CryptGenerateKeyedHash( TPMT_PUBLIC *publicArea, // IN/OUT: the public area template // for the new key. TPMT_SENSITIVE *sensitive, // OUT: sensitive area TPMS_SENSITIVE_CREATE *sensitiveCreate, // IN: sensitive creation data RAND_STATE *rand // IN: "entropy" source ) { TPMT_KEYEDHASH_SCHEME *scheme; TPM_ALG_ID hashAlg; UINT16 digestSize; scheme = &publicArea->parameters.keyedHashDetail.scheme; if(publicArea->type != TPM_ALG_KEYEDHASH) return TPM_RC_FAILURE; // Pick the limiting hash algorithm if(scheme->scheme == TPM_ALG_NULL) hashAlg = publicArea->nameAlg; else if(scheme->scheme == TPM_ALG_XOR) hashAlg = scheme->details.xorr.hashAlg; else hashAlg = scheme->details.hmac.hashAlg; /* hashBlockSize = CryptHashGetBlockSize(hashAlg); */ digestSize = CryptHashGetDigestSize(hashAlg); // if this is a signing or a decryption key, then the limit // for the data size is the block size of the hash. This limit // is set because larger values have lower entropy because of the // HMAC function. The lower limit is 1/2 the size of the digest // //If the user provided the key, check that it is a proper size if(sensitiveCreate->data.t.size != 0) { if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, decrypt) || IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign)) { if(sensitiveCreate->data.t.size > CryptHashGetBlockSize(hashAlg)) return TPM_RC_SIZE; #if 0 // May make this a FIPS-mode requirement if(sensitiveCreate->data.t.size < (digestSize / 2)) return TPM_RC_SIZE; #endif } // If this is a data blob, then anything that will get past the unmarshaling // is OK MemoryCopy2B(&sensitive->sensitive.bits.b, &sensitiveCreate->data.b, sizeof(sensitive->sensitive.bits.t.buffer)); } else { // The TPM is going to generate the data so set the size to be the // size of the digest of the algorithm sensitive->sensitive.bits.t.size = DRBG_Generate(rand, sensitive->sensitive.bits.t.buffer, digestSize); if(sensitive->sensitive.bits.t.size == 0) return (g_inFailureMode) ? TPM_RC_FAILURE : TPM_RC_NO_RESULT; } return TPM_RC_SUCCESS; } /* 10.2.6.3.4 CryptIsSchemeAnonymous() */ /* This function is used to test a scheme to see if it is an anonymous scheme The only anonymous scheme is ECDAA. ECDAA can be used to do things like U-Prove. */ BOOL CryptIsSchemeAnonymous( TPM_ALG_ID scheme // IN: the scheme algorithm to test ) { return scheme == TPM_ALG_ECDAA; } /* 10.2.6.4 Symmetric Functions */ /* 10.2.6.4.1 ParmDecryptSym() */ /* This function performs parameter decryption using symmetric block cipher. */ void ParmDecryptSym( TPM_ALG_ID symAlg, // IN: the symmetric algorithm TPM_ALG_ID hash, // IN: hash algorithm for KDFa UINT16 keySizeInBits, // IN: the key size in bits TPM2B *key, // IN: KDF HMAC key TPM2B *nonceCaller, // IN: nonce caller TPM2B *nonceTpm, // IN: nonce TPM UINT32 dataSize, // IN: size of parameter buffer BYTE *data // OUT: buffer to be decrypted ) { // KDF output buffer // It contains parameters for the CFB encryption // From MSB to LSB, they are the key and iv BYTE symParmString[MAX_SYM_KEY_BYTES + MAX_SYM_BLOCK_SIZE]; // Symmetric key size in byte UINT16 keySize = (keySizeInBits + 7) / 8; TPM2B_IV iv; iv.t.size = CryptGetSymmetricBlockSize(symAlg, keySizeInBits); // If there is decryption to do... if(iv.t.size > 0) { // Generate key and iv CryptKDFa(hash, key, CFB_KEY, nonceCaller, nonceTpm, keySizeInBits + (iv.t.size * 8), symParmString, NULL, FALSE); MemoryCopy(iv.t.buffer, &symParmString[keySize], iv.t.size); CryptSymmetricDecrypt(data, symAlg, keySizeInBits, symParmString, &iv, TPM_ALG_CFB, dataSize, data); } return; } /* 10.2.6.4.2 ParmEncryptSym() */ /* This function performs parameter encryption using symmetric block cipher. */ void ParmEncryptSym( TPM_ALG_ID symAlg, // IN: symmetric algorithm TPM_ALG_ID hash, // IN: hash algorithm for KDFa UINT16 keySizeInBits, // IN: AES symmetric key size in bits TPM2B *key, // IN: KDF HMAC key TPM2B *nonceCaller, // IN: nonce caller TPM2B *nonceTpm, // IN: nonce TPM UINT32 dataSize, // IN: size of parameter buffer BYTE *data // OUT: buffer to be encrypted ) { // KDF output buffer // It contains parameters for the CFB encryption BYTE symParmString[MAX_SYM_KEY_BYTES + MAX_SYM_BLOCK_SIZE]; // Symmetric key size in bytes UINT16 keySize = (keySizeInBits + 7) / 8; TPM2B_IV iv; iv.t.size = CryptGetSymmetricBlockSize(symAlg, keySizeInBits); // See if there is any encryption to do if(iv.t.size > 0) { // Generate key and iv CryptKDFa(hash, key, CFB_KEY, nonceTpm, nonceCaller, keySizeInBits + (iv.t.size * 8), symParmString, NULL, FALSE); MemoryCopy(iv.t.buffer, &symParmString[keySize], iv.t.size); CryptSymmetricEncrypt(data, symAlg, keySizeInBits, symParmString, &iv, TPM_ALG_CFB, dataSize, data); } return; } /* 10.2.6.4.3 CryptGenerateKeySymmetric() */ /* This function generates a symmetric cipher key. The derivation process is determined by the type of the provided rand */ /* Error Returns Meaning */ /* TPM_RC_NO_RESULT cannot get a random value */ /* TPM_RC_KEY_SIZE key size in the public area does not match the size in the sensitive creation area */ /* TPM_RC_KEY provided key value is not allowed */ static TPM_RC CryptGenerateKeySymmetric( TPMT_PUBLIC *publicArea, // IN/OUT: The public area template // for the new key. TPMT_SENSITIVE *sensitive, // OUT: sensitive area TPMS_SENSITIVE_CREATE *sensitiveCreate, // IN: sensitive creation data RAND_STATE *rand // IN: the "entropy" source for ) { UINT16 keyBits = publicArea->parameters.symDetail.sym.keyBits.sym; TPM_RC result; // // only do multiples of RADIX_BITS if((keyBits % RADIX_BITS) != 0) return TPM_RC_KEY_SIZE; // If this is not a new key, then the provided key data must be the right size if(sensitiveCreate->data.t.size != 0) { result = CryptSymKeyValidate(&publicArea->parameters.symDetail.sym, (TPM2B_SYM_KEY *)&sensitiveCreate->data); if(result == TPM_RC_SUCCESS) MemoryCopy2B(&sensitive->sensitive.sym.b, &sensitiveCreate->data.b, sizeof(sensitive->sensitive.sym.t.buffer)); } #if ALG_TDES else if(publicArea->parameters.symDetail.sym.algorithm == TPM_ALG_TDES) { sensitive->sensitive.sym.t.size = keyBits / 8; result = CryptGenerateKeyDes(publicArea, sensitive, rand); } #endif else { sensitive->sensitive.sym.t.size = DRBG_Generate(rand, sensitive->sensitive.sym.t.buffer, BITS_TO_BYTES(keyBits)); if(g_inFailureMode) result = TPM_RC_FAILURE; else if(sensitive->sensitive.sym.t.size == 0) result = TPM_RC_NO_RESULT; else result = TPM_RC_SUCCESS; } return result; } /* 10.2.6.4.4 CryptXORObfuscation() */ /* This function implements XOR obfuscation. It should not be called if the hash algorithm is not implemented. The only return value from this function is TPM_RC_SUCCESS. */ void CryptXORObfuscation( TPM_ALG_ID hash, // IN: hash algorithm for KDF TPM2B *key, // IN: KDF key TPM2B *contextU, // IN: contextU TPM2B *contextV, // IN: contextV UINT32 dataSize, // IN: size of data buffer BYTE *data // IN/OUT: data to be XORed in place ) { BYTE mask[MAX_DIGEST_SIZE]; // Allocate a digest sized buffer BYTE *pm; UINT32 i; UINT32 counter = 0; UINT16 hLen = CryptHashGetDigestSize(hash); UINT32 requestSize = dataSize * 8; INT32 remainBytes = (INT32)dataSize; pAssert((key != NULL) && (data != NULL) && (hLen != 0)); // Call KDFa to generate XOR mask for(; remainBytes > 0; remainBytes -= hLen) { // Make a call to KDFa to get next iteration CryptKDFa(hash, key, XOR_KEY, contextU, contextV, requestSize, mask, &counter, TRUE); // XOR next piece of the data pm = mask; for(i = hLen < remainBytes ? hLen : remainBytes; i > 0; i--) *data++ ^= *pm++; } return; } /* 10.2.6.5 Initialization and shut down */ /* 10.2.6.5.1 CryptInit() */ /* This function is called when the TPM receives a _TPM_Init() indication. */ /* NOTE: The hash algorithms do not have to be tested, they just need to be available. They have to be tested before the TPM can accept HMAC authorization or return any result that relies on a hash algorithm. */ /* Return Values Meaning */ /* TRUE initializations succeeded */ /* FALSE initialization failed and caller should place the TPM into Failure Mode */ BOOL CryptInit( void ) { BOOL ok; // Initialize the vector of implemented algorithms AlgorithmGetImplementedVector(&g_implementedAlgorithms); // Indicate that all test are necessary CryptInitializeToTest(); // Do any library initializations that are necessary. If any fails, // the caller should go into failure mode; ok = SupportLibInit(); ok = ok && CryptSymInit(); ok = ok && CryptRandInit(); ok = ok && CryptHashInit(); #if ALG_RSA ok = ok && CryptRsaInit(); #endif // TPM_ALG_RSA #if ALG_ECC ok = ok && CryptEccInit(); #endif // TPM_ALG_ECC return ok; } /* 10.2.6.5.2 CryptStartup() */ /* This function is called by TPM2_Startup() to initialize the functions in this cryptographic library and in the provided CryptoLibrary(). This function and CryptUtilInit() are both provided so that the implementation may move the initialization around to get the best interaction. */ /* Return Values Meaning */ /* TRUE startup succeeded */ /* FALSE startup failed and caller should place the TPM into Failure Mode */ BOOL CryptStartup( STARTUP_TYPE type // IN: the startup type ) { BOOL OK; NOT_REFERENCED(type); OK = CryptSymStartup(); OK = OK && CryptRandStartup(); OK = OK && CryptHashStartup(); #if ALG_RSA OK = OK && CryptRsaStartup(); #endif // TPM_ALG_RSA #if ALG_ECC OK = OK && CryptEccStartup(); #endif // TPM_ALG_ECC ; #if ALG_ECC // Don't directly check for SU_RESET because that is the default if(OK && (type != SU_RESTART) && (type != SU_RESUME)) { // If the shutdown was orderly, then the values recovered from NV will // be OK to use. // Get a new random commit nonce gr.commitNonce.t.size = sizeof(gr.commitNonce.t.buffer); CryptRandomGenerate(gr.commitNonce.t.size, gr.commitNonce.t.buffer); // Reset the counter and commit array gr.commitCounter = 0; MemorySet(gr.commitArray, 0, sizeof(gr.commitArray)); } #endif // TPM_ALG_ECC return OK; } /* 10.2.6.6 Algorithm-Independent Functions */ /* 10.2.6.6.1 Introduction */ /* These functions are used generically when a function of a general type (e.g., symmetric encryption) is required. The functions will modify the parameters as required to interface to the indicated algorithms. */ /* 10.2.6.6.2 CryptIsAsymAlgorithm() */ /* This function indicates if an algorithm is an asymmetric algorithm. */ /* Return Values Meaning */ /* TRUE if it is an asymmetric algorithm */ /* FALSE if it is not an asymmetric algorithm */ BOOL CryptIsAsymAlgorithm( TPM_ALG_ID algID // IN: algorithm ID ) { switch(algID) { #if ALG_RSA case TPM_ALG_RSA: #endif #if ALG_ECC case TPM_ALG_ECC: #endif return TRUE; break; default: break; } return FALSE; } /* 10.2.6.6.3 CryptSecretEncrypt() */ /* This function creates a secret value and its associated secret structure using an asymmetric algorithm. */ /* This function is used by TPM2_Rewrap() TPM2_MakeCredential(), and TPM2_Duplicate(). */ /* Error Returns Meaning */ /* TPM_RC_ATTRIBUTES keyHandle does not reference a valid decryption key */ /* TPM_RC_KEY invalid ECC key (public point is not on the curve) */ /* TPM_RC_SCHEME RSA key with an unsupported padding scheme */ /* TPM_RC_VALUE numeric value of the data to be decrypted is greater than the RSA key modulus */ TPM_RC CryptSecretEncrypt( OBJECT *encryptKey, // IN: encryption key object const TPM2B *label, // IN: a null-terminated string as L TPM2B_DATA *data, // OUT: secret value TPM2B_ENCRYPTED_SECRET *secret // OUT: secret structure ) { TPMT_RSA_DECRYPT scheme; TPM_RC result = TPM_RC_SUCCESS; // if(data == NULL || secret == NULL) return TPM_RC_FAILURE; // The output secret value has the size of the digest produced by the nameAlg. data->t.size = CryptHashGetDigestSize(encryptKey->publicArea.nameAlg); // The encryption scheme is OAEP using the nameAlg of the encrypt key. scheme.scheme = TPM_ALG_OAEP; scheme.details.anySig.hashAlg = encryptKey->publicArea.nameAlg; if(!IS_ATTRIBUTE(encryptKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt)) return TPM_RC_ATTRIBUTES; switch(encryptKey->publicArea.type) { #if ALG_RSA case TPM_ALG_RSA: { // Create secret data from RNG CryptRandomGenerate(data->t.size, data->t.buffer); // Encrypt the data by RSA OAEP into encrypted secret result = CryptRsaEncrypt((TPM2B_PUBLIC_KEY_RSA *)secret, &data->b, encryptKey, &scheme, label, NULL); } break; #endif //TPM_ALG_RSA #if ALG_ECC case TPM_ALG_ECC: { TPMS_ECC_POINT eccPublic; TPM2B_ECC_PARAMETER eccPrivate; TPMS_ECC_POINT eccSecret; BYTE *buffer = secret->t.secret; // Need to make sure that the public point of the key is on the // curve defined by the key. if(!CryptEccIsPointOnCurve( encryptKey->publicArea.parameters.eccDetail.curveID, &encryptKey->publicArea.unique.ecc)) result = TPM_RC_KEY; else { // Call crypto engine to create an auxiliary ECC key // We assume crypt engine initialization should always success. // Otherwise, TPM should go to failure mode. CryptEccNewKeyPair(&eccPublic, &eccPrivate, encryptKey->publicArea.parameters.eccDetail.curveID); // Marshal ECC public to secret structure. This will be used by the // recipient to decrypt the secret with their private key. secret->t.size = TPMS_ECC_POINT_Marshal(&eccPublic, &buffer, NULL); // Compute ECDH shared secret which is R = [d]Q where d is the // private part of the ephemeral key and Q is the public part of a // TPM key. TPM_RC_KEY error return from CryptComputeECDHSecret // because the auxiliary ECC key is just created according to the // parameters of input ECC encrypt key. if(CryptEccPointMultiply(&eccSecret, encryptKey->publicArea.parameters.eccDetail.curveID, &encryptKey->publicArea.unique.ecc, &eccPrivate, NULL, NULL) != TPM_RC_SUCCESS) result = TPM_RC_KEY; else { // The secret value is computed from Z using KDFe as: // secret := KDFe(HashID, Z, Use, PartyUInfo, PartyVInfo, bits) // Where: // HashID the nameAlg of the decrypt key // Z the x coordinate (Px) of the product (P) of the point // (Q) of the secret and the private x coordinate (de,V) // of the decryption key // Use a null-terminated string containing "SECRET" // PartyUInfo the x coordinate of the point in the secret // (Qe,U ) // PartyVInfo the x coordinate of the public key (Qs,V ) // bits the number of bits in the digest of HashID // Retrieve seed from KDFe CryptKDFe(encryptKey->publicArea.nameAlg, &eccSecret.x.b, label, &eccPublic.x.b, &encryptKey->publicArea.unique.ecc.x.b, data->t.size * 8, data->t.buffer); } } } break; #endif //TPM_ALG_ECC default: FAIL(FATAL_ERROR_INTERNAL); break; } return result; } /* 10.2.6.6.4 CryptSecretDecrypt() */ /* Decrypt a secret value by asymmetric (or symmetric) algorithm This function is used for ActivateCredential() and Import for asymmetric decryption, and StartAuthSession() for both asymmetric and symmetric decryption process */ /* Error Returns Meaning */ /* TPM_RC_ATTRIBUTES RSA key is not a decryption key */ /* TPM_RC_BINDING Invalid RSA key (public and private parts are not cryptographically bound. */ /* TPM_RC_ECC_POINT ECC point in the secret is not on the curve */ /* TPM_RC_INSUFFICIENT failed to retrieve ECC point from the secret */ /* TPM_RC_NO_RESULT multiplication resulted in ECC point at infinity */ /* TPM_RC_SIZE data to decrypt is not of the same size as RSA key */ /* TPM_RC_VALUE For RSA key, numeric value of the encrypted data is greater than the modulus, or the recovered data is larger than the output buffer. For keyedHash or symmetric key, the secret is larger than the size of the digest produced by the name algorithm. */ /* TPM_RC_FAILURE internal error */ TPM_RC CryptSecretDecrypt( OBJECT *decryptKey, // IN: decrypt key TPM2B_NONCE *nonceCaller, // IN: nonceCaller. It is needed for // symmetric decryption. For // asymmetric decryption, this // parameter is NULL const TPM2B *label, // IN: a value for L TPM2B_ENCRYPTED_SECRET *secret, // IN: input secret TPM2B_DATA *data // OUT: decrypted secret value ) { TPM_RC result = TPM_RC_SUCCESS; // Decryption for secret switch(decryptKey->publicArea.type) { #if ALG_RSA case TPM_ALG_RSA: { TPMT_RSA_DECRYPT scheme; TPMT_RSA_SCHEME *keyScheme = &decryptKey->publicArea.parameters.rsaDetail.scheme; UINT16 digestSize; scheme = *(TPMT_RSA_DECRYPT *)keyScheme; // If the key scheme is TPM_ALG_NULL, set the scheme to OAEP and // set the algorithm to the name algorithm. if(scheme.scheme == TPM_ALG_NULL) { // Use OAEP scheme scheme.scheme = TPM_ALG_OAEP; scheme.details.oaep.hashAlg = decryptKey->publicArea.nameAlg; } // use the digestSize as an indicator of whether or not the scheme // is using a supported hash algorithm. // Note: depending on the scheme used for encryption, a hashAlg might // not be needed. However, the return value has to have some upper // limit on the size. In this case, it is the size of the digest of the // hash algorithm. It is checked after the decryption is done but, there // is no point in doing the decryption if the size is going to be // 'wrong' anyway. digestSize = CryptHashGetDigestSize(scheme.details.oaep.hashAlg); if(scheme.scheme != TPM_ALG_OAEP || digestSize == 0) return TPM_RC_SCHEME; // Set the output buffer capacity data->t.size = sizeof(data->t.buffer); // Decrypt seed by RSA OAEP result = CryptRsaDecrypt(&data->b, &secret->b, decryptKey, &scheme, label); if((result == TPM_RC_SUCCESS) && (data->t.size > digestSize)) result = TPM_RC_VALUE; } break; #endif //TPM_ALG_RSA #if ALG_ECC case TPM_ALG_ECC: { TPMS_ECC_POINT eccPublic; TPMS_ECC_POINT eccSecret; BYTE *buffer = secret->t.secret; INT32 size = secret->t.size; // Retrieve ECC point from secret buffer result = TPMS_ECC_POINT_Unmarshal(&eccPublic, &buffer, &size); if(result == TPM_RC_SUCCESS) { result = CryptEccPointMultiply(&eccSecret, decryptKey->publicArea.parameters.eccDetail.curveID, &eccPublic, &decryptKey->sensitive.sensitive.ecc, NULL, NULL); if(result == TPM_RC_SUCCESS) { // Set the size of the "recovered" secret value to be the size // of the digest produced by the nameAlg. data->t.size = CryptHashGetDigestSize(decryptKey->publicArea.nameAlg); // The secret value is computed from Z using KDFe as: // secret := KDFe(HashID, Z, Use, PartyUInfo, PartyVInfo, bits) // Where: // HashID -- the nameAlg of the decrypt key // Z -- the x coordinate (Px) of the product (P) of the point // (Q) of the secret and the private x coordinate (de,V) // of the decryption key // Use -- a null-terminated string containing "SECRET" // PartyUInfo -- the x coordinate of the point in the secret // (Qe,U ) // PartyVInfo -- the x coordinate of the public key (Qs,V ) // bits -- the number of bits in the digest of HashID // Retrieve seed from KDFe CryptKDFe(decryptKey->publicArea.nameAlg, &eccSecret.x.b, label, &eccPublic.x.b, &decryptKey->publicArea.unique.ecc.x.b, data->t.size * 8, data->t.buffer); } } } break; #endif //TPM_ALG_ECC #if !ALG_KEYEDHASH # error "KEYEDHASH support is required" #endif case TPM_ALG_KEYEDHASH: // The seed size can not be bigger than the digest size of nameAlg if(secret->t.size > CryptHashGetDigestSize(decryptKey->publicArea.nameAlg)) result = TPM_RC_VALUE; else { // Retrieve seed by XOR Obfuscation: // seed = XOR(secret, hash, key, nonceCaller, nullNonce) // where: // secret the secret parameter from the TPM2_StartAuthHMAC // command that contains the seed value // hash nameAlg of tpmKey // key the key or data value in the object referenced by // entityHandle in the TPM2_StartAuthHMAC command // nonceCaller the parameter from the TPM2_StartAuthHMAC command // nullNonce a zero-length nonce // XOR Obfuscation in place CryptXORObfuscation(decryptKey->publicArea.nameAlg, &decryptKey->sensitive.sensitive.bits.b, &nonceCaller->b, NULL, secret->t.size, secret->t.secret); // Copy decrypted seed MemoryCopy2B(&data->b, &secret->b, sizeof(data->t.buffer)); } break; case TPM_ALG_SYMCIPHER: { TPM2B_IV iv = {{0}}; TPMT_SYM_DEF_OBJECT *symDef; // The seed size can not be bigger than the digest size of nameAlg if(secret->t.size > CryptHashGetDigestSize(decryptKey->publicArea.nameAlg)) result = TPM_RC_VALUE; else { symDef = &decryptKey->publicArea.parameters.symDetail.sym; iv.t.size = CryptGetSymmetricBlockSize(symDef->algorithm, symDef->keyBits.sym); if(iv.t.size == 0) return TPM_RC_FAILURE; if(nonceCaller->t.size >= iv.t.size) { MemoryCopy(iv.t.buffer, nonceCaller->t.buffer, iv.t.size); } else { if(nonceCaller->t.size > sizeof(iv.t.buffer)) return TPM_RC_FAILURE; MemoryCopy(iv.t.buffer, nonceCaller->t.buffer, // libtpms changed: use iv.t.buffer nonceCaller->t.size); } // make sure secret will fit if(secret->t.size > data->t.size) return TPM_RC_FAILURE; data->t.size = secret->t.size; // CFB decrypt, using nonceCaller as iv CryptSymmetricDecrypt(data->t.buffer, symDef->algorithm, symDef->keyBits.sym, decryptKey->sensitive.sensitive.sym.t.buffer, &iv, TPM_ALG_CFB, secret->t.size, secret->t.secret); } } break; default: FAIL(FATAL_ERROR_INTERNAL); break; } return result; } /* 10.2.6.6.5 CryptParameterEncryption() */ /* This function does in-place encryption of a response parameter. */ void CryptParameterEncryption( TPM_HANDLE handle, // IN: encrypt session handle TPM2B *nonceCaller, // IN: nonce caller UINT16 leadingSizeInByte, // IN: the size of the leading size field in // bytes TPM2B_AUTH *extraKey, // IN: additional key material other than // sessionAuth BYTE *buffer // IN/OUT: parameter buffer to be encrypted ) { SESSION *session = SessionGet(handle); // encrypt session TPM2B_TYPE(TEMP_KEY, (sizeof(extraKey->t.buffer) + sizeof(session->sessionKey.t.buffer))); TPM2B_TEMP_KEY key; // encryption key UINT32 cipherSize = 0; // size of cipher text // Retrieve encrypted data size. if(leadingSizeInByte == 2) { // Extract the first two bytes as the size field as the data size // encrypt cipherSize = (UINT32)BYTE_ARRAY_TO_UINT16(buffer); // advance the buffer buffer = &buffer[2]; } #ifdef TPM4B else if(leadingSizeInByte == 4) { // use the first four bytes to indicate the number of bytes to encrypt cipherSize = BYTE_ARRAY_TO_UINT32(buffer); //advance pointer buffer = &buffer[4]; } #endif else { FAIL(FATAL_ERROR_INTERNAL); } // Compute encryption key by concatenating sessionKey with extra key MemoryCopy2B(&key.b, &session->sessionKey.b, sizeof(key.t.buffer)); MemoryConcat2B(&key.b, &extraKey->b, sizeof(key.t.buffer)); if(session->symmetric.algorithm == TPM_ALG_XOR) // XOR parameter encryption formulation: // XOR(parameter, hash, sessionAuth, nonceNewer, nonceOlder) CryptXORObfuscation(session->authHashAlg, &(key.b), &(session->nonceTPM.b), nonceCaller, cipherSize, buffer); else ParmEncryptSym(session->symmetric.algorithm, session->authHashAlg, session->symmetric.keyBits.aes, &(key.b), nonceCaller, &(session->nonceTPM.b), cipherSize, buffer); return; } /* 10.2.6.6.6 CryptParameterDecryption() */ /* This function does in-place decryption of a command parameter. */ /* Error Returns Meaning */ /* TPM_RC_SIZE The number of bytes in the input buffer is less than the number of bytes to be decrypted. */ TPM_RC CryptParameterDecryption( TPM_HANDLE handle, // IN: encrypted session handle TPM2B *nonceCaller, // IN: nonce caller UINT32 bufferSize, // IN: size of parameter buffer UINT16 leadingSizeInByte, // IN: the size of the leading size field in // byte TPM2B_AUTH *extraKey, // IN: the authValue BYTE *buffer // IN/OUT: parameter buffer to be decrypted ) { SESSION *session = SessionGet(handle); // encrypt session // The HMAC key is going to be the concatenation of the session key and any // additional key material (like the authValue). The size of both of these // is the size of the buffer which can contain a TPMT_HA. TPM2B_TYPE(HMAC_KEY, (sizeof(extraKey->t.buffer) + sizeof(session->sessionKey.t.buffer))); TPM2B_HMAC_KEY key; // decryption key UINT32 cipherSize = 0; // size of cipher text // Retrieve encrypted data size. if(leadingSizeInByte == 2) { // The first two bytes of the buffer are the size of the // data to be decrypted cipherSize = (UINT32)BYTE_ARRAY_TO_UINT16(buffer); buffer = &buffer[2]; // advance the buffer } #ifdef TPM4B else if(leadingSizeInByte == 4) { // the leading size is four bytes so get the four byte size field cipherSize = BYTE_ARRAY_TO_UINT32(buffer); buffer = &buffer[4]; //advance pointer } #endif else { FAIL(FATAL_ERROR_INTERNAL); } if(cipherSize > bufferSize) return TPM_RC_SIZE; // Compute decryption key by concatenating sessionAuth with extra input key MemoryCopy2B(&key.b, &session->sessionKey.b, sizeof(key.t.buffer)); MemoryConcat2B(&key.b, &extraKey->b, sizeof(key.t.buffer)); if(session->symmetric.algorithm == TPM_ALG_XOR) // XOR parameter decryption formulation: // XOR(parameter, hash, sessionAuth, nonceNewer, nonceOlder) // Call XOR obfuscation function CryptXORObfuscation(session->authHashAlg, &key.b, nonceCaller, &(session->nonceTPM.b), cipherSize, buffer); else // Assume that it is one of the symmetric block ciphers. ParmDecryptSym(session->symmetric.algorithm, session->authHashAlg, session->symmetric.keyBits.sym, &key.b, nonceCaller, &session->nonceTPM.b, cipherSize, buffer); return TPM_RC_SUCCESS; } /* 10.2.6.6.7 CryptComputeSymmetricUnique() */ /* This function computes the unique field in public area for symmetric objects. */ void CryptComputeSymmetricUnique( TPMT_PUBLIC *publicArea, // IN: the object's public area TPMT_SENSITIVE *sensitive, // IN: the associated sensitive area TPM2B_DIGEST *unique // OUT: unique buffer ) { // For parents (symmetric and derivation), use an HMAC to compute // the 'unique' field if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted) && IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, decrypt)) { // Unique field is HMAC(sensitive->seedValue, sensitive->sensitive) HMAC_STATE hmacState; unique->b.size = CryptHmacStart2B(&hmacState, publicArea->nameAlg, &sensitive->seedValue.b); CryptDigestUpdate2B(&hmacState.hashState, &sensitive->sensitive.any.b); CryptHmacEnd2B(&hmacState, &unique->b); } else { HASH_STATE hashState; // Unique := Hash(sensitive->seedValue || sensitive->sensitive) unique->t.size = CryptHashStart(&hashState, publicArea->nameAlg); CryptDigestUpdate2B(&hashState, &sensitive->seedValue.b); CryptDigestUpdate2B(&hashState, &sensitive->sensitive.any.b); CryptHashEnd2B(&hashState, &unique->b); } return; } /* 10.2.6.6.8 CryptCreateObject() */ /* This function creates an object. For an asymmetric key, it will create a key pair and, for a parent key, a seed value for child protections. */ /* For an symmetric object, (TPM_ALG_SYMCIPHER or TPM_ALG_KEYEDHASH), it will create a secret key if the caller did not provide one. It will create a random secret seed value that is hashed with the secret value to create the public unique value. */ /* publicArea, sensitive, and sensitiveCreate are the only required parameters and are the only ones that are used by TPM2_Create(). The other parameters are optional and are used when the generated Object needs to be deterministic. This is the case for both Primary Objects and Derived Objects. */ /* When a seed value is provided, a RAND_STATE will be populated and used for all operations in the object generation that require a random number. In the simplest case, TPM2_CreatePrimary() will use seed, label and context with context being the hash of the template. If the Primary Object is in the Endorsement hierarchy, it will also populate proof with ehProof. */ /* For derived keys, seed will be the secret value from the parent, label and context will be set according to the parameters of TPM2_CreateLoaded() and hashAlg will be set which causes the RAND_STATE to be a KDF generator. */ /* Error Returns Meaning */ /* TPM_RC_KEY a provided key is not an allowed value */ /* TPM_RC_KEY_SIZE key size in the public area does not match the size in the sensitive creation area for a symmetric key */ /* TPM_RC_NO_RESULT unable to get random values (only in derivation) */ /* TPM_RC_RANGE for an RSA key, the exponent is not supported */ /* TPM_RC_SIZE sensitive data size is larger than allowed for the scheme for a keyed hash object */ /* TPM_RC_VALUE exponent is not prime or could not find a prime using the provided parameters for an RSA key; unsupported name algorithm for an ECC key */ TPM_RC CryptCreateObject( OBJECT *object, // IN: new object structure pointer TPMS_SENSITIVE_CREATE *sensitiveCreate, // IN: sensitive creation RAND_STATE *rand // IN: the random number generator // to use ) { TPMT_PUBLIC *publicArea = &object->publicArea; TPMT_SENSITIVE *sensitive = &object->sensitive; TPM_RC result = TPM_RC_SUCCESS; // // Set the sensitive type for the object sensitive->sensitiveType = publicArea->type; // For all objects, copy the initial authorization data sensitive->authValue = sensitiveCreate->userAuth; // If the TPM is the source of the data, set the size of the provided data to // zero so that there's no confusion about what to do. if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sensitiveDataOrigin)) sensitiveCreate->data.t.size = 0; // Generate the key and unique fields for the asymmetric keys and just the // sensitive value for symmetric object switch(publicArea->type) { #if ALG_RSA // Create RSA key case TPM_ALG_RSA: // RSA uses full object so that it has a place to put the private // exponent result = CryptRsaGenerateKey(object, rand); break; #endif // TPM_ALG_RSA #if ALG_ECC // Create ECC key case TPM_ALG_ECC: result = CryptEccGenerateKey(publicArea, sensitive, rand); break; #endif // TPM_ALG_ECC case TPM_ALG_SYMCIPHER: result = CryptGenerateKeySymmetric(publicArea, sensitive, sensitiveCreate, rand); break; case TPM_ALG_KEYEDHASH: result = CryptGenerateKeyedHash(publicArea, sensitive, sensitiveCreate, rand); break; default: FAIL(FATAL_ERROR_INTERNAL); break; } if(result != TPM_RC_SUCCESS) return result; // Create the sensitive seed value // If this is a primary key in the endorsement hierarchy, stir the DRBG state // This implementation uses both shProof and ehProof to make sure that there // is no leakage of either. if(object->attributes.primary && object->attributes.epsHierarchy) { DRBG_AdditionalData((DRBG_STATE *)rand, &gp.shProof.b); DRBG_AdditionalData((DRBG_STATE *)rand, &gp.ehProof.b); } // Generate a seedValue that is the size of the digest produced by nameAlg sensitive->seedValue.t.size = DRBG_Generate(rand, object->sensitive.seedValue.t.buffer, CryptHashGetDigestSize(publicArea->nameAlg)); if(g_inFailureMode) return TPM_RC_FAILURE; else if(sensitive->seedValue.t.size == 0) return TPM_RC_NO_RESULT; // For symmetric objects, need to compute the unique value for the public area if(publicArea->type == TPM_ALG_SYMCIPHER || publicArea->type == TPM_ALG_KEYEDHASH) { CryptComputeSymmetricUnique(publicArea, sensitive, &publicArea->unique.sym); } else { // if this is an asymmetric key and it isn't a parent, then // get rid of the seed. if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign) || !IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted)) memset(&sensitive->seedValue, 0, sizeof(sensitive->seedValue)); } // Compute the name PublicMarshalAndComputeName(publicArea, &object->name); return result; } /* 10.2.6.6.9 CryptGetSignHashAlg() */ /* Get the hash algorithm of signature from a TPMT_SIGNATURE structure. It assumes the signature is not NULL This is a function for easy access */ TPMI_ALG_HASH CryptGetSignHashAlg( TPMT_SIGNATURE *auth // IN: signature ) { if(auth->sigAlg == TPM_ALG_NULL) FAIL(FATAL_ERROR_INTERNAL); // Get authHash algorithm based on signing scheme switch(auth->sigAlg) { #if ALG_RSA // If RSA is supported, both RSASSA and RSAPSS are required # if !defined TPM_ALG_RSASSA || !defined TPM_ALG_RSAPSS # error "RSASSA and RSAPSS are required for RSA" # endif case TPM_ALG_RSASSA: return auth->signature.rsassa.hash; case TPM_ALG_RSAPSS: return auth->signature.rsapss.hash; #endif //TPM_ALG_RSA #if ALG_ECC // If ECC is defined, ECDSA is mandatory # ifndef TPM_ALG_ECDSA # error "ECDSA is required for ECC" # endif case TPM_ALG_ECDSA: // SM2 and ECSCHNORR are optional # if ALG_SM2 case TPM_ALG_SM2: # endif # if ALG_ECSCHNORR case TPM_ALG_ECSCHNORR: # endif //all ECC signatures look the same return auth->signature.ecdsa.hash; # if ALG_ECDAA // Don't know how to verify an ECDAA signature case TPM_ALG_ECDAA: break; # endif #endif //TPM_ALG_ECC case TPM_ALG_HMAC: return auth->signature.hmac.hashAlg; default: break; } return TPM_ALG_NULL; } /* 10.2.6.6.10 CryptIsSplitSign() */ /* This function us used to determine if the signing operation is a split signing operation that required a TPM2_Commit(). */ BOOL CryptIsSplitSign( TPM_ALG_ID scheme // IN: the algorithm selector ) { switch(scheme) { # if ALG_ECDAA case TPM_ALG_ECDAA: return TRUE; break; # endif // TPM_ALG_ECDAA default: return FALSE; break; } } /* 10.2.6.6.11 CryptIsAsymSignScheme() */ /* This function indicates if a scheme algorithm is a sign algorithm. */ BOOL CryptIsAsymSignScheme( TPMI_ALG_PUBLIC publicType, // IN: Type of the object TPMI_ALG_ASYM_SCHEME scheme // IN: the scheme ) { BOOL isSignScheme = TRUE; switch(publicType) { #if ALG_RSA case TPM_ALG_RSA: switch(scheme) { # if !defined TPM_ALG_RSASSA || !defined TPM_ALG_RSAPSS # error "RSASSA and PSAPSS required if RSA used." # endif case TPM_ALG_RSASSA: case TPM_ALG_RSAPSS: break; default: isSignScheme = FALSE; break; } break; #endif //TPM_ALG_RSA #if ALG_ECC // If ECC is implemented ECDSA is required case TPM_ALG_ECC: switch(scheme) { // Support for ECDSA is required for ECC case TPM_ALG_ECDSA: #if ALG_ECDAA // ECDAA is optional case TPM_ALG_ECDAA: #endif #if ALG_ECSCHNORR // Schnorr is also optional case TPM_ALG_ECSCHNORR: #endif #if ALG_SM2 // SM2 is optional case TPM_ALG_SM2: #endif break; default: isSignScheme = FALSE; break; } break; #endif //TPM_ALG_ECC default: isSignScheme = FALSE; break; } return isSignScheme; } /* 10.2.6.6.12 CryptIsAsymDecryptScheme() */ /* This function indicate if a scheme algorithm is a decrypt algorithm. */ BOOL CryptIsAsymDecryptScheme( TPMI_ALG_PUBLIC publicType, // IN: Type of the object TPMI_ALG_ASYM_SCHEME scheme // IN: the scheme ) { BOOL isDecryptScheme = TRUE; switch(publicType) { #if ALG_RSA case TPM_ALG_RSA: switch(scheme) { case TPM_ALG_RSAES: case TPM_ALG_OAEP: break; default: isDecryptScheme = FALSE; break; } break; #endif //TPM_ALG_RSA #if ALG_ECC // If ECC is implemented ECDH is required case TPM_ALG_ECC: switch(scheme) { #if !ALG_ECDH # error "ECDH is required for ECC" #endif case TPM_ALG_ECDH: #if ALG_SM2 case TPM_ALG_SM2: #endif #if ALG_ECMQV case TPM_ALG_ECMQV: #endif break; default: isDecryptScheme = FALSE; break; } break; #endif //TPM_ALG_ECC default: isDecryptScheme = FALSE; break; } return isDecryptScheme; } /* 10.2.6.6.13 CryptSelectSignScheme() */ /* This function is used by the attestation and signing commands. It implements the rules for selecting the signature scheme to use in signing. This function requires that the signing key either be TPM_RH_NULL or be loaded. */ /* If a default scheme is defined in object, the default scheme should be chosen, otherwise, the input scheme should be chosen. In the case that both object and input scheme has a non-NULL scheme algorithm, if the schemes are compatible, the input scheme will be chosen. */ /* This function should not be called if 'signObject->publicArea.type' == TPM_ALG_SYMCIPHER. */ /* Return Values Meaning */ /* TRUE scheme selected */ /* FALSE both scheme and key's default scheme are empty; or scheme is empty while key's default scheme requires explicit input scheme (split signing); or non-empty default key scheme differs from scheme */ BOOL CryptSelectSignScheme( OBJECT *signObject, // IN: signing key TPMT_SIG_SCHEME *scheme // IN/OUT: signing scheme ) { TPMT_SIG_SCHEME *objectScheme; TPMT_PUBLIC *publicArea; BOOL OK; // If the signHandle is TPM_RH_NULL, then the NULL scheme is used, regardless // of the setting of scheme if(signObject == NULL) { OK = TRUE; scheme->scheme = TPM_ALG_NULL; scheme->details.any.hashAlg = TPM_ALG_NULL; } else { // assignment to save typing. publicArea = &signObject->publicArea; // A symmetric cipher can be used to encrypt and decrypt but it can't // be used for signing if(publicArea->type == TPM_ALG_SYMCIPHER) return FALSE; // Point to the scheme object if(CryptIsAsymAlgorithm(publicArea->type)) objectScheme = (TPMT_SIG_SCHEME *)&publicArea->parameters.asymDetail.scheme; else objectScheme = (TPMT_SIG_SCHEME *)&publicArea->parameters.keyedHashDetail.scheme; // If the object doesn't have a default scheme, then use the // input scheme. if(objectScheme->scheme == TPM_ALG_NULL) { // Input and default can't both be NULL OK = (scheme->scheme != TPM_ALG_NULL); // Assume that the scheme is compatible with the key. If not, // an error will be generated in the signing operation. } else if(scheme->scheme == TPM_ALG_NULL) { // input scheme is NULL so use default // First, check to see if the default requires that the caller // provided scheme data OK = !CryptIsSplitSign(objectScheme->scheme); if(OK) { // The object has a scheme and the input is TPM_ALG_NULL so copy // the object scheme as the final scheme. It is better to use a // structure copy than a copy of the individual fields. *scheme = *objectScheme; } } else { // Both input and object have scheme selectors // If the scheme and the hash are not the same then... // NOTE: the reason that there is no copy here is that the input // might contain extra data for a split signing scheme and that // data is not in the object so, it has to be preserved. OK = (objectScheme->scheme == scheme->scheme) && (objectScheme->details.any.hashAlg == scheme->details.any.hashAlg); } } return OK; } /* 10.2.6.6.14 CryptSign() */ /* Sign a digest with asymmetric key or HMAC. This function is called by attestation commands and the generic TPM2_Sign() command. This function checks the key scheme and digest size. It does not check if the sign operation is allowed for restricted key. It should be checked before the function is called. The function will assert if the key is not a signing key. */ /* Error Returns Meaning */ /* TPM_RC_SCHEME signScheme is not compatible with the signing key type */ /* TPM_RC_VALUE digest value is greater than the modulus of signHandle or size of hashData does not match hash algorithm insignScheme (for an RSA key); invalid commit status or failed to generate r value (for an ECC key) */ TPM_RC CryptSign( OBJECT *signKey, // IN: signing key TPMT_SIG_SCHEME *signScheme, // IN: sign scheme. TPM2B_DIGEST *digest, // IN: The digest being signed TPMT_SIGNATURE *signature // OUT: signature ) { TPM_RC result = TPM_RC_SCHEME; // Initialize signature scheme signature->sigAlg = signScheme->scheme; // If the signature algorithm is TPM_ALG_NULL or the signing key is NULL, // then we are done if((signature->sigAlg == TPM_ALG_NULL) || (signKey == NULL)) return TPM_RC_SUCCESS; // Initialize signature hash // Note: need to do the check for TPM_ALG_NULL first because the null scheme // doesn't have a hashAlg member. signature->signature.any.hashAlg = signScheme->details.any.hashAlg; // perform sign operation based on different key type switch(signKey->publicArea.type) { #if ALG_RSA case TPM_ALG_RSA: result = CryptRsaSign(signature, signKey, digest, NULL); break; #endif //TPM_ALG_RSA #if ALG_ECC case TPM_ALG_ECC: // The reason that signScheme is passed to CryptEccSign but not to the // other signing methods is that the signing for ECC may be split and // need the 'r' value that is in the scheme but not in the signature. result = CryptEccSign(signature, signKey, digest, (TPMT_ECC_SCHEME *)signScheme, NULL); break; #endif //TPM_ALG_ECC case TPM_ALG_KEYEDHASH: result = CryptHmacSign(signature, signKey, digest); break; default: FAIL(FATAL_ERROR_INTERNAL); break; } return result; } /* 10.2.6.6.15 CryptValidateSignature() */ /* This function is used to verify a signature. It is called by TPM2_VerifySignature() and TPM2_PolicySigned(). */ /* Since this operation only requires use of a public key, no consistency checks are necessary for the key to signature type because a caller can load any public key that they like with any scheme that they like. This routine simply makes sure that the signature is correct, whatever the type. */ /* Error Returns Meaning */ /* TPM_RC_SIGNATURE the signature is not genuine */ /* TPM_RC_SCHEME the scheme is not supported */ /* TPM_RC_HANDLE an HMAC key was selected but the private part of the key is not loaded */ TPM_RC CryptValidateSignature( TPMI_DH_OBJECT keyHandle, // IN: The handle of sign key TPM2B_DIGEST *digest, // IN: The digest being validated TPMT_SIGNATURE *signature // IN: signature ) { // NOTE: HandleToObject will either return a pointer to a loaded object or // will assert. It will never return a non-valid value. This makes it save // to initialize 'publicArea' with the return value from HandleToObject() // without checking it first. OBJECT *signObject = HandleToObject(keyHandle); TPMT_PUBLIC *publicArea = &signObject->publicArea; TPM_RC result = TPM_RC_SCHEME; // The input unmarshaling should prevent any input signature from being // a NULL signature, but just in case if(signature->sigAlg == TPM_ALG_NULL) return TPM_RC_SIGNATURE; switch(publicArea->type) { #if ALG_RSA case TPM_ALG_RSA: { // // Call RSA code to verify signature result = CryptRsaValidateSignature(signature, signObject, digest); break; } #endif //TPM_ALG_RSA #if ALG_ECC case TPM_ALG_ECC: result = CryptEccValidateSignature(signature, signObject, digest); break; #endif // TPM_ALG_ECC case TPM_ALG_KEYEDHASH: if(signObject->attributes.publicOnly) result = TPM_RCS_HANDLE; else result = CryptHMACVerifySignature(signObject, digest, signature); break; default: break; } return result; } /* 10.2.6.6.16 CryptGetTestResult */ /* This function returns the results of a self-test function. */ /* NOTE: the behavior in this function is NOT the correct behavior for a real TPM implementation. An artificial behavior is placed here due to the limitation of a software simulation environment. For the correct behavior, consult the part 3 specification for TPM2_GetTestResult(). */ TPM_RC CryptGetTestResult( TPM2B_MAX_BUFFER *outData // OUT: test result data ) { outData->t.size = 0; return TPM_RC_SUCCESS; } /* 10.2.6.6.17 CryptValidateKeys() */ /* This function is used to verify that the key material of an object is valid. For a publicOnly object, the key is verified for size and, if it is an ECC key, it is verified to be on the specified curve. For a key with a sensitive area, the binding between the public and private parts of the key are verified. If the nameAlg of the key is TPM_ALG_NULL, then the size of the sensitive area is verified but the public portion is not verified, unless the key is an RSA key. For an RSA key, the reason for loading the sensitive area is to use it. The only way to use a private RSA key is to compute the private exponent. To compute the private exponent, the public modulus is used. */ /* Error Returns Meaning */ /* TPM_RC_BINDING the public and private parts are not cryptographically bound */ /* TPM_RC_HASH cannot have a publicOnly key with nameAlg of TPM_ALG_NULL */ /* TPM_RC_KEY the public unique is not valid */ /* TPM_RC_KEY_SIZE the private area key is not valid */ /* TPM_RC_TYPE the types of the sensitive and private parts do not match */ TPM_RC CryptValidateKeys( TPMT_PUBLIC *publicArea, TPMT_SENSITIVE *sensitive, TPM_RC blamePublic, TPM_RC blameSensitive ) { TPM_RC result; UINT16 keySizeInBytes; UINT16 digestSize = CryptHashGetDigestSize(publicArea->nameAlg); TPMU_PUBLIC_PARMS *params = &publicArea->parameters; TPMU_PUBLIC_ID *unique = &publicArea->unique; if(sensitive != NULL) { // Make sure that the types of the public and sensitive are compatible if(publicArea->type != sensitive->sensitiveType) return TPM_RCS_TYPE + blameSensitive; // Make sure that the authValue is not bigger than allowed // If there is no name algorithm, then the size just needs to be less than // the maximum size of the buffer used for authorization. That size check // was made during unmarshaling of the sensitive area if((sensitive->authValue.t.size) > digestSize && (digestSize > 0)) return TPM_RCS_SIZE + blameSensitive; } switch(publicArea->type) { #if ALG_RSA case TPM_ALG_RSA: keySizeInBytes = BITS_TO_BYTES(params->rsaDetail.keyBits); // Regardless of whether there is a sensitive area, the public modulus // needs to have the correct size. Otherwise, it can't be used for // any public key operation nor can it be used to compute the private // exponent. // NOTE: This implementation only supports key sizes that are multiples // of 1024 bits which means that the MSb of the 0th byte will always be // SET in either a prime or the public modulus. if((unique->rsa.t.size != keySizeInBytes) || (unique->rsa.t.buffer[0] < 0x80)) return TPM_RCS_KEY + blamePublic; if(params->rsaDetail.exponent != 0 && params->rsaDetail.exponent < 7) return TPM_RCS_VALUE + blamePublic; if(sensitive != NULL) { // If there is a sensitive area, it has to be the correct size // including having the correct high order bit SET. if(((sensitive->sensitive.rsa.t.size * 2) != keySizeInBytes) || (sensitive->sensitive.rsa.t.buffer[0] < 0x80)) return TPM_RCS_KEY_SIZE + blameSensitive; } break; #endif #if ALG_ECC case TPM_ALG_ECC: { TPMI_ECC_CURVE curveId; curveId = params->eccDetail.curveID; keySizeInBytes = BITS_TO_BYTES(CryptEccGetKeySizeForCurve(curveId)); if(sensitive == NULL) { // Validate the public key size if(unique->ecc.x.t.size != keySizeInBytes || unique->ecc.y.t.size != keySizeInBytes) return TPM_RCS_KEY + blamePublic; if(publicArea->nameAlg != TPM_ALG_NULL) { if(!CryptEccIsPointOnCurve(curveId, &unique->ecc)) return TPM_RCS_ECC_POINT + blamePublic; } } else { // If the nameAlg is TPM_ALG_NULL, then only verify that the // private part of the key is OK. if(!CryptEccIsValidPrivateKey(&sensitive->sensitive.ecc, curveId)) return TPM_RCS_KEY_SIZE; if(publicArea->nameAlg != TPM_ALG_NULL) { // Full key load, verify that the public point belongs to the // private key. TPMS_ECC_POINT toCompare; result = CryptEccPointMultiply(&toCompare, curveId, NULL, &sensitive->sensitive.ecc, NULL, NULL); if(result != TPM_RC_SUCCESS) return TPM_RCS_BINDING; else { // Make sure that the private key generated the public key. // The input values and the values produced by the point // multiply may not be the same size so adjust the computed // value to match the size of the input value by adding or // removing zeros. AdjustNumberB(&toCompare.x.b, unique->ecc.x.t.size); AdjustNumberB(&toCompare.y.b, unique->ecc.y.t.size); if(!MemoryEqual2B(&unique->ecc.x.b, &toCompare.x.b) || !MemoryEqual2B(&unique->ecc.y.b, &toCompare.y.b)) return TPM_RCS_BINDING; } } } break; } #endif default: // Checks for SYMCIPHER and KEYEDHASH are largely the same // If public area has a nameAlg, then validate the public area size // and if there is also a sensitive area, validate the binding // For consistency, if the object is public-only just make sure that // the unique field is consistent with the name algorithm if(sensitive == NULL) { if(unique->sym.t.size != digestSize) return TPM_RCS_KEY + blamePublic; } else { // Make sure that the key size in the sensitive area is consistent. if(publicArea->type == TPM_ALG_SYMCIPHER) { result = CryptSymKeyValidate(¶ms->symDetail.sym, &sensitive->sensitive.sym); if(result != TPM_RC_SUCCESS) return result + blameSensitive; } else { // For a keyed hash object, the key has to be less than the // smaller of the block size of the hash used in the scheme or // 128 bytes. The worst case value is limited by the // unmarshaling code so the only thing left to be checked is // that it does not exceed the block size of the hash. // by the hash algorithm of the scheme. TPMT_KEYEDHASH_SCHEME *scheme; UINT16 maxSize; scheme = ¶ms->keyedHashDetail.scheme; if(scheme->scheme == TPM_ALG_XOR) { maxSize = CryptHashGetBlockSize(scheme->details.xorr.hashAlg); } else if(scheme->scheme == TPM_ALG_HMAC) { maxSize = CryptHashGetBlockSize(scheme->details.hmac.hashAlg); } else if(scheme->scheme == TPM_ALG_NULL) { // Not signing or xor so must be a data block maxSize = 128; } else return TPM_RCS_SCHEME + blamePublic; if(sensitive->sensitive.bits.t.size > maxSize) return TPM_RCS_KEY_SIZE + blameSensitive; } // If there is a nameAlg, check the binding if(publicArea->nameAlg != TPM_ALG_NULL) { TPM2B_DIGEST compare; if(sensitive->seedValue.t.size != digestSize) return TPM_RCS_KEY_SIZE + blameSensitive; CryptComputeSymmetricUnique(publicArea, sensitive, &compare); if(!MemoryEqual2B(&unique->sym.b, &compare.b)) return TPM_RC_BINDING; } } break; } // For a parent, need to check that the seedValue is the correct size for // protections. It should be at least half the size of the nameAlg if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted) && IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, decrypt) && sensitive != NULL && publicArea->nameAlg != TPM_ALG_NULL) { if((sensitive->seedValue.t.size < (digestSize / 2)) || (sensitive->seedValue.t.size > digestSize)) return TPM_RCS_SIZE + blameSensitive; } return TPM_RC_SUCCESS; } /* 10.2.6.6.18 CryptSelectMac() */ /* This function is used to set the MAC scheme based on the key parameters and the input scheme. */ /* Error Returns Meaning */ /* TPM_RC_SCHEME the scheme is not a valid mac scheme */ /* TPM_RC_TYPE the input key is not a type that supports a mac */ /* TPM_RC_VALUE the input scheme and the key scheme are not compatible */ TPM_RC CryptSelectMac( TPMT_PUBLIC *publicArea, TPMI_ALG_MAC_SCHEME *inMac ) { TPM_ALG_ID macAlg = TPM_ALG_NULL; switch(publicArea->type) { case TPM_ALG_KEYEDHASH: { // Local value to keep lines from getting too long TPMT_KEYEDHASH_SCHEME *scheme; scheme = &publicArea->parameters.keyedHashDetail.scheme; // Expect that the scheme is either HMAC or NULL if(scheme->scheme != TPM_ALG_NULL) macAlg = scheme->details.hmac.hashAlg; break; } case TPM_ALG_SYMCIPHER: { TPMT_SYM_DEF_OBJECT *scheme; scheme = &publicArea->parameters.symDetail.sym; // Expect that the scheme is either valid symmetric cipher or NULL if(scheme->algorithm != TPM_ALG_NULL) macAlg = scheme->mode.sym; break; } default: return TPM_RCS_TYPE; } // If the input value is not TPM_ALG_NULL ... if(*inMac != TPM_ALG_NULL) { // ... then either the scheme in the key must be TPM_ALG_NULL or the input // value must match if((macAlg != TPM_ALG_NULL) && (*inMac != macAlg)) return TPM_RCS_VALUE; } else { // Since the input value is TPM_ALG_NULL, then the key value can't be // TPM_ALG_NULL if(macAlg == TPM_ALG_NULL) return TPM_RCS_VALUE; *inMac = macAlg; } if(!CryptMacIsValidForKey(publicArea->type, *inMac, FALSE)) return TPM_RCS_SCHEME; return TPM_RC_SUCCESS; } /* 10.2.6.6.19 CryptMacIsValidForKey() */ /* Check to see if the key type is compatible with the mac type */ BOOL CryptMacIsValidForKey( TPM_ALG_ID keyType, TPM_ALG_ID macAlg, BOOL flag ) { switch(keyType) { case TPM_ALG_KEYEDHASH: return CryptHashIsValidAlg(macAlg, flag); break; case TPM_ALG_SYMCIPHER: return CryptSmacIsValidAlg(macAlg, flag); break; default: break; } return FALSE; } /* 10.2.6.6.20 CryptSmacIsValidAlg() */ /* This function is used to test if an algorithm is a supported SMAC algorithm. It needs to be updated as new algorithms are added. */ BOOL CryptSmacIsValidAlg( TPM_ALG_ID alg, BOOL FLAG // IN: Indicates if TPM_ALG_NULL is valid ) { switch (alg) { #if ALG_CMAC case TPM_ALG_CMAC: return TRUE; break; #endif case TPM_ALG_NULL: return FLAG; break; default: return FALSE; } } /* 10.2.6.6.21 CryptSymModeIsValid() */ /* Function checks to see if an algorithm ID is a valid, symmetric block cipher mode for the TPM. If flag is SET, them TPM_ALG_NULL is a valid mode. not include the modes used for SMAC */ BOOL CryptSymModeIsValid( TPM_ALG_ID mode, BOOL flag ) { switch(mode) { #if ALG_CTR case TPM_ALG_CTR: #endif // ALG_CTR #if ALG_OFB case TPM_ALG_OFB: #endif // ALG_OFB #if ALG_CBC case TPM_ALG_CBC: #endif // ALG_CBC #if ALG_CFB case TPM_ALG_CFB: #endif // ALG_CFB #if ALG_ECB case TPM_ALG_ECB: #endif // ALG_ECB return TRUE; case TPM_ALG_NULL: return flag; break; default: break; } return FALSE; } libtpms-0.9.3/src/tpm2/DA.c000066400000000000000000000222511421143571500153030ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Dictionary Attack Logic. */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: DA.c 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ /* 8.2 DA.c */ /* 8.2.1 Introduction */ /* This file contains the functions and data definitions relating to the dictionary attack logic. */ /* 8.2.2 Includes and Data Definitions */ #define DA_C #include "Tpm.h" /* 8.2.3 Functions */ /* 8.2.3.1 DAPreInstall_Init() */ /* This function initializes the DA parameters to their manufacturer-default values. The default values are determined by a platform-specific specification. */ /* This function should not be called outside of a manufacturing or simulation environment. */ /* The DA parameters will be restored to these initial values by TPM2_Clear(). */ void DAPreInstall_Init( void ) { gp.failedTries = 0; gp.maxTries = 3; gp.recoveryTime = 1000; // in seconds (~16.67 minutes) gp.lockoutRecovery = 1000; // in seconds gp.lockOutAuthEnabled = TRUE; // Use of lockoutAuth is enabled // Record persistent DA parameter changes to NV NV_SYNC_PERSISTENT(failedTries); NV_SYNC_PERSISTENT(maxTries); NV_SYNC_PERSISTENT(recoveryTime); NV_SYNC_PERSISTENT(lockoutRecovery); NV_SYNC_PERSISTENT(lockOutAuthEnabled); return; } /* 8.2.3.2 DAStartup() */ /* This function is called by TPM2_Startup() to initialize the DA parameters. In the case of Startup(CLEAR), use of lockoutAuth will be enabled if the lockout recovery time is 0. Otherwise, lockoutAuth will not be enabled until the TPM has been continuously powered for the lockoutRecovery time. */ /* This function requires that NV be available and not rate limiting. */ BOOL DAStartup( STARTUP_TYPE type // IN: startup type ) { NOT_REFERENCED(type); #if !ACCUMULATE_SELF_HEAL_TIMER _plat__TimerWasReset(); s_selfHealTimer = 0; s_lockoutTimer = 0; #else if(_plat__TimerWasReset()) { if(!NV_IS_ORDERLY) { // If shutdown was not orderly, then don't really know if go.time has // any useful value so reset the timer to 0. This is what the tick // was reset to s_selfHealTimer = 0; s_lockoutTimer = 0; } else { // If we know how much time was accumulated at the last orderly shutdown // subtract that from the saved timer values so that they effectively // have the accumulated values s_selfHealTimer -= go.time; s_lockoutTimer -= go.time; } } #endif // For any Startup(), if lockoutRecovery is 0, enable use of lockoutAuth. if(gp.lockoutRecovery == 0) { gp.lockOutAuthEnabled = TRUE; // Record the changes to NV NV_SYNC_PERSISTENT(lockOutAuthEnabled); } // If DA has not been disabled and the previous shutdown is not orderly // failedTries is not already at its maximum then increment 'failedTries' if(gp.recoveryTime != 0 && gp.failedTries < gp.maxTries && !IS_ORDERLY(g_prevOrderlyState)) { #if USE_DA_USED gp.failedTries += g_daUsed; g_daUsed = FALSE; #else gp.failedTries++; #endif // Record the change to NV NV_SYNC_PERSISTENT(failedTries); } // Before Startup, the TPM will not do clock updates. At startup, need to // do a time update which will do the DA update. TimeUpdate(); return TRUE; } /* 8.2.3.3 DARegisterFailure() */ /* This function is called when an authorization failure occurs on an entity that is subject to dictionary-attack protection. When a DA failure is triggered, register the failure by resetting the relevant self-healing timer to the current time. */ void DARegisterFailure( TPM_HANDLE handle // IN: handle for failure ) { // Reset the timer associated with lockout if the handle is the lockoutAuth. if(handle == TPM_RH_LOCKOUT) s_lockoutTimer = g_time; else s_selfHealTimer = g_time; return; } /* 8.2.3.4 DASelfHeal() */ /* This function is called to check if sufficient time has passed to allow decrement of failedTries or to re-enable use of lockoutAuth. */ /* This function should be called when the time interval is updated. */ void DASelfHeal( void ) { // Regular authorization self healing logic // If no failed authorization tries, do nothing. Otherwise, try to // decrease failedTries if(gp.failedTries != 0) { // if recovery time is 0, DA logic has been disabled. Clear failed tries // immediately if(gp.recoveryTime == 0) { gp.failedTries = 0; // Update NV record NV_SYNC_PERSISTENT(failedTries); } else { UINT64 decreaseCount; #if 0 // Errata eliminates this code // In the unlikely event that failedTries should become larger than // maxTries if(gp.failedTries > gp.maxTries) gp.failedTries = gp.maxTries; #endif // How much can failedTries be decreased // Cast s_selfHealTimer to an int in case it became negative at // startup decreaseCount = ((g_time - (INT64)s_selfHealTimer) / 1000) / gp.recoveryTime; if(gp.failedTries <= (UINT32)decreaseCount) // should not set failedTries below zero gp.failedTries = 0; else gp.failedTries -= (UINT32)decreaseCount; // the cast prevents overflow of the product s_selfHealTimer += (decreaseCount * (UINT64)gp.recoveryTime) * 1000; if(decreaseCount != 0) // If there was a change to the failedTries, record the changes // to NV NV_SYNC_PERSISTENT(failedTries); } } // LockoutAuth self healing logic // If lockoutAuth is enabled, do nothing. Otherwise, try to see if we // may enable it if(!gp.lockOutAuthEnabled) { // if lockout authorization recovery time is 0, a reboot is required to // re-enable use of lockout authorization. Self-healing would not // apply in this case. if(gp.lockoutRecovery != 0) { if(((g_time - (INT64)s_lockoutTimer) / 1000) >= gp.lockoutRecovery) { gp.lockOutAuthEnabled = TRUE; // Record the changes to NV NV_SYNC_PERSISTENT(lockOutAuthEnabled); } } } return; } libtpms-0.9.3/src/tpm2/DA_fp.h000066400000000000000000000071651421143571500160040ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: DA_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ #ifndef DA_FP_H #define DA_FP_H void DAPreInstall_Init( void ); void DAInit( void ); BOOL DAStartup( STARTUP_TYPE type // IN: startup type ); void DARegisterFailure( TPM_HANDLE handle // IN: handle for failure ); void DASelfHeal( void ); #endif libtpms-0.9.3/src/tpm2/DebugHelpers.c000066400000000000000000000126541421143571500173760ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Debug Helper */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: DebugHelpers.c 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2019 - 2021 */ /* */ /********************************************************************************/ /* C.13 DebugHelpers.c */ /* C.13.1. Description */ /* This file contains the NV read and write access methods. This implementation uses RAM/file and does not manage the RAM/file as NV blocks. The implementation may become more sophisticated over time. */ /* C.13.2. Includes and Local */ #include #include #include "Platform.h" #include "DebugHelpers_fp.h" #if CERTIFYX509_DEBUG const char *debugFileName = "DebugFile.txt"; /* C.13.2.1. fileOpen() */ /* This exists to allow use of the safe version of fopen() with a MS runtime. */ static FILE * fileOpen( const char *fn, const char *mode ) { FILE *f; # if defined _MSC_VER if(fopen_s(&f, fn, mode) != 0) f = NULL; # else f = fopen(fn, mode); # endif return f; } /* C.13.2.2. DebugFileInit() */ /* This function initializes the file containing the debug data with the time of the file creation. */ /* This function opens the file used to hold the debug data. */ /* Return Value Meaning */ /* 0 success */ /* != 0 error */ int DebugFileInit( void ) { FILE *f = NULL; time_t t = time(NULL); // // Get current date and time. # if defined _MSC_VER char timeString[100]; ctime_s(timeString, (size_t)sizeof(timeString), &t); # else char *timeString; timeString = ctime(&t); # endif // Try to open the debug file f = fileOpen(debugFileName, "w"); if(f) { /* Initialize the contents with the time. */ fprintf(f, "%s\n", timeString); fclose(f); return 0; } return -1; } /* C.13.2.3. DebugDumpBuffer() */ void DebugDumpBuffer( int size, unsigned char *buf, const char *identifier ) { int i; // FILE *f = fileOpen(debugFileName, "a"); if(!f) return; if(identifier) fprintf(f, "%s\n", identifier); if(buf) { for(i = 0; i < size; i++) { if(((i % 16) == 0) && (i)) fprintf(f, "\n"); fprintf(f, " %02X", buf[i]); } if((size % 16) != 0) fprintf(f, "\n"); } fclose(f); } #endif // CERTIFYX509_DEBUG libtpms-0.9.3/src/tpm2/DebugHelpers_fp.h000066400000000000000000000071111421143571500200600ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Debug Helper */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: DebugHelpers_fp.h 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2019 - 2021 */ /* */ /********************************************************************************/ #ifndef DEBUGHELPERS_FP_H #define DEBUGHELPERS_FP_H int DebugFileInit( void ); void DebugFileClose( void ); void DebugDumpBuffer( int size, unsigned char *buf, const char *identifier ); #endif libtpms-0.9.3/src/tpm2/DictionaryAttackLockReset_fp.h000066400000000000000000000073061421143571500225660ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: DictionaryAttackLockReset_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef DICTIONARYATTACKLOCKRESET_FP_H #define DICTIONARYATTACKLOCKRESET_FP_H typedef struct { TPMI_RH_LOCKOUT lockHandle; } DictionaryAttackLockReset_In; #define RC_DictionaryAttackLockReset_lockHandle (TPM_RC_H + TPM_RC_1) TPM_RC TPM2_DictionaryAttackLockReset( DictionaryAttackLockReset_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/DictionaryAttackParameters_fp.h000066400000000000000000000077651421143571500230070ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: DictionaryAttackParameters_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef DICTIONARYATTACKPARAMETERS_FP_H #define DICTIONARYATTACKPARAMETERS_FP_H typedef struct { TPMI_RH_LOCKOUT lockHandle; UINT32 newMaxTries; UINT32 newRecoveryTime; UINT32 lockoutRecovery; } DictionaryAttackParameters_In; #define RC_DictionaryAttackParameters_lockHandle (TPM_RC_H + TPM_RC_1) #define RC_DictionaryAttackParameters_newMaxTries (TPM_RC_P + TPM_RC_1) #define RC_DictionaryAttackParameters_newRecoveryTime (TPM_RC_P + TPM_RC_2) #define RC_DictionaryAttackParameters_lockoutRecovery (TPM_RC_P + TPM_RC_3) TPM_RC TPM2_DictionaryAttackParameters( DictionaryAttackParameters_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/DictionaryCommands.c000066400000000000000000000113421421143571500206050ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Dictionary Attack Functions */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: DictionaryCommands.c 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2018 */ /* */ /********************************************************************************/ #include "Tpm.h" #include "DictionaryAttackLockReset_fp.h" #if CC_DictionaryAttackLockReset // Conditional expansion of this file TPM_RC TPM2_DictionaryAttackLockReset( DictionaryAttackLockReset_In *in // IN: input parameter list ) { // Input parameter is not reference in command action NOT_REFERENCED(in); // The command needs NV update. RETURN_IF_NV_IS_NOT_AVAILABLE; // Internal Data Update // Set failed tries to 0 gp.failedTries = 0; // Record the changes to NV NV_SYNC_PERSISTENT(failedTries); return TPM_RC_SUCCESS; } #endif // CC_DictionaryAttackLockReset #include "Tpm.h" #include "DictionaryAttackParameters_fp.h" #if CC_DictionaryAttackParameters // Conditional expansion of this file TPM_RC TPM2_DictionaryAttackParameters( DictionaryAttackParameters_In *in // IN: input parameter list ) { // The command needs NV update. RETURN_IF_NV_IS_NOT_AVAILABLE; // Internal Data Update // Set dictionary attack parameters gp.maxTries = in->newMaxTries; gp.recoveryTime = in->newRecoveryTime; gp.lockoutRecovery = in->lockoutRecovery; // Record the changes to NV NV_SYNC_PERSISTENT(failedTries); NV_SYNC_PERSISTENT(maxTries); NV_SYNC_PERSISTENT(recoveryTime); NV_SYNC_PERSISTENT(lockoutRecovery); return TPM_RC_SUCCESS; } #endif // CC_DictionaryAttackParameters libtpms-0.9.3/src/tpm2/Duplicate_fp.h000066400000000000000000000101221421143571500174150ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Duplicate_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef DUPLICATE_FP_H #define DUPLICATE_FP_H typedef struct { TPMI_DH_OBJECT objectHandle; TPMI_DH_OBJECT newParentHandle; TPM2B_DATA encryptionKeyIn; TPMT_SYM_DEF_OBJECT symmetricAlg; } Duplicate_In; typedef struct { TPM2B_DATA encryptionKeyOut; TPM2B_PRIVATE duplicate; TPM2B_ENCRYPTED_SECRET outSymSeed; } Duplicate_Out; #define RC_Duplicate_objectHandle (TPM_RC_H + TPM_RC_1) #define RC_Duplicate_newParentHandle (TPM_RC_H + TPM_RC_2) #define RC_Duplicate_encryptionKeyIn (TPM_RC_P + TPM_RC_1) #define RC_Duplicate_symmetricAlg (TPM_RC_P + TPM_RC_2) TPM_RC TPM2_Duplicate( Duplicate_In *in, // IN: input parameter list Duplicate_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/DuplicationCommands.c000066400000000000000000000354461421143571500207660ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Duplication Commands */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: DuplicationCommands.c 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ #include "Tpm.h" #include "Duplicate_fp.h" #if CC_Duplicate // Conditional expansion of this file #include "Object_spt_fp.h" TPM_RC TPM2_Duplicate( Duplicate_In *in, // IN: input parameter list Duplicate_Out *out // OUT: output parameter list ) { TPM_RC result = TPM_RC_SUCCESS; TPMT_SENSITIVE sensitive; UINT16 innerKeySize = 0; // encrypt key size for inner wrap OBJECT *object; OBJECT *newParent; TPM2B_DATA data; // Input Validation // Get duplicate object pointer object = HandleToObject(in->objectHandle); // Get new parent newParent = HandleToObject(in->newParentHandle); // duplicate key must have fixParent bit CLEAR. if(IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, fixedParent)) return TPM_RCS_ATTRIBUTES + RC_Duplicate_objectHandle; // Do not duplicate object with NULL nameAlg if(object->publicArea.nameAlg == TPM_ALG_NULL) return TPM_RCS_TYPE + RC_Duplicate_objectHandle; // new parent key must be a storage object or TPM_RH_NULL if(in->newParentHandle != TPM_RH_NULL && !ObjectIsStorage(in->newParentHandle)) return TPM_RCS_TYPE + RC_Duplicate_newParentHandle; // If the duplicated object has encryptedDuplication SET, then there must be // an inner wrapper and the new parent may not be TPM_RH_NULL if(IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, encryptedDuplication)) { if(in->symmetricAlg.algorithm == TPM_ALG_NULL) return TPM_RCS_SYMMETRIC + RC_Duplicate_symmetricAlg; if(in->newParentHandle == TPM_RH_NULL) return TPM_RCS_HIERARCHY + RC_Duplicate_newParentHandle; } if(in->symmetricAlg.algorithm == TPM_ALG_NULL) { // if algorithm is TPM_ALG_NULL, input key size must be 0 if(in->encryptionKeyIn.t.size != 0) return TPM_RCS_SIZE + RC_Duplicate_encryptionKeyIn; } else { // Get inner wrap key size innerKeySize = in->symmetricAlg.keyBits.sym; // If provided the input symmetric key must match the size of the algorithm if(in->encryptionKeyIn.t.size != 0 && in->encryptionKeyIn.t.size != (innerKeySize + 7) / 8) return TPM_RCS_SIZE + RC_Duplicate_encryptionKeyIn; } // Command Output if(in->newParentHandle != TPM_RH_NULL) { // Make encrypt key and its associated secret structure. A TPM_RC_KEY // error may be returned at this point out->outSymSeed.t.size = sizeof(out->outSymSeed.t.secret); result = CryptSecretEncrypt(newParent, DUPLICATE_STRING, &data, &out->outSymSeed); if(result != TPM_RC_SUCCESS) return result; } else { // Do not apply outer wrapper data.t.size = 0; out->outSymSeed.t.size = 0; } // Copy sensitive area sensitive = object->sensitive; // Prepare output private data from sensitive. // Note: If there is no encryption key, one will be provided by // SensitiveToDuplicate(). This is why the assignment of encryptionKeyIn to // encryptionKeyOut will work properly and is not conditional. SensitiveToDuplicate(&sensitive, &object->name.b, newParent, object->publicArea.nameAlg, &data.b, &in->symmetricAlg, &in->encryptionKeyIn, &out->duplicate); out->encryptionKeyOut = in->encryptionKeyIn; return TPM_RC_SUCCESS; } #endif // CC_Duplicate #include "Tpm.h" #include "Rewrap_fp.h" #if CC_Rewrap // Conditional expansion of this file #include "Object_spt_fp.h" TPM_RC TPM2_Rewrap( Rewrap_In *in, // IN: input parameter list Rewrap_Out *out // OUT: output parameter list ) { TPM_RC result = TPM_RC_SUCCESS; TPM2B_DATA data; // symmetric key UINT16 hashSize = 0; TPM2B_PRIVATE privateBlob; // A temporary private blob // to transit between old // and new wrappers // Input Validation if((in->inSymSeed.t.size == 0 && in->oldParent != TPM_RH_NULL) || (in->inSymSeed.t.size != 0 && in->oldParent == TPM_RH_NULL)) return TPM_RCS_HANDLE + RC_Rewrap_oldParent; if(in->oldParent != TPM_RH_NULL) { OBJECT *oldParent = HandleToObject(in->oldParent); // old parent key must be a storage object if(!ObjectIsStorage(in->oldParent)) return TPM_RCS_TYPE + RC_Rewrap_oldParent; // Decrypt input secret data via asymmetric decryption. A // TPM_RC_VALUE, TPM_RC_KEY or unmarshal errors may be returned at this // point result = CryptSecretDecrypt(oldParent, NULL, DUPLICATE_STRING, &in->inSymSeed, &data); if(result != TPM_RC_SUCCESS) return TPM_RCS_VALUE + RC_Rewrap_inSymSeed; // Unwrap Outer result = UnwrapOuter(oldParent, &in->name.b, oldParent->publicArea.nameAlg, &data.b, FALSE, in->inDuplicate.t.size, in->inDuplicate.t.buffer); if(result != TPM_RC_SUCCESS) return RcSafeAddToResult(result, RC_Rewrap_inDuplicate); // Copy unwrapped data to temporary variable, remove the integrity field hashSize = sizeof(UINT16) + CryptHashGetDigestSize(oldParent->publicArea.nameAlg); privateBlob.t.size = in->inDuplicate.t.size - hashSize; pAssert(privateBlob.t.size <= sizeof(privateBlob.t.buffer)); MemoryCopy(privateBlob.t.buffer, in->inDuplicate.t.buffer + hashSize, privateBlob.t.size); } else { // No outer wrap from input blob. Direct copy. privateBlob = in->inDuplicate; } if(in->newParent != TPM_RH_NULL) { OBJECT *newParent; newParent = HandleToObject(in->newParent); // New parent must be a storage object if(!ObjectIsStorage(in->newParent)) return TPM_RCS_TYPE + RC_Rewrap_newParent; // Make new encrypt key and its associated secret structure. A // TPM_RC_VALUE error may be returned at this point if RSA algorithm is // enabled in TPM out->outSymSeed.t.size = sizeof(out->outSymSeed.t.secret); result = CryptSecretEncrypt(newParent, DUPLICATE_STRING, &data, &out->outSymSeed); if(result != TPM_RC_SUCCESS) return result; // Copy temporary variable to output, reserve the space for integrity hashSize = sizeof(UINT16) + CryptHashGetDigestSize(newParent->publicArea.nameAlg); // Make sure that everything fits into the output buffer // Note: this is mostly only an issue if there was no outer wrapper on // 'inDuplicate'. It could be as large as a TPM2B_PRIVATE buffer. If we add // a digest for an outer wrapper, it won't fit anymore. if((privateBlob.t.size + hashSize) > sizeof(out->outDuplicate.t.buffer)) return TPM_RCS_VALUE + RC_Rewrap_inDuplicate; // Command output out->outDuplicate.t.size = privateBlob.t.size; pAssert(privateBlob.t.size <= sizeof(out->outDuplicate.t.buffer) - hashSize); MemoryCopy(out->outDuplicate.t.buffer + hashSize, privateBlob.t.buffer, privateBlob.t.size); // Produce outer wrapper for output out->outDuplicate.t.size = ProduceOuterWrap(newParent, &in->name.b, newParent->publicArea.nameAlg, &data.b, FALSE, out->outDuplicate.t.size, out->outDuplicate.t.buffer); } else // New parent is a null key so there is no seed { out->outSymSeed.t.size = 0; // Copy privateBlob directly out->outDuplicate = privateBlob; } return TPM_RC_SUCCESS; } #endif // CC_Rewrap #include "Tpm.h" #include "Import_fp.h" #if CC_Import // Conditional expansion of this file #include "Object_spt_fp.h" TPM_RC TPM2_Import( Import_In *in, // IN: input parameter list Import_Out *out // OUT: output parameter list ) { TPM_RC result = TPM_RC_SUCCESS; OBJECT *parentObject; TPM2B_DATA data; // symmetric key TPMT_SENSITIVE sensitive; TPM2B_NAME name; TPMA_OBJECT attributes; UINT16 innerKeySize = 0; // encrypt key size for inner // wrapper // Input Validation // to save typing attributes = in->objectPublic.publicArea.objectAttributes; // FixedTPM and fixedParent must be CLEAR if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM) || IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedParent)) return TPM_RCS_ATTRIBUTES + RC_Import_objectPublic; // Get parent pointer parentObject = HandleToObject(in->parentHandle); if(!ObjectIsParent(parentObject)) return TPM_RCS_TYPE + RC_Import_parentHandle; if(in->symmetricAlg.algorithm != TPM_ALG_NULL) { // Get inner wrap key size innerKeySize = in->symmetricAlg.keyBits.sym; // Input symmetric key must match the size of algorithm. if(in->encryptionKey.t.size != (innerKeySize + 7) / 8) return TPM_RCS_SIZE + RC_Import_encryptionKey; } else { // If input symmetric algorithm is NULL, input symmetric key size must // be 0 as well if(in->encryptionKey.t.size != 0) return TPM_RCS_SIZE + RC_Import_encryptionKey; // If encryptedDuplication is SET, then the object must have an inner // wrapper if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, encryptedDuplication)) return TPM_RCS_ATTRIBUTES + RC_Import_encryptionKey; } // See if there is an outer wrapper if(in->inSymSeed.t.size != 0) { // in->inParentHandle is a parent, but in order to decrypt an outer wrapper, // it must be able to do key exchange and a symmetric key can't do that. if(parentObject->publicArea.type == TPM_ALG_SYMCIPHER) return TPM_RCS_TYPE + RC_Import_parentHandle; // Decrypt input secret data via asymmetric decryption. TPM_RC_ATTRIBUTES, // TPM_RC_ECC_POINT, TPM_RC_INSUFFICIENT, TPM_RC_KEY, TPM_RC_NO_RESULT, // TPM_RC_SIZE, TPM_RC_VALUE may be returned at this point result = CryptSecretDecrypt(parentObject, NULL, DUPLICATE_STRING, &in->inSymSeed, &data); pAssert(result != TPM_RC_BINDING); if(result != TPM_RC_SUCCESS) return RcSafeAddToResult(result, RC_Import_inSymSeed); } else { // If encrytpedDuplication is set, then the object must have an outer // wrapper if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, encryptedDuplication)) return TPM_RCS_ATTRIBUTES + RC_Import_inSymSeed; data.t.size = 0; } // Compute name of object PublicMarshalAndComputeName(&(in->objectPublic.publicArea), &name); if(name.t.size == 0) return TPM_RCS_HASH + RC_Import_objectPublic; // Retrieve sensitive from private. // TPM_RC_INSUFFICIENT, TPM_RC_INTEGRITY, TPM_RC_SIZE may be returned here. result = DuplicateToSensitive(&in->duplicate.b, &name.b, parentObject, in->objectPublic.publicArea.nameAlg, &data.b, &in->symmetricAlg, &in->encryptionKey.b, &sensitive); if(result != TPM_RC_SUCCESS) return RcSafeAddToResult(result, RC_Import_duplicate); // If the parent of this object has fixedTPM SET, then validate this // object as if it were being loaded so that validation can be skipped // when it is actually loaded. if(IS_ATTRIBUTE(parentObject->publicArea.objectAttributes, TPMA_OBJECT, fixedTPM)) { result = ObjectLoad(NULL, NULL, &in->objectPublic.publicArea, &sensitive, RC_Import_objectPublic, RC_Import_duplicate, NULL); } // Command output if(result == TPM_RC_SUCCESS) { // Prepare output private data from sensitive SensitiveToPrivate(&sensitive, &name, parentObject, in->objectPublic.publicArea.nameAlg, &out->outPrivate); } return result; } #endif // CC_Import libtpms-0.9.3/src/tpm2/EACommands.c000066400000000000000000001360521421143571500167730ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Enhanced Authorization Commands */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: EACommands.c 1519 2019-11-15 20:43:51Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ #include "Tpm.h" #include "Policy_spt_fp.h" #include "PolicySigned_fp.h" #if CC_PolicySigned // Conditional expansion of this file /*TPM_RC_CPHASH cpHash was previously set to a different value */ /*TPM_RC_EXPIRED expiration indicates a time in the past or expiration is non-zero but no nonceTPM is present */ /*TPM_RC_NONCE nonceTPM is not the nonce associated with the policySession */ /*TPM_RC_SCHEME the signing scheme of auth is not supported by the TPM */ /*TPM_RC_SIGNATURE the signature is not genuine */ /*TPM_RC_SIZE input cpHash has wrong size */ TPM_RC TPM2_PolicySigned( PolicySigned_In *in, // IN: input parameter list PolicySigned_Out *out // OUT: output parameter list ) { TPM_RC result = TPM_RC_SUCCESS; SESSION *session; TPM2B_NAME entityName; TPM2B_DIGEST authHash; HASH_STATE hashState; UINT64 authTimeout = 0; // Input Validation // Set up local pointers session = SessionGet(in->policySession); // the session structure // Only do input validation if this is not a trial policy session if(session->attributes.isTrialPolicy == CLEAR) { authTimeout = ComputeAuthTimeout(session, in->expiration, &in->nonceTPM); result = PolicyParameterChecks(session, authTimeout, &in->cpHashA, &in->nonceTPM, RC_PolicySigned_nonceTPM, RC_PolicySigned_cpHashA, RC_PolicySigned_expiration); if(result != TPM_RC_SUCCESS) return result; // Re-compute the digest being signed // Start hash authHash.t.size = CryptHashStart(&hashState, CryptGetSignHashAlg(&in->auth)); // If there is no digest size, then we don't have a verification function // for this algorithm (e.g. TPM_ALG_ECDAA) so indicate that it is a // bad scheme. if(authHash.t.size == 0) return TPM_RCS_SCHEME + RC_PolicySigned_auth; // nonceTPM CryptDigestUpdate2B(&hashState, &in->nonceTPM.b); // expiration CryptDigestUpdateInt(&hashState, sizeof(UINT32), in->expiration); // cpHashA CryptDigestUpdate2B(&hashState, &in->cpHashA.b); // policyRef CryptDigestUpdate2B(&hashState, &in->policyRef.b); // Complete digest CryptHashEnd2B(&hashState, &authHash.b); // Validate Signature. A TPM_RC_SCHEME, TPM_RC_HANDLE or TPM_RC_SIGNATURE // error may be returned at this point result = CryptValidateSignature(in->authObject, &authHash, &in->auth); if(result != TPM_RC_SUCCESS) return RcSafeAddToResult(result, RC_PolicySigned_auth); } // Internal Data Update // Update policy with input policyRef and name of authorization key // These values are updated even if the session is a trial session PolicyContextUpdate(TPM_CC_PolicySigned, EntityGetName(in->authObject, &entityName), &in->policyRef, &in->cpHashA, authTimeout, session); // Command Output // Create ticket and timeout buffer if in->expiration < 0 and this is not // a trial session. // NOTE: PolicyParameterChecks() makes sure that nonceTPM is present // when expiration is non-zero. if(in->expiration < 0 && session->attributes.isTrialPolicy == CLEAR) { BOOL expiresOnReset = (in->nonceTPM.t.size == 0); // Compute policy ticket authTimeout &= ~EXPIRATION_BIT; TicketComputeAuth(TPM_ST_AUTH_SIGNED, EntityGetHierarchy(in->authObject), authTimeout, expiresOnReset, &in->cpHashA, &in->policyRef, &entityName, &out->policyTicket); // Generate timeout buffer. The format of output timeout buffer is // TPM-specific. // Note: In this implementation, the timeout buffer value is computed after // the ticket is produced so, when the ticket is checked, the expiration // flag needs to be extracted before the ticket is checked. // In the Windows compatible version, the least-significant bit of the // timeout value is used as a flag to indicate if the authorization expires // on reset. The flag is the MSb. out->timeout.t.size = sizeof(authTimeout); if(expiresOnReset) authTimeout |= EXPIRATION_BIT; UINT64_TO_BYTE_ARRAY(authTimeout, out->timeout.t.buffer); } else { // Generate a null ticket. // timeout buffer is null out->timeout.t.size = 0; // authorization ticket is null out->policyTicket.tag = TPM_ST_AUTH_SIGNED; out->policyTicket.hierarchy = TPM_RH_NULL; out->policyTicket.digest.t.size = 0; } return TPM_RC_SUCCESS; } #endif // CC_PolicySigned #include "Tpm.h" #include "PolicySecret_fp.h" #if CC_PolicySecret // Conditional expansion of this file #include "Policy_spt_fp.h" #include "NV_spt_fp.h" /* TPM_RC_CPHASH cpHash for policy was previously set to a value that is not the same as cpHashA */ /* TPM_RC_EXPIRED expiration indicates a time in the past */ /* TPM_RC_NONCE nonceTPM does not match the nonce associated with policySession */ /* TPM_RC_SIZE cpHashA is not the size of a digest for the hash associated with policySession */ TPM_RC TPM2_PolicySecret( PolicySecret_In *in, // IN: input parameter list PolicySecret_Out *out // OUT: output parameter list ) { TPM_RC result; SESSION *session; TPM2B_NAME entityName; UINT64 authTimeout = 0; // Input Validation // Get pointer to the session structure session = SessionGet(in->policySession); //Only do input validation if this is not a trial policy session if(session->attributes.isTrialPolicy == CLEAR) { authTimeout = ComputeAuthTimeout(session, in->expiration, &in->nonceTPM); result = PolicyParameterChecks(session, authTimeout, &in->cpHashA, &in->nonceTPM, RC_PolicySecret_nonceTPM, RC_PolicySecret_cpHashA, RC_PolicySecret_expiration); if(result != TPM_RC_SUCCESS) return result; } // Internal Data Update // Update policy context with input policyRef and name of authorizing key // This value is computed even for trial sessions. Possibly update the cpHash PolicyContextUpdate(TPM_CC_PolicySecret, EntityGetName(in->authHandle, &entityName), &in->policyRef, &in->cpHashA, authTimeout, session); // Command Output // Create ticket and timeout buffer if in->expiration < 0 and this is not // a trial session. // NOTE: PolicyParameterChecks() makes sure that nonceTPM is present // when expiration is non-zero. if(in->expiration < 0 && session->attributes.isTrialPolicy == CLEAR && !NvIsPinPassIndex(in->authHandle)) { BOOL expiresOnReset = (in->nonceTPM.t.size == 0); // Compute policy ticket authTimeout &= ~EXPIRATION_BIT; TicketComputeAuth(TPM_ST_AUTH_SECRET, EntityGetHierarchy(in->authHandle), authTimeout, expiresOnReset, &in->cpHashA, &in->policyRef, &entityName, &out->policyTicket); // Generate timeout buffer. The format of output timeout buffer is // TPM-specific. // Note: In this implementation, the timeout buffer value is computed after // the ticket is produced so, when the ticket is checked, the expiration // flag needs to be extracted before the ticket is checked. out->timeout.t.size = sizeof(authTimeout); // In the Windows compatible version, the least-significant bit of the // timeout value is used as a flag to indicate if the authorization expires // on reset. The flag is the MSb. if(expiresOnReset) authTimeout |= EXPIRATION_BIT; UINT64_TO_BYTE_ARRAY(authTimeout, out->timeout.t.buffer); } else { // timeout buffer is null out->timeout.t.size = 0; // authorization ticket is null out->policyTicket.tag = TPM_ST_AUTH_SECRET; out->policyTicket.hierarchy = TPM_RH_NULL; out->policyTicket.digest.t.size = 0; } return TPM_RC_SUCCESS; } #endif // CC_PolicySecret #include "Tpm.h" #include "PolicyTicket_fp.h" #if CC_PolicyTicket // Conditional expansion of this file #include "Policy_spt_fp.h" /* TPM_RC_CPHASH policy's cpHash was previously set to a different value */ /* TPM_RC_EXPIRED timeout value in the ticket is in the past and the ticket has expired */ /* TPM_RC_SIZE timeout or cpHash has invalid size for the */ /* TPM_RC_TICKET ticket is not valid */ TPM_RC TPM2_PolicyTicket( PolicyTicket_In *in // IN: input parameter list ) { TPM_RC result; SESSION *session; UINT64 authTimeout; TPMT_TK_AUTH ticketToCompare; TPM_CC commandCode = TPM_CC_PolicySecret; BOOL expiresOnReset; // Input Validation // Get pointer to the session structure session = SessionGet(in->policySession); // NOTE: A trial policy session is not allowed to use this command. // A ticket is used in place of a previously given authorization. Since // a trial policy doesn't actually authenticate, the validated // ticket is not necessary and, in place of using a ticket, one // should use the intended authorization for which the ticket // would be a substitute. if(session->attributes.isTrialPolicy) return TPM_RCS_ATTRIBUTES + RC_PolicyTicket_policySession; // Restore timeout data. The format of timeout buffer is TPM-specific. // In this implementation, the most significant bit of the timeout value is // used as the flag to indicate that the ticket expires on TPM Reset or // TPM Restart. The flag has to be removed before the parameters and ticket // are checked. if(in->timeout.t.size != sizeof(UINT64)) return TPM_RCS_SIZE + RC_PolicyTicket_timeout; authTimeout = BYTE_ARRAY_TO_UINT64(in->timeout.t.buffer); // extract the flag expiresOnReset = (authTimeout & EXPIRATION_BIT) != 0; authTimeout &= ~EXPIRATION_BIT; // Do the normal checks on the cpHashA and timeout values result = PolicyParameterChecks(session, authTimeout, &in->cpHashA, NULL, // no nonce 0, // no bad nonce return RC_PolicyTicket_cpHashA, RC_PolicyTicket_timeout); if(result != TPM_RC_SUCCESS) return result; // Validate Ticket // Re-generate policy ticket by input parameters TicketComputeAuth(in->ticket.tag, in->ticket.hierarchy, authTimeout, expiresOnReset, &in->cpHashA, &in->policyRef, &in->authName, &ticketToCompare); // Compare generated digest with input ticket digest if(!MemoryEqual2B(&in->ticket.digest.b, &ticketToCompare.digest.b)) return TPM_RCS_TICKET + RC_PolicyTicket_ticket; // Internal Data Update // Is this ticket to take the place of a TPM2_PolicySigned() or // a TPM2_PolicySecret()? if(in->ticket.tag == TPM_ST_AUTH_SIGNED) commandCode = TPM_CC_PolicySigned; else if(in->ticket.tag == TPM_ST_AUTH_SECRET) commandCode = TPM_CC_PolicySecret; else // There could only be two possible tag values. Any other value should // be caught by the ticket validation process. FAIL(FATAL_ERROR_INTERNAL); // Update policy context PolicyContextUpdate(commandCode, &in->authName, &in->policyRef, &in->cpHashA, authTimeout, session); return TPM_RC_SUCCESS; } #endif // CC_PolicyTicket #include "Tpm.h" #include "PolicyOR_fp.h" #if CC_PolicyOR // Conditional expansion of this file #include "Policy_spt_fp.h" TPM_RC TPM2_PolicyOR( PolicyOR_In *in // IN: input parameter list ) { SESSION *session; UINT32 i; // Input Validation and Update // Get pointer to the session structure session = SessionGet(in->policySession); // Compare and Update Internal Session policy if match for(i = 0; i < in->pHashList.count; i++) { if(session->attributes.isTrialPolicy == SET || (MemoryEqual2B(&session->u2.policyDigest.b, &in->pHashList.digests[i].b))) { // Found a match HASH_STATE hashState; TPM_CC commandCode = TPM_CC_PolicyOR; // Start hash session->u2.policyDigest.t.size = CryptHashStart(&hashState, session->authHashAlg); // Set policyDigest to 0 string and add it to hash MemorySet(session->u2.policyDigest.t.buffer, 0, session->u2.policyDigest.t.size); CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); // add command code CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode); // Add each of the hashes in the list for(i = 0; i < in->pHashList.count; i++) { // Extend policyDigest CryptDigestUpdate2B(&hashState, &in->pHashList.digests[i].b); } // Complete digest CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); return TPM_RC_SUCCESS; } } // None of the values in the list matched the current policyDigest return TPM_RCS_VALUE + RC_PolicyOR_pHashList; } #endif // CC_PolicyOR #include "Tpm.h" #include "PolicyPCR_fp.h" #if CC_PolicyPCR // Conditional expansion of this file /* TPM_RC_VALUE if provided, pcrDigest does not match the current PCR settings */ /* TPM_RC_PCR_CHANGED a previous TPM2_PolicyPCR() set pcrCounter and it has changed */ TPM_RC TPM2_PolicyPCR( PolicyPCR_In *in // IN: input parameter list ) { SESSION *session; TPM2B_DIGEST pcrDigest; BYTE pcrs[sizeof(TPML_PCR_SELECTION)]; UINT32 pcrSize; BYTE *buffer; TPM_CC commandCode = TPM_CC_PolicyPCR; HASH_STATE hashState; // Input Validation // Get pointer to the session structure session = SessionGet(in->policySession); // Compute current PCR digest PCRComputeCurrentDigest(session->authHashAlg, &in->pcrs, &pcrDigest); // Do validation for non trial session if(session->attributes.isTrialPolicy == CLEAR) { // Make sure that this is not going to invalidate a previous PCR check if(session->pcrCounter != 0 && session->pcrCounter != gr.pcrCounter) return TPM_RC_PCR_CHANGED; // If the caller specified the PCR digest and it does not // match the current PCR settings, return an error.. if(in->pcrDigest.t.size != 0) { if(!MemoryEqual2B(&in->pcrDigest.b, &pcrDigest.b)) return TPM_RCS_VALUE + RC_PolicyPCR_pcrDigest; } } else { // For trial session, just use the input PCR digest if one provided // Note: It can't be too big because it is a TPM2B_DIGEST and the size // would have been checked during unmarshaling if(in->pcrDigest.t.size != 0) pcrDigest = in->pcrDigest; } // Internal Data Update // Update policy hash // policyDigestnew = hash( policyDigestold || TPM_CC_PolicyPCR // || PCRS || pcrDigest) // Start hash CryptHashStart(&hashState, session->authHashAlg); // add old digest CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); // add commandCode CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode); // add PCRS buffer = pcrs; pcrSize = TPML_PCR_SELECTION_Marshal(&in->pcrs, &buffer, NULL); CryptDigestUpdate(&hashState, pcrSize, pcrs); // add PCR digest CryptDigestUpdate2B(&hashState, &pcrDigest.b); // complete the hash and get the results CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); // update pcrCounter in session context for non trial session if(session->attributes.isTrialPolicy == CLEAR) { session->pcrCounter = gr.pcrCounter; } return TPM_RC_SUCCESS; } #endif // CC_PolicyPCR #include "Tpm.h" #include "PolicyLocality_fp.h" #if CC_PolicyLocality // Conditional expansion of this file TPM_RC TPM2_PolicyLocality( PolicyLocality_In *in // IN: input parameter list ) { SESSION *session; BYTE marshalBuffer[sizeof(TPMA_LOCALITY)]; BYTE prevSetting[sizeof(TPMA_LOCALITY)]; UINT32 marshalSize; BYTE *buffer; TPM_CC commandCode = TPM_CC_PolicyLocality; HASH_STATE hashState; // Input Validation // Get pointer to the session structure session = SessionGet(in->policySession); // Get new locality setting in canonical form marshalBuffer[0] = 0; // Code analysis says that this is not initialized buffer = marshalBuffer; marshalSize = TPMA_LOCALITY_Marshal(&in->locality, &buffer, NULL); // Its an error if the locality parameter is zero if(marshalBuffer[0] == 0) return TPM_RCS_RANGE + RC_PolicyLocality_locality; // Get existing locality setting in canonical form prevSetting[0] = 0; // Code analysis says that this is not initialized buffer = prevSetting; TPMA_LOCALITY_Marshal(&session->commandLocality, &buffer, NULL); // If the locality has previously been set if(prevSetting[0] != 0 // then the current locality setting and the requested have to be the same // type (that is, either both normal or both extended && ((prevSetting[0] < 32) != (marshalBuffer[0] < 32))) return TPM_RCS_RANGE + RC_PolicyLocality_locality; // See if the input is a regular or extended locality if(marshalBuffer[0] < 32) { // if there was no previous setting, start with all normal localities // enabled if(prevSetting[0] == 0) prevSetting[0] = 0x1F; // AND the new setting with the previous setting and store it in prevSetting prevSetting[0] &= marshalBuffer[0]; // The result setting can not be 0 if(prevSetting[0] == 0) return TPM_RCS_RANGE + RC_PolicyLocality_locality; } else { // for extended locality // if the locality has already been set, then it must match the if(prevSetting[0] != 0 && prevSetting[0] != marshalBuffer[0]) return TPM_RCS_RANGE + RC_PolicyLocality_locality; // Setting is OK prevSetting[0] = marshalBuffer[0]; } // Internal Data Update // Update policy hash // policyDigestnew = hash(policyDigestold || TPM_CC_PolicyLocality || locality) // Start hash CryptHashStart(&hashState, session->authHashAlg); // add old digest CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); // add commandCode CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode); // add input locality CryptDigestUpdate(&hashState, marshalSize, marshalBuffer); // complete the digest CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); // update session locality by unmarshal function. The function must succeed // because both input and existing locality setting have been validated. buffer = prevSetting; TPMA_LOCALITY_Unmarshal(&session->commandLocality, &buffer, (INT32 *)&marshalSize); return TPM_RC_SUCCESS; } #endif // CC_PolicyLocality #include "Tpm.h" #include "PolicyNV_fp.h" #if CC_PolicyNV // Conditional expansion of this file #include "Policy_spt_fp.h" TPM_RC TPM2_PolicyNV( PolicyNV_In *in // IN: input parameter list ) { TPM_RC result; SESSION *session; NV_REF locator; NV_INDEX *nvIndex; BYTE nvBuffer[sizeof(in->operandB.t.buffer)]; TPM2B_NAME nvName; TPM_CC commandCode = TPM_CC_PolicyNV; HASH_STATE hashState; TPM2B_DIGEST argHash; // Input Validation // Get pointer to the session structure session = SessionGet(in->policySession); //If this is a trial policy, skip all validations and the operation if(session->attributes.isTrialPolicy == CLEAR) { // No need to access the actual NV index information for a trial policy. nvIndex = NvGetIndexInfo(in->nvIndex, &locator); // Common read access checks. NvReadAccessChecks() may return // TPM_RC_NV_AUTHORIZATION, TPM_RC_NV_LOCKED, or TPM_RC_NV_UNINITIALIZED result = NvReadAccessChecks(in->authHandle, in->nvIndex, nvIndex->publicArea.attributes); if(result != TPM_RC_SUCCESS) return result; // Make sure that offset is withing range if(in->offset > nvIndex->publicArea.dataSize) return TPM_RCS_VALUE + RC_PolicyNV_offset; // Valid NV data size should not be smaller than input operandB size if((nvIndex->publicArea.dataSize - in->offset) < in->operandB.t.size) return TPM_RCS_SIZE + RC_PolicyNV_operandB; // Get NV data. The size of NV data equals the input operand B size NvGetIndexData(nvIndex, locator, in->offset, in->operandB.t.size, nvBuffer); // Check to see if the condition is valid if(!PolicySptCheckCondition(in->operation, nvBuffer, in->operandB.t.buffer, in->operandB.t.size)) return TPM_RC_POLICY; } // Internal Data Update // Start argument hash argHash.t.size = CryptHashStart(&hashState, session->authHashAlg); // add operandB CryptDigestUpdate2B(&hashState, &in->operandB.b); // add offset CryptDigestUpdateInt(&hashState, sizeof(UINT16), in->offset); // add operation CryptDigestUpdateInt(&hashState, sizeof(TPM_EO), in->operation); // complete argument digest CryptHashEnd2B(&hashState, &argHash.b); // Update policyDigest // Start digest CryptHashStart(&hashState, session->authHashAlg); // add old digest CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); // add commandCode CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode); // add argument digest CryptDigestUpdate2B(&hashState, &argHash.b); // Adding nvName CryptDigestUpdate2B(&hashState, &EntityGetName(in->nvIndex, &nvName)->b); // complete the digest CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); return TPM_RC_SUCCESS; } #endif // CC_PolicyNV #include "Tpm.h" #include "PolicyCounterTimer_fp.h" #if CC_PolicyCounterTimer // Conditional expansion of this file #include "Policy_spt_fp.h" TPM_RC TPM2_PolicyCounterTimer( PolicyCounterTimer_In *in // IN: input parameter list ) { SESSION *session; TIME_INFO infoData; // data buffer of TPMS_TIME_INFO BYTE *pInfoData = (BYTE *)&infoData; UINT16 infoDataSize; TPM_CC commandCode = TPM_CC_PolicyCounterTimer; HASH_STATE hashState; TPM2B_DIGEST argHash; // Input Validation // Get a marshaled time structure infoDataSize = TimeGetMarshaled(&infoData); pAssert(infoDataSize <= sizeof(infoData)); // libtpms added; 25 < 32 ==> unfounded coverity complaint // Make sure that the referenced stays within the bounds of the structure. // NOTE: the offset checks are made even for a trial policy because the policy // will not make any sense if the references are out of bounds of the timer // structure. if(in->offset > infoDataSize) return TPM_RCS_VALUE + RC_PolicyCounterTimer_offset; if((UINT32)in->offset + (UINT32)in->operandB.t.size > infoDataSize) return TPM_RCS_RANGE; // Get pointer to the session structure session = SessionGet(in->policySession); //If this is a trial policy, skip the check to see if the condition is met. if(session->attributes.isTrialPolicy == CLEAR) { // If the command is going to use any part of the counter or timer, need // to verify that time is advancing. // The time and clock vales are the first two 64-bit values in the clock if(in->offset < sizeof(UINT64) + sizeof(UINT64)) { // Using Clock or Time so see if clock is running. Clock doesn't // run while NV is unavailable. // TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned here. RETURN_IF_NV_IS_NOT_AVAILABLE; } // offset to the starting position pInfoData = (BYTE *)infoData; // Check to see if the condition is valid if(!PolicySptCheckCondition(in->operation, pInfoData + in->offset, in->operandB.t.buffer, in->operandB.t.size)) return TPM_RC_POLICY; } // Internal Data Update // Start argument list hash argHash.t.size = CryptHashStart(&hashState, session->authHashAlg); // add operandB CryptDigestUpdate2B(&hashState, &in->operandB.b); // add offset CryptDigestUpdateInt(&hashState, sizeof(UINT16), in->offset); // add operation CryptDigestUpdateInt(&hashState, sizeof(TPM_EO), in->operation); // complete argument hash CryptHashEnd2B(&hashState, &argHash.b); // update policyDigest // start hash CryptHashStart(&hashState, session->authHashAlg); // add old digest CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); // add commandCode CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode); // add argument digest CryptDigestUpdate2B(&hashState, &argHash.b); // complete the digest CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); return TPM_RC_SUCCESS; } #endif // CC_PolicyCounterTimer #include "Tpm.h" #include "PolicyCommandCode_fp.h" #if CC_PolicyCommandCode // Conditional expansion of this file /* Error Returns Meaning */ /* TPM_RC_VALUE commandCode of policySession previously set to a different value */ TPM_RC TPM2_PolicyCommandCode( PolicyCommandCode_In *in // IN: input parameter list ) { SESSION *session; TPM_CC commandCode = TPM_CC_PolicyCommandCode; HASH_STATE hashState; // Input validation // Get pointer to the session structure session = SessionGet(in->policySession); if(session->commandCode != 0 && session->commandCode != in->code) return TPM_RCS_VALUE + RC_PolicyCommandCode_code; if(CommandCodeToCommandIndex(in->code) == UNIMPLEMENTED_COMMAND_INDEX) return TPM_RCS_POLICY_CC + RC_PolicyCommandCode_code; // Internal Data Update // Update policy hash // policyDigestnew = hash(policyDigestold || TPM_CC_PolicyCommandCode || code) // Start hash CryptHashStart(&hashState, session->authHashAlg); // add old digest CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); // add commandCode CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode); // add input commandCode CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), in->code); // complete the hash and get the results CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); // update commandCode value in session context session->commandCode = in->code; return TPM_RC_SUCCESS; } #endif // CC_PolicyCommandCode #include "Tpm.h" #include "PolicyPhysicalPresence_fp.h" #if CC_PolicyPhysicalPresence // Conditional expansion of this file TPM_RC TPM2_PolicyPhysicalPresence( PolicyPhysicalPresence_In *in // IN: input parameter list ) { SESSION *session; TPM_CC commandCode = TPM_CC_PolicyPhysicalPresence; HASH_STATE hashState; // Internal Data Update // Get pointer to the session structure session = SessionGet(in->policySession); // Update policy hash // policyDigestnew = hash(policyDigestold || TPM_CC_PolicyPhysicalPresence) // Start hash CryptHashStart(&hashState, session->authHashAlg); // add old digest CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); // add commandCode CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode); // complete the digest CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); // update session attribute session->attributes.isPPRequired = SET; return TPM_RC_SUCCESS; } #endif // CC_PolicyPhysicalPresence #include "Tpm.h" #include "PolicyCpHash_fp.h" #if CC_PolicyCpHash // Conditional expansion of this file TPM_RC TPM2_PolicyCpHash( PolicyCpHash_In *in // IN: input parameter list ) { SESSION *session; TPM_CC commandCode = TPM_CC_PolicyCpHash; HASH_STATE hashState; // Input Validation // Get pointer to the session structure session = SessionGet(in->policySession); // A valid cpHash must have the same size as session hash digest // NOTE: the size of the digest can't be zero because TPM_ALG_NULL // can't be used for the authHashAlg. if(in->cpHashA.t.size != CryptHashGetDigestSize(session->authHashAlg)) return TPM_RCS_SIZE + RC_PolicyCpHash_cpHashA; // error if the cpHash in session context is not empty and is not the same // as the input or is not a cpHash if((session->u1.cpHash.t.size != 0) && (!session->attributes.isCpHashDefined || !MemoryEqual2B(&in->cpHashA.b, &session->u1.cpHash.b))) return TPM_RC_CPHASH; // Internal Data Update // Update policy hash // policyDigestnew = hash(policyDigestold || TPM_CC_PolicyCpHash || cpHashA) // Start hash CryptHashStart(&hashState, session->authHashAlg); // add old digest CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); // add commandCode CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode); // add cpHashA CryptDigestUpdate2B(&hashState, &in->cpHashA.b); // complete the digest and get the results CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); // update cpHash in session context session->u1.cpHash = in->cpHashA; session->attributes.isCpHashDefined = SET; return TPM_RC_SUCCESS; } #endif // CC_PolicyCpHash #include "Tpm.h" #include "PolicyNameHash_fp.h" #if CC_PolicyNameHash // Conditional expansion of this file TPM_RC TPM2_PolicyNameHash( PolicyNameHash_In *in // IN: input parameter list ) { SESSION *session; TPM_CC commandCode = TPM_CC_PolicyNameHash; HASH_STATE hashState; // Input Validation // Get pointer to the session structure session = SessionGet(in->policySession); // A valid nameHash must have the same size as session hash digest // Since the authHashAlg for a session cannot be TPM_ALG_NULL, the digest size // is always non-zero. if(in->nameHash.t.size != CryptHashGetDigestSize(session->authHashAlg)) return TPM_RCS_SIZE + RC_PolicyNameHash_nameHash; // u1 in the policy session context cannot otherwise be occupied if(session->u1.cpHash.b.size != 0 || session->attributes.isBound || session->attributes.isCpHashDefined || session->attributes.isTemplateSet) return TPM_RC_CPHASH; // Internal Data Update // Update policy hash // policyDigestnew = hash(policyDigestold || TPM_CC_PolicyNameHash || nameHash) // Start hash CryptHashStart(&hashState, session->authHashAlg); // add old digest CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); // add commandCode CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode); // add nameHash CryptDigestUpdate2B(&hashState, &in->nameHash.b); // complete the digest CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); // update nameHash in session context session->u1.cpHash = in->nameHash; return TPM_RC_SUCCESS; } #endif // CC_PolicyNameHash #include "Tpm.h" #include "PolicyDuplicationSelect_fp.h" #if CC_PolicyDuplicationSelect // Conditional expansion of this file TPM_RC TPM2_PolicyDuplicationSelect( PolicyDuplicationSelect_In *in // IN: input parameter list ) { SESSION *session; HASH_STATE hashState; TPM_CC commandCode = TPM_CC_PolicyDuplicationSelect; // Input Validation // Get pointer to the session structure session = SessionGet(in->policySession); // cpHash in session context must be empty if(session->u1.cpHash.t.size != 0) return TPM_RC_CPHASH; // commandCode in session context must be empty if(session->commandCode != 0) return TPM_RC_COMMAND_CODE; // Internal Data Update // Update name hash session->u1.cpHash.t.size = CryptHashStart(&hashState, session->authHashAlg); // add objectName CryptDigestUpdate2B(&hashState, &in->objectName.b); // add new parent name CryptDigestUpdate2B(&hashState, &in->newParentName.b); // complete hash CryptHashEnd2B(&hashState, &session->u1.cpHash.b); // update policy hash // Old policyDigest size should be the same as the new policyDigest size since // they are using the same hash algorithm session->u2.policyDigest.t.size = CryptHashStart(&hashState, session->authHashAlg); // add old policy CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); // add command code CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode); // add objectName if(in->includeObject == YES) CryptDigestUpdate2B(&hashState, &in->objectName.b); // add new parent name CryptDigestUpdate2B(&hashState, &in->newParentName.b); // add includeObject CryptDigestUpdateInt(&hashState, sizeof(TPMI_YES_NO), in->includeObject); // complete digest CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); // set commandCode in session context session->commandCode = TPM_CC_Duplicate; return TPM_RC_SUCCESS; } #endif // CC_PolicyDuplicationSelect #include "Tpm.h" #include "PolicyAuthorize_fp.h" #if CC_PolicyAuthorize // Conditional expansion of this file #include "Policy_spt_fp.h" TPM_RC TPM2_PolicyAuthorize( PolicyAuthorize_In *in // IN: input parameter list ) { SESSION *session; TPM2B_DIGEST authHash; HASH_STATE hashState; TPMT_TK_VERIFIED ticket; TPM_ALG_ID hashAlg; UINT16 digestSize; // Input Validation // Get pointer to the session structure session = SessionGet(in->policySession); // Extract from the Name of the key, the algorithm used to compute it's Name hashAlg = BYTE_ARRAY_TO_UINT16(in->keySign.t.name); // 'keySign' parameter needs to use a supported hash algorithm, otherwise // can't tell how large the digest should be if(!CryptHashIsValidAlg(hashAlg, FALSE)) return TPM_RCS_HASH + RC_PolicyAuthorize_keySign; digestSize = CryptHashGetDigestSize(hashAlg); if(digestSize != (in->keySign.t.size - 2)) return TPM_RCS_SIZE + RC_PolicyAuthorize_keySign; //If this is a trial policy, skip all validations if(session->attributes.isTrialPolicy == CLEAR) { // Check that "approvedPolicy" matches the current value of the // policyDigest in policy session if(!MemoryEqual2B(&session->u2.policyDigest.b, &in->approvedPolicy.b)) return TPM_RCS_VALUE + RC_PolicyAuthorize_approvedPolicy; // Validate ticket TPMT_TK_VERIFIED // Compute aHash. The authorizing object sign a digest // aHash := hash(approvedPolicy || policyRef). // Start hash authHash.t.size = CryptHashStart(&hashState, hashAlg); // add approvedPolicy CryptDigestUpdate2B(&hashState, &in->approvedPolicy.b); // add policyRef CryptDigestUpdate2B(&hashState, &in->policyRef.b); // complete hash CryptHashEnd2B(&hashState, &authHash.b); // re-compute TPMT_TK_VERIFIED TicketComputeVerified(in->checkTicket.hierarchy, &authHash, &in->keySign, &ticket); // Compare ticket digest. If not match, return error if(!MemoryEqual2B(&in->checkTicket.digest.b, &ticket.digest.b)) return TPM_RCS_VALUE + RC_PolicyAuthorize_checkTicket; } // Internal Data Update // Set policyDigest to zero digest PolicyDigestClear(session); // Update policyDigest PolicyContextUpdate(TPM_CC_PolicyAuthorize, &in->keySign, &in->policyRef, NULL, 0, session); return TPM_RC_SUCCESS; } #endif // CC_PolicyAuthorize #include "Tpm.h" #include "PolicyAuthValue_fp.h" #if CC_PolicyAuthValue // Conditional expansion of this file #include "Policy_spt_fp.h" TPM_RC TPM2_PolicyAuthValue( PolicyAuthValue_In *in // IN: input parameter list ) { SESSION *session; TPM_CC commandCode = TPM_CC_PolicyAuthValue; HASH_STATE hashState; // Internal Data Update // Get pointer to the session structure session = SessionGet(in->policySession); // Update policy hash // policyDigestnew = hash(policyDigestold || TPM_CC_PolicyAuthValue) // Start hash CryptHashStart(&hashState, session->authHashAlg); // add old digest CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); // add commandCode CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode); // complete the hash and get the results CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); // update isAuthValueNeeded bit in the session context session->attributes.isAuthValueNeeded = SET; session->attributes.isPasswordNeeded = CLEAR; return TPM_RC_SUCCESS; } #endif // CC_PolicyAuthValue #include "Tpm.h" #include "PolicyPassword_fp.h" #if CC_PolicyPassword // Conditional expansion of this file #include "Policy_spt_fp.h" TPM_RC TPM2_PolicyPassword( PolicyPassword_In *in // IN: input parameter list ) { SESSION *session; TPM_CC commandCode = TPM_CC_PolicyAuthValue; HASH_STATE hashState; // Internal Data Update // Get pointer to the session structure session = SessionGet(in->policySession); // Update policy hash // policyDigestnew = hash(policyDigestold || TPM_CC_PolicyAuthValue) // Start hash CryptHashStart(&hashState, session->authHashAlg); // add old digest CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); // add commandCode CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode); // complete the digest CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); // Update isPasswordNeeded bit session->attributes.isPasswordNeeded = SET; session->attributes.isAuthValueNeeded = CLEAR; return TPM_RC_SUCCESS; } #endif // CC_PolicyPassword #include "Tpm.h" #include "PolicyGetDigest_fp.h" #if CC_PolicyGetDigest // Conditional expansion of this file TPM_RC TPM2_PolicyGetDigest( PolicyGetDigest_In *in, // IN: input parameter list PolicyGetDigest_Out *out // OUT: output parameter list ) { SESSION *session; // Command Output // Get pointer to the session structure session = SessionGet(in->policySession); out->policyDigest = session->u2.policyDigest; return TPM_RC_SUCCESS; } #endif // CC_PolicyGetDigest #include "Tpm.h" #include "PolicyNvWritten_fp.h" #if CC_PolicyNvWritten // Conditional expansion of this file TPM_RC TPM2_PolicyNvWritten( PolicyNvWritten_In *in // IN: input parameter list ) { SESSION *session; TPM_CC commandCode = TPM_CC_PolicyNvWritten; HASH_STATE hashState; // Input Validation // Get pointer to the session structure session = SessionGet(in->policySession); // If already set is this a duplicate (the same setting)? If it // is a conflicting setting, it is an error if(session->attributes.checkNvWritten == SET) { if(((session->attributes.nvWrittenState == SET) != (in->writtenSet == YES))) return TPM_RCS_VALUE + RC_PolicyNvWritten_writtenSet; } // Internal Data Update // Set session attributes so that the NV Index needs to be checked session->attributes.checkNvWritten = SET; session->attributes.nvWrittenState = (in->writtenSet == YES); // Update policy hash // policyDigestnew = hash(policyDigestold || TPM_CC_PolicyNvWritten // || writtenSet) // Start hash CryptHashStart(&hashState, session->authHashAlg); // add old digest CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); // add commandCode CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode); // add the byte of writtenState CryptDigestUpdateInt(&hashState, sizeof(TPMI_YES_NO), in->writtenSet); // complete the digest CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); return TPM_RC_SUCCESS; } #endif // CC_PolicyNvWritten #include "Tpm.h" #include "PolicyTemplate_fp.h" #if CC_PolicyTemplate // Conditional expansion of this file TPM_RC TPM2_PolicyTemplate( PolicyTemplate_In *in // IN: input parameter list ) { SESSION *session; TPM_CC commandCode = TPM_CC_PolicyTemplate; HASH_STATE hashState; // Input Validation // Get pointer to the session structure session = SessionGet(in->policySession); // If the template is set, make sure that it is the same as the input value if(session->attributes.isTemplateSet) { if(!MemoryEqual2B(&in->templateHash.b, &session->u1.cpHash.b)) return TPM_RCS_VALUE + RC_PolicyTemplate_templateHash; } // error if cpHash contains something that is not a template else if(session->u1.templateHash.t.size != 0) return TPM_RC_CPHASH; // A valid templateHash must have the same size as session hash digest if(in->templateHash.t.size != CryptHashGetDigestSize(session->authHashAlg)) return TPM_RCS_SIZE + RC_PolicyTemplate_templateHash; // Internal Data Update // Update policy hash // policyDigestnew = hash(policyDigestold || TPM_CC_PolicyCpHash // || cpHashA.buffer) // Start hash CryptHashStart(&hashState, session->authHashAlg); // add old digest CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); // add commandCode CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), commandCode); // add cpHashA CryptDigestUpdate2B(&hashState, &in->templateHash.b); // complete the digest and get the results CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); // update cpHash in session context session->u1.templateHash = in->templateHash; session->attributes.isTemplateSet = SET; return TPM_RC_SUCCESS; } #endif // CC_PolicyTemplateHash #include "Tpm.h" #if CC_PolicyAuthorizeNV // Conditional expansion of this file #include "PolicyAuthorizeNV_fp.h" #include "Policy_spt_fp.h" TPM_RC TPM2_PolicyAuthorizeNV( PolicyAuthorizeNV_In *in ) { SESSION *session; TPM_RC result; NV_REF locator; NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, &locator); TPM2B_NAME name; TPMT_HA policyInNv; BYTE nvTemp[sizeof(TPMT_HA)]; BYTE *buffer = nvTemp; INT32 size; // Input Validation // Get pointer to the session structure session = SessionGet(in->policySession); // Skip checks if this is a trial policy if(!session->attributes.isTrialPolicy) { // Check the authorizations for reading // Common read access checks. NvReadAccessChecks() returns // TPM_RC_NV_AUTHORIZATION, TPM_RC_NV_LOCKED, or TPM_RC_NV_UNINITIALIZED // error may be returned at this point result = NvReadAccessChecks(in->authHandle, in->nvIndex, nvIndex->publicArea.attributes); if(result != TPM_RC_SUCCESS) return result; // Read the contents of the index into a temp buffer size = MIN(nvIndex->publicArea.dataSize, sizeof(TPMT_HA)); NvGetIndexData(nvIndex, locator, 0, (UINT16)size, nvTemp); // Unmarshal the contents of the buffer into the internal format of a // TPMT_HA so that the hash and digest elements can be accessed from the // structure rather than the byte array that is in the Index (written by // user of the Index). result = TPMT_HA_Unmarshal(&policyInNv, &buffer, &size, FALSE); if(result != TPM_RC_SUCCESS) return result; // Verify that the hash is the same if(policyInNv.hashAlg != session->authHashAlg) return TPM_RC_HASH; // See if the contents of the digest in the Index matches the value // in the policy if(!MemoryEqual(&policyInNv.digest, &session->u2.policyDigest.t.buffer, session->u2.policyDigest.t.size)) return TPM_RC_VALUE; } // Internal Data Update // Set policyDigest to zero digest PolicyDigestClear(session); // Update policyDigest PolicyContextUpdate(TPM_CC_PolicyAuthorizeNV, EntityGetName(in->nvIndex, &name), NULL, NULL, 0, session); return TPM_RC_SUCCESS; } #endif // CC_PolicyAuthorizeNV libtpms-0.9.3/src/tpm2/ECC_Parameters_fp.h000066400000000000000000000074171421143571500202750ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: ECC_Parameters_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef ECC_PARAMETERS_FP_H #define ECC_PARAMETERS_FP_H typedef struct { TPMI_ECC_CURVE curveID; } ECC_Parameters_In; #define RC_ECC_Parameters_curveID (TPM_RC_P + TPM_RC_1) typedef struct { TPMS_ALGORITHM_DETAIL_ECC parameters; } ECC_Parameters_Out; TPM_RC TPM2_ECC_Parameters( ECC_Parameters_In *in, // IN: input parameter list ECC_Parameters_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/ECDH_KeyGen_fp.h000066400000000000000000000074061421143571500174630ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: ECDH_KeyGen_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef ECDH_KEYGEN_FP_H #define ECDH_KEYGEN_FP_H typedef struct { TPMI_DH_OBJECT keyHandle; } ECDH_KeyGen_In; #define RC_ECDH_KeyGen_keyHandle (TPM_RC_H + TPM_RC_1) typedef struct { TPM2B_ECC_POINT zPoint; TPM2B_ECC_POINT pubPoint; } ECDH_KeyGen_Out; TPM_RC TPM2_ECDH_KeyGen( ECDH_KeyGen_In *in, // IN: input parameter list ECDH_KeyGen_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/ECDH_ZGen_fp.h000066400000000000000000000074641421143571500171500ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: ECDH_ZGen_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef ECDH_ZGEN_FP_H #define ECDH_ZGEN_FP_H typedef struct { TPMI_DH_OBJECT keyHandle; TPM2B_ECC_POINT inPoint; } ECDH_ZGen_In; #define RC_ECDH_ZGen_keyHandle (TPM_RC_H + TPM_RC_1) #define RC_ECDH_ZGen_inPoint (TPM_RC_P + TPM_RC_1) typedef struct { TPM2B_ECC_POINT outPoint; } ECDH_ZGen_Out; TPM_RC TPM2_ECDH_ZGen( ECDH_ZGen_In *in, // IN: input parameter list ECDH_ZGen_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/EC_Ephemeral_fp.h000066400000000000000000000073741421143571500177730ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: EC_Ephemeral_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef EC_EPHEMERAL_FP_H #define EC_EPHEMERAL_FP_H typedef struct { TPMI_ECC_CURVE curveID; } EC_Ephemeral_In; #define RC_EC_Ephemeral_curveID (TPM_RC_P + TPM_RC_1) typedef struct { TPM2B_ECC_POINT Q; UINT16 counter; } EC_Ephemeral_Out; TPM_RC TPM2_EC_Ephemeral( EC_Ephemeral_In *in, // IN: input parameter list EC_Ephemeral_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/EccTestData.h000066400000000000000000000226401421143571500171520ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Parameter data for ECC testing */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: EccTestData.h 1259 2018-07-10 19:11:09Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2018 */ /* */ /********************************************************************************/ #ifdef SELF_TEST_DATA TPM2B_TYPE(EC_TEST, 32); const TPM_ECC_CURVE c_testCurve = 00003; // The static key const TPM2B_EC_TEST c_ecTestKey_ds = {{32, { 0xdf,0x8d,0xa4,0xa3,0x88,0xf6,0x76,0x96,0x89,0xfc,0x2f,0x2d,0xa1,0xb4,0x39,0x7a, 0x78,0xc4,0x7f,0x71,0x8c,0xa6,0x91,0x85,0xc0,0xbf,0xf3,0x54,0x20,0x91,0x2f,0x73}}}; const TPM2B_EC_TEST c_ecTestKey_QsX = {{32, { 0x17,0xad,0x2f,0xcb,0x18,0xd4,0xdb,0x3f,0x2c,0x53,0x13,0x82,0x42,0x97,0xff,0x8d, 0x99,0x50,0x16,0x02,0x35,0xa7,0x06,0xae,0x1f,0xda,0xe2,0x9c,0x12,0x77,0xc0,0xf9}}}; const TPM2B_EC_TEST c_ecTestKey_QsY = {{32, { 0xa6,0xca,0xf2,0x18,0x45,0x96,0x6e,0x58,0xe6,0x72,0x34,0x12,0x89,0xcd,0xaa,0xad, 0xcb,0x68,0xb2,0x51,0xdc,0x5e,0xd1,0x6d,0x38,0x20,0x35,0x57,0xb2,0xfd,0xc7,0x52}}}; // The ephemeral key const TPM2B_EC_TEST c_ecTestKey_de = {{32, { 0xb6,0xb5,0x33,0x5c,0xd1,0xee,0x52,0x07,0x99,0xea,0x2e,0x8f,0x8b,0x19,0x18,0x07, 0xc1,0xf8,0xdf,0xdd,0xb8,0x77,0x00,0xc7,0xd6,0x53,0x21,0xed,0x02,0x53,0xee,0xac}}}; const TPM2B_EC_TEST c_ecTestKey_QeX = {{32, { 0xa5,0x1e,0x80,0xd1,0x76,0x3e,0x8b,0x96,0xce,0xcc,0x21,0x82,0xc9,0xa2,0xa2,0xed, 0x47,0x21,0x89,0x53,0x44,0xe9,0xc7,0x92,0xe7,0x31,0x48,0x38,0xe6,0xea,0x93,0x47}}}; const TPM2B_EC_TEST c_ecTestKey_QeY = {{32, { 0x30,0xe6,0x4f,0x97,0x03,0xa1,0xcb,0x3b,0x32,0x2a,0x70,0x39,0x94,0xeb,0x4e,0xea, 0x55,0x88,0x81,0x3f,0xb5,0x00,0xb8,0x54,0x25,0xab,0xd4,0xda,0xfd,0x53,0x7a,0x18}}}; // ECDH test results const TPM2B_EC_TEST c_ecTestEcdh_X = {{32, { 0x64,0x02,0x68,0x92,0x78,0xdb,0x33,0x52,0xed,0x3b,0xfa,0x3b,0x74,0xa3,0x3d,0x2c, 0x2f,0x9c,0x59,0x03,0x07,0xf8,0x22,0x90,0xed,0xe3,0x45,0xf8,0x2a,0x0a,0xd8,0x1d}}}; const TPM2B_EC_TEST c_ecTestEcdh_Y = {{32, { 0x58,0x94,0x05,0x82,0xbe,0x5f,0x33,0x02,0x25,0x90,0x3a,0x33,0x90,0x89,0xe3,0xe5, 0x10,0x4a,0xbc,0x78,0xa5,0xc5,0x07,0x64,0xaf,0x91,0xbc,0xe6,0xff,0x85,0x11,0x40}}}; TPM2B_TYPE(TEST_VALUE, 64); const TPM2B_TEST_VALUE c_ecTestValue = {{64, { 0x78,0xd5,0xd4,0x56,0x43,0x61,0xdb,0x97,0xa4,0x32,0xc4,0x0b,0x06,0xa9,0xa8,0xa0, 0xf4,0x45,0x7f,0x13,0xd8,0x13,0x81,0x0b,0xe5,0x76,0xbe,0xaa,0xb6,0x3f,0x8d,0x4d, 0x23,0x65,0xcc,0xa7,0xc9,0x19,0x10,0xce,0x69,0xcb,0x0c,0xc7,0x11,0x8d,0xc3,0xff, 0x62,0x69,0xa2,0xbe,0x46,0x90,0xe7,0x7d,0x81,0x77,0x94,0x65,0x1c,0x3e,0xc1,0x3e}}}; #if ALG_SHA1_VALUE == DEFAULT_TEST_HASH const TPM2B_EC_TEST c_TestEcDsa_r = {{32, { 0x57,0xf3,0x36,0xb7,0xec,0xc2,0xdd,0x76,0x0e,0xe2,0x81,0x21,0x49,0xc5,0x66,0x11, 0x4b,0x8a,0x4f,0x17,0x62,0x82,0xcc,0x06,0xf6,0x64,0x78,0xef,0x6b,0x7c,0xf2,0x6c}}}; const TPM2B_EC_TEST c_TestEcDsa_s = {{32, { 0x1b,0xed,0x23,0x72,0x8f,0x17,0x5f,0x47,0x2e,0xa7,0x97,0x2c,0x51,0x57,0x20,0x70, 0x6f,0x89,0x74,0x8a,0xa8,0xf4,0x26,0xf4,0x96,0xa1,0xb8,0x3e,0xe5,0x35,0xc5,0x94}}}; const TPM2B_EC_TEST c_TestEcSchnorr_r = {{32,{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0x08,0x9f,0xde, 0xef,0x62,0xe3,0xf1,0x14,0xcb,0x54,0x28,0x13,0x76,0xfc,0x6d,0x69,0x22,0xb5,0x3e}}}; const TPM2B_EC_TEST c_TestEcSchnorr_s = {{32,{ 0xd9,0xd3,0x20,0xfb,0x4d,0x16,0xf2,0xe6,0xe2,0x45,0x07,0x45,0x1c,0x92,0x92,0x92, 0xa9,0x6b,0x48,0xf8,0xd1,0x98,0x29,0x4d,0xd3,0x8f,0x56,0xf2,0xbb,0x2e,0x22,0x3b}}}; #endif // SHA1 #if ALG_SHA256_VALUE == DEFAULT_TEST_HASH const TPM2B_EC_TEST c_TestEcDsa_r = {{32, { 0x04,0x7d,0x54,0xeb,0x04,0x6f,0x56,0xec,0xa2,0x6c,0x38,0x8c,0xeb,0x43,0x0b,0x71, 0xf8,0xf2,0xf4,0xa5,0xe0,0x1d,0x3c,0xa2,0x39,0x31,0xe4,0xe7,0x36,0x3b,0xb5,0x5f}}}; const TPM2B_EC_TEST c_TestEcDsa_s = {{32, { 0x8f,0xd0,0x12,0xd9,0x24,0x75,0xf6,0xc4,0x3b,0xb5,0x46,0x75,0x3a,0x41,0x8d,0x80, 0x23,0x99,0x38,0xd7,0xe2,0x40,0xca,0x9a,0x19,0x2a,0xfc,0x54,0x75,0xd3,0x4a,0x6e}}}; const TPM2B_EC_TEST c_TestEcSchnorr_r = {{32, { 0xf7,0xb9,0x15,0x4c,0x34,0xf6,0x41,0x19,0xa3,0xd2,0xf1,0xbd,0xf4,0x13,0x6a,0x4f, 0x63,0xb8,0x4d,0xb5,0xc8,0xcd,0xde,0x85,0x95,0xa5,0x39,0x0a,0x14,0x49,0x3d,0x2f}}}; const TPM2B_EC_TEST c_TestEcSchnorr_s = {{32,{ 0xfe,0xbe,0x17,0xaa,0x31,0x22,0x9f,0xd0,0xd2,0xf5,0x25,0x04,0x92,0xb0,0xaa,0x4e, 0xcc,0x1c,0xb6,0x79,0xd6,0x42,0xb3,0x4e,0x3f,0xbb,0xfe,0x5f,0xd0,0xd0,0x8b,0xc3}}}; #endif // SHA256 #if ALG_SHA384_VALUE == DEFAULT_TEST_HASH const TPM2B_EC_TEST c_TestEcDsa_r = {{32, { 0xf5,0x74,0x6d,0xd6,0xc6,0x56,0x86,0xbb,0xba,0x1c,0xba,0x75,0x65,0xee,0x64,0x31, 0xce,0x04,0xe3,0x9f,0x24,0x3f,0xbd,0xfe,0x04,0xcd,0xab,0x7e,0xfe,0xad,0xcb,0x82}}}; const TPM2B_EC_TEST c_TestEcDsa_s = {{32, { 0xc2,0x4f,0x32,0xa1,0x06,0xc0,0x85,0x4f,0xc6,0xd8,0x31,0x66,0x91,0x9f,0x79,0xcd, 0x5b,0xe5,0x7b,0x94,0xa1,0x91,0x38,0xac,0xd4,0x20,0xa2,0x10,0xf0,0xd5,0x9d,0xbf}}}; const TPM2B_EC_TEST c_TestEcSchnorr_r = {{32, { 0x1e,0xb8,0xe1,0xbf,0xa1,0x9e,0x39,0x1e,0x58,0xa2,0xe6,0x59,0xd0,0x1a,0x6a,0x03, 0x6a,0x1f,0x1c,0x4f,0x36,0x19,0xc1,0xec,0x30,0xa4,0x85,0x1b,0xe9,0x74,0x35,0x66}}}; const TPM2B_EC_TEST c_TestEcSchnorr_s = {{32,{ 0xb9,0xe6,0xe3,0x7e,0xcb,0xb9,0xea,0xf1,0xcc,0xf4,0x48,0x44,0x4a,0xda,0xc8,0xd7, 0x87,0xb4,0xba,0x40,0xfe,0x5b,0x68,0x11,0x14,0xcf,0xa0,0x0e,0x85,0x46,0x99,0x01}}}; #endif // SHA384 #if ALG_SHA512_VALUE == DEFAULT_TEST_HASH const TPM2B_EC_TEST c_TestEcDsa_r = {{32, { 0xc9,0x71,0xa6,0xb4,0xaf,0x46,0x26,0x8c,0x27,0x00,0x06,0x3b,0x00,0x0f,0xa3,0x17, 0x72,0x48,0x40,0x49,0x4d,0x51,0x4f,0xa4,0xcb,0x7e,0x86,0xe9,0xe7,0xb4,0x79,0xb2}}}; const TPM2B_EC_TEST c_TestEcDsa_s = {{32,{ 0x87,0xbc,0xc0,0xed,0x74,0x60,0x9e,0xfa,0x4e,0xe8,0x16,0xf3,0xf9,0x6b,0x26,0x07, 0x3c,0x74,0x31,0x7e,0xf0,0x62,0x46,0xdc,0xd6,0x45,0x22,0x47,0x3e,0x0c,0xa0,0x02}}}; const TPM2B_EC_TEST c_TestEcSchnorr_r = {{32,{ 0xcc,0x07,0xad,0x65,0x91,0xdd,0xa0,0x10,0x23,0xae,0x53,0xec,0xdf,0xf1,0x50,0x90, 0x16,0x96,0xf4,0x45,0x09,0x73,0x9c,0x84,0xb5,0x5c,0x5f,0x08,0x51,0xcb,0x60,0x01}}}; const TPM2B_EC_TEST c_TestEcSchnorr_s = {{32,{ 0x55,0x20,0x21,0x54,0xe2,0x49,0x07,0x47,0x71,0xf4,0x99,0x15,0x54,0xf3,0xab,0x14, 0xdb,0x8e,0xda,0x79,0xb6,0x02,0x0e,0xe3,0x5e,0x6f,0x2c,0xb6,0x05,0xbd,0x14,0x10}}}; #endif // SHA512 #endif // SELF_TEST_DATA libtpms-0.9.3/src/tpm2/EncryptDecrypt2_fp.h000066400000000000000000000101751421143571500205540ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: EncryptDecrypt2_fp.h 1047 2017-07-20 18:27:34Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015, 2016 */ /* */ /********************************************************************************/ /* rev 146 */ #ifndef ENCRYPTDECRYPT2_FP_H #define ENCRYPTDECRYPT2_FP_H typedef struct { TPMI_DH_OBJECT keyHandle; TPM2B_MAX_BUFFER inData; TPMI_YES_NO decrypt; TPMI_ALG_CIPHER_MODE mode; TPM2B_IV ivIn; } EncryptDecrypt2_In; #define RC_EncryptDecrypt2_keyHandle (TPM_RC_H + TPM_RC_1) #define RC_EncryptDecrypt2_inData (TPM_RC_P + TPM_RC_1) #define RC_EncryptDecrypt2_decrypt (TPM_RC_P + TPM_RC_2) #define RC_EncryptDecrypt2_mode (TPM_RC_P + TPM_RC_3) #define RC_EncryptDecrypt2_ivIn (TPM_RC_P + TPM_RC_4) typedef struct { TPM2B_MAX_BUFFER outData; TPM2B_IV ivOut; } EncryptDecrypt2_Out; TPM_RC TPM2_EncryptDecrypt2( EncryptDecrypt2_In *in, // IN: input parameter list EncryptDecrypt2_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/EncryptDecrypt_fp.h000066400000000000000000000101511421143571500204640ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: EncryptDecrypt_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef ENCRYPTDECRYPT_FP_H #define ENCRYPTDECRYPT_FP_H typedef struct { TPMI_DH_OBJECT keyHandle; TPMI_YES_NO decrypt; TPMI_ALG_CIPHER_MODE mode; TPM2B_IV ivIn; TPM2B_MAX_BUFFER inData; } EncryptDecrypt_In; #define RC_EncryptDecrypt_keyHandle (TPM_RC_H + TPM_RC_1) #define RC_EncryptDecrypt_decrypt (TPM_RC_P + TPM_RC_1) #define RC_EncryptDecrypt_mode (TPM_RC_P + TPM_RC_2) #define RC_EncryptDecrypt_ivIn (TPM_RC_P + TPM_RC_3) #define RC_EncryptDecrypt_inData (TPM_RC_P + TPM_RC_4) typedef struct { TPM2B_MAX_BUFFER outData; TPM2B_IV ivOut; } EncryptDecrypt_Out; TPM_RC TPM2_EncryptDecrypt( EncryptDecrypt_In *in, // IN: input parameter list EncryptDecrypt_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/EncryptDecrypt_spt.c000066400000000000000000000166461421143571500206770ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Encrypt Decrypt Support */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: EncryptDecrypt_spt.c 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2021 */ /* */ /********************************************************************************/ /* 7.7 Encrypt Decrypt Support (EncryptDecrypt_spt.c) */ #include "Tpm.h" #include "EncryptDecrypt_fp.h" #include "EncryptDecrypt_spt_fp.h" #if CC_EncryptDecrypt2 /* Error Returns Meaning */ /* TPM_RC_KEY is not a symmetric decryption key with both public and private portions loaded */ /* TPM_RC_SIZE IvIn size is incompatible with the block cipher mode; or inData size is not an even multiple of the block size for CBC or ECB mode */ /* TPM_RC_VALUE keyHandle is restricted and the argument mode does not match the key's mode */ TPM_RC EncryptDecryptShared( TPMI_DH_OBJECT keyHandleIn, TPMI_YES_NO decryptIn, TPMI_ALG_SYM_MODE modeIn, TPM2B_IV *ivIn, TPM2B_MAX_BUFFER *inData, EncryptDecrypt_Out *out ) { OBJECT *symKey; UINT16 keySize; UINT16 blockSize; BYTE *key; TPM_ALG_ID alg; TPM_ALG_ID mode; TPM_RC result; BOOL OK; // Input Validation symKey = HandleToObject(keyHandleIn); mode = symKey->publicArea.parameters.symDetail.sym.mode.sym; // The input key should be a symmetric key if(symKey->publicArea.type != TPM_ALG_SYMCIPHER) return TPM_RCS_KEY + RC_EncryptDecrypt_keyHandle; // The key must be unrestricted and allow the selected operation OK = !IS_ATTRIBUTE(symKey->publicArea.objectAttributes, TPMA_OBJECT, restricted); if(YES == decryptIn) OK = OK && IS_ATTRIBUTE(symKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt); else OK = OK && IS_ATTRIBUTE(symKey->publicArea.objectAttributes, TPMA_OBJECT, sign); if(!OK) return TPM_RCS_ATTRIBUTES + RC_EncryptDecrypt_keyHandle; // Make sure that key is an encrypt/decrypt key and not SMAC if(!CryptSymModeIsValid(mode, TRUE)) return TPM_RCS_MODE + RC_EncryptDecrypt_keyHandle; // If the key mode is not TPM_ALG_NULL... // or TPM_ALG_NULL if(mode != TPM_ALG_NULL) { // then the input mode has to be TPM_ALG_NULL or the same as the key if((modeIn != TPM_ALG_NULL) && (modeIn != mode)) return TPM_RCS_MODE + RC_EncryptDecrypt_mode; } else { // if the key mode is null, then the input can't be null if(modeIn == TPM_ALG_NULL) return TPM_RCS_MODE + RC_EncryptDecrypt_mode; mode = modeIn; } // The input iv for ECB mode should be an Empty Buffer. All the other modes // should have an iv size same as encryption block size keySize = symKey->publicArea.parameters.symDetail.sym.keyBits.sym; alg = symKey->publicArea.parameters.symDetail.sym.algorithm; blockSize = CryptGetSymmetricBlockSize(alg, keySize); // reverify the algorithm. This is mainly to keep static analysis tools happy if(blockSize == 0) return TPM_RCS_KEY + RC_EncryptDecrypt_keyHandle; if(((mode == TPM_ALG_ECB) && (ivIn->t.size != 0)) || ((mode != TPM_ALG_ECB) && (ivIn->t.size != blockSize))) return TPM_RCS_SIZE + RC_EncryptDecrypt_ivIn; // The input data size of CBC mode or ECB mode must be an even multiple of // the symmetric algorithm's block size if(((mode == TPM_ALG_CBC) || (mode == TPM_ALG_ECB)) && ((inData->t.size % blockSize) != 0)) return TPM_RCS_SIZE + RC_EncryptDecrypt_inData; // Copy IV // Note: This is copied here so that the calls to the encrypt/decrypt functions // will modify the output buffer, not the input buffer out->ivOut = *ivIn; // Command Output key = symKey->sensitive.sensitive.sym.t.buffer; // For symmetric encryption, the cipher data size is the same as plain data // size. out->outData.t.size = inData->t.size; if(decryptIn == YES) { // Decrypt data to output result = CryptSymmetricDecrypt(out->outData.t.buffer, alg, keySize, key, &(out->ivOut), mode, inData->t.size, inData->t.buffer); } else { // Encrypt data to output result = CryptSymmetricEncrypt(out->outData.t.buffer, alg, keySize, key, &(out->ivOut), mode, inData->t.size, inData->t.buffer); } return result; } #endif // CC_EncryptDecrypt libtpms-0.9.3/src/tpm2/EncryptDecrypt_spt_fp.h000066400000000000000000000072211421143571500213560ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: EncryptDecrypt_spt_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 */ /* */ /********************************************************************************/ #ifndef ENCRYPTDECRYPT_SPT_FP_H #define ENCRYPTDECRYPT_SPT_FP_H TPM_RC EncryptDecryptShared( TPMI_DH_OBJECT keyHandleIn, TPMI_YES_NO decryptIn, TPMI_ALG_SYM_MODE modeIn, TPM2B_IV *ivIn, TPM2B_MAX_BUFFER *inData, EncryptDecrypt_Out *out ); #endif libtpms-0.9.3/src/tpm2/Entity.c000066400000000000000000000422071421143571500162760ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Accessing properties for handles of various types */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Entity.c 1594 2020-03-26 22:15:48Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2020 */ /* */ /********************************************************************************/ /* 9.4 Entity.c */ /* 9.4.1 Description */ /* The functions in this file are used for accessing properties for handles of various types. Functions in other files require handles of a specific type but the functions in this file allow use of any handle type. */ /* 9.4.2 Includes */ #include "Tpm.h" /* 9.4.3 Functions */ /* 9.4.3.1 EntityGetLoadStatus() */ /* This function will check that all the handles access loaded entities. */ /* Error Returns Meaning */ /* TPM_RC_HANDLE handle type does not match */ /* TPM_RC_REFERENCE_Hx() entity is not present */ /* TPM_RC_HIERARCHY entity belongs to a disabled hierarchy */ /* TPM_RC_OBJECT_MEMORY handle is an evict object but there is no space to load it to RAM */ TPM_RC EntityGetLoadStatus( COMMAND *command // IN/OUT: command parsing structure ) { UINT32 i; TPM_RC result = TPM_RC_SUCCESS; // for(i = 0; i < command->handleNum; i++) { TPM_HANDLE handle = command->handles[i]; switch(HandleGetType(handle)) { // For handles associated with hierarchies, the entity is present // only if the associated enable is SET. case TPM_HT_PERMANENT: switch(handle) { case TPM_RH_OWNER: if(!gc.shEnable) result = TPM_RC_HIERARCHY; break; #ifdef VENDOR_PERMANENT case VENDOR_PERMANENT: #endif case TPM_RH_ENDORSEMENT: if(!gc.ehEnable) result = TPM_RC_HIERARCHY; break; case TPM_RH_PLATFORM: if(!g_phEnable) result = TPM_RC_HIERARCHY; break; // null handle, PW session handle and lockout // handle are always available case TPM_RH_NULL: case TPM_RS_PW: // Need to be careful for lockout. Lockout is always available // for policy checks but not always available when authValue // is being checked. case TPM_RH_LOCKOUT: // Rather than have #ifdefs all over the code, // CASE_ACT_HANDLE is defined in ACT.h. It is 'case TPM_RH_ACT_x:' // FOR_EACH_ACT(CASE_ACT_HANDLE) creates a simple // case TPM_RH_ACT_x: // for each of the implemented ACT. FOR_EACH_ACT(CASE_ACT_HANDLE) break; default: // If the implementation has a manufacturer-specific value // then test for it here. Since this implementation does // not have any, this implementation returns the same failure // that unmarshaling of a bad handle would produce. if(((TPM_RH)handle >= TPM_RH_AUTH_00) && ((TPM_RH)handle <= TPM_RH_AUTH_FF)) // if the implementation has a manufacturer-specific value result = TPM_RC_VALUE; else // The handle is in the range of reserved handles but is // not implemented in this TPM. result = TPM_RC_VALUE; break; } break; case TPM_HT_TRANSIENT: // For a transient object, check if the handle is associated // with a loaded object. if(!IsObjectPresent(handle)) result = TPM_RC_REFERENCE_H0; break; case TPM_HT_PERSISTENT: // Persistent object // Copy the persistent object to RAM and replace the handle with the // handle of the assigned slot. A TPM_RC_OBJECT_MEMORY, // TPM_RC_HIERARCHY or TPM_RC_REFERENCE_H0 error may be returned by // ObjectLoadEvict() result = ObjectLoadEvict(&command->handles[i], command->index); break; case TPM_HT_HMAC_SESSION: // For an HMAC session, see if the session is loaded // and if the session in the session slot is actually // an HMAC session. if(SessionIsLoaded(handle)) { SESSION *session; session = SessionGet(handle); // Check if the session is a HMAC session if(session->attributes.isPolicy == SET) result = TPM_RC_HANDLE; } else result = TPM_RC_REFERENCE_H0; break; case TPM_HT_POLICY_SESSION: // For a policy session, see if the session is loaded // and if the session in the session slot is actually // a policy session. if(SessionIsLoaded(handle)) { SESSION *session; session = SessionGet(handle); // Check if the session is a policy session if(session->attributes.isPolicy == CLEAR) result = TPM_RC_HANDLE; } else result = TPM_RC_REFERENCE_H0; break; case TPM_HT_NV_INDEX: // For an NV Index, use the TPM-specific routine // to search the IN Index space. result = NvIndexIsAccessible(handle); break; case TPM_HT_PCR: // Any PCR handle that is unmarshaled successfully referenced // a PCR that is defined. break; #if CC_AC_Send case TPM_HT_AC: // Use the TPM-specific routine to search for the AC result = AcIsAccessible(handle); break; #endif default: // Any other handle type is a defect in the unmarshaling code. FAIL(FATAL_ERROR_INTERNAL); break; } if(result != TPM_RC_SUCCESS) { if(result == TPM_RC_REFERENCE_H0) result = result + i; else result = RcSafeAddToResult(result, TPM_RC_H + g_rcIndex[i]); break; } } return result; } /* 9.4.3.2 EntityGetAuthValue() */ /* This function is used to access the authValue associated with a handle. This function assumes that the handle references an entity that is accessible and the handle is not for a persistent objects. That is EntityGetLoadStatus() should have been called. Also, the accessibility of the authValue should have been verified by IsAuthValueAvailable(). */ /* This function copies the authorization value of the entity to auth. */ /* Return Values Meaning */ /* count number of bytes in the authValue with zeros stripped */ UINT16 EntityGetAuthValue( TPMI_DH_ENTITY handle, // IN: handle of entity TPM2B_AUTH *auth // OUT: authValue of the entity ) { TPM2B_AUTH *pAuth = NULL; auth->t.size = 0; switch(HandleGetType(handle)) { case TPM_HT_PERMANENT: { switch(handle) { case TPM_RH_OWNER: // ownerAuth for TPM_RH_OWNER pAuth = &gp.ownerAuth; break; case TPM_RH_ENDORSEMENT: // endorsementAuth for TPM_RH_ENDORSEMENT pAuth = &gp.endorsementAuth; break; // The ACT use platformAuth for auth FOR_EACH_ACT(CASE_ACT_HANDLE) case TPM_RH_PLATFORM: // platformAuth for TPM_RH_PLATFORM pAuth = &gc.platformAuth; break; case TPM_RH_LOCKOUT: // lockoutAuth for TPM_RH_LOCKOUT pAuth = &gp.lockoutAuth; break; case TPM_RH_NULL: // nullAuth for TPM_RH_NULL. Return 0 directly here return 0; break; #ifdef VENDOR_PERMANENT case VENDOR_PERMANENT: // vendor authorization value pAuth = &g_platformUniqueDetails; #endif default: // If any other permanent handle is present it is // a code defect. FAIL(FATAL_ERROR_INTERNAL); break; } break; } case TPM_HT_TRANSIENT: // authValue for an object // A persistent object would have been copied into RAM // and would have an transient object handle here. { OBJECT *object; object = HandleToObject(handle); // special handling if this is a sequence object if(ObjectIsSequence(object)) { pAuth = &((HASH_OBJECT *)object)->auth; } else { // Authorization is available only when the private portion of // the object is loaded. The check should be made before // this function is called pAssert(object->attributes.publicOnly == CLEAR); pAuth = &object->sensitive.authValue; } } break; case TPM_HT_NV_INDEX: // authValue for an NV index { NV_INDEX *nvIndex = NvGetIndexInfo(handle, NULL); pAssert(nvIndex != NULL); pAuth = &nvIndex->authValue; } break; case TPM_HT_PCR: // authValue for PCR pAuth = PCRGetAuthValue(handle); break; default: // If any other handle type is present here, then there is a defect // in the unmarshaling code. FAIL(FATAL_ERROR_INTERNAL); break; } // Copy the authValue MemoryCopy2B((TPM2B *)auth, (TPM2B *)pAuth, sizeof(auth->t.buffer)); MemoryRemoveTrailingZeros(auth); return auth->t.size; } /* 9.4.3.3 EntityGetAuthPolicy() */ /* This function is used to access the authPolicy associated with a handle. This function assumes that the handle references an entity that is accessible and the handle is not for a persistent objects. That is EntityGetLoadStatus() should have been called. Also, the accessibility of the authPolicy should have been verified by IsAuthPolicyAvailable(). */ /* This function copies the authorization policy of the entity to authPolicy. */ /* The return value is the hash algorithm for the policy. */ TPMI_ALG_HASH EntityGetAuthPolicy( TPMI_DH_ENTITY handle, // IN: handle of entity TPM2B_DIGEST *authPolicy // OUT: authPolicy of the entity ) { TPMI_ALG_HASH hashAlg = TPM_ALG_NULL; authPolicy->t.size = 0; switch(HandleGetType(handle)) { case TPM_HT_PERMANENT: switch(handle) { case TPM_RH_OWNER: // ownerPolicy for TPM_RH_OWNER *authPolicy = gp.ownerPolicy; hashAlg = gp.ownerAlg; break; case TPM_RH_ENDORSEMENT: // endorsementPolicy for TPM_RH_ENDORSEMENT *authPolicy = gp.endorsementPolicy; hashAlg = gp.endorsementAlg; break; case TPM_RH_PLATFORM: // platformPolicy for TPM_RH_PLATFORM *authPolicy = gc.platformPolicy; hashAlg = gc.platformAlg; break; case TPM_RH_LOCKOUT: // lockoutPolicy for TPM_RH_LOCKOUT *authPolicy = gp.lockoutPolicy; hashAlg = gp.lockoutAlg; break; #define ACT_GET_POLICY(N) \ case TPM_RH_ACT_##N: \ *authPolicy = go.ACT_##N.authPolicy; \ hashAlg = go.ACT_##N.hashAlg; \ break; // Get the policy for each implemented ACT FOR_EACH_ACT(ACT_GET_POLICY) default: hashAlg = TPM_ALG_ERROR; break; } break; case TPM_HT_TRANSIENT: // authPolicy for an object { OBJECT *object = HandleToObject(handle); *authPolicy = object->publicArea.authPolicy; hashAlg = object->publicArea.nameAlg; } break; case TPM_HT_NV_INDEX: // authPolicy for a NV index { NV_INDEX *nvIndex = NvGetIndexInfo(handle, NULL); pAssert(nvIndex != 0); *authPolicy = nvIndex->publicArea.authPolicy; hashAlg = nvIndex->publicArea.nameAlg; } break; case TPM_HT_PCR: // authPolicy for a PCR hashAlg = PCRGetAuthPolicy(handle, authPolicy); break; default: // If any other handle type is present it is a code defect. FAIL(FATAL_ERROR_INTERNAL); break; } return hashAlg; } /* 9.4.3.4 EntityGetName() */ /* This function returns the Name associated with a handle. */ TPM2B_NAME * EntityGetName( TPMI_DH_ENTITY handle, // IN: handle of entity TPM2B_NAME *name // OUT: name of entity ) { switch(HandleGetType(handle)) { case TPM_HT_TRANSIENT: { // Name for an object OBJECT *object = HandleToObject(handle); // an object with no nameAlg has no name if(object->publicArea.nameAlg == TPM_ALG_NULL) name->b.size = 0; else *name = object->name; break; } case TPM_HT_NV_INDEX: // Name for a NV index NvGetNameByIndexHandle(handle, name); break; default: // For all other types, the handle is the Name name->t.size = sizeof(TPM_HANDLE); UINT32_TO_BYTE_ARRAY(handle, name->t.name); break; } return name; } /* 9.4.3.5 EntityGetHierarchy() */ /* This function returns the hierarchy handle associated with an entity. */ /* a) A handle that is a hierarchy handle is associated with itself. */ /* b) An NV index belongs to TPM_RH_PLATFORM if TPMA_NV_PLATFORMCREATE, is SET, otherwise it belongs to TPM_RH_OWNER */ /* c) An object handle belongs to its hierarchy. All other handles belong to the platform hierarchy. or an NV Index. */ TPMI_RH_HIERARCHY EntityGetHierarchy( TPMI_DH_ENTITY handle // IN :handle of entity ) { TPMI_RH_HIERARCHY hierarchy = TPM_RH_NULL; switch(HandleGetType(handle)) { case TPM_HT_PERMANENT: // hierarchy for a permanent handle switch(handle) { case TPM_RH_PLATFORM: case TPM_RH_ENDORSEMENT: case TPM_RH_NULL: hierarchy = handle; break; // all other permanent handles are associated with the owner // hierarchy. (should only be TPM_RH_OWNER and TPM_RH_LOCKOUT) default: hierarchy = TPM_RH_OWNER; break; } break; case TPM_HT_NV_INDEX: // hierarchy for NV index { NV_INDEX *nvIndex = NvGetIndexInfo(handle, NULL); pAssert(nvIndex != NULL); // If only the platform can delete the index, then it is // considered to be in the platform hierarchy, otherwise it // is in the owner hierarchy. if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, PLATFORMCREATE)) hierarchy = TPM_RH_PLATFORM; else hierarchy = TPM_RH_OWNER; } break; case TPM_HT_TRANSIENT: // hierarchy for an object { OBJECT *object; object = HandleToObject(handle); if(object->attributes.ppsHierarchy) { hierarchy = TPM_RH_PLATFORM; } else if(object->attributes.epsHierarchy) { hierarchy = TPM_RH_ENDORSEMENT; } else if(object->attributes.spsHierarchy) { hierarchy = TPM_RH_OWNER; } } break; case TPM_HT_PCR: hierarchy = TPM_RH_OWNER; break; default: FAIL(FATAL_ERROR_INTERNAL); break; } // this is unreachable but it provides a return value for the default // case which makes the compiler happy return hierarchy; } libtpms-0.9.3/src/tpm2/Entity_fp.h000066400000000000000000000100711421143571500167620ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Entity_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 */ /* */ /********************************************************************************/ #ifndef ENTITY_FP_H #define ENTITY_FP_H TPM_RC EntityGetLoadStatus( COMMAND *command // IN/OUT: command parsing structure ); UINT16 EntityGetAuthValue( TPMI_DH_ENTITY handle, // IN: handle of entity TPM2B_AUTH *auth // OUT: authValue of the entity ); TPMI_ALG_HASH EntityGetAuthPolicy( TPMI_DH_ENTITY handle, // IN: handle of entity TPM2B_DIGEST *authPolicy // OUT: authPolicy of the entity ); TPM2B_NAME * EntityGetName( TPMI_DH_ENTITY handle, // IN: handle of entity TPM2B_NAME *name // OUT: name of entity ); TPMI_RH_HIERARCHY EntityGetHierarchy( TPMI_DH_ENTITY handle // IN :handle of entity ); #endif libtpms-0.9.3/src/tpm2/Entropy.c000066400000000000000000000172621421143571500164650ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Entropy */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Entropy.c 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ /* C.4 Entropy.c */ /* C.4.1. Includes and Local values*/ #define _CRT_RAND_S #include #include #include /* libtpms added */ #include #include "Platform.h" #ifdef _MSC_VER #include #else #include #endif /* This is the last 32-bits of hardware entropy produced. We have to check to see that two consecutive 32-bit values are not the same because (according to FIPS 140-2, annex C */ /* "If each call to a RNG produces blocks of n bits (where n > 15), the first n-bit block generated after power-up, initialization, or reset shall not be used, but shall be saved for comparison with the next n-bit block to be generated. Each subsequent generation of an n-bit block shall be compared with the previously generated block. The test shall fail if any two compared n-bit blocks are equal." */ extern uint32_t lastEntropy; /* C.4.2. Functions */ /* C.4.2.1. rand32() */ /* Local function to get a 32-bit random number */ static uint32_t rand32( void ) { uint32_t rndNum = rand(); #if RAND_MAX < UINT16_MAX // If the maximum value of the random number is a 15-bit number, then shift it up // 15 bits, get 15 more bits, shift that up 2 and then XOR in another value to get // a full 32 bits. rndNum = (rndNum << 15) ^ rand(); rndNum = (rndNum << 2) ^ rand(); #elif RAND_MAX == UINT16_MAX // If the maximum size is 16-bits, shift it and add another 16 bits rndNum = (rndNum << 16) ^ rand(); #elif RAND_MAX < UINT32_MAX // If 31 bits, then shift 1 and include another random value to get the extra bit rndNum = (rndNum << 1) ^ rand(); #endif return rndNum; } /* C.4.2.2 _plat__GetEntropy() */ /* This function is used to get available hardware entropy. In a hardware implementation of this function, there would be no call to the system to get entropy. */ /* Return Values Meaning */ /* < 0 hardware failure of the entropy generator, this is sticky */ /* >= 0 the returned amount of entropy (bytes) */ LIB_EXPORT int32_t _plat__GetEntropy( unsigned char *entropy, // output buffer uint32_t amount // amount requested ) { uint32_t rndNum; int32_t ret; // // libtpms added begin if (amount > 0 && RAND_bytes(entropy, amount) == 1) return amount; // fall back to 'original' method // libtpms added end if(amount == 0) { // Seed the platform entropy source if the entropy source is software. There is // no reason to put a guard macro (#if or #ifdef) around this code because this // code would not be here if someone was changing it for a system with actual // hardware. // // NOTE 1: The following command does not provide proper cryptographic entropy. // Its primary purpose to make sure that different instances of the simulator, // possibly started by a script on the same machine, are seeded differently. // Vendors of the actual TPMs need to ensure availability of proper entropy // using their platform specific means. // // NOTE 2: In debug builds by default the reference implementation will seed // its RNG deterministically (without using any platform provided randomness). // See the USE_DEBUG_RNG macro and DRBG_GetEntropy() function. #ifdef _MSC_VER srand((unsigned)_plat__RealTime() ^ _getpid()); #else srand((unsigned)_plat__RealTime() ^ getpid()); #endif lastEntropy = rand32(); ret = 0; } else { rndNum = rand32(); if(rndNum == lastEntropy) { ret = -1; } else { lastEntropy = rndNum; // Each process will have its random number generator initialized according // to the process id and the initialization time. This is not a lot of // entropy so, to add a bit more, XOR the current time value into the // returned entropy value. // NOTE: the reason for including the time here rather than have it in // in the value assigned to lastEntropy is that rand() could be broken and // using the time would in the lastEntropy value would hide this. rndNum ^= (uint32_t)_plat__RealTime(); // Only provide entropy 32 bits at a time to test the ability // of the caller to deal with partial results. ret = MIN(amount, sizeof(rndNum)); memcpy(entropy, &rndNum, ret); } } return ret; } libtpms-0.9.3/src/tpm2/EphemeralCommands.c000066400000000000000000000203051421143571500204010ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Ephemeral EC Keys */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: EphemeralCommands.c 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ #include "Tpm.h" #include "Commit_fp.h" #if CC_Commit // Conditional expansion of this file TPM_RC TPM2_Commit( Commit_In *in, // IN: input parameter list Commit_Out *out // OUT: output parameter list ) { OBJECT *eccKey; TPMS_ECC_POINT P2; TPMS_ECC_POINT *pP2 = NULL; TPMS_ECC_POINT *pP1 = NULL; TPM2B_ECC_PARAMETER r; TPM2B_ECC_PARAMETER p; TPM_RC result; TPMS_ECC_PARMS *parms; // Input Validation eccKey = HandleToObject(in->signHandle); parms = &eccKey->publicArea.parameters.eccDetail; // Input key must be an ECC key if(eccKey->publicArea.type != TPM_ALG_ECC) return TPM_RCS_KEY + RC_Commit_signHandle; // This command may only be used with a sign-only key using an anonymous // scheme. // NOTE: a sign + decrypt key has no scheme so it will not be an anonymous one // and an unrestricted sign key might no have a signing scheme but it can't // be use in Commit() if(!CryptIsSchemeAnonymous(parms->scheme.scheme)) return TPM_RCS_SCHEME + RC_Commit_signHandle; // Make sure that both parts of P2 are present if either is present if((in->s2.t.size == 0) != (in->y2.t.size == 0)) return TPM_RCS_SIZE + RC_Commit_y2; // Get prime modulus for the curve. This is needed later but getting this now // allows confirmation that the curve exists. if(!CryptEccGetParameter(&p, 'p', parms->curveID)) return TPM_RCS_KEY + RC_Commit_signHandle; // Get the random value that will be used in the point multiplications // Note: this does not commit the count. if(!CryptGenerateR(&r, NULL, parms->curveID, &eccKey->name)) return TPM_RC_NO_RESULT; // Set up P2 if s2 and Y2 are provided if(in->s2.t.size != 0) { TPM2B_DIGEST x2; pP2 = &P2; // copy y2 for P2 P2.y = in->y2; // Compute x2 HnameAlg(s2) mod p // do the hash operation on s2 with the size of curve 'p' x2.t.size = CryptHashBlock(eccKey->publicArea.nameAlg, in->s2.t.size, in->s2.t.buffer, sizeof(x2.t.buffer), x2.t.buffer); // If there were error returns in the hash routine, indicate a problem // with the hash algorithm selection if(x2.t.size == 0) return TPM_RCS_HASH + RC_Commit_signHandle; // The size of the remainder will be same as the size of p. DivideB() will // pad the results (leading zeros) if necessary to make the size the same P2.x.t.size = p.t.size; // set p2.x = hash(s2) mod p if(DivideB(&x2.b, &p.b, NULL, &P2.x.b) != TPM_RC_SUCCESS) return TPM_RC_NO_RESULT; if(!CryptEccIsPointOnCurve(parms->curveID, pP2)) return TPM_RCS_ECC_POINT + RC_Commit_s2; if(eccKey->attributes.publicOnly == SET) return TPM_RCS_KEY + RC_Commit_signHandle; } // If there is a P1, make sure that it is on the curve // NOTE: an "empty" point has two UINT16 values which are the size values // for each of the coordinates. if(in->P1.size > 4) { pP1 = &in->P1.point; if(!CryptEccIsPointOnCurve(parms->curveID, pP1)) return TPM_RCS_ECC_POINT + RC_Commit_P1; } // Pass the parameters to CryptCommit. // The work is not done in-line because it does several point multiplies // with the same curve. It saves work by not having to reload the curve // parameters multiple times. result = CryptEccCommitCompute(&out->K.point, &out->L.point, &out->E.point, parms->curveID, pP1, pP2, &eccKey->sensitive.sensitive.ecc, &r); if(result != TPM_RC_SUCCESS) return result; // The commit computation was successful so complete the commit by setting // the bit out->counter = CryptCommit(); return TPM_RC_SUCCESS; } #endif // CC_Commit #include "Tpm.h" #include "EC_Ephemeral_fp.h" #if CC_EC_Ephemeral // Conditional expansion of this file TPM_RC TPM2_EC_Ephemeral( EC_Ephemeral_In *in, // IN: input parameter list EC_Ephemeral_Out *out // OUT: output parameter list ) { TPM2B_ECC_PARAMETER r; TPM_RC result; // do { // Get the random value that will be used in the point multiplications // Note: this does not commit the count. if(!CryptGenerateR(&r, NULL, in->curveID, NULL)) return TPM_RC_NO_RESULT; // do a point multiply result = CryptEccPointMultiply(&out->Q.point, in->curveID, NULL, &r, NULL, NULL); // commit the count value if either the r value results in the point at // infinity or if the value is good. The commit on the r value for infinity // is so that the r value will be skipped. if((result == TPM_RC_SUCCESS) || (result == TPM_RC_NO_RESULT)) out->counter = CryptCommit(); } while(result == TPM_RC_NO_RESULT); return TPM_RC_SUCCESS; } #endif // CC_EC_Ephemeral libtpms-0.9.3/src/tpm2/EventSequenceComplete_fp.h000066400000000000000000000100041421143571500217450ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: EventSequenceComplete_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef EVENTSEQUENCECOMPLETE_FP_H #define EVENTSEQUENCECOMPLETE_FP_H typedef struct { TPMI_DH_PCR pcrHandle; TPMI_DH_OBJECT sequenceHandle; TPM2B_MAX_BUFFER buffer; } EventSequenceComplete_In; #define RC_EventSequenceComplete_pcrHandle (TPM_RC_H + TPM_RC_1) #define RC_EventSequenceComplete_sequenceHandle (TPM_RC_H + TPM_RC_2) #define RC_EventSequenceComplete_buffer (TPM_RC_P + TPM_RC_1) typedef struct { TPML_DIGEST_VALUES results; } EventSequenceComplete_Out; TPM_RC TPM2_EventSequenceComplete( EventSequenceComplete_In *in, // IN: input parameter list EventSequenceComplete_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/EvictControl_fp.h000066400000000000000000000074521421143571500201320ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: EvictControl_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef EVICTCONTROL_FP_H #define EVICTCONTROL_FP_H typedef struct { TPMI_RH_PROVISION auth; TPMI_DH_OBJECT objectHandle; TPMI_DH_PERSISTENT persistentHandle; } EvictControl_In; #define RC_EvictControl_auth (TPM_RC_H + TPM_RC_1) #define RC_EvictControl_objectHandle (TPM_RC_H + TPM_RC_2) #define RC_EvictControl_persistentHandle (TPM_RC_P + TPM_RC_1) TPM_RC TPM2_EvictControl( EvictControl_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/ExecCommand.c000066400000000000000000000350401421143571500172020ustar00rootroot00000000000000/********************************************************************************/ /* */ /* ExecCommand */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: ExecCommand.c 1600 2020-03-30 22:08:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2020 */ /* */ /********************************************************************************/ /* 6.2 ExecCommand.c */ /* This file contains the entry function ExecuteCommand() which provides the main control flow for TPM command execution. */ #include "Tpm.h" #include "ExecCommand_fp.h" #define TPM_HAVE_TPM2_DECLARATIONS #include "tpm_library_intern.h" // libtpms added /* Uncomment this next #include if doing static command/response buffer sizing */ // #include "CommandResponseSizes_fp.h" // The function performs the following steps. // a) Parses the command header from input buffer. // b) Calls ParseHandleBuffer() to parse the handle area of the command. // c) Validates that each of the handles references a loaded entity. // d) Calls ParseSessionBuffer() () to: // 1) unmarshal and parse the session area; // 2) check the authorizations; and // 3) when necessary, decrypt a parameter. // e) Calls CommandDispatcher() to: // 1) unmarshal the command parameters from the command buffer; // 2) call the routine that performs the command actions; and // 3) marshal the responses into the response buffer. // f) If any error occurs in any of the steps above create the error response and return. // g) Calls BuildResponseSession() to: // 1) when necessary, encrypt a parameter // 2) build the response authorization sessions // 3) update the audit sessions and nonces // h) Calls BuildResponseHeader() to complete the construction of the response. // responseSize is set by the caller to the maximum number of bytes available in the output // buffer. ExecuteCommand() will adjust the value and return the number of bytes placed in // the buffer. // response is also set by the caller to indicate the buffer into which ExecuteCommand() is // to place the response. // request and response may point to the same buffer // NOTE: As of February, 2016, the failure processing has been moved to the platform-specific // code. When the TPM code encounters an unrecoverable failure, it will SET g_inFailureMode // and call _plat__Fail(). That function should not return but may call ExecuteCommand(). LIB_EXPORT void ExecuteCommand( uint32_t requestSize, // IN: command buffer size unsigned char *request, // IN: command buffer uint32_t *responseSize, // IN/OUT: response buffer size unsigned char **response // IN/OUT: response buffer ) { // Command local variables UINT32 commandSize; COMMAND command; // Response local variables UINT32 maxResponse = *responseSize; TPM_RC result; // return code for the command // This next function call is used in development to size the command and response // buffers. The values printed are the sizes of the internal structures and // not the sizes of the canonical forms of he command response structures. Also, // the sizes do not include the tag, command.code, requestSize, or the authorization // fields. //CommandResponseSizes(); // Set flags for NV access state. This should happen before any other // operation that may require a NV write. Note, that this needs to be done // even when in failure mode. Otherwise, g_updateNV would stay SET while in // Failure mode and the NV would be written on each call. g_updateNV = UT_NONE; g_clearOrderly = FALSE; if(g_inFailureMode) { // Do failure mode processing TpmFailureMode(requestSize, request, responseSize, response); return; } // Query platform to get the NV state. The result state is saved internally // and will be reported by NvIsAvailable(). The reference code requires that // accessibility of NV does not change during the execution of a command. // Specifically, if NV is available when the command execution starts and then // is not available later when it is necessary to write to NV, then the TPM // will go into failure mode. NvCheckState(); // Due to the limitations of the simulation, TPM clock must be explicitly // synchronized with the system clock whenever a command is received. // This function call is not necessary in a hardware TPM. However, taking // a snapshot of the hardware timer at the beginning of the command allows // the time value to be consistent for the duration of the command execution. TimeUpdateToCurrent(); // Any command through this function will unceremoniously end the // _TPM_Hash_Data/_TPM_Hash_End sequence. if(g_DRTMHandle != TPM_RH_UNASSIGNED) ObjectTerminateEvent(); // Get command buffer size and command buffer. command.parameterBuffer = request; command.parameterSize = requestSize; // Parse command header: tag, commandSize and command.code. // First parse the tag. The unmarshaling routine will validate // that it is either TPM_ST_SESSIONS or TPM_ST_NO_SESSIONS. result = TPMI_ST_COMMAND_TAG_Unmarshal(&command.tag, &command.parameterBuffer, &command.parameterSize); if(result != TPM_RC_SUCCESS) goto Cleanup; // Unmarshal the commandSize indicator. result = UINT32_Unmarshal(&commandSize, &command.parameterBuffer, &command.parameterSize); if(result != TPM_RC_SUCCESS) goto Cleanup; // On a TPM that receives bytes on a port, the number of bytes that were // received on that port is requestSize it must be identical to commandSize. // In addition, commandSize must not be larger than MAX_COMMAND_SIZE allowed // by the implementation. The check against MAX_COMMAND_SIZE may be redundant // as the input processing (the function that receives the command bytes and // places them in the input buffer) would likely have the input truncated when // it reaches MAX_COMMAND_SIZE, and requestSize would not equal commandSize. if(commandSize != requestSize || commandSize > MAX_COMMAND_SIZE) { result = TPM_RC_COMMAND_SIZE; goto Cleanup; } // Unmarshal the command code. result = TPM_CC_Unmarshal(&command.code, &command.parameterBuffer, &command.parameterSize); if(result != TPM_RC_SUCCESS) goto Cleanup; // Check to see if the command is implemented. command.index = CommandCodeToCommandIndex(command.code); if(UNIMPLEMENTED_COMMAND_INDEX == command.index) { result = TPM_RC_COMMAND_CODE; goto Cleanup; } #if FIELD_UPGRADE_IMPLEMENTED == YES // If the TPM is in FUM, then the only allowed command is // TPM_CC_FieldUpgradeData. if(IsFieldUgradeMode() && (command.code != TPM_CC_FieldUpgradeData)) { result = TPM_RC_UPGRADE; goto Cleanup; } else #endif // Excepting FUM, the TPM only accepts TPM2_Startup() after // _TPM_Init. After getting a TPM2_Startup(), TPM2_Startup() // is no longer allowed. if((!TPMIsStarted() && command.code != TPM_CC_Startup) || (TPMIsStarted() && command.code == TPM_CC_Startup)) { result = TPM_RC_INITIALIZE; goto Cleanup; } // Start regular command process. NvIndexCacheInit(); // Parse Handle buffer. result = ParseHandleBuffer(&command); if(result != TPM_RC_SUCCESS) goto Cleanup; // All handles in the handle area are required to reference TPM-resident // entities. result = EntityGetLoadStatus(&command); if(result != TPM_RC_SUCCESS) goto Cleanup; // Authorization session handling for the command. ClearCpRpHashes(&command); if(command.tag == TPM_ST_SESSIONS) { // Find out session buffer size. result = UINT32_Unmarshal((UINT32 *)&command.authSize, &command.parameterBuffer, &command.parameterSize); if(result != TPM_RC_SUCCESS) goto Cleanup; // Perform sanity check on the unmarshaled value. If it is smaller than // the smallest possible session or larger than the remaining size of // the command, then it is an error. NOTE: This check could pass but the // session size could still be wrong. That will be determined after the // sessions are unmarshaled. if(command.authSize < 9 || command.authSize > command.parameterSize) { result = TPM_RC_SIZE; goto Cleanup; } command.parameterSize -= command.authSize; // The actions of ParseSessionBuffer() are described in the introduction. // As the sessions are parsed command.parameterBuffer is advanced so, on a // successful return, command.parameterBuffer should be pointing at the // first byte of the parameters. result = ParseSessionBuffer(&command); if(result != TPM_RC_SUCCESS) goto Cleanup; } else { command.authSize = 0; // The command has no authorization sessions. // If the command requires authorizations, then CheckAuthNoSession() will // return an error. result = CheckAuthNoSession(&command); if(result != TPM_RC_SUCCESS) goto Cleanup; } // Set up the response buffer pointers. CommandDispatch will marshal the // response parameters starting at the address in command.responseBuffer. // *response = MemoryGetResponseBuffer(command.index); // leave space for the command header command.responseBuffer = *response + STD_RESPONSE_HEADER; // leave space for the parameter size field if needed if(command.tag == TPM_ST_SESSIONS) command.responseBuffer += sizeof(UINT32); if(IsHandleInResponse(command.index)) command.responseBuffer += sizeof(TPM_HANDLE); // CommandDispatcher returns a response handle buffer and a response parameter // buffer if it succeeds. It will also set the parameterSize field in the // buffer if the tag is TPM_RC_SESSIONS. result = CommandDispatcher(&command); if(result != TPM_RC_SUCCESS) goto Cleanup; // Build the session area at the end of the parameter area. BuildResponseSession(&command); Cleanup: if(g_clearOrderly == TRUE && NV_IS_ORDERLY) { #if USE_DA_USED gp.orderlyState = g_daUsed ? SU_DA_USED_VALUE : SU_NONE_VALUE; #else gp.orderlyState = SU_NONE_VALUE; #endif NV_SYNC_PERSISTENT(orderlyState); } // This implementation loads an "evict" object to a transient object slot in // RAM whenever an "evict" object handle is used in a command so that the // access to any object is the same. These temporary objects need to be // cleared from RAM whether the command succeeds or fails. ObjectCleanupEvict(); // The parameters and sessions have been marshaled. Now tack on the header and // set the sizes BuildResponseHeader(&command, *response, result); // Try to commit all the writes to NV if any NV write happened during this // command execution. This check should be made for both succeeded and failed // commands, because a failed one may trigger a NV write in DA logic as well. // This is the only place in the command execution path that may call the NV // commit. If the NV commit fails, the TPM should be put in failure mode. if((g_updateNV != UT_NONE) && !g_inFailureMode) { if(g_updateNV == UT_ORDERLY) NvUpdateIndexOrderlyData(); if(!NvCommit()) FAIL(FATAL_ERROR_INTERNAL); g_updateNV = UT_NONE; } pAssert((UINT32)command.parameterSize <= maxResponse); // Clear unused bits in response buffer. MemorySet(*response + *responseSize, 0, maxResponse - *responseSize); // as a final act, and not before, update the response size. *responseSize = (UINT32)command.parameterSize; return; } libtpms-0.9.3/src/tpm2/ExecCommand_fp.h000066400000000000000000000072521421143571500177000ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: ExecCommand_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 */ /* */ /********************************************************************************/ #ifndef EXECCOMMAND_FP_H #define EXECCOMMAND_FP_H LIB_EXPORT void ExecuteCommand( uint32_t requestSize, // IN: command buffer size unsigned char *request, // IN: command buffer uint32_t *responseSize, // IN/OUT: response buffer size unsigned char **response // IN/OUT: response buffer ); #endif libtpms-0.9.3/src/tpm2/FlushContext_fp.h000066400000000000000000000071551421143571500201450ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: FlushContext_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef FLUSHCONTEXT_FP_H #define FLUSHCONTEXT_FP_H typedef struct { TPMI_DH_CONTEXT flushHandle; } FlushContext_In; #define RC_FlushContext_flushHandle (TPM_RC_P + TPM_RC_1) TPM_RC TPM2_FlushContext( FlushContext_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/GetCapability_fp.h000066400000000000000000000077041421143571500202400ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: GetCapability_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef GETCAPABILITY_FP_H #define GETCAPABILITY_FP_H typedef struct { TPM_CAP capability; UINT32 property; UINT32 propertyCount; } GetCapability_In; #define RC_GetCapability_capability (TPM_RC_P + TPM_RC_1) #define RC_GetCapability_property (TPM_RC_P + TPM_RC_2) #define RC_GetCapability_propertyCount (TPM_RC_P + TPM_RC_3) typedef struct { TPMI_YES_NO moreData; TPMS_CAPABILITY_DATA capabilityData; } GetCapability_Out; TPM_RC TPM2_GetCapability( GetCapability_In *in, // IN: input parameter list GetCapability_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/GetCommandAuditDigest_fp.h000066400000000000000000000102141421143571500216520ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: GetCommandAuditDigest_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef GETCOMMANDAUDITDIGEST_FP_H #define GETCOMMANDAUDITDIGEST_FP_H typedef struct { TPMI_RH_ENDORSEMENT privacyHandle; TPMI_DH_OBJECT signHandle; TPM2B_DATA qualifyingData; TPMT_SIG_SCHEME inScheme; } GetCommandAuditDigest_In; #define RC_GetCommandAuditDigest_privacyHandle (TPM_RC_H + TPM_RC_1) #define RC_GetCommandAuditDigest_signHandle (TPM_RC_H + TPM_RC_2) #define RC_GetCommandAuditDigest_qualifyingData (TPM_RC_P + TPM_RC_1) #define RC_GetCommandAuditDigest_inScheme (TPM_RC_P + TPM_RC_2) typedef struct { TPM2B_ATTEST auditInfo; TPMT_SIGNATURE signature; } GetCommandAuditDigest_Out; TPM_RC TPM2_GetCommandAuditDigest( GetCommandAuditDigest_In *in, // IN: input parameter list GetCommandAuditDigest_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/GetRandom_fp.h000066400000000000000000000073441421143571500173770ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: GetRandom_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef GETRANDOM_FP_H #define GETRANDOM_FP_H typedef struct { UINT16 bytesRequested; } GetRandom_In; #define RC_GetRandom_bytesRequested (TPM_RC_P + TPM_RC_1) typedef struct { TPM2B_DIGEST randomBytes; } GetRandom_Out; TPM_RC TPM2_GetRandom( GetRandom_In *in, // IN: input parameter list GetRandom_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/GetSessionAuditDigest_fp.h000066400000000000000000000104021421143571500217160ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: GetSessionAuditDigest_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef GETSESSIONAUDITDIGEST_FP_H #define GETSESSIONAUDITDIGEST_FP_H typedef struct { TPMI_RH_ENDORSEMENT privacyAdminHandle; TPMI_DH_OBJECT signHandle; TPMI_SH_HMAC sessionHandle; TPM2B_DATA qualifyingData; TPMT_SIG_SCHEME inScheme; } GetSessionAuditDigest_In; #define RC_GetSessionAuditDigest_privacyAdminHandle (TPM_RC_H + TPM_RC_1) #define RC_GetSessionAuditDigest_signHandle (TPM_RC_H + TPM_RC_2) #define RC_GetSessionAuditDigest_sessionHandle (TPM_RC_H + TPM_RC_3) #define RC_GetSessionAuditDigest_qualifyingData (TPM_RC_P + TPM_RC_1) #define RC_GetSessionAuditDigest_inScheme (TPM_RC_P + TPM_RC_2) typedef struct { TPM2B_ATTEST auditInfo; TPMT_SIGNATURE signature; } GetSessionAuditDigest_Out; TPM_RC TPM2_GetSessionAuditDigest( GetSessionAuditDigest_In *in, // IN: input parameter list GetSessionAuditDigest_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/GetTestResult_fp.h000066400000000000000000000071261421143571500202730ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: GetTestResult_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2016 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef GETTESTRESULT_FP_H #define GETTESTRESULT_FP_H typedef struct{ TPM2B_MAX_BUFFER outData; TPM_RC testResult; } GetTestResult_Out; TPM_RC TPM2_GetTestResult( GetTestResult_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/GetTime_fp.h000066400000000000000000000077771421143571500170670ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: GetTime_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef GETTIME_FP_H #define GETTIME_FP_H typedef struct { TPMI_RH_ENDORSEMENT privacyAdminHandle; TPMI_DH_OBJECT signHandle; TPM2B_DATA qualifyingData; TPMT_SIG_SCHEME inScheme; } GetTime_In; #define RC_GetTime_privacyAdminHandle (TPM_RC_H + TPM_RC_1) #define RC_GetTime_signHandle (TPM_RC_H + TPM_RC_2) #define RC_GetTime_qualifyingData (TPM_RC_P + TPM_RC_1) #define RC_GetTime_inScheme (TPM_RC_P + TPM_RC_2) typedef struct { TPM2B_ATTEST timeInfo; TPMT_SIGNATURE signature; } GetTime_Out; TPM_RC TPM2_GetTime( GetTime_In *in, // IN: input parameter list GetTime_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/Global.c000066400000000000000000000110531421143571500162150ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM variables that are not stack allocated */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Global.c 1519 2019-11-15 20:43:51Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ /* 9.5 Global.c */ /* 9.5.1 Description */ /* This file will instance the TPM variables that are not stack allocated. Descriptions of global variables are in Global.h. There macro macro definitions that allows a variable to be instanced or simply defined as an external variable. When global.h is included from this .c file, GLOBAL_C is defined and values are instanced (and possibly initialized), but when global.h is included by any other file, they are simply defined as external values. DO NOT DEFINE GLOBAL_C IN ANY OTHER FILE. */ /* NOTE: This is a change from previous implementations where Global.h just contained the extern declaration and values were instanced in this file. This change keeps the definition and instance in one file making maintenance easier. The instanced data will still be in the global.obj file. */ /* The OIDs.h file works in a way that is similar to the Global.h with the definition of the values in OIDs.h such that they are instanced in global.obj. The macros that are defined in Global.h are used in OIDs.h in the same way as they are in Global.h. */ #define GLOBAL_C #include "Tpm.h" #include "OIDs.h" #if CC_CertifyX509 # include "X509.h" #endif // CC_CertifyX509 libtpms-0.9.3/src/tpm2/Global.h000066400000000000000000002015461421143571500162320ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Internal Global Type Definitions */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Global.h 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2021 */ /* */ /********************************************************************************/ /* 5.9 Global.h */ /* 5.9.2 Includes */ #if !defined _TPM_H_ #error "Should only be instanced in TPM.h" #endif #ifndef GLOBAL_H #define GLOBAL_H _REDUCE_WARNING_LEVEL_(2) #include #include _NORMAL_WARNING_LEVEL_ #include "BackwardsCompatibility.h" // libtpms added #include "Capabilities.h" #include "TpmTypes.h" #include "CommandAttributes.h" #include "CryptTest.h" #include "BnValues.h" #include "CryptHash.h" #include "CryptSym.h" #include "CryptRand.h" #include "CryptEcc.h" #include "CryptRsa.h" #include "CryptTest.h" #include "TpmError.h" #include "NV.h" #include "ACT.h" #include "Utils.h" // libtpms added //** Defines and Types //*** Size Types // These types are used to differentiate the two different size values used. // // NUMBYTES is used when a size is a number of bytes (usually a TPM2B) typedef UINT16 NUMBYTES; //*** Other Types // An AUTH_VALUE is a BYTE array containing a digest (TPMU_HA) typedef BYTE AUTH_VALUE[sizeof(TPMU_HA)]; /* A TIME_INFO is a BYTE array that can contain a TPMS_TIME_INFO */ typedef BYTE TIME_INFO[sizeof(TPMS_TIME_INFO)]; /* A NAME is a BYTE array that can contain a TPMU_NAME */ typedef BYTE NAME[sizeof(TPMU_NAME)]; /* Definition for a PROOF value */ TPM2B_TYPE(PROOF, PROOF_SIZE); /* Definition for a Primary Seed value */ TPM2B_TYPE(SEED, PRIMARY_SEED_SIZE); /* A CLOCK_NONCE is used to tag the time value in the authorization session and in the ticket computation so that the ticket expires when there is a time discontinuity. When the clock stops during normal operation, the nonce is 64-bit value kept in RAM but it is a 32-bit counter when the clock only stops during power events. */ #if CLOCK_STOPS typedef UINT64 CLOCK_NONCE; #else typedef UINT32 CLOCK_NONCE; #endif // 5.9.3 Loaded Object Structures // 5.9.3.1 Description // The structures in this section define the object layout as it exists in TPM memory. // Two types of objects are defined: an ordinary object such as a key, and a sequence object that // may be a hash, HMAC, or event. /* 5.9.3.2 OBJECT_ATTRIBUTES */ /* An OBJECT_ATTRIBUTES structure contains the variable attributes of an object. These properties are not part of the public properties but are used by the TPM in managing the object. An OBJECT_ATTRIBUTES is used in the definition of the OBJECT data type. */ typedef struct { #if LITTLE_ENDIAN_TPM == YES /* libtpms added */ unsigned publicOnly : 1; //0) SET if only the public portion of // an object is loaded unsigned epsHierarchy : 1; //1) SET if the object belongs to EPS // Hierarchy unsigned ppsHierarchy : 1; //2) SET if the object belongs to PPS // Hierarchy unsigned spsHierarchy : 1; //3) SET f the object belongs to SPS // Hierarchy unsigned evict : 1; //4) SET if the object is a platform or // owner evict object. Platform- // evict object belongs to PPS // hierarchy, owner-evict object // belongs to SPS or EPS hierarchy. // This bit is also used to mark a // completed sequence object so it // will be flush when the // SequenceComplete command succeeds. unsigned primary : 1; //5) SET for a primary object unsigned temporary : 1; //6) SET for a temporary object unsigned stClear : 1; //7) SET for an stClear object unsigned hmacSeq : 1; //8) SET for an HMAC or MAC sequence object unsigned hashSeq : 1; //9) SET for a hash sequence object unsigned eventSeq : 1; //10) SET for an event sequence object unsigned ticketSafe : 1; //11) SET if a ticket is safe to create // for hash sequence object unsigned firstBlock : 1; //12) SET if the first block of hash // data has been received. It // works with ticketSafe bit unsigned isParent : 1; //13) SET if the key has the proper // attributes to be a parent key unsigned privateExp : 1; //14) SET when the private exponent // of an RSA key has been validated. unsigned occupied : 1; //15) SET when the slot is occupied. unsigned derivation : 1; //16) SET when the key is a derivation // parent unsigned external : 1; //17) SET when the object is loaded with // TPM2_LoadExternal(); unsigned reserved : 14; //18-31) /* libtpms added */ #endif /* libtpms added */ #if BIG_ENDIAN_TPM == YES /* libtpms added begin */ unsigned reserved : 14; //18-31) unsigned external : 1; //17) SET when the object is loaded with unsigned derivation : 1; //16) SET when the key is a derivation unsigned occupied : 1; //15) SET when the slot is occupied. unsigned privateExp : 1; //14) SET when the private exponent unsigned isParent : 1; //13) SET if the key has the proper unsigned firstBlock : 1; //12) SET if the first block of hash unsigned ticketSafe : 1; //11) SET if a ticket is safe to create unsigned eventSeq : 1; //10) SET for an event sequence object unsigned hashSeq : 1; //9) SET for a hash sequence object unsigned hmacSeq : 1; //8) SET for an HMAC sequence object unsigned stClear : 1; //7) SET for an stClear object unsigned temporary : 1; //6) SET for a temporary object unsigned primary : 1; //5) SET for a primary object unsigned evict : 1; //4) SET if the object is a platform or unsigned spsHierarchy : 1; //3) SET f the object belongs to SPS unsigned ppsHierarchy : 1; //2) SET if the object belongs to PPS unsigned epsHierarchy : 1; //1) SET if the object belongs to EPS unsigned publicOnly : 1; //0) SET if only the public portion of #endif /* libtpms added end */ } OBJECT_ATTRIBUTES; #if ALG_RSA /* There is an overload of the sensitive.rsa.t.size field of a TPMT_SENSITIVE when an RSA key is loaded. When the sensitive->sensitive contains an RSA key with all of the CRT values, then the MSB of the size field will be set to indicate that the buffer contains all 5 of the CRT private key values. */ #define RSA_prime_flag 0x8000 #endif /* 5.9.3.3 OBJECT Structure */ /* An OBJECT structure holds the object public, sensitive, and meta-data associated. This structure is implementation dependent. For this implementation, the structure is not optimized for space but rather for clarity of the reference implementation. Other implementations may choose to overlap portions of the structure that are not used simultaneously. These changes would necessitate changes to the source code but those changes would be compatible with the reference implementation. */ typedef struct OBJECT { // The attributes field is required to be first followed by the publicArea. // This allows the overlay of the object structure and a sequence structure OBJECT_ATTRIBUTES attributes; // object attributes TPMT_PUBLIC publicArea; // public area of an object TPMT_SENSITIVE sensitive; // sensitive area of an object #if ALG_RSA privateExponent_t privateExponent; // Additional field for the private #endif TPM2B_NAME qualifiedName; // object qualified name TPMI_DH_OBJECT evictHandle; // if the object is an evict object, // the original handle is kept here. // The 'working' handle will be the // handle of an object slot. TPM2B_NAME name; // Name of the object name. Kept here // to avoid repeatedly computing it. // libtpms added: SEED_COMPAT_LEVEL to use for deriving child keys SEED_COMPAT_LEVEL seedCompatLevel; // libtpms added: OBJECT lies in NVRAM; to avoid that it needs different number // of bytes on 32 bit and 64 bit architectures, we need to make sure it's the // same size; simple padding at the end works here UINT8 _pad[3]; } OBJECT; /* 5.9.3.4 HASH_OBJECT Structure */ /* This structure holds a hash sequence object or an event sequence object. */ /* The first four components of this structure are manually set to be the same as the first four components of the object structure. This prevents the object from being inadvertently misused as sequence objects occupy the same memory as a regular object. A debug check is present to make sure that the offsets are what they are supposed to be. */ /* NOTE: In a future version, this will probably be renamed as SEQUENCE_OBJECT */ typedef struct HASH_OBJECT { OBJECT_ATTRIBUTES attributes; // The attributes of the HASH object TPMI_ALG_PUBLIC type; // algorithm TPMI_ALG_HASH nameAlg; // name algorithm TPMA_OBJECT objectAttributes; // object attributes // The data below is unique to a sequence object TPM2B_AUTH auth; // authorization for use of sequence union { HASH_STATE hashState[HASH_COUNT]; HMAC_STATE hmacState; } state; } HASH_OBJECT; typedef BYTE HASH_OBJECT_BUFFER[sizeof(HASH_OBJECT)]; /* 5.9.3.5 ANY_OBJECT */ /* This is the union for holding either a sequence object or a regular object. for ContextSave() and ContextLoad() */ typedef union ANY_OBJECT { OBJECT entity; HASH_OBJECT hash; } ANY_OBJECT; typedef BYTE ANY_OBJECT_BUFFER[sizeof(ANY_OBJECT)]; /* 5.9.4 AUTH_DUP Types */ /* These values are used in the authorization processing. */ typedef UINT32 AUTH_ROLE; #define AUTH_NONE ((AUTH_ROLE)(0)) #define AUTH_USER ((AUTH_ROLE)(1)) #define AUTH_ADMIN ((AUTH_ROLE)(2)) #define AUTH_DUP ((AUTH_ROLE)(3)) /* 5.9.5 Active Session Context */ /* 5.9.5.1 Description */ /* The structures in this section define the internal structure of a session context. */ /* 5.9.5.2 SESSION_ATTRIBUTES */ /* The attributes in the SESSION_ATTRIBUTES structure track the various properties of the session. It maintains most of the tracking state information for the policy session. It is used within the SESSION structure. */ typedef struct SESSION_ATTRIBUTES { #if LITTLE_ENDIAN_TPM == YES /* libtpms added */ unsigned isPolicy : 1; //1) SET if the session may only be used // for policy unsigned isAudit : 1; //2) SET if the session is used for audit unsigned isBound : 1; //3) SET if the session is bound to with an // entity. This attribute will be CLEAR // if either isPolicy or isAudit is SET. unsigned isCpHashDefined : 1; //4) SET if the cpHash has been defined // This attribute is not SET unless // 'isPolicy' is SET. unsigned isAuthValueNeeded : 1; //5) SET if the authValue is required for // computing the session HMAC. This // attribute is not SET unless 'isPolicy' // is SET. unsigned isPasswordNeeded : 1; //6) SET if a password authValue is required // for authorization This attribute is not // SET unless 'isPolicy' is SET. unsigned isPPRequired : 1; //7) SET if physical presence is required to // be asserted when the authorization is // checked. This attribute is not SET // unless 'isPolicy' is SET. unsigned isTrialPolicy : 1; //8) SET if the policy session is created // for trial of the policy's policyHash // generation. This attribute is not SET // unless 'isPolicy' is SET. unsigned isDaBound : 1; //9) SET if the bind entity had noDA CLEAR. // If this is SET, then an authorization // failure using this session will count // against lockout even if the object // being authorized is exempt from DA. unsigned isLockoutBound : 1; //10) SET if the session is bound to // lockoutAuth. unsigned includeAuth : 1; //11) This attribute is SET when the // authValue of an object is to be // included in the computation of the // HMAC key for the command and response // computations. (was 'requestWasBound') unsigned checkNvWritten : 1; //12) SET if the TPMA_NV_WRITTEN attribute // needs to be checked when the policy is // used for authorization for NV access. // If this is SET for any other type, the // policy will fail. unsigned nvWrittenState : 1; //13) SET if TPMA_NV_WRITTEN is required to // be SET. Used when 'checkNvWritten' is // SET unsigned isTemplateSet : 1; //14) SET if the templateHash needs to be // checked for Create, CreatePrimary, or // CreateLoaded. unsigned _reserved : 18; //15-32 /* libtpms added */ #endif /* libtpms added */ #if BIG_ENDIAN_TPM == YES /* libtpms added begin */ unsigned _reserved : 18; //15-32 unsigned isTemplateSet : 1; //14) SET if the templateHash needs to be unsigned nvWrittenState : 1; //13) SET if TPMA_NV_WRITTEN is required to unsigned checkNvWritten : 1; //12) SET if the TPMA_NV_WRITTEN attribute unsigned includeAuth : 1; //11) This attribute is SET when the unsigned isLockoutBound : 1; //10) SET if the session is bound to unsigned isDaBound : 1; //9) SET if the bind entity had noDA CLEAR. unsigned isTrialPolicy : 1; //8) SET if the policy session is created unsigned isPPRequired : 1; //7) SET if physical presence is required to unsigned isPasswordNeeded : 1; //6) SET if a password authValue is required unsigned isAuthValueNeeded : 1; //5) SET if the authValue is required for unsigned isCpHashDefined : 1; //4) SET if the cpHash has been defined unsigned isBound : 1; //3) SET if the session is bound to with an unsigned isAudit : 1; //2) SET if the session is used for audit unsigned isPolicy : 1; //1) SET if the session may only be used #endif /* libtpms added end */ } SESSION_ATTRIBUTES; /* 5.9.5.3 SESSION Structure */ /* The SESSION structure contains all the context of a session except for the associated contextID. */ /* NOTE: The contextID of a session is only relevant when the session context is stored off the TPM. */ typedef struct SESSION { SESSION_ATTRIBUTES attributes; // session attributes UINT32 pcrCounter; // PCR counter value when PCR is // included (policy session) // If no PCR is included, this // value is 0. UINT64 startTime; // The value in g_time // when the session was started (policy session) UINT64 timeout; // The timeout relative to g_time // There is no timeout if this value // is 0. CLOCK_NONCE epoch; // The g_clockEpoch value when the // session was started. If g_clockEpoch // does not match this value when the // timeout is used, then // then the command will fail. TPM_CC commandCode; // command code (policy session) TPM_ALG_ID authHashAlg; // session hash algorithm TPMA_LOCALITY commandLocality; // command locality (policy session) TPMT_SYM_DEF symmetric; // session symmetric algorithm (if any) TPM2B_AUTH sessionKey; // session secret value used for // this session TPM2B_NONCE nonceTPM; // last TPM-generated nonce for // generating HMAC and encryption keys union { TPM2B_NAME boundEntity; // value used to track the entity to // which the session is bound TPM2B_DIGEST cpHash; // the required cpHash value for the // command being authorized TPM2B_DIGEST nameHash; // the required nameHash TPM2B_DIGEST templateHash; // the required template for creation } u1; union { TPM2B_DIGEST auditDigest; // audit session digest TPM2B_DIGEST policyDigest; // policyHash } u2; // audit log and policyHash may // share space to save memory } SESSION; #define EXPIRES_ON_RESET INT32_MIN #define TIMEOUT_ON_RESET UINT64_MAX #define EXPIRES_ON_RESTART (INT32_MIN + 1) #define TIMEOUT_ON_RESTART (UINT64_MAX - 1) typedef BYTE SESSION_BUF[sizeof(SESSION)]; /* 5.9.7 PCR */ /* 5.9.7.1 PCR_SAVE Structure */ /* The PCR_SAVE structure type contains the PCR data that are saved across power cycles. Only the static PCR are required to be saved across power cycles. The DRTM and resettable PCR are not saved. The number of static and resettable PCR is determined by the platform-specific specification to which the TPM is built. */ #define PCR_SAVE_SPACE(HASH, Hash) BYTE Hash[NUM_STATIC_PCR][HASH##_DIGEST_SIZE]; typedef struct PCR_SAVE { FOR_EACH_HASH(PCR_SAVE_SPACE) // This counter increments whenever the PCR are updated. // NOTE: A platform-specific specification may designate // certain PCR changes as not causing this counter // to increment. UINT32 pcrCounter; } PCR_SAVE; /* 5.9.6.2 PCR_POLICY */ #if defined NUM_POLICY_PCR_GROUP && NUM_POLICY_PCR_GROUP > 0 /* This structure holds the PCR policies, one for each group of PCR controlled by policy. */ typedef struct PCR_POLICY { TPMI_ALG_HASH hashAlg[NUM_POLICY_PCR_GROUP]; TPM2B_DIGEST a_unused; /* libtpms: renamed field since not used and not initialized */ TPM2B_DIGEST policy[NUM_POLICY_PCR_GROUP]; } PCR_POLICY; #endif /* 5.9.6.3 PCR_AUTHVALUE */ /* This structure holds the PCR policies, one for each group of PCR controlled by policy. */ typedef struct PCR_AUTH_VALUE { TPM2B_DIGEST auth[NUM_AUTHVALUE_PCR_GROUP]; } PCR_AUTHVALUE; /* 5.9.7 STARTUP_TYPE */ /* This enumeration is the possible startup types. The type is determined by the combination of TPM2_ShutDown() and TPM2_Startup(). */ typedef enum { SU_RESET, SU_RESTART, SU_RESUME } STARTUP_TYPE; /* 5.9.8 NV */ /* 5.9.8.1 NV_INDEX */ /* The NV_INDEX structure defines the internal format for an NV index. The indexData size varies according to the type of the index. In this implementation, all of the index is manipulated as a unit. */ typedef struct NV_INDEX { TPMS_NV_PUBLIC publicArea; TPM2B_AUTH authValue; } NV_INDEX; /* 5.9.8.2 NV_REF */ /* An NV_REF is an opaque value returned by the NV subsystem. It is used to reference and NV Index in a relatively efficient way. Rather than having to continually search for an Index, its reference value may be used. In this implementation, an NV_REF is a byte pointer that points to the copy of the NV memory that is kept in RAM. */ typedef UINT32 NV_REF; typedef BYTE *NV_RAM_REF; /* 5.9.8.3 NV_PIN */ /* This structure deals with the possible endianness differences between the canonical form of the TPMS_NV_PIN_COUNTER_PARAMETERS structure and the internal value. The structures allow the data in a PIN index to be read as an 8-octet value using NvReadUINT64Data(). That function will byte swap all the values on a little endian system. This will put the bytes with the 4-octet values in the correct order but will swap the pinLimit and pinCount values. When written, the PIN index is simply handled as a normal index with the octets in canonical order. */ #if BIG_ENDIAN_TPM typedef struct { UINT32 pinCount; UINT32 pinLimit; } PIN_DATA; #else typedef struct { UINT32 pinLimit; UINT32 pinCount; } PIN_DATA; #endif typedef union { UINT64 intVal; PIN_DATA pin; } NV_PIN; /* 5.9.9 COMMIT_INDEX_MASK */ /* This is the define for the mask value that is used when manipulating the bits in the commit bit array. The commit counter is a 64-bit value and the low order bits are used to index the commitArray. This mask value is applied to the commit counter to extract the bit number in the array. */ #if ALG_ECC #define COMMIT_INDEX_MASK ((UINT16)((sizeof(gr.commitArray)*8)-1)) #endif /* 5.9.10 RAM Global Values */ /* 5.9.10.1 Description */ /* The values in this section are only extant in RAM or ROM as constant values. */ /* 5.9.10.2 Crypto Self-Test Values */ EXTERN ALGORITHM_VECTOR g_implementedAlgorithms; EXTERN ALGORITHM_VECTOR g_toTest; /* 5.9.10.3 g_rcIndex[] */ /* This array is used to contain the array of values that are added to a return code when it is a parameter-, handle-, or session-related error. This is an implementation choice and the same result can be achieved by using a macro. */ #define g_rcIndexInitializer { TPM_RC_1, TPM_RC_2, TPM_RC_3, TPM_RC_4, \ TPM_RC_5, TPM_RC_6, TPM_RC_7, TPM_RC_8, \ TPM_RC_9, TPM_RC_A, TPM_RC_B, TPM_RC_C, \ TPM_RC_D, TPM_RC_E, TPM_RC_F } EXTERN const UINT16 g_rcIndex[15] INITIALIZER(g_rcIndexInitializer); /* 5.9.10.4 g_exclusiveAuditSession */ /* This location holds the session handle for the current exclusive audit session. If there is no exclusive audit session, the location is set to TPM_RH_UNASSIGNED. */ EXTERN TPM_HANDLE g_exclusiveAuditSession; /* 5.9.10.5 g_time */ /* This is the value in which we keep the current command time. This is initialized at the start of each command. The time is the accumulated time since the last time that the TPM's timer was last powered up. Clock is the accumulated time since the last time that the TPM was cleared. g_time is in mS. */ EXTERN UINT64 g_time; /* 5.9.10.6 g_timeEpoch */ /* This value contains the current clock Epoch. It changes when there is a clock discontinuity. It may be necessary to place this in NV should the timer be able to run across a power down of the TPM but not in all cases (e.g. dead battery). If the nonce is placed in NV, it should go in gp because it should be changing slowly. */ #if CLOCK_STOPS EXTERN CLOCK_NONCE g_timeEpoch; #else #define g_timeEpoch gp.timeEpoch #endif /* 5.9.10.7 g_phEnable */ /* This is the platform hierarchy control and determines if the platform hierarchy is available. This value is SET on each TPM2_Startup(). The default value is SET. */ EXTERN BOOL g_phEnable; /* 5.9.10.8 g_pcrReConfig */ /* This value is SET if a TPM2_PCR_Allocate() command successfully executed since the last TPM2_Startup(). If so, then the next shutdown is required to be Shutdown(CLEAR). */ EXTERN BOOL g_pcrReConfig; /* 5.9.10.9 g_DRTMHandle */ /* This location indicates the sequence object handle that holds the DRTM sequence data. When not used, it is set to TPM_RH_UNASSIGNED. A sequence DRTM sequence is started on either _TPM_Init() or _TPM_Hash_Start(). */ EXTERN TPMI_DH_OBJECT g_DRTMHandle; /* 5.9.10.10 g_DrtmPreStartup */ /* This value indicates that an H-CRTM occurred after _TPM_Init() but before TPM2_Startup(). The define for PRE_STARTUP_FLAG is used to add the g_DrtmPreStartup value to gp_orderlyState at shutdown. This hack is to avoid adding another NV variable. */ EXTERN BOOL g_DrtmPreStartup; /* 5.9.10.11 g_StartupLocality3 */ /* This value indicates that a TPM2_Startup() occurred at locality 3. Otherwise, it at locality 0. The define for STARTUP_LOCALITY_3 is to indicate that the startup was not at locality 0. This hack is to avoid adding another NV variable. */ EXTERN BOOL g_StartupLocality3; /* 5.9.10.12 TPM_SU_NONE */ /* Part 2 defines the two shutdown/startup types that may be used in TPM2_Shutdown() and TPM2_Starup(). This additional define is used by the TPM to indicate that no shutdown was received. */ /* NOTE: This is a reserved value. */ #define SU_NONE_VALUE (0xFFFF) #define TPM_SU_NONE (TPM_SU)(SU_NONE_VALUE) /* 5.9.10.13 TPM_SU_DA_USED */ /* As with TPM_SU_NONE, this value is added to allow indication that the shutdown was not orderly and that a DA=protected object was reference during the previous cycle. */ #define SU_DA_USED_VALUE (SU_NONE_VALUE - 1) #define TPM_SU_DA_USED (TPM_SU)(SU_DA_USED_VALUE) /* 5.9.10.14 Startup Flags */ /* These flags are included in gp.orderlyState. These are hacks and are being used to avoid having to change the layout of gp. The PRE_STARTUP_FLAG indicates that a _TPM_Hash_Start()/_Data()/_End() sequence was received after _TPM_Init() but before TPM2_StartUp(). STARTUP_LOCALITY_3 indicates that the last TPM2_Startup() was received at locality 3. These flags are only relevant if after a TPM2_Shutdown(STATE). */ #define PRE_STARTUP_FLAG 0x8000 #define STARTUP_LOCALITY_3 0x4000 #define TPM_SU_STATE_MASK ~(PRE_STARTUP_FLAG | STARTUP_LOCALITY_3) // libtpms added #if USE_DA_USED /* 5.9.10.15 g_daUsed */ /* This location indicates if a DA-protected value is accessed during a boot cycle. If none has, then there is no need to increment failedTries on the next non-orderly startup. This bit is merged with gp.orderlyState when gp.orderly is set to SU_NONE_VALUE */ /* This global is set to FALSE on startup (after a decision has been made on whether to increment the failedTries or not). On a first attempt to access a DA protected object: this global is set to 1, the orderlyState is set to SU_DA_USED, committed to NV and the command execution returns with RC_RETRY (without exposing any information on the DA attempt). */ EXTERN BOOL g_daUsed; #endif /* 5.9.10.16 g_updateNV */ /* This flag indicates if NV should be updated at the end of a command. This flag is set to UT_NONE at the beginning of each command in ExecuteCommand(). This flag is checked in ExecuteCommand() after the detailed actions of a command complete. If the command execution was successful and this flag is not UT_NONE, any pending NV writes will be committed to NV. UT_ORDERLY causes any RAM data to be written to the orderly space for staging the write to NV. */ typedef BYTE UPDATE_TYPE; #define UT_NONE (UPDATE_TYPE)0 #define UT_NV (UPDATE_TYPE)1 #define UT_ORDERLY (UPDATE_TYPE)(UT_NV + 2) EXTERN UPDATE_TYPE g_updateNV; /* 5.9.10.17 g_powerWasLost */ /* This flag is used to indicate if the power was lost. It is SET in _TPM__Init(). This flag is cleared by TPM2_Startup() after all power-lost activities are completed. */ /* NOTE: When power is applied, this value can come up as anything. However, _plat__WasPowerLost() will provide the proper indication in that case. So, when power is actually lost, we get the correct answer. When power was not lost, but the power-lost processing has not been completed before the next _TPM_Init(), then the TPM still does the correct thing. */ EXTERN BOOL g_powerWasLost; /* 5.9.10.18 g_clearOrderly */ /* This flag indicates if the execution of a command should cause the orderly state to be cleared. This flag is set to FALSE at the beginning of each command in ExecuteCommand() and is checked in ExecuteCommand() after the detailed actions of a command complete but before the check of g_updateNV. If this flag is TRUE, and the orderly state is not SU_NONE_VALUE, then the orderly state in NV memory will be changed to SU_NONE_VALUE or SU_DA_USED_VALUE. */ EXTERN BOOL g_clearOrderly; /* 5.9.10.19 g_prevOrderlyState */ /* This location indicates how the TPM was shut down before the most recent TPM2_Startup(). This value, along with the startup type, determines if the TPM should do a TPM Reset, TPM Restart, or TPM Resume. */ EXTERN TPM_SU g_prevOrderlyState; /* 5.9.10.20 g_nvOk */ /* This value indicates if the NV integrity check was successful or not. If not and the failure was severe, then the TPM would have been put into failure mode after it had been re-manufactured. If the NV failure was in the area where the state-save data is kept, then this variable will have a value of FALSE indicating that a TPM2_Startup(CLEAR) is required. */ EXTERN BOOL g_nvOk; /* NV availability is sampled as the start of each command and stored here so that its value remains consistent during the command execution */ EXTERN TPM_RC g_NvStatus; /* 5.9.10.21 g_platformUnique */ /* This location contains the unique value(s) used to identify the TPM. It is loaded on every _TPM2_Startup() The first value is used to seed the RNG. The second value is used as a vendor authValue. The value used by the RNG would be the value derived from the chip unique value (such as fused) with a dependency on the authorities of the code in the TPM boot path. The second would be derived from the chip unique value with a dependency on the details of the code in the boot path. That is, the first value depends on the various signers of the code and the second depends on what was signed. The TPM vendor should not be able to know the first value but they are expected to know the second. */ EXTERN TPM2B_AUTH g_platformUniqueAuthorities; // Reserved for RNG EXTERN TPM2B_AUTH g_platformUniqueDetails; // referenced by VENDOR_PERMANENT //********************************************************************************* //********************************************************************************* //** Persistent Global Values //********************************************************************************* //********************************************************************************* //*** Description // The values in this section are global values that are persistent across power // events. The lifetime of the values determines the structure in which the value // is placed. /* 5.9.11.2 PERSISTENT_DATA */ /* This structure holds the persistent values that only change as a consequence of a specific Protected Capability and are not affected by TPM power events (TPM2_Startup() or TPM2_Shutdown(). */ typedef struct { //********************************************************************************* // Hierarchy //********************************************************************************* // The values in this section are related to the hierarchies. BOOL disableClear; // TRUE if TPM2_Clear() using // lockoutAuth is disabled // Hierarchy authPolicies TPMI_ALG_HASH ownerAlg; TPMI_ALG_HASH endorsementAlg; TPMI_ALG_HASH lockoutAlg; TPM2B_DIGEST ownerPolicy; TPM2B_DIGEST endorsementPolicy; TPM2B_DIGEST lockoutPolicy; // Hierarchy authValues TPM2B_AUTH ownerAuth; TPM2B_AUTH endorsementAuth; TPM2B_AUTH lockoutAuth; // Primary Seeds TPM2B_SEED EPSeed; TPM2B_SEED SPSeed; TPM2B_SEED PPSeed; // SEED_COMPAT_LEVELs related to creation time of seeds SEED_COMPAT_LEVEL EPSeedCompatLevel; // libtpms added begin SEED_COMPAT_LEVEL SPSeedCompatLevel; SEED_COMPAT_LEVEL PPSeedCompatLevel; // libtpms added end // Note there is a nullSeed in the state_reset memory. // Hierarchy proofs TPM2B_PROOF phProof; TPM2B_PROOF shProof; TPM2B_PROOF ehProof; // Note there is a nullProof in the state_reset memory. //********************************************************************************* // Reset Events //********************************************************************************* // A count that increments at each TPM reset and never get reset during the life // time of TPM. The value of this counter is initialized to 1 during TPM // manufacture process. It is used to invalidate all saved contexts after a TPM // Reset. UINT64 totalResetCount; // This counter increments on each TPM Reset. The counter is reset by // TPM2_Clear(). UINT32 resetCount; //********************************************************************************* // PCR //********************************************************************************* // This structure hold the policies for those PCR that have an update policy. // This implementation only supports a single group of PCR controlled by // policy. If more are required, then this structure would be changed to // an array. #if defined NUM_POLICY_PCR_GROUP && NUM_POLICY_PCR_GROUP > 0 PCR_POLICY pcrPolicies; #endif // This structure indicates the allocation of PCR. The structure contains a // list of PCR allocations for each implemented algorithm. If no PCR are // allocated for an algorithm, a list entry still exists but the bit map // will contain no SET bits. TPML_PCR_SELECTION pcrAllocated; //********************************************************************************* // Physical Presence //********************************************************************************* // The PP_LIST type contains a bit map of the commands that require physical // to be asserted when the authorization is evaluated. Physical presence will be // checked if the corresponding bit in the array is SET and if the authorization // handle is TPM_RH_PLATFORM. // // These bits may be changed with TPM2_PP_Commands(). BYTE ppList[(COMMAND_COUNT + 7) / 8]; //********************************************************************************* // Dictionary attack values //********************************************************************************* // These values are used for dictionary attack tracking and control. UINT32 failedTries; // the current count of unexpired // authorization failures UINT32 maxTries; // number of unexpired authorization // failures before the TPM is in // lockout UINT32 recoveryTime; // time between authorization failures // before failedTries is decremented UINT32 lockoutRecovery; // time that must expire between // authorization failures associated // with lockoutAuth BOOL lockOutAuthEnabled; // TRUE if use of lockoutAuth is // allowed //***************************************************************************** // Orderly State //***************************************************************************** // The orderly state for current cycle TPM_SU orderlyState; //***************************************************************************** // Command audit values. //***************************************************************************** BYTE auditCommands[((COMMAND_COUNT + 1) + 7) / 8]; TPMI_ALG_HASH auditHashAlg; UINT64 auditCounter; //***************************************************************************** // Algorithm selection //***************************************************************************** // // The 'algorithmSet' value indicates the collection of algorithms that are // currently in used on the TPM. The interpretation of value is vendor dependent. UINT32 algorithmSet; //***************************************************************************** // Firmware version //***************************************************************************** // The firmwareV1 and firmwareV2 values are instanced in TimeStamp.c. This is // a scheme used in development to allow determination of the linker build time // of the TPM. An actual implementation would implement these values in a way that // is consistent with vendor needs. The values are maintained in RAM for simplified // access with a master version in NV. These values are modified in a // vendor-specific way. // g_firmwareV1 contains the more significant 32-bits of the vendor version number. // In the reference implementation, if this value is printed as a hex // value, it will have the format of YYYYMMDD UINT32 firmwareV1; // g_firmwareV1 contains the less significant 32-bits of the vendor version number. // In the reference implementation, if this value is printed as a hex // value, it will have the format of 00 HH MM SS UINT32 firmwareV2; //***************************************************************************** // Timer Epoch //***************************************************************************** // timeEpoch contains a nonce that has a vendor=specific size (should not be // less than 8 bytes. This nonce changes when the clock epoch changes. The clock // epoch changes when there is a discontinuity in the timing of the TPM. #if !CLOCK_STOPS CLOCK_NONCE timeEpoch; #endif } PERSISTENT_DATA; EXTERN PERSISTENT_DATA gp; /* 5.9.11.3 ORDERLY_DATA */ /* The data in this structure is saved to NV on each TPM2_Shutdown(). */ typedef struct orderly_data { //***************************************************************************** // TIME //***************************************************************************** // Clock has two parts. One is the state save part and one is the NV part. The // state save version is updated on each command. When the clock rolls over, the // NV version is updated. When the TPM starts up, if the TPM was shutdown in and // orderly way, then the sClock value is used to initialize the clock. If the // TPM shutdown was not orderly, then the persistent value is used and the safe // attribute is clear. UINT64 clock; // The orderly version of clock TPMI_YES_NO clockSafe; // Indicates if the clock value is // safe. // In many implementations, the quality of the entropy available is not that // high. To compensate, the current value of the drbgState can be saved and // restored on each power cycle. This prevents the internal state from reverting // to the initial state on each power cycle and starting with a limited amount // of entropy. By keeping the old state and adding entropy, the entropy will // accumulate. DRBG_STATE drbgState; // These values allow the accumulation of self-healing time across orderly shutdown // of the TPM. #if ACCUMULATE_SELF_HEAL_TIMER UINT64 selfHealTimer; // current value of s_selfHealTimer UINT64 lockoutTimer; // current value of s_lockoutTimer UINT64 time; // current value of g_time at shutdown #endif // ACCUMULATE_SELF_HEAL_TIMER #ifndef __ACT_DISABLED // libtpms added #error ACT not supported in ORDERLY_DATA! // These are the ACT Timeout values. They are saved with the other timers #define DefineActData(N) ACT_STATE ACT_##N; FOR_EACH_ACT(DefineActData) // this is the 'signaled' attribute data for all the ACT. It is done this way so // that they can be manipulated by ACT number rather than having to access a // structure. UINT16 signaledACT; UINT16 preservedSignaled; #endif // libtpms added } ORDERLY_DATA; #if ACCUMULATE_SELF_HEAL_TIMER #define s_selfHealTimer go.selfHealTimer #define s_lockoutTimer go.lockoutTimer #endif // ACCUMULATE_SELF_HEAL_TIMER # define drbgDefault go.drbgState EXTERN ORDERLY_DATA go; /* 5.9.11.4 STATE_CLEAR_DATA */ /* This structure contains the data that is saved on Shutdown(STATE). and restored on Startup(STATE). The values are set to their default settings on any Startup(Clear). In other words the data is only persistent across TPM Resume. */ /* If the comments associated with a parameter indicate a default reset value, the value is applied on each Startup(CLEAR). */ typedef struct state_clear_data { //***************************************************************************** // Hierarchy Control //***************************************************************************** BOOL shEnable; // default reset is SET BOOL ehEnable; // default reset is SET BOOL phEnableNV; // default reset is SET TPMI_ALG_HASH platformAlg; // default reset is TPM_ALG_NULL TPM2B_DIGEST platformPolicy; // default reset is an Empty Buffer TPM2B_AUTH platformAuth; // default reset is an Empty Buffer //***************************************************************************** // PCR //***************************************************************************** // The set of PCR to be saved on Shutdown(STATE) PCR_SAVE pcrSave; // default reset is 0...0 // This structure hold the authorization values for those PCR that have an // update authorization. // This implementation only supports a single group of PCR controlled by // authorization. If more are required, then this structure would be changed to // an array. PCR_AUTHVALUE pcrAuthValues; #ifndef __ACT_DISABLED // libtpms added //***************************************************************************** // ACT //***************************************************************************** #define DefineActPolicySpace(N) TPMT_HA act_##N; FOR_EACH_ACT(DefineActPolicySpace) #endif // libtpms added } STATE_CLEAR_DATA; EXTERN STATE_CLEAR_DATA gc; /* 5.9.11.5 State Reset Data */ /* This structure contains data is that is saved on Shutdown(STATE) and restored on the subsequent Startup(ANY). That is, the data is preserved across TPM Resume and TPM Restart. */ /* If a default value is specified in the comments this value is applied on TPM Reset. */ typedef struct state_reset_data { //***************************************************************************** // Hierarchy Control //***************************************************************************** TPM2B_PROOF nullProof; // The proof value associated with // the TPM_RH_NULL hierarchy. The // default reset value is from the RNG. TPM2B_SEED nullSeed; // The seed value for the TPM_RN_NULL SEED_COMPAT_LEVEL nullSeedCompatLevel; // libtpms added // hierarchy. The default reset value // is from the RNG. //***************************************************************************** // Context //***************************************************************************** // The 'clearCount' counter is incremented each time the TPM successfully executes // a TPM Resume. The counter is included in each saved context that has 'stClear' // SET (including descendants of keys that have 'stClear' SET). This prevents these // objects from being loaded after a TPM Resume. // If 'clearCount' is at its maximum value when the TPM receives a Shutdown(STATE), // the TPM will return TPM_RC_RANGE and the TPM will only accept Shutdown(CLEAR). UINT32 clearCount; // The default reset value is 0. UINT64 objectContextID; // This is the context ID for a saved // object context. The default reset // value is 0. CONTEXT_SLOT contextArray[MAX_ACTIVE_SESSIONS]; // This array contains // contains the values used to track // the version numbers of saved // contexts (see // Session.c in for details). The // default reset value is {0}. CONTEXT_COUNTER contextCounter; // This is the value from which the // 'contextID' is derived. The // default reset value is {0}. //***************************************************************************** // Command Audit //***************************************************************************** // When an audited command completes, ExecuteCommand() checks the return // value. If it is TPM_RC_SUCCESS, and the command is an audited command, the // TPM will extend the cpHash and rpHash for the command to this value. If this // digest was the Zero Digest before the cpHash was extended, the audit counter // is incremented. TPM2B_DIGEST commandAuditDigest; // This value is set to an Empty Digest // by TPM2_GetCommandAuditDigest() or a // TPM Reset. //***************************************************************************** // Boot counter //***************************************************************************** UINT32 restartCount; // This counter counts TPM Restarts. // The default reset value is 0. //********************************************************************************* // PCR //********************************************************************************* // This counter increments whenever the PCR are updated. This counter is preserved // across TPM Resume even though the PCR are not preserved. This is because // sessions remain active across TPM Restart and the count value in the session // is compared to this counter so this counter must have values that are unique // as long as the sessions are active. // NOTE: A platform-specific specification may designate that certain PCR changes // do not increment this counter to increment. UINT32 pcrCounter; // The default reset value is 0. #if ALG_ECC //***************************************************************************** // ECDAA //***************************************************************************** UINT64 commitCounter; // This counter increments each time // TPM2_Commit() returns // TPM_RC_SUCCESS. The default reset // value is 0. TPM2B_NONCE commitNonce; // This random value is used to compute // the commit values. The default reset // value is from the RNG. // This implementation relies on the number of bits in g_commitArray being a // power of 2 (8, 16, 32, 64, etc.) and no greater than 64K. BYTE commitArray[16]; // The default reset value is {0}. #endif // ALG_ECC } STATE_RESET_DATA; EXTERN STATE_RESET_DATA gr; // libtpms added begin /* The s_ContextSlotMask masks CONTEXT_SLOT values; this variable can have * only two valid values, 0xff or 0xffff. The former is used to simulate * a CONTEXT_SLOT defined as UINT8, the latter is used for the CONTEXT_SLOT * when it is a UINT16. The original TPM 2 code uses a cast to CONTEXT_SLOT * to truncate larger values and has been modified to use CONTEXT_SLOT_MASKED * to achieve the same effect with the above two values. * * Using CONTEXT_SLOT_MASKED we make sure that when we write values into * gr.contextArray that these values are properly masked/truncated so that * when we read values from gr.contextArray that we don't have to mask * them again. * * s_ContextSlotMask may only be initialized to 0xff when resuming an older * state from the time when CONTEXT_SLOT was UINT8, otherwise it must be set * to 0xffff. We set it to 0xffff in SessionStartup(SU_CLEAR) and to be * able to save the TPM state really early (and restore it) also in * TPM_Manufacture(). */ EXTERN CONTEXT_SLOT s_ContextSlotMask; #define CONTEXT_SLOT_MASKED(val) ((CONTEXT_SLOT)(val) & s_ContextSlotMask) // libtpms added end /* 5.9.12 NV Layout */ /* The NV data organization is */ /* a) a PERSISTENT_DATA structure */ /* b) a STATE_RESET_DATA structure */ /* c) a STATE_CLEAR_DATA structure */ /* d) an ORDERLY_DATA structure */ /* e) the user defined NV index space */ /* libtpms added: to put certain data structure at fixed offsets * to give the ones below some room to expand */ #define NV_PERSISTENT_DATA (0) #define NV_STATE_RESET_DATA (NV_PERSISTENT_DATA + sizeof(PERSISTENT_DATA)) #define NV_STATE_CLEAR_DATA (NV_STATE_RESET_DATA + sizeof(STATE_RESET_DATA)) #define NV_ORDERLY_DATA (NV_STATE_CLEAR_DATA + sizeof(STATE_CLEAR_DATA)) #define NV_INDEX_RAM_DATA TPM2_ROUNDUP(NV_ORDERLY_DATA + sizeof(ORDERLY_DATA),\ 1024) /* libtpms added */ #define NV_USER_DYNAMIC (NV_INDEX_RAM_DATA + sizeof(s_indexOrderlyRam)) #define NV_USER_DYNAMIC_END NV_MEMORY_SIZE /* 5.9.13 Global Macro Definitions */ /* The NV_READ_PERSISTENT and NV_WRITE_PERSISTENT macros are used to access members of the PERSISTENT_DATA structure in NV. */ #define NV_READ_PERSISTENT(to, from) \ NvRead(&to, offsetof(PERSISTENT_DATA, from), sizeof(to)) #define NV_WRITE_PERSISTENT(to, from) \ NvWrite(offsetof(PERSISTENT_DATA, to), sizeof(gp.to), &from) #define CLEAR_PERSISTENT(item) \ NvClearPersistent(offsetof(PERSISTENT_DATA, item), sizeof(gp.item)) #define NV_SYNC_PERSISTENT(item) NV_WRITE_PERSISTENT(item, gp.item) /* At the start of command processing, the index of the command is determined. This index value is used to access the various data tables that contain per-command information. There are multiple options for how the per-command tables can be implemented. This is resolved in GetClosestCommandIndex(). */ typedef UINT16 COMMAND_INDEX; #define UNIMPLEMENTED_COMMAND_INDEX ((COMMAND_INDEX)(~0)) #if 0 /* libtpms added */ typedef struct _COMMAND_FLAGS_ { #if LITTLE_ENDIAN_TPM == YES /* libtpms added */ unsigned trialPolicy : 1; //1) If SET, one of the handles references a // trial policy and authorization may be // skipped. This is only allowed for a policy // command. unsigned reserved : 31; //2-31) /* libtpms added begin */ #endif #if BIG_ENDIAN_TPM == YES unsigned reserved : 31; //2-31) unsigned trialPolicy : 1; //1) If SET, one of the handles references a #endif /* libtpms added end */ } COMMAND_FLAGS; #endif /* libtpms added */ /* This structure is used to avoid having to manage a large number of parameters being passed through various levels of the command input processing. The following macros are used to define the space for the CP and RP hashes. Space is provided for each implemented hash algorithm because it is not known what the caller may use. */ #define CP_HASH(HASH, Hash) TPM2B_##HASH##_DIGEST Hash##CpHash; #define RP_HASH(HASH, Hash) TPM2B_##HASH##_DIGEST Hash##RpHash; typedef struct _COMMAND_ { TPM_ST tag; // the parsed command tag TPM_CC code; // the parsed command code COMMAND_INDEX index; // the computed command index UINT32 handleNum; // the number of entity handles in the // handle area of the command TPM_HANDLE handles[MAX_HANDLE_NUM]; // the parsed handle values UINT32 sessionNum; // the number of sessions found INT32 parameterSize; // starts out with the parsed command size // and is reduced and values are unmarshaled. Just before calling the command actions, this // should be zero. After the command actions, this number should grow as values are marshaled // in to the response buffer. INT32 authSize; // this is initialized with the parsed size // of authorizationSize field and should be zero when the authorizations are parsed. BYTE *parameterBuffer; // input to ExecuteCommand BYTE *responseBuffer; // input to ExecuteCommand FOR_EACH_HASH(CP_HASH) // space for the CP hashes FOR_EACH_HASH(RP_HASH) // space for the RP hashes } COMMAND; // Global string constants for consistency in KDF function calls. These string constants are shared // across functions to make sure that they are all using consistent string values. #define STRING_INITIALIZER(value) {{sizeof(value), {value}}} #define TPM2B_STRING(name, value) \ typedef union name##_ { \ struct { \ UINT16 size; \ BYTE buffer[sizeof(value)]; \ } t; \ TPM2B b; \ } TPM2B_##name##_; \ EXTERN const TPM2B_##name##_ name##_ INITIALIZER(STRING_INITIALIZER(value)); \ EXTERN const TPM2B *name INITIALIZER(&name##_.b) TPM2B_STRING(PRIMARY_OBJECT_CREATION, "Primary Object Creation"); TPM2B_STRING(CFB_KEY, "CFB"); TPM2B_STRING(CONTEXT_KEY, "CONTEXT"); TPM2B_STRING(INTEGRITY_KEY, "INTEGRITY"); TPM2B_STRING(SECRET_KEY, "SECRET"); TPM2B_STRING(SESSION_KEY, "ATH"); TPM2B_STRING(STORAGE_KEY, "STORAGE"); TPM2B_STRING(XOR_KEY, "XOR"); TPM2B_STRING(COMMIT_STRING, "ECDAA Commit"); TPM2B_STRING(DUPLICATE_STRING, "DUPLICATE"); TPM2B_STRING(IDENTITY_STRING, "IDENTITY"); TPM2B_STRING(OBFUSCATE_STRING, "OBFUSCATE"); #if SELF_TEST TPM2B_STRING(OAEP_TEST_STRING, "OAEP Test Value"); #endif // SELF_TEST // 5.9.14 From CryptTest.c // This structure contains the self-test state values for the cryptographic modules. EXTERN CRYPTO_SELF_TEST_STATE g_cryptoSelfTestState; /* 5.9.15 From Manufacture.c */ EXTERN BOOL g_manufactured; /* This value indicates if a TPM2_Startup() commands has been receive since the power on event. This flag is maintained in power simulation module because this is the only place that may reliably set this flag to FALSE. */ EXTERN BOOL g_initialized; /* 5.9.16 Private data */ #if defined SESSION_PROCESS_C || defined GLOBAL_C || defined MANUFACTURE_C /* From SessionProcess.c */ /* The following arrays are used to save command sessions information so that the command handle/session buffer does not have to be preserved for the duration of the command. These arrays are indexed by the session index in accordance with the order of sessions in the session area of the command. */ /* Array of the authorization session handles */ EXTERN TPM_HANDLE s_sessionHandles[MAX_SESSION_NUM]; /* Array of authorization session attributes */ EXTERN TPMA_SESSION s_attributes[MAX_SESSION_NUM]; /* Array of handles authorized by the corresponding authorization sessions; and if none, then TPM_RH_UNASSIGNED value is used */ EXTERN TPM_HANDLE s_associatedHandles[MAX_SESSION_NUM]; /* Array of nonces provided by the caller for the corresponding sessions */ EXTERN TPM2B_NONCE s_nonceCaller[MAX_SESSION_NUM]; /* Array of authorization values (HMAC's or passwords) for the corresponding sessions */ EXTERN TPM2B_AUTH s_inputAuthValues[MAX_SESSION_NUM]; /* Array of pointers to the SESSION structures for the sessions in a command */ EXTERN SESSION *s_usedSessions[MAX_SESSION_NUM]; /* Special value to indicate an undefined session index */ #define UNDEFINED_INDEX (0xFFFF) /* Index of the session used for encryption of a response parameter */ EXTERN UINT32 s_encryptSessionIndex; /* Index of the session used for decryption of a command parameter */ EXTERN UINT32 s_decryptSessionIndex; /* Index of a session used for audit */ EXTERN UINT32 s_auditSessionIndex; /* The cpHash for command audit */ #if CC_GetCommandAuditDigest EXTERN TPM2B_DIGEST s_cpHashForCommandAudit; #endif /* Flag indicating if NV update is pending for the lockOutAuthEnabled or failedTries DA parameter */ EXTERN BOOL s_DAPendingOnNV; #endif // SESSION_PROCESS_C /* 5.9.16.2 From DA.c */ #if defined DA_C || defined GLOBAL_C || defined MANUFACTURE_C /* From DA.c */ /* This variable holds the accumulated time since the last time that failedTries was decremented. This value is in millisecond. */ #if !ACCUMULATE_SELF_HEAL_TIMER EXTERN UINT64 s_selfHealTimer; /* This variable holds the accumulated time that the lockoutAuth has been blocked. */ EXTERN UINT64 s_lockoutTimer; #endif // ACCUMULATE_SELF_HEAL_TIMER #endif // DA_C /* 5.9.16.3 From NV.c */ #if defined NV_C || defined GLOBAL_C /* From NV.c */ /* This marks the end of the NV area. This is a run-time variable as it might not be compile-time constant. */ EXTERN NV_REF s_evictNvEnd; /* This space is used to hold the index data for an orderly Index. It also contains the attributes for the index. */ EXTERN BYTE s_indexOrderlyRam[RAM_INDEX_SPACE]; // The orderly NV Index data /* This value contains the current max counter value. It is written to the end of allocatable NV space each time an index is deleted or added. This value is initialized on Startup. The indices are searched and the maximum of all the current counter indices and this value is the initial value for this. */ EXTERN UINT64 s_maxCounter; /* This is space used for the NV Index cache. As with a persistent object, the contents of a referenced index are copied into the cache so that the NV Index memory scanning and data copying can be reduced. Only code that operates on NV Index data should use this cache directly. When that action code runs, s_lastNvIndex will contain the index header information. It will have been loaded when the handles were verified. */ /* NOTE: An NV index handle can appear in many commands that do not operate on the NV data (e.g. TPM2_StartAuthSession()). However, only one NV Index at a time is ever directly referenced by any command. If that changes, then the NV Index caching needs to be changed to accommodate that. Currently, the code will verify that only one NV Index is referenced by the handles of the command. */ EXTERN NV_INDEX s_cachedNvIndex; EXTERN NV_REF s_cachedNvRef; EXTERN BYTE *s_cachedNvRamRef; /* Initial NV Index/evict object iterator value */ #define NV_REF_INIT (NV_REF)0xFFFFFFFF #endif /* 5.9.16.4 From Object.c */ #if defined OBJECT_C || defined GLOBAL_C /* This type is the container for an object. */ EXTERN OBJECT s_objects[MAX_LOADED_OBJECTS]; #endif // OBJECT_C /* 5.9.17.5 From PCR.c */ #if defined PCR_C || defined GLOBAL_C /* The following macro is used to define the per-implemented-hash space. This implementation reserves space for all implemented hashes. */ #define PCR_ALL_HASH(HASH, Hash) BYTE Hash##Pcr[HASH##_DIGEST_SIZE]; typedef struct { FOR_EACH_HASH(PCR_ALL_HASH) } PCR; typedef struct { unsigned int stateSave : 1; // if the PCR value should be // saved in state save unsigned int resetLocality : 5; // The locality that the PCR // can be reset unsigned int extendLocality : 5; // The locality that the PCR // can be extend } PCR_Attributes; EXTERN PCR s_pcrs[IMPLEMENTATION_PCR]; #endif // PCR_C /* 5.9.16.6 From Session.c */ #if defined SESSION_C || defined GLOBAL_C /* Container for HMAC or policy session tracking information */ typedef struct { BOOL occupied; SESSION session; // session structure } SESSION_SLOT; EXTERN SESSION_SLOT s_sessions[MAX_LOADED_SESSIONS]; /* The index in contextArray that has the value of the oldest saved session context. When no context is saved, this will have a value that is greater than or equal to MAX_ACTIVE_SESSIONS. */ EXTERN UINT32 s_oldestSavedSession; /* The number of available session slot openings. When this is 1, a session can't be created or loaded if the GAP is maxed out. The exception is that the oldest saved session context can always be loaded (assuming that there is a space in memory to put it) */ EXTERN int s_freeSessionSlots; #endif // SESSION_C /* 5.9.16.7 From IoBuffers.c */ #if defined IO_BUFFER_C || defined GLOBAL_C /* The value of s_actionIoAllocation is the number of UINT64 values allocated. It is used to set the pointer for the response structure. */ EXTERN UINT64 s_actionIoBuffer[768]; // action I/O buffer EXTERN UINT32 s_actionIoAllocation; // number of UIN64 allocated for the action input // structure #endif // MEMORY_LIB_C /* 5.9.16.8 From TPMFail.c */ /* This value holds the address of the string containing the name of the function in which the failure occurred. This address value isn't useful for anything other than helping the vendor to know in which file the failure occurred. */ EXTERN BOOL g_inFailureMode; // Indicates that the TPM is in failure mode #if SIMULATION EXTERN BOOL g_forceFailureMode; // flag to force failure mode during test #endif typedef void(FailFunction)(const char *function, int line, int code); #if defined TPM_FAIL_C || defined GLOBAL_C || 1 EXTERN UINT32 s_failFunction; EXTERN UINT32 s_failLine; // the line in the file at which // the error was signaled EXTERN UINT32 s_failCode; // the error code used EXTERN FailFunction *LibFailCallback; #endif // TPM_FAIL_C //***************************************************************************** //*** From ACT_spt.c //***************************************************************************** // This value is used to indicate if an ACT has been updated since the last // TPM2_Startup() (one bit for each ACT). If the ACT is not updated // (TPM2_ACT_SetTimeout()) after a startup, then on each TPM2_Shutdown() the TPM will // save 1/2 of the current timer value. This prevents an attack on the ACT by saving // the counter and then running for a long period of time before doing a TPM Restart. // A quick TPM2_Shutdown() after each EXTERN UINT16 s_ActUpdated; /* 5.9.16.9 From CommandCodeAttributes.c */ extern const TPMA_CC s_ccAttr[]; extern const COMMAND_ATTRIBUTES s_commandAttributes[]; #endif // GLOBAL_H libtpms-0.9.3/src/tpm2/GpMacros.h000066400000000000000000000370601421143571500165430ustar00rootroot00000000000000/********************************************************************************/ /* */ /* This file is a collection of miscellaneous macros. */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: GpMacros.h 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2021 */ /* */ /********************************************************************************/ #ifndef GPMACROS_H #define GPMACROS_H /* 5.10.1 Introduction */ /* This file is a collection of miscellaneous macros. */ #ifndef NULL #define NULL 0 #endif #include "swap.h" #include "VendorString.h" /* 5.10.2 For Self-test */ /* These macros are used in CryptUtil() to invoke the incremental self test. */ #if SELF_TEST # define TEST(alg) if(TEST_BIT(alg, g_toTest)) CryptTestAlgorithm(alg, NULL) /* Use of TPM_ALG_NULL is reserved for RSAEP/RSADP testing. If someone is wanting to test a hash with that value, don't do it. */ # define TEST_HASH(alg) \ if(TEST_BIT(alg, g_toTest) \ && (alg != TPM_ALG_NULL)) \ CryptTestAlgorithm(alg, NULL) #else # define TEST(alg) # define TEST_HASH(alg) #endif // SELF_TEST /* 5.10.3 For Failures */ #if defined _POSIX_ # define FUNCTION_NAME __func__ /* libtpms changed */ #else # define FUNCTION_NAME __FUNCTION__ #endif #if !FAIL_TRACE # define FAIL(errorCode) (TpmFail(errorCode)) # define LOG_FAILURE(errorCode) (TpmLogFailure(errorCode)) #else # define FAIL(errorCode) TpmFail(FUNCTION_NAME, __LINE__, errorCode) # define LOG_FAILURE(errorCode) TpmLogFailure(FUNCTION_NAME, __LINE__, errorCode) #endif /* If implementation is using longjmp, then the call to TpmFail() does not return and the compiler will complain about unreachable code that comes after. To allow for not having longjmp, TpmFail() will return and the subsequent code will be executed. This macro accounts for the difference. */ #ifndef NO_LONGJMP # define FAIL_RETURN(returnCode) # define TPM_FAIL_RETURN NORETURN void #else # define FAIL_RETURN(returnCode) return (returnCode) # define TPM_FAIL_RETURN void #endif /* This macro tests that a condition is TRUE and puts the TPM into failure mode if it is not. If longjmp is being used, then the FAIL(FATAL_ERROR_) macro makes a call from which there is no return. Otherwise, it returns and the function will exit with the appropriate return code. */ #define REQUIRE(condition, errorCode, returnCode) \ { \ if(!!(condition)) \ { \ FAIL(FATAL_ERROR_errorCode); \ FAIL_RETURN(returnCode); \ } \ } #define PARAMETER_CHECK(condition, returnCode) \ REQUIRE((condition), PARAMETER, returnCode) #if defined EMPTY_ASSERT && (EMPTY_ASSERT != NO) # define pAssert(a) ((void)0) #else # define pAssert(a) {if(!(a)) FAIL(FATAL_ERROR_PARAMETER);} #endif /* 5.10.4 Derived from Vendor-specific values */ /* Values derived from vendor specific settings in TpmProfile.h */ #define PCR_SELECT_MIN ((PLATFORM_PCR+7)/8) #define PCR_SELECT_MAX ((IMPLEMENTATION_PCR+7)/8) #define MAX_ORDERLY_COUNT ((1 << ORDERLY_BITS) - 1) #define RSA_MAX_PRIME (MAX_RSA_KEY_BYTES / 2) #define RSA_PRIVATE_SIZE (RSA_MAX_PRIME * 5) /* 5.10.5 Compile-time Checks */ /* In some cases, the relationship between two values may be dependent on things that change based on various selections like the chosen cryptographic libraries. It is possible that these selections will result in incompatible settings. These are often detectable by the compiler but it isn't always possible to do the check in the preprocessor code. For example, when the check requires use of sizeof then the preprocessor can't do the comparison. For these cases, we include a special macro that, depending on the compiler will generate a warning to indicate if the check always passes or always fails because it involves fixed constants. To run these checks, define COMPILER_CHECKS in TpmBuildSwitches.h */ #if COMPILER_CHECKS # define cAssert pAssert #else # define cAssert(value) #endif /* This is used commonly in the Crypt code as a way to keep listings from getting too long. This is not to save paper but to allow one to see more useful stuff on the screen at any given time. */ #define ERROR_RETURN(returnCode) \ { \ retVal = returnCode; \ goto Exit; \ } #ifndef MAX # define MAX(a, b) ((a) > (b) ? (a) : (b)) #endif #ifndef MIN # define MIN(a, b) ((a) < (b) ? (a) : (b)) #endif #ifndef IsOdd # define IsOdd(a) (((a) & 1) != 0) #endif #ifndef BITS_TO_BYTES # define BITS_TO_BYTES(bits) (((bits) + 7) >> 3) #endif #ifndef DIV_UP # define DIV_UP(var, div) ((var + div - 1) / (div)) #endif /* These are defined for use when the size of the vector being checked is known at compile time. */ #define TEST_BIT(bit, vector) TestBit((bit), (BYTE *)&(vector), sizeof(vector)) #define SET_BIT(bit, vector) SetBit((bit), (BYTE *)&(vector), sizeof(vector)) #define CLEAR_BIT(bit, vector) ClearBit((bit), (BYTE *)&(vector), sizeof(vector)) /* The following definitions are used if they have not already been defined. The defaults for these settings are compatible with ISO/IEC 9899:2011 (E) */ #ifndef LIB_EXPORT # define LIB_EXPORT # define LIB_IMPORT #endif #ifndef NORETURN # define NORETURN _Noreturn #endif #ifndef NOT_REFERENCED # define NOT_REFERENCED(x = x) ((void) (x)) #endif #define STD_RESPONSE_HEADER (sizeof(TPM_ST) + sizeof(UINT32) + sizeof(TPM_RC)) #define JOIN(x,y) x##y #define JOIN3(x, y, z) x##y##z #define CONCAT(x,y) JOIN(x, y) #define CONCAT3(x, y, z) JOIN3(x,y,z) /* If CONTEXT_INTEGRITY_HASH_ALG is defined, then the vendor is using the old style table. Otherwise, pick the strongest implemented hash algorithm as the context hash. */ #ifndef CONTEXT_HASH_ALGORITHM # if defined ALG_SHA3_512 && ALG_SHA3_512 == YES # define CONTEXT_HASH_ALGORITHM SHA3_512 # elif defined ALG_SHA512 && ALG_SHA512 == YES # define CONTEXT_HASH_ALGORITHM SHA512 # elif defined ALG_SHA3_384 && ALG_SHA3_384 == YES # define CONTEXT_HASH_ALGORITHM SHA3_384 # elif defined ALG_SHA384 && ALG_SHA384 == YES # define CONTEXT_HASH_ALGORITHM SHA384 # elif defined ALG_SHA3_256 && ALG_SHA3_256 == YES # define CONTEXT_HASH_ALGORITHM SHA3_256 # elif defined ALG_SHA256 && ALG_SHA256 == YES # define CONTEXT_HASH_ALGORITHM SHA256 # elif defined ALG_SM3_256 && ALG_SM3_256 == YES # define CONTEXT_HASH_ALGORITHM SM3_256 # elif defined ALG_SHA1 && ALG_SHA1 == YES # define CONTEXT_HASH_ALGORITHM SHA1 # endif # define CONTEXT_INTEGRITY_HASH_ALG CONCAT(TPM_ALG_, CONTEXT_HASH_ALGORITHM) #if CONTEXT_HASH_ALGORITHM != SHA512 // libtpms added begin #error CONTEXT_HASH_ALGORITHM must remain SHA512 #endif // libtpms added end #endif #ifndef CONTEXT_INTEGRITY_HASH_SIZE #define CONTEXT_INTEGRITY_HASH_SIZE CONCAT(CONTEXT_HASH_ALGORITHM, _DIGEST_SIZE) #endif #if ALG_RSA #define RSA_SECURITY_STRENGTH (MAX_RSA_KEY_BITS >= 15360 ? 256 : \ (MAX_RSA_KEY_BITS >= 7680 ? 192 : \ (MAX_RSA_KEY_BITS >= 3072 ? 128 : \ (MAX_RSA_KEY_BITS >= 2048 ? 112 : \ (MAX_RSA_KEY_BITS >= 1024 ? 80 : 0))))) #else #define RSA_SECURITY_STRENGTH 0 #endif // ALG_RSA #if ALG_ECC #define ECC_SECURITY_STRENGTH (MAX_ECC_KEY_BITS >= 521 ? 256 : \ (MAX_ECC_KEY_BITS >= 384 ? 192 : \ (MAX_ECC_KEY_BITS >= 256 ? 128 : 0))) #else #define ECC_SECURITY_STRENGTH 0 #endif // ALG_ECC #define MAX_ASYM_SECURITY_STRENGTH \ MAX(RSA_SECURITY_STRENGTH, ECC_SECURITY_STRENGTH) #define MAX_HASH_SECURITY_STRENGTH ((CONTEXT_INTEGRITY_HASH_SIZE * 8) / 2) /* Unless some algorithm is broken... */ #define MAX_SYM_SECURITY_STRENGTH MAX_SYM_KEY_BITS #define MAX_SECURITY_STRENGTH_BITS \ MAX(MAX_ASYM_SECURITY_STRENGTH, \ MAX(MAX_SYM_SECURITY_STRENGTH, \ MAX_HASH_SECURITY_STRENGTH)) /* This is the size that was used before the 1.38 errata requiring that P1.14.4 be followed */ #define PROOF_SIZE CONTEXT_INTEGRITY_HASH_SIZE /* As required by P1.14.4 */ #define COMPLIANT_PROOF_SIZE \ (MAX(CONTEXT_INTEGRITY_HASH_SIZE, (2 * MAX_SYM_KEY_BYTES))) /* As required by P1.14.3.1 */ #define COMPLIANT_PRIMARY_SEED_SIZE \ BITS_TO_BYTES(MAX_SECURITY_STRENGTH_BITS * 2) /* This is the pre-errata version */ #ifndef PRIMARY_SEED_SIZE # define PRIMARY_SEED_SIZE PROOF_SIZE #endif #if USE_SPEC_COMPLIANT_PROOFS # undef PROOF_SIZE # define PROOF_SIZE COMPLIANT_PROOF_SIZE # undef PRIMARY_SEED_SIZE # define PRIMARY_SEED_SIZE COMPLIANT_PRIMARY_SEED_SIZE #endif // USE_SPEC_COMPLIANT_PROOFS #if !SKIP_PROOF_ERRORS # if PROOF_SIZE < COMPLIANT_PROOF_SIZE # error "PROOF_SIZE is not compliant with TPM specification" # endif # if PRIMARY_SEED_SIZE < COMPLIANT_PRIMARY_SEED_SIZE # error "Non-compliant PRIMARY_SEED_SIZE" # endif #endif // !SKIP_PROOF_ERRORS /* If CONTEXT_ENCRYPT_ALG is defined, then the vendor is using the old style table */ #if defined CONTEXT_ENCRYPT_ALG # undef CONTEXT_ENCRYPT_ALGORITHM # if CONTEXT_ENCRYPT_ALG == ALG_AES_VALUE # define CONTEXT_ENCRYPT_ALGORITHM AES # elif CONTEXT_ENCRYPT_ALG == ALG_SM4_VALUE # define CONTEXT_ENCRYPT_ALGORITHM SM4 # elif CONTEXT_ENCRYPT_ALG == ALG_CAMELLIA_VALUE # define CONTEXT_ENCRYPT_ALGORITHM CAMELLIA # elif CONTEXT_ENCRYPT_ALG == ALG_TDES_VALUE # error Are you kidding? # else # error Unknown value for CONTEXT_ENCRYPT_ALG # endif // CONTEXT_ENCRYPT_ALG == ALG_AES_VALUE #else # define CONTEXT_ENCRYPT_ALG \ CONCAT3(ALG_, CONTEXT_ENCRYPT_ALGORITHM, _VALUE) #endif // CONTEXT_ENCRYPT_ALG #define CONTEXT_ENCRYPT_KEY_BITS \ CONCAT(CONTEXT_ENCRYPT_ALGORITHM, _MAX_KEY_SIZE_BITS) #define CONTEXT_ENCRYPT_KEY_BYTES ((CONTEXT_ENCRYPT_KEY_BITS+7)/8) /* This is updated to follow the requirement of P2 that the label not be larger than 32 bytes. */ #ifndef LABEL_MAX_BUFFER #define LABEL_MAX_BUFFER MIN(32, MAX(MAX_ECC_KEY_BYTES, MAX_DIGEST_SIZE)) #endif /* This bit is used to indicate that an authorization ticket expires on TPM Reset and TPM Restart.It is added to the timeout value returned by TPM2_PoliySigned() and TPM2_PolicySecret() and used by TPM2_PolicyTicket(). The timeout value is relative to Time (g_time). Time is reset whenever the TPM loses power and cannot be moved forward by the user (as can Clock). g_time is a 64-bit value expressing time in ms. Stealing the MSb() for a flag means that the TPM needs to be reset at least once every 292,471,208 years rather than once every 584,942,417 years. */ #define EXPIRATION_BIT ((UINT64)1 << 63) /* Check for consistency of the bit ordering of bit fields */ #if BIG_ENDIAN_TPM && MOST_SIGNIFICANT_BIT_0 && USE_BIT_FIELD_STRUCTURES # error "Settings not consistent" #endif /* These macros are used to handle the variation in handling of bit fields. If */ #if USE_BIT_FIELD_STRUCTURES // The default, old version, with bit fields # define IS_ATTRIBUTE(a, type, b) ((a.b) != 0) # define SET_ATTRIBUTE(a, type, b) (a.b = SET) # define CLEAR_ATTRIBUTE(a, type, b) (a.b = CLEAR) # define GET_ATTRIBUTE(a, type, b) (a.b) # define TPMA_ZERO_INITIALIZER() {0} #else # define IS_ATTRIBUTE(a, type, b) ((a & type##_##b) != 0) # define SET_ATTRIBUTE(a, type, b) (a |= type##_##b) # define CLEAR_ATTRIBUTE(a, type, b) (a &= ~type##_##b) # define GET_ATTRIBUTE(a, type, b) \ (type)((a & type##_##b) >> type##_##b##_SHIFT) # define TPMA_ZERO_INITIALIZER() (0) #endif #define VERIFY(_X) if(!(_X)) goto Error // These macros determine if the values in this file are referenced or instanced. // Global.c defines GLOBAL_C so all the values in this file will be instanced in // Global.obj. For all other files that include this file, the values will simply // be external references. For constants, there can be an initializer. #ifdef GLOBAL_C #define EXTERN #define INITIALIZER(_value_) = _value_ #else #define EXTERN extern #define INITIALIZER(_value_) #endif // This macro will create an OID. All OIDs are in DER form with a first octet of // 0x06 indicating an OID fallowed by an octet indicating the number of octets in the // rest of the OID. This allows a user of this OID to know how much/little to copy. #define MAKE_OID(NAME) \ EXTERN const BYTE OID##NAME[] INITIALIZER({OID##NAME##_VALUE}) /* This definition is moved from TpmProfile.h because it is not actually vendor- specific. It has to be the same size as the sequence parameter of a TPMS_CONTEXT and that is a UINT64. So, this is an invariant value */ #define CONTEXT_COUNTER UINT64 #endif // GP_MACROS_H libtpms-0.9.3/src/tpm2/HMAC_Start_fp.h000066400000000000000000000075541421143571500174070ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: HMAC_Start_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef HMAC_START_FP_H #define HMAC_START_FP_H typedef struct { TPMI_DH_OBJECT handle; TPM2B_AUTH auth; TPMI_ALG_HASH hashAlg; } HMAC_Start_In; typedef struct { TPMI_DH_OBJECT sequenceHandle; } HMAC_Start_Out; #define RC_HMAC_Start_handle (TPM_RC_H + TPM_RC_1) #define RC_HMAC_Start_auth (TPM_RC_P + TPM_RC_1) #define RC_HMAC_Start_hashAlg (TPM_RC_P + TPM_RC_2) TPM_RC TPM2_HMAC_Start( HMAC_Start_In *in, // IN: input parameter list HMAC_Start_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/HMAC_fp.h000066400000000000000000000074761421143571500162350ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: HMAC_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef HMAC_FP_H #define HMAC_FP_H typedef struct { TPMI_DH_OBJECT handle; TPM2B_MAX_BUFFER buffer; TPMI_ALG_HASH hashAlg; } HMAC_In; #define RC_HMAC_handle (TPM_RC_H + TPM_RC_1) #define RC_HMAC_buffer (TPM_RC_P + TPM_RC_1) #define RC_HMAC_hashAlg (TPM_RC_P + TPM_RC_2) typedef struct { TPM2B_DIGEST outHMAC; } HMAC_Out; TPM_RC TPM2_HMAC( HMAC_In *in, // IN: input parameter list HMAC_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/Handle.c000066400000000000000000000204631421143571500162150ustar00rootroot00000000000000/********************************************************************************/ /* */ /* fUnctions that return the type of a handle. */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Handle.c 1519 2019-11-15 20:43:51Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ /* 9.6 Handle.c */ /* 9.6.1 Description */ /* This file contains the functions that return the type of a handle. */ /* 9.6.2 Includes */ #include "Tpm.h" /* 9.6.3 Functions */ /* 9.6.3.1 HandleGetType() */ /* This function returns the type of a handle which is the MSO of the handle. */ TPM_HT HandleGetType( TPM_HANDLE handle // IN: a handle to be checked ) { // return the upper bytes of input data return (TPM_HT)((handle & HR_RANGE_MASK) >> HR_SHIFT); } /* 9.6.3.2 NextPermanentHandle() */ /* This function returns the permanent handle that is equal to the input value or is the next higher value. If there is no handle with the input value and there is no next higher value, it returns 0: */ TPM_HANDLE NextPermanentHandle( TPM_HANDLE inHandle // IN: the handle to check ) { // If inHandle is below the start of the range of permanent handles // set it to the start and scan from there if(inHandle < TPM_RH_FIRST) inHandle = TPM_RH_FIRST; // scan from input value until we find an implemented permanent handle // or go out of range for(; inHandle <= TPM_RH_LAST; inHandle++) { switch(inHandle) { case TPM_RH_OWNER: case TPM_RH_NULL: case TPM_RS_PW: case TPM_RH_LOCKOUT: case TPM_RH_ENDORSEMENT: case TPM_RH_PLATFORM: case TPM_RH_PLATFORM_NV: #ifdef VENDOR_PERMANENT case VENDOR_PERMANENT: #endif // Each of the implemented ACT #define ACT_IMPLEMENTED_CASE(N) \ case TPM_RH_ACT_##N: FOR_EACH_ACT(ACT_IMPLEMENTED_CASE) return inHandle; break; default: break; } } // Out of range on the top return 0; } /* 9.6.3.3 PermanentCapGetHandles() */ /* This function returns a list of the permanent handles of PCR, started from handle. If handle is larger than the largest permanent handle, an empty list will be returned with more set to NO. */ /* Return Values Meaning */ /* YES if there are more handles available */ /* NO all the available handles has been returned */ TPMI_YES_NO PermanentCapGetHandles( TPM_HANDLE handle, // IN: start handle UINT32 count, // IN: count of returned handles TPML_HANDLE *handleList // OUT: list of handle ) { TPMI_YES_NO more = NO; UINT32 i; pAssert(HandleGetType(handle) == TPM_HT_PERMANENT); // Initialize output handle list handleList->count = 0; // The maximum count of handles we may return is MAX_CAP_HANDLES if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES; // Iterate permanent handle range for(i = NextPermanentHandle(handle); i != 0; i = NextPermanentHandle(i + 1)) { if(handleList->count < count) { // If we have not filled up the return list, add this permanent // handle to it handleList->handle[handleList->count] = i; handleList->count++; } else { // If the return list is full but we still have permanent handle // available, report this and stop iterating more = YES; break; } } return more; } /* 9.6.3.4 PermanentHandleGetPolicy() */ /* This function returns a list of the permanent handles of PCR, started from handle. If handle is larger than the largest permanent handle, an empty list will be returned with more set to NO. */ /* Return Values Meaning */ /* YES if there are more handles available */ /* NO all the available handles has been returned */ TPMI_YES_NO PermanentHandleGetPolicy( TPM_HANDLE handle, // IN: start handle UINT32 count, // IN: max count of returned handles TPML_TAGGED_POLICY *policyList // OUT: list of handle ) { TPMI_YES_NO more = NO; pAssert(HandleGetType(handle) == TPM_HT_PERMANENT); // Initialize output handle list policyList->count = 0; // The maximum count of policies we may return is MAX_TAGGED_POLICIES if(count > MAX_TAGGED_POLICIES) count = MAX_TAGGED_POLICIES; // Iterate permanent handle range for(handle = NextPermanentHandle(handle); handle != 0; handle = NextPermanentHandle(handle + 1)) { TPM2B_DIGEST policyDigest; TPM_ALG_ID policyAlg; // Check to see if this permanent handle has a policy policyAlg = EntityGetAuthPolicy(handle, &policyDigest); if(policyAlg == TPM_ALG_ERROR) continue; if(policyList->count < count) { // If we have not filled up the return list, add this // policy to the list; policyList->policies[policyList->count].handle = handle; policyList->policies[policyList->count].policyHash.hashAlg = policyAlg; MemoryCopy(&policyList->policies[policyList->count].policyHash.digest, policyDigest.t.buffer, policyDigest.t.size); policyList->count++; } else { // If the return list is full but we still have permanent handle // available, report this and stop iterating more = YES; break; } } return more; } libtpms-0.9.3/src/tpm2/Handle_fp.h000066400000000000000000000100341421143571500167000ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Handle_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 */ /* */ /********************************************************************************/ #ifndef HANDLE_FP_H #define HANDLE_FP_H TPM_HT HandleGetType( TPM_HANDLE handle // IN: a handle to be checked ); TPM_HANDLE NextPermanentHandle( TPM_HANDLE inHandle // IN: the handle to check ); TPMI_YES_NO PermanentCapGetHandles( TPM_HANDLE handle, // IN: start handle UINT32 count, // IN: count of returned handles TPML_HANDLE *handleList // OUT: list of handle ); TPMI_YES_NO PermanentHandleGetPolicy( TPM_HANDLE handle, // IN: start handle UINT32 count, // IN: count of returned handles TPML_TAGGED_POLICY *policyList // OUT: list of handle ); #endif libtpms-0.9.3/src/tpm2/HashCommands.c000066400000000000000000000365641421143571500174000ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Hash/HMAC/Event Sequences */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: HashCommands.c 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2018 */ /* */ /********************************************************************************/ #include "Tpm.h" #include "HMAC_Start_fp.h" #if CC_HMAC_Start // Conditional expansion of this file TPM_RC TPM2_HMAC_Start( HMAC_Start_In *in, // IN: input parameter list HMAC_Start_Out *out // OUT: output parameter list ) { OBJECT *keyObject; TPMT_PUBLIC *publicArea; TPM_ALG_ID hashAlg; // Input Validation // Get HMAC key object and public area pointers keyObject = HandleToObject(in->handle); publicArea = &keyObject->publicArea; // Make sure that the key is an HMAC key if(publicArea->type != TPM_ALG_KEYEDHASH) return TPM_RCS_TYPE + RC_HMAC_Start_handle; // and that it is unrestricted if (IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted)) return TPM_RCS_ATTRIBUTES + RC_HMAC_Start_handle; // and that it is a signing key if (!IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign)) return TPM_RCS_KEY + RC_HMAC_Start_handle; // See if the key has a default if(publicArea->parameters.keyedHashDetail.scheme.scheme == TPM_ALG_NULL) // it doesn't so use the input value hashAlg = in->hashAlg; else { // key has a default so use it hashAlg = publicArea->parameters.keyedHashDetail.scheme.details.hmac.hashAlg; // and verify that the input was either the TPM_ALG_NULL or the default if(in->hashAlg != TPM_ALG_NULL && in->hashAlg != hashAlg) hashAlg = TPM_ALG_NULL; } // if we ended up without a hash algorithm then return an error if(hashAlg == TPM_ALG_NULL) return TPM_RCS_VALUE + RC_HMAC_Start_hashAlg; // Internal Data Update // Create a HMAC sequence object. A TPM_RC_OBJECT_MEMORY error may be // returned at this point return ObjectCreateHMACSequence(hashAlg, keyObject, &in->auth, &out->sequenceHandle); } #endif // CC_HMAC_Start #include "Tpm.h" #include "MAC_Start_fp.h" #if CC_MAC_Start // Conditional expansion of this file /* Error Returns Meaning */ /* TPM_RC_ATTRIBUTES key referenced by handle is not a signing key or is restricted */ /* TPM_RC_OBJECT_MEMORY no space to create an internal object */ /* TPM_RC_KEY key referenced by handle is not an HMAC key */ /* TPM_RC_VALUE hashAlg is not compatible with the hash algorithm of the scheme of the object referenced by handle */ TPM_RC TPM2_MAC_Start( MAC_Start_In *in, // IN: input parameter list MAC_Start_Out *out // OUT: output parameter list ) { OBJECT *keyObject; TPMT_PUBLIC *publicArea; TPM_RC result; // Input Validation // Get HMAC key object and public area pointers keyObject = HandleToObject(in->handle); publicArea = &keyObject->publicArea; // Make sure that the key can do what is required result = CryptSelectMac(publicArea, &in->inScheme); // If the key is not able to do a MAC, indicate that the handle selects an // object that can't do a MAC if(result == TPM_RCS_TYPE) return TPM_RCS_TYPE + RC_MAC_Start_handle; // If there is another error type, indicate that the scheme and key are not // compatible if(result != TPM_RC_SUCCESS) return RcSafeAddToResult(result, RC_MAC_Start_inScheme); // Make sure that the key is not restricted if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted)) return TPM_RCS_ATTRIBUTES + RC_MAC_Start_handle; // and that it is a signing key if(!IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign)) return TPM_RCS_KEY + RC_MAC_Start_handle; // Internal Data Update // Create a HMAC sequence object. A TPM_RC_OBJECT_MEMORY error may be // returned at this point return ObjectCreateHMACSequence(in->inScheme, keyObject, &in->auth, &out->sequenceHandle); } #endif // CC_MAC_Start #include "Tpm.h" #include "HashSequenceStart_fp.h" #if CC_HashSequenceStart // Conditional expansion of this file TPM_RC TPM2_HashSequenceStart( HashSequenceStart_In *in, // IN: input parameter list HashSequenceStart_Out *out // OUT: output parameter list ) { // Internal Data Update if(in->hashAlg == TPM_ALG_NULL) // Start a event sequence. A TPM_RC_OBJECT_MEMORY error may be // returned at this point return ObjectCreateEventSequence(&in->auth, &out->sequenceHandle); // Start a hash sequence. A TPM_RC_OBJECT_MEMORY error may be // returned at this point return ObjectCreateHashSequence(in->hashAlg, &in->auth, &out->sequenceHandle); } #endif // CC_HashSequenceStart #include "Tpm.h" #include "SequenceUpdate_fp.h" #if CC_SequenceUpdate // Conditional expansion of this file TPM_RC TPM2_SequenceUpdate( SequenceUpdate_In *in // IN: input parameter list ) { OBJECT *object; HASH_OBJECT *hashObject; // Input Validation // Get sequence object pointer object = HandleToObject(in->sequenceHandle); hashObject = (HASH_OBJECT *)object; // Check that referenced object is a sequence object. if(!ObjectIsSequence(object)) return TPM_RCS_MODE + RC_SequenceUpdate_sequenceHandle; // Internal Data Update if(object->attributes.eventSeq == SET) { // Update event sequence object UINT32 i; for(i = 0; i < HASH_COUNT; i++) { // Update sequence object CryptDigestUpdate2B(&hashObject->state.hashState[i], &in->buffer.b); } } else { // Update hash/HMAC sequence object if(hashObject->attributes.hashSeq == SET) { // Is this the first block of the sequence if(hashObject->attributes.firstBlock == CLEAR) { // If so, indicate that first block was received hashObject->attributes.firstBlock = SET; // Check the first block to see if the first block can contain // the TPM_GENERATED_VALUE. If it does, it is not safe for // a ticket. if(TicketIsSafe(&in->buffer.b)) hashObject->attributes.ticketSafe = SET; } // Update sequence object hash/HMAC stack CryptDigestUpdate2B(&hashObject->state.hashState[0], &in->buffer.b); } else if(object->attributes.hmacSeq == SET) { // Update sequence object HMAC stack CryptDigestUpdate2B(&hashObject->state.hmacState.hashState, &in->buffer.b); } } return TPM_RC_SUCCESS; } #endif // CC_SequenceUpdate #include "Tpm.h" #include "SequenceComplete_fp.h" #if CC_SequenceComplete // Conditional expansion of this file /* Error Returns Meaning */ /* TPM_RC_MODE sequenceHandle does not reference a hash or HMAC sequence object */ TPM_RC TPM2_SequenceComplete( SequenceComplete_In *in, // IN: input parameter list SequenceComplete_Out *out // OUT: output parameter list ) { HASH_OBJECT *hashObject; // Input validation // Get hash object pointer hashObject = (HASH_OBJECT *)HandleToObject(in->sequenceHandle); // input handle must be a hash or HMAC sequence object. if(hashObject->attributes.hashSeq == CLEAR && hashObject->attributes.hmacSeq == CLEAR) return TPM_RCS_MODE + RC_SequenceComplete_sequenceHandle; // Command Output if(hashObject->attributes.hashSeq == SET) // sequence object for hash { // Get the hash algorithm before the algorithm is lost in CryptHashEnd TPM_ALG_ID hashAlg = hashObject->state.hashState[0].hashAlg; // Update last piece of the data CryptDigestUpdate2B(&hashObject->state.hashState[0], &in->buffer.b); // Complete hash out->result.t.size = CryptHashEnd(&hashObject->state.hashState[0], sizeof(out->result.t.buffer), out->result.t.buffer); // Check if the first block of the sequence has been received if(hashObject->attributes.firstBlock == CLEAR) { // If not, then this is the first block so see if it is 'safe' // to sign. if(TicketIsSafe(&in->buffer.b)) hashObject->attributes.ticketSafe = SET; } // Output ticket out->validation.tag = TPM_ST_HASHCHECK; out->validation.hierarchy = in->hierarchy; if(in->hierarchy == TPM_RH_NULL) { // Ticket is not required out->validation.digest.t.size = 0; } else if(hashObject->attributes.ticketSafe == CLEAR) { // Ticket is not safe to generate out->validation.hierarchy = TPM_RH_NULL; out->validation.digest.t.size = 0; } else { // Compute ticket TicketComputeHashCheck(out->validation.hierarchy, hashAlg, &out->result, &out->validation); } } else { // Update last piece of data CryptDigestUpdate2B(&hashObject->state.hmacState.hashState, &in->buffer.b); #if !SMAC_IMPLEMENTED // Complete HMAC out->result.t.size = CryptHmacEnd(&(hashObject->state.hmacState), sizeof(out->result.t.buffer), out->result.t.buffer); #else // Complete the MAC out->result.t.size = CryptMacEnd(&hashObject->state.hmacState, sizeof(out->result.t.buffer), out->result.t.buffer); #endif // No ticket is generated for HMAC sequence out->validation.tag = TPM_ST_HASHCHECK; out->validation.hierarchy = TPM_RH_NULL; out->validation.digest.t.size = 0; } // Internal Data Update // mark sequence object as evict so it will be flushed on the way out hashObject->attributes.evict = SET; return TPM_RC_SUCCESS; } #endif // CC_SequenceComplete #include "Tpm.h" #include "EventSequenceComplete_fp.h" #if CC_EventSequenceComplete // Conditional expansion of this file TPM_RC TPM2_EventSequenceComplete( EventSequenceComplete_In *in, // IN: input parameter list EventSequenceComplete_Out *out // OUT: output parameter list ) { HASH_OBJECT *hashObject; UINT32 i; TPM_ALG_ID hashAlg; // Input validation // get the event sequence object pointer hashObject = (HASH_OBJECT *)HandleToObject(in->sequenceHandle); // input handle must reference an event sequence object if(hashObject->attributes.eventSeq != SET) return TPM_RCS_MODE + RC_EventSequenceComplete_sequenceHandle; // see if a PCR extend is requested in call if(in->pcrHandle != TPM_RH_NULL) { // see if extend of the PCR is allowed at the locality of the command, if(!PCRIsExtendAllowed(in->pcrHandle)) return TPM_RC_LOCALITY; // if an extend is going to take place, then check to see if there has // been an orderly shutdown. If so, and the selected PCR is one of the // state saved PCR, then the orderly state has to change. The orderly state // does not change for PCR that are not preserved. // NOTE: This doesn't just check for Shutdown(STATE) because the orderly // state will have to change if this is a state-saved PCR regardless // of the current state. This is because a subsequent Shutdown(STATE) will // check to see if there was an orderly shutdown and not do anything if // there was. So, this must indicate that a future Shutdown(STATE) has // something to do. if(PCRIsStateSaved(in->pcrHandle)) RETURN_IF_ORDERLY; } // Command Output out->results.count = 0; for(i = 0; i < HASH_COUNT; i++) { hashAlg = CryptHashGetAlgByIndex(i); // Update last piece of data CryptDigestUpdate2B(&hashObject->state.hashState[i], &in->buffer.b); // Complete hash out->results.digests[out->results.count].hashAlg = hashAlg; CryptHashEnd(&hashObject->state.hashState[i], CryptHashGetDigestSize(hashAlg), (BYTE *)&out->results.digests[out->results.count].digest); // Extend PCR if(in->pcrHandle != TPM_RH_NULL) PCRExtend(in->pcrHandle, hashAlg, CryptHashGetDigestSize(hashAlg), (BYTE *)&out->results.digests[out->results.count].digest); out->results.count++; } // Internal Data Update // mark sequence object as evict so it will be flushed on the way out hashObject->attributes.evict = SET; return TPM_RC_SUCCESS; } #endif // CC_EventSequenceComplete libtpms-0.9.3/src/tpm2/HashSequenceStart_fp.h000066400000000000000000000075741421143571500211160ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: HashSequenceStart_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef HASHSEQUENCESTART_FP_H #define HASHSEQUENCESTART_FP_H typedef struct { TPM2B_AUTH auth; TPMI_ALG_HASH hashAlg; } HashSequenceStart_In; #define RC_HashSequenceStart_auth (TPM_RC_P + TPM_RC_1) #define RC_HashSequenceStart_hashAlg (TPM_RC_P + TPM_RC_2) typedef struct { TPMI_DH_OBJECT sequenceHandle; } HashSequenceStart_Out; TPM_RC TPM2_HashSequenceStart( HashSequenceStart_In *in, // IN: input parameter list HashSequenceStart_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/HashTestData.h000066400000000000000000000233301421143571500173400ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Hash Test Vectors */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: HashTestData.h 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2021 */ /* */ /********************************************************************************/ #ifndef HASHTESTDATA_H #define HASHTESTDATA_H /* 10.1.8 HashTestData.h */ /* Hash Test Vectors */ TPM2B_TYPE(HASH_TEST_KEY, 128); // Twice the largest digest size TPM2B_HASH_TEST_KEY c_hashTestKey = {{128, { 0xa0,0xed,0x5c,0x9a,0xd2,0x4a,0x21,0x40,0x1a,0xd0,0x81,0x47,0x39,0x63,0xf9,0x50, 0xdc,0x59,0x47,0x11,0x40,0x13,0x99,0x92,0xc0,0x72,0xa4,0x0f,0xe2,0x33,0xe4,0x63, 0x9b,0xb6,0x76,0xc3,0x1e,0x6f,0x13,0xee,0xcc,0x99,0x71,0xa5,0xc0,0xcf,0x9a,0x40, 0xcf,0xdb,0x66,0x70,0x05,0x63,0x54,0x12,0x25,0xf4,0xe0,0x1b,0x23,0x35,0xe3,0x70, 0x7d,0x19,0x5f,0x00,0xe4,0xf1,0x61,0x73,0x05,0xd8,0x58,0x7f,0x60,0x61,0x84,0x36, 0xec,0xbe,0x96,0x1b,0x69,0x00,0xf0,0x9a,0x6e,0xe3,0x26,0x73,0x0d,0x17,0x5b,0x33, 0x41,0x44,0x9d,0x90,0xab,0xd9,0x6b,0x7d,0x48,0x99,0x25,0x93,0x29,0x14,0x2b,0xce, 0x93,0x8d,0x8c,0xaf,0x31,0x0e,0x9c,0x57,0xd8,0x5b,0x57,0x20,0x1b,0x9f,0x2d,0xa5 }}}; TPM2B_TYPE(HASH_TEST_DATA, 256); // Twice the largest block size TPM2B_HASH_TEST_DATA c_hashTestData = {{256, { 0x88,0xac,0xc3,0xe5,0x5f,0x66,0x9d,0x18,0x80,0xc9,0x7a,0x9c,0xa4,0x08,0x90,0x98, 0x0f,0x3a,0x53,0x92,0x4c,0x67,0x4e,0xb7,0x37,0xec,0x67,0x87,0xb6,0xbe,0x10,0xca, 0x11,0x5b,0x4a,0x0b,0x45,0xc3,0x32,0x68,0x48,0x69,0xce,0x25,0x1b,0xc8,0xaf,0x44, 0x79,0x22,0x83,0xc8,0xfb,0xe2,0x63,0x94,0xa2,0x3c,0x59,0x3e,0x3e,0xc6,0x64,0x2c, 0x1f,0x8c,0x11,0x93,0x24,0xa3,0x17,0xc5,0x2f,0x37,0xcf,0x95,0x97,0x8e,0x63,0x39, 0x68,0xd5,0xca,0xba,0x18,0x37,0x69,0x6e,0x4f,0x19,0xfd,0x8a,0xc0,0x8d,0x87,0x3a, 0xbc,0x31,0x42,0x04,0x05,0xef,0xb5,0x02,0xef,0x1e,0x92,0x4b,0xb7,0x73,0x2c,0x8c, 0xeb,0x23,0x13,0x81,0x34,0xb9,0xb5,0xc1,0x17,0x37,0x39,0xf8,0x3e,0xe4,0x4c,0x06, 0xa8,0x81,0x52,0x2f,0xef,0xc9,0x9c,0x69,0x89,0xbc,0x85,0x9c,0x30,0x16,0x02,0xca, 0xe3,0x61,0xd4,0x0f,0xed,0x34,0x1b,0xca,0xc1,0x1b,0xd1,0xfa,0xc1,0xa2,0xe0,0xdf, 0x52,0x2f,0x0b,0x4b,0x9f,0x0e,0x45,0x54,0xb9,0x17,0xb6,0xaf,0xd6,0xd5,0xca,0x90, 0x29,0x57,0x7b,0x70,0x50,0x94,0x5c,0x8e,0xf6,0x4e,0x21,0x8b,0xc6,0x8b,0xa6,0xbc, 0xb9,0x64,0xd4,0x4d,0xf3,0x68,0xd8,0xac,0xde,0xd8,0xd8,0xb5,0x6d,0xcd,0x93,0xeb, 0x28,0xa4,0xe2,0x5c,0x44,0xef,0xf0,0xe1,0x6f,0x38,0x1a,0x3c,0xe6,0xef,0xa2,0x9d, 0xb9,0xa8,0x05,0x2a,0x95,0xec,0x5f,0xdb,0xb0,0x25,0x67,0x9c,0x86,0x7a,0x8e,0xea, 0x51,0xcc,0xc3,0xd3,0xff,0x6e,0xf0,0xed,0xa3,0xae,0xf9,0x5d,0x33,0x70,0xf2,0x11 }}}; #if ALG_SHA1 == YES TPM2B_TYPE(SHA1, 20); TPM2B_SHA1 c_SHA1_digest = {{20, { 0xee,0x2c,0xef,0x93,0x76,0xbd,0xf8,0x91,0xbc,0xe6,0xe5,0x57,0x53,0x77,0x01,0xb5, 0x70,0x95,0xe5,0x40 }}}; #endif #if ALG_SHA256 == YES TPM2B_TYPE(SHA256, 32); TPM2B_SHA256 c_SHA256_digest = {{32, { 0x64,0xe8,0xe0,0xc3,0xa9,0xa4,0x51,0x49,0x10,0x55,0x8d,0x31,0x71,0xe5,0x2f,0x69, 0x3a,0xdc,0xc7,0x11,0x32,0x44,0x61,0xbd,0x34,0x39,0x57,0xb0,0xa8,0x75,0x86,0x1b }}}; #endif #if ALG_SHA384 == YES TPM2B_TYPE(SHA384, 48); TPM2B_SHA384 c_SHA384_digest = {{48, { 0x37,0x75,0x29,0xb5,0x20,0x15,0x6e,0xa3,0x7e,0xa3,0x0d,0xcd,0x80,0xa8,0xa3,0x3d, 0xeb,0xe8,0xad,0x4e,0x1c,0x77,0x94,0x5a,0xaf,0x6c,0xd0,0xc1,0xfa,0x43,0x3f,0xc7, 0xb8,0xf1,0x01,0xc0,0x60,0xbf,0xf2,0x87,0xe8,0x71,0x9e,0x51,0x97,0xa0,0x09,0x8d }}}; #endif #if ALG_SHA512 == YES TPM2B_TYPE(SHA512, 64); TPM2B_SHA512 c_SHA512_digest = {{64, { 0xe2,0x7b,0x10,0x3d,0x5e,0x48,0x58,0x44,0x67,0xac,0xa3,0x81,0x8c,0x1d,0xc5,0x71, 0x66,0x92,0x8a,0x89,0xaa,0xd4,0x35,0x51,0x60,0x37,0x31,0xd7,0xba,0xe7,0x93,0x0b, 0x16,0x4d,0xb3,0xc8,0x34,0x98,0x3c,0xd3,0x53,0xde,0x5e,0xe8,0x0c,0xbc,0xaf,0xc9, 0x24,0x2c,0xcc,0xed,0xdb,0xde,0xba,0x1f,0x14,0x14,0x5a,0x95,0x80,0xde,0x66,0xbd }}}; #endif TPM2B_TYPE(EMPTY, 1); #if ALG_SM3_256 == YES TPM2B_EMPTY c_SM3_256_digest = {{0, {0}}}; #endif #if ALG_SHA3_256 == YES TPM2B_EMPTY c_SHA3_256_digest = {{0, {0}}}; #endif #if ALG_SHA3_384 == YES TPM2B_EMPTY c_SHA3_384_digest = {{0, {0}}}; #endif #if ALG_SHA3_512 == YES TPM2B_EMPTY c_SHA3_512_digest = {{0, {0}}}; #endif // libtpms added begin #if SMAC_IMPLEMENTED && ALG_CMAC TPM2B_TYPE(AES128, 16); static TPM2B_AES128 cmac_aeskey = {{16, { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }}}; static const struct CMACTest { TPM2B *key; const BYTE data[64]; UINT32 datalen; const BYTE out[16]; UINT16 outlen; } CMACTests[] = { { .key = &cmac_aeskey.b, .data = { }, .datalen = 0, .out = { 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28, 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46}, .outlen = 16, }, { .key = &cmac_aeskey.b, .data = { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a}, .datalen = 16, .out = { 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44, 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c}, .outlen = 16, }, { .key = &cmac_aeskey.b, .data = { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11}, .datalen = 40, .out = { 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30, 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27}, .outlen = 16, }, { .key = &cmac_aeskey.b, .data = { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10}, .datalen = 64, .out = { 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92, 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe}, .outlen = 16, }, { .key = NULL, } }; #endif // libtpms added end #endif libtpms-0.9.3/src/tpm2/Hash_fp.h000066400000000000000000000075431421143571500164030ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Hash_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef HASH_FP_H #define HASH_FP_H typedef struct { TPM2B_MAX_BUFFER data; TPMI_ALG_HASH hashAlg; TPMI_RH_HIERARCHY hierarchy; } Hash_In; #define RC_Hash_data (TPM_RC_P + TPM_RC_1) #define RC_Hash_hashAlg (TPM_RC_P + TPM_RC_2) #define RC_Hash_hierarchy (TPM_RC_P + TPM_RC_3) typedef struct { TPM2B_DIGEST outHash; TPMT_TK_HASHCHECK validation; } Hash_Out; TPM_RC TPM2_Hash( Hash_In *in, // IN: input parameter list Hash_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/Hierarchy.c000066400000000000000000000233431421143571500167400ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Managing and accessing the hierarchy-related values */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Hierarchy.c 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ /* 8.3 Hierarchy.c */ /* 8.3.1 Introduction */ /* This file contains the functions used for managing and accessing the hierarchy-related values. */ /* 8.3.2 Includes */ #include "Tpm.h" /* 8.3.3 Functions */ /* 8.3.3.1 HierarchyPreInstall() */ /* This function performs the initialization functions for the hierarchy when the TPM is simulated. This function should not be called if the TPM is not in a manufacturing mode at the manufacturer, or in a simulated environment. */ void HierarchyPreInstall_Init( void ) { // Allow lockout clear command gp.disableClear = FALSE; // Initialize Primary Seeds gp.EPSeed.t.size = sizeof(gp.EPSeed.t.buffer); gp.SPSeed.t.size = sizeof(gp.SPSeed.t.buffer); gp.PPSeed.t.size = sizeof(gp.PPSeed.t.buffer); #if (defined USE_PLATFORM_EPS) && (USE_PLATFORM_EPS != NO) _plat__GetEPS(gp.EPSeed.t.size, gp.EPSeed.t.buffer); #else CryptRandomGenerate(gp.EPSeed.t.size, gp.EPSeed.t.buffer); #endif CryptRandomGenerate(gp.SPSeed.t.size, gp.SPSeed.t.buffer); CryptRandomGenerate(gp.PPSeed.t.size, gp.PPSeed.t.buffer); gp.EPSeedCompatLevel = SEED_COMPAT_LEVEL_LAST; // libtpms added begin gp.SPSeedCompatLevel = SEED_COMPAT_LEVEL_LAST; gp.PPSeedCompatLevel = SEED_COMPAT_LEVEL_LAST; // libtpms added end // Initialize owner, endorsement and lockout authorization gp.ownerAuth.t.size = 0; gp.endorsementAuth.t.size = 0; gp.lockoutAuth.t.size = 0; // Initialize owner, endorsement, and lockout policy gp.ownerAlg = TPM_ALG_NULL; gp.ownerPolicy.t.size = 0; gp.endorsementAlg = TPM_ALG_NULL; gp.endorsementPolicy.t.size = 0; gp.lockoutAlg = TPM_ALG_NULL; gp.lockoutPolicy.t.size = 0; // Initialize ehProof, shProof and phProof gp.phProof.t.size = sizeof(gp.phProof.t.buffer); gp.shProof.t.size = sizeof(gp.shProof.t.buffer); gp.ehProof.t.size = sizeof(gp.ehProof.t.buffer); CryptRandomGenerate(gp.phProof.t.size, gp.phProof.t.buffer); CryptRandomGenerate(gp.shProof.t.size, gp.shProof.t.buffer); CryptRandomGenerate(gp.ehProof.t.size, gp.ehProof.t.buffer); // Write hierarchy data to NV NV_SYNC_PERSISTENT(disableClear); NV_SYNC_PERSISTENT(EPSeed); NV_SYNC_PERSISTENT(SPSeed); NV_SYNC_PERSISTENT(PPSeed); NV_SYNC_PERSISTENT(EPSeedCompatLevel); // libtpms added begin NV_SYNC_PERSISTENT(SPSeedCompatLevel); NV_SYNC_PERSISTENT(PPSeedCompatLevel); // libtpms added end NV_SYNC_PERSISTENT(ownerAuth); NV_SYNC_PERSISTENT(endorsementAuth); NV_SYNC_PERSISTENT(lockoutAuth); NV_SYNC_PERSISTENT(ownerAlg); NV_SYNC_PERSISTENT(ownerPolicy); NV_SYNC_PERSISTENT(endorsementAlg); NV_SYNC_PERSISTENT(endorsementPolicy); NV_SYNC_PERSISTENT(lockoutAlg); NV_SYNC_PERSISTENT(lockoutPolicy); NV_SYNC_PERSISTENT(phProof); NV_SYNC_PERSISTENT(shProof); NV_SYNC_PERSISTENT(ehProof); return; } /* 8.3.3.2 HierarchyStartup() */ /* This function is called at TPM2_Startup() to initialize the hierarchy related values. */ BOOL HierarchyStartup( STARTUP_TYPE type // IN: start up type ) { // phEnable is SET on any startup g_phEnable = TRUE; // Reset platformAuth, platformPolicy; enable SH and EH at TPM_RESET and // TPM_RESTART if(type != SU_RESUME) { gc.platformAuth.t.size = 0; gc.platformPolicy.t.size = 0; gc.platformAlg = TPM_ALG_NULL; // enable the storage and endorsement hierarchies and the platformNV gc.shEnable = gc.ehEnable = gc.phEnableNV = TRUE; } // nullProof and nullSeed are updated at every TPM_RESET if((type != SU_RESTART) && (type != SU_RESUME)) { gr.nullProof.t.size = sizeof(gr.nullProof.t.buffer); CryptRandomGenerate(gr.nullProof.t.size, gr.nullProof.t.buffer); gr.nullSeed.t.size = sizeof(gr.nullSeed.t.buffer); CryptRandomGenerate(gr.nullSeed.t.size, gr.nullSeed.t.buffer); gr.nullSeedCompatLevel = SEED_COMPAT_LEVEL_LAST; // libtpms added } return TRUE; } /* 8.3.3.3 HierarchyGetProof() */ /* This function finds the proof value associated with a hierarchy.It returns a pointer to the proof value. */ TPM2B_PROOF * HierarchyGetProof( TPMI_RH_HIERARCHY hierarchy // IN: hierarchy constant ) { TPM2B_PROOF *proof = NULL; switch(hierarchy) { case TPM_RH_PLATFORM: // phProof for TPM_RH_PLATFORM proof = &gp.phProof; break; case TPM_RH_ENDORSEMENT: // ehProof for TPM_RH_ENDORSEMENT proof = &gp.ehProof; break; case TPM_RH_OWNER: // shProof for TPM_RH_OWNER proof = &gp.shProof; break; default: // nullProof for TPM_RH_NULL or anything else proof = &gr.nullProof; break; } return proof; } /* 8.3.3.4 HierarchyGetPrimarySeed() */ /* This function returns the primary seed of a hierarchy. */ TPM2B_SEED * HierarchyGetPrimarySeed( TPMI_RH_HIERARCHY hierarchy // IN: hierarchy ) { TPM2B_SEED *seed = NULL; switch(hierarchy) { case TPM_RH_PLATFORM: seed = &gp.PPSeed; break; case TPM_RH_OWNER: seed = &gp.SPSeed; break; case TPM_RH_ENDORSEMENT: seed = &gp.EPSeed; break; default: seed = &gr.nullSeed; break; } return seed; } // libtpms added begin SEED_COMPAT_LEVEL HierarchyGetPrimarySeedCompatLevel( TPMI_RH_HIERARCHY hierarchy // IN: hierarchy ) { switch(hierarchy) { case TPM_RH_PLATFORM: return gp.PPSeedCompatLevel; break; case TPM_RH_OWNER: return gp.SPSeedCompatLevel; break; case TPM_RH_ENDORSEMENT: return gp.EPSeedCompatLevel; break; case TPM_RH_NULL: return gr.nullSeedCompatLevel; default: FAIL(FATAL_ERROR_INTERNAL); break; } } // libtpms added end /* 8.3.3.5 HierarchyIsEnabled() */ /* This function checks to see if a hierarchy is enabled. */ /* NOTE: The TPM_RH_NULL hierarchy is always enabled. */ /* Return Values Meaning */ /* TRUE hierarchy is enabled */ /* FALSE hierarchy is disabled */ BOOL HierarchyIsEnabled( TPMI_RH_HIERARCHY hierarchy // IN: hierarchy ) { BOOL enabled = FALSE; switch(hierarchy) { case TPM_RH_PLATFORM: enabled = g_phEnable; break; case TPM_RH_OWNER: enabled = gc.shEnable; break; case TPM_RH_ENDORSEMENT: enabled = gc.ehEnable; break; case TPM_RH_NULL: enabled = TRUE; break; default: enabled = FALSE; break; } return enabled; } libtpms-0.9.3/src/tpm2/HierarchyChangeAuth_fp.h000066400000000000000000000073701421143571500213640ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: HierarchyChangeAuth_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef HIERARCHYCHANGEAUTH_FP_H #define HIERARCHYCHANGEAUTH_FP_H typedef struct { TPMI_RH_HIERARCHY_AUTH authHandle; TPM2B_AUTH newAuth; } HierarchyChangeAuth_In; #define RC_HierarchyChangeAuth_authHandle (TPM_RC_H + TPM_RC_1) #define RC_HierarchyChangeAuth_newAuth (TPM_RC_P + TPM_RC_2) TPM_RC TPM2_HierarchyChangeAuth( HierarchyChangeAuth_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/HierarchyCommands.c000066400000000000000000000500571421143571500204240ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Hierarchy Commands */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: HierarchyCommands.c 1519 2019-11-15 20:43:51Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ #include "Tpm.h" #include "CreatePrimary_fp.h" #if CC_CreatePrimary // Conditional expansion of this file TPM_RC TPM2_CreatePrimary( CreatePrimary_In *in, // IN: input parameter list CreatePrimary_Out *out // OUT: output parameter list ) { TPM_RC result = TPM_RC_SUCCESS; TPMT_PUBLIC *publicArea; DRBG_STATE rand; OBJECT *newObject; TPM2B_NAME name; // Input Validation // Will need a place to put the result newObject = FindEmptyObjectSlot(&out->objectHandle); if(newObject == NULL) return TPM_RC_OBJECT_MEMORY; // Get the address of the public area in the new object // (this is just to save typing) publicArea = &newObject->publicArea; *publicArea = in->inPublic.publicArea; // Check attributes in input public area. CreateChecks() checks the things that // are unique to creation and then validates the attributes and values that are // common to create and load. result = CreateChecks(NULL, publicArea, in->inSensitive.sensitive.data.t.size); if(result != TPM_RC_SUCCESS) return RcSafeAddToResult(result, RC_CreatePrimary_inPublic); // Validate the sensitive area values if(!AdjustAuthSize(&in->inSensitive.sensitive.userAuth, publicArea->nameAlg)) return TPM_RCS_SIZE + RC_CreatePrimary_inSensitive; // Command output // Compute the name using out->name as a scratch area (this is not the value // that ultimately will be returned, then instantiate the state that will be // used as a random number generator during the object creation. // The caller does not know the seed values so the actual name does not have // to be over the input, it can be over the unmarshaled structure. result = DRBG_InstantiateSeeded(&rand, &HierarchyGetPrimarySeed(in->primaryHandle)->b, PRIMARY_OBJECT_CREATION, (TPM2B *)PublicMarshalAndComputeName(publicArea, &name), &in->inSensitive.sensitive.data.b, HierarchyGetPrimarySeedCompatLevel(in->primaryHandle)); // libtpms added if (result == TPM_RC_SUCCESS) { newObject->attributes.primary = SET; if(in->primaryHandle == TPM_RH_ENDORSEMENT) newObject->attributes.epsHierarchy = SET; // Create the primary object. result = CryptCreateObject(newObject, &in->inSensitive.sensitive, (RAND_STATE *)&rand); } if(result != TPM_RC_SUCCESS) return result; // Set the publicArea and name from the computed values out->outPublic.publicArea = newObject->publicArea; out->name = newObject->name; // Fill in creation data FillInCreationData(in->primaryHandle, publicArea->nameAlg, &in->creationPCR, &in->outsideInfo, &out->creationData, &out->creationHash); // Compute creation ticket TicketComputeCreation(EntityGetHierarchy(in->primaryHandle), &out->name, &out->creationHash, &out->creationTicket); // Set the remaining attributes for a loaded object ObjectSetLoadedAttributes(newObject, in->primaryHandle, HierarchyGetPrimarySeedCompatLevel(in->primaryHandle)); // libtpms added return result; } #endif // CC_CreatePrimary #include "Tpm.h" #include "HierarchyControl_fp.h" #if CC_HierarchyControl // Conditional expansion of this file TPM_RC TPM2_HierarchyControl( HierarchyControl_In *in // IN: input parameter list ) { BOOL select = (in->state == YES); BOOL *selected = NULL; // Input Validation switch(in->enable) { // Platform hierarchy has to be disabled by PlatformAuth // If the platform hierarchy has already been disabled, only a reboot // can enable it again case TPM_RH_PLATFORM: case TPM_RH_PLATFORM_NV: if(in->authHandle != TPM_RH_PLATFORM) return TPM_RC_AUTH_TYPE; break; // ShEnable may be disabled if PlatformAuth/PlatformPolicy or // OwnerAuth/OwnerPolicy is provided. If ShEnable is disabled, then it // may only be enabled if PlatformAuth/PlatformPolicy is provided. case TPM_RH_OWNER: if(in->authHandle != TPM_RH_PLATFORM && in->authHandle != TPM_RH_OWNER) return TPM_RC_AUTH_TYPE; if(gc.shEnable == FALSE && in->state == YES && in->authHandle != TPM_RH_PLATFORM) return TPM_RC_AUTH_TYPE; break; // EhEnable may be disabled if either PlatformAuth/PlatformPolicy or // EndosementAuth/EndorsementPolicy is provided. If EhEnable is disabled, // then it may only be enabled if PlatformAuth/PlatformPolicy is // provided. case TPM_RH_ENDORSEMENT: if(in->authHandle != TPM_RH_PLATFORM && in->authHandle != TPM_RH_ENDORSEMENT) return TPM_RC_AUTH_TYPE; if(gc.ehEnable == FALSE && in->state == YES && in->authHandle != TPM_RH_PLATFORM) return TPM_RC_AUTH_TYPE; break; default: FAIL(FATAL_ERROR_INTERNAL); break; } // Internal Data Update // Enable or disable the selected hierarchy // Note: the authorization processing for this command may keep these // command actions from being executed. For example, if phEnable is // CLEAR, then platformAuth cannot be used for authorization. This // means that would not be possible to use platformAuth to change the // state of phEnable from CLEAR to SET. // If it is decided that platformPolicy can still be used when phEnable // is CLEAR, then this code could SET phEnable when proper platform // policy is provided. switch(in->enable) { case TPM_RH_OWNER: selected = &gc.shEnable; break; case TPM_RH_ENDORSEMENT: selected = &gc.ehEnable; break; case TPM_RH_PLATFORM: selected = &g_phEnable; break; case TPM_RH_PLATFORM_NV: selected = &gc.phEnableNV; break; default: FAIL(FATAL_ERROR_INTERNAL); break; } if(selected != NULL && *selected != select) { // Before changing the internal state, make sure that NV is available. // Only need to update NV if changing the orderly state RETURN_IF_ORDERLY; // state is changing and NV is available so modify *selected = select; // If a hierarchy was just disabled, flush it if(select == CLEAR && in->enable != TPM_RH_PLATFORM_NV) // Flush hierarchy ObjectFlushHierarchy(in->enable); // orderly state should be cleared because of the update to state clear data // This gets processed in ExecuteCommand() on the way out. g_clearOrderly = TRUE; } return TPM_RC_SUCCESS; } #endif // CC_HierarchyControl #include "Tpm.h" #include "SetPrimaryPolicy_fp.h" #if CC_SetPrimaryPolicy // Conditional expansion of this file TPM_RC TPM2_SetPrimaryPolicy( SetPrimaryPolicy_In *in // IN: input parameter list ) { // Input Validation // Check the authPolicy consistent with hash algorithm. If the policy size is // zero, then the algorithm is required to be TPM_ALG_NULL if(in->authPolicy.t.size != CryptHashGetDigestSize(in->hashAlg)) return TPM_RCS_SIZE + RC_SetPrimaryPolicy_authPolicy; // The command need NV update for OWNER and ENDORSEMENT hierarchy, and // might need orderlyState update for PLATFORM hierarchy. // Check if NV is available. A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE // error may be returned at this point RETURN_IF_NV_IS_NOT_AVAILABLE; // Internal Data Update // Set hierarchy policy switch(in->authHandle) { case TPM_RH_OWNER: gp.ownerAlg = in->hashAlg; gp.ownerPolicy = in->authPolicy; NV_SYNC_PERSISTENT(ownerAlg); NV_SYNC_PERSISTENT(ownerPolicy); break; case TPM_RH_ENDORSEMENT: gp.endorsementAlg = in->hashAlg; gp.endorsementPolicy = in->authPolicy; NV_SYNC_PERSISTENT(endorsementAlg); NV_SYNC_PERSISTENT(endorsementPolicy); break; case TPM_RH_PLATFORM: gc.platformAlg = in->hashAlg; gc.platformPolicy = in->authPolicy; // need to update orderly state g_clearOrderly = TRUE; break; case TPM_RH_LOCKOUT: gp.lockoutAlg = in->hashAlg; gp.lockoutPolicy = in->authPolicy; NV_SYNC_PERSISTENT(lockoutAlg); NV_SYNC_PERSISTENT(lockoutPolicy); break; #define SET_ACT_POLICY(N) \ case TPM_RH_ACT_##N: \ go.ACT_##N.hashAlg = in->hashAlg; \ go.ACT_##N.authPolicy = in->authPolicy; \ g_clearOrderly = TRUE; \ break; FOR_EACH_ACT(SET_ACT_POLICY) default: FAIL(FATAL_ERROR_INTERNAL); break; } return TPM_RC_SUCCESS; } #endif // CC_SetPrimaryPolicy #include "Tpm.h" #include "ChangePPS_fp.h" #if CC_ChangePPS // Conditional expansion of this file TPM_RC TPM2_ChangePPS( ChangePPS_In *in // IN: input parameter list ) { UINT32 i; // Check if NV is available. A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE // error may be returned at this point RETURN_IF_NV_IS_NOT_AVAILABLE; // Input parameter is not reference in command action NOT_REFERENCED(in); // Internal Data Update // Reset platform hierarchy seed from RNG CryptRandomGenerate(sizeof(gp.PPSeed.t.buffer), gp.PPSeed.t.buffer); gp.PPSeedCompatLevel = SEED_COMPAT_LEVEL_LAST; // libtpms added // Create a new phProof value from RNG to prevent the saved platform // hierarchy contexts being loaded CryptRandomGenerate(sizeof(gp.phProof.t.buffer), gp.phProof.t.buffer); // Set platform authPolicy to null gc.platformAlg = TPM_ALG_NULL; gc.platformPolicy.t.size = 0; // Flush loaded object in platform hierarchy ObjectFlushHierarchy(TPM_RH_PLATFORM); // Flush platform evict object and index in NV NvFlushHierarchy(TPM_RH_PLATFORM); // Save hierarchy changes to NV NV_SYNC_PERSISTENT(PPSeed); NV_SYNC_PERSISTENT(PPSeedCompatLevel); // libtpms added NV_SYNC_PERSISTENT(phProof); // Re-initialize PCR policies #if defined NUM_POLICY_PCR_GROUP && NUM_POLICY_PCR_GROUP > 0 for(i = 0; i < NUM_POLICY_PCR_GROUP; i++) { gp.pcrPolicies.hashAlg[i] = TPM_ALG_NULL; gp.pcrPolicies.policy[i].t.size = 0; } NV_SYNC_PERSISTENT(pcrPolicies); #endif // orderly state should be cleared because of the update to state clear data g_clearOrderly = TRUE; return TPM_RC_SUCCESS; } #endif // CC_ChangePPS #include "Tpm.h" #include "ChangeEPS_fp.h" #if CC_ChangeEPS // Conditional expansion of this file TPM_RC TPM2_ChangeEPS( ChangeEPS_In *in // IN: input parameter list ) { // The command needs NV update. Check if NV is available. // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at // this point RETURN_IF_NV_IS_NOT_AVAILABLE; // Input parameter is not reference in command action NOT_REFERENCED(in); // Internal Data Update // Reset endorsement hierarchy seed from RNG CryptRandomGenerate(sizeof(gp.EPSeed.t.buffer), gp.EPSeed.t.buffer); gp.EPSeedCompatLevel = SEED_COMPAT_LEVEL_LAST; // libtpms added // Create new ehProof value from RNG CryptRandomGenerate(sizeof(gp.ehProof.t.buffer), gp.ehProof.t.buffer); // Enable endorsement hierarchy gc.ehEnable = TRUE; // set authValue buffer to zeros MemorySet(gp.endorsementAuth.t.buffer, 0, gp.endorsementAuth.t.size); // Set endorsement authValue to null gp.endorsementAuth.t.size = 0; // Set endorsement authPolicy to null gp.endorsementAlg = TPM_ALG_NULL; gp.endorsementPolicy.t.size = 0; // Flush loaded object in endorsement hierarchy ObjectFlushHierarchy(TPM_RH_ENDORSEMENT); // Flush evict object of endorsement hierarchy stored in NV NvFlushHierarchy(TPM_RH_ENDORSEMENT); // Save hierarchy changes to NV NV_SYNC_PERSISTENT(EPSeed); NV_SYNC_PERSISTENT(EPSeedCompatLevel); // libtpms added NV_SYNC_PERSISTENT(ehProof); NV_SYNC_PERSISTENT(endorsementAuth); NV_SYNC_PERSISTENT(endorsementAlg); NV_SYNC_PERSISTENT(endorsementPolicy); // orderly state should be cleared because of the update to state clear data g_clearOrderly = TRUE; return TPM_RC_SUCCESS; } #endif // CC_ChangeEPS #include "Tpm.h" #include "Clear_fp.h" #if CC_Clear // Conditional expansion of this file TPM_RC TPM2_Clear( Clear_In *in // IN: input parameter list ) { // Input parameter is not reference in command action NOT_REFERENCED(in); // The command needs NV update. Check if NV is available. // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at // this point RETURN_IF_NV_IS_NOT_AVAILABLE; // Input Validation // If Clear command is disabled, return an error if(gp.disableClear) return TPM_RC_DISABLED; // Internal Data Update // Reset storage hierarchy seed from RNG CryptRandomGenerate(sizeof(gp.SPSeed.t.buffer), gp.SPSeed.t.buffer); gp.SPSeedCompatLevel = SEED_COMPAT_LEVEL_LAST; // libtpms added // Create new shProof and ehProof value from RNG CryptRandomGenerate(sizeof(gp.shProof.t.buffer), gp.shProof.t.buffer); CryptRandomGenerate(sizeof(gp.ehProof.t.buffer), gp.ehProof.t.buffer); // Enable storage and endorsement hierarchy gc.shEnable = gc.ehEnable = TRUE; // set the authValue buffers to zero MemorySet(&gp.ownerAuth, 0, sizeof(gp.ownerAuth)); MemorySet(&gp.endorsementAuth, 0, sizeof(gp.endorsementAuth)); MemorySet(&gp.lockoutAuth, 0, sizeof(gp.lockoutAuth)); // Set storage, endorsement, and lockout authPolicy to null gp.ownerAlg = gp.endorsementAlg = gp.lockoutAlg = TPM_ALG_NULL; MemorySet(&gp.ownerPolicy, 0, sizeof(gp.ownerPolicy)); MemorySet(&gp.endorsementPolicy, 0, sizeof(gp.endorsementPolicy)); MemorySet(&gp.lockoutPolicy, 0, sizeof(gp.lockoutPolicy)); // Flush loaded object in storage and endorsement hierarchy ObjectFlushHierarchy(TPM_RH_OWNER); ObjectFlushHierarchy(TPM_RH_ENDORSEMENT); // Flush owner and endorsement object and owner index in NV NvFlushHierarchy(TPM_RH_OWNER); NvFlushHierarchy(TPM_RH_ENDORSEMENT); // Initialize dictionary attack parameters DAPreInstall_Init(); // Reset clock go.clock = 0; go.clockSafe = YES; NvWrite(NV_ORDERLY_DATA, sizeof(ORDERLY_DATA), &go); // Reset counters gp.resetCount = gr.restartCount = gr.clearCount = 0; gp.auditCounter = 0; // Save persistent data changes to NV // Note: since there are so many changes to the persistent data structure, the // entire PERSISTENT_DATA structure is written as a unit NvWrite(NV_PERSISTENT_DATA, sizeof(PERSISTENT_DATA), &gp); // Reset the PCR authValues (this does not change the PCRs) PCR_ClearAuth(); // Bump the PCR counter PCRChanged(0); // orderly state should be cleared because of the update to state clear data g_clearOrderly = TRUE; return TPM_RC_SUCCESS; } #endif // CC_Clear #include "Tpm.h" #include "ClearControl_fp.h" #if CC_ClearControl // Conditional expansion of this file TPM_RC TPM2_ClearControl( ClearControl_In *in // IN: input parameter list ) { // The command needs NV update. RETURN_IF_NV_IS_NOT_AVAILABLE; // Input Validation // LockoutAuth may be used to set disableLockoutClear to TRUE but not to FALSE if(in->auth == TPM_RH_LOCKOUT && in->disable == NO) return TPM_RC_AUTH_FAIL; // Internal Data Update if(in->disable == YES) gp.disableClear = TRUE; else gp.disableClear = FALSE; // Record the change to NV NV_SYNC_PERSISTENT(disableClear); return TPM_RC_SUCCESS; } #endif // CC_ClearControl #include "Tpm.h" #include "HierarchyChangeAuth_fp.h" #if CC_HierarchyChangeAuth // Conditional expansion of this file #include "Object_spt_fp.h" TPM_RC TPM2_HierarchyChangeAuth( HierarchyChangeAuth_In *in // IN: input parameter list ) { // The command needs NV update. RETURN_IF_NV_IS_NOT_AVAILABLE; // Make sure that the authorization value is a reasonable size (not larger than // the size of the digest produced by the integrity hash. The integrity // hash is assumed to produce the longest digest of any hash implemented // on the TPM. This will also remove trailing zeros from the authValue. if(MemoryRemoveTrailingZeros(&in->newAuth) > CONTEXT_INTEGRITY_HASH_SIZE) return TPM_RCS_SIZE + RC_HierarchyChangeAuth_newAuth; // Set hierarchy authValue switch(in->authHandle) { case TPM_RH_OWNER: gp.ownerAuth = in->newAuth; NV_SYNC_PERSISTENT(ownerAuth); break; case TPM_RH_ENDORSEMENT: gp.endorsementAuth = in->newAuth; NV_SYNC_PERSISTENT(endorsementAuth); break; case TPM_RH_PLATFORM: gc.platformAuth = in->newAuth; // orderly state should be cleared g_clearOrderly = TRUE; break; case TPM_RH_LOCKOUT: gp.lockoutAuth = in->newAuth; NV_SYNC_PERSISTENT(lockoutAuth); break; default: FAIL(FATAL_ERROR_INTERNAL); break; } return TPM_RC_SUCCESS; } #endif // CC_HierarchyChangeAuth libtpms-0.9.3/src/tpm2/HierarchyControl_fp.h000066400000000000000000000074661421143571500210030ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: HierarchyControl_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef HIERARCHYCONTROL_FP_H #define HIERARCHYCONTROL_FP_H typedef struct { TPMI_RH_HIERARCHY authHandle; TPMI_RH_ENABLES enable; TPMI_YES_NO state; } HierarchyControl_In; #define RC_HierarchyControl_authHandle (TPM_RC_H + TPM_RC_1) #define RC_HierarchyControl_enable (TPM_RC_P + TPM_RC_1) #define RC_HierarchyControl_state (TPM_RC_P + TPM_RC_2) TPM_RC TPM2_HierarchyControl( HierarchyControl_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/Hierarchy_fp.h000066400000000000000000000100001421143571500174140ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Hierarchy_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ #ifndef HIERARCHY_FP_H #define HIERARCHY_FP_H void HierarchyPreInstall_Init( void ); BOOL HierarchyStartup( STARTUP_TYPE type // IN: start up type ); TPM2B_PROOF * HierarchyGetProof( TPMI_RH_HIERARCHY hierarchy // IN: hierarchy constant ); TPM2B_SEED * HierarchyGetPrimarySeed( TPMI_RH_HIERARCHY hierarchy // IN: hierarchy ); // libtpms added begin SEED_COMPAT_LEVEL HierarchyGetPrimarySeedCompatLevel( TPMI_RH_HIERARCHY hierarchy // IN: hierarchy ); // libtpms added end BOOL HierarchyIsEnabled( TPMI_RH_HIERARCHY hierarchy // IN: hierarchy ); #endif libtpms-0.9.3/src/tpm2/Import_fp.h000066400000000000000000000101751421143571500167650ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Import_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef IMPORT_FP_H #define IMPORT_FP_H typedef struct { TPMI_DH_OBJECT parentHandle; TPM2B_DATA encryptionKey; TPM2B_PUBLIC objectPublic; TPM2B_PRIVATE duplicate; TPM2B_ENCRYPTED_SECRET inSymSeed; TPMT_SYM_DEF_OBJECT symmetricAlg; } Import_In; #define RC_Import_parentHandle (TPM_RC_H + TPM_RC_1) #define RC_Import_encryptionKey (TPM_RC_P + TPM_RC_1) #define RC_Import_objectPublic (TPM_RC_P + TPM_RC_2) #define RC_Import_duplicate (TPM_RC_P + TPM_RC_3) #define RC_Import_inSymSeed (TPM_RC_P + TPM_RC_4) #define RC_Import_symmetricAlg (TPM_RC_P + TPM_RC_5) typedef struct { TPM2B_PRIVATE outPrivate; } Import_Out; TPM_RC TPM2_Import( Import_In *in, // IN: input parameter list Import_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/IncrementalSelfTest_fp.h000066400000000000000000000074401421143571500214270ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: IncrementalSelfTest_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef INCREMENTALSELFTEST_FP_H #define INCREMENTALSELFTEST_FP_H typedef struct{ TPML_ALG toTest; } IncrementalSelfTest_In; typedef struct{ TPML_ALG toDoList; } IncrementalSelfTest_Out; #define RC_IncrementalSelfTest_toTest (TPM_RC_P + TPM_RC_1) TPM_RC TPM2_IncrementalSelfTest( IncrementalSelfTest_In *in, // IN: input parameter list IncrementalSelfTest_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/IntegrityCommands.c000066400000000000000000000372401421143571500204630ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Integrity Collection (PCR) */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: IntegrityCommands.c 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2018 */ /* */ /********************************************************************************/ #include "Tpm.h" #include "PCR_Extend_fp.h" #if CC_PCR_Extend // Conditional expansion of this file TPM_RC TPM2_PCR_Extend( PCR_Extend_In *in // IN: input parameter list ) { UINT32 i; // Input Validation // NOTE: This function assumes that the unmarshaling function for 'digests' will // have validated that all of the indicated hash algorithms are valid. If the // hash algorithms are correct, the unmarshaling code will unmarshal a digest // of the size indicated by the hash algorithm. If the overall size is not // consistent, the unmarshaling code will run out of input data or have input // data left over. In either case, it will cause an unmarshaling error and this // function will not be called. // For NULL handle, do nothing and return success if(in->pcrHandle == TPM_RH_NULL) return TPM_RC_SUCCESS; // Check if the extend operation is allowed by the current command locality if(!PCRIsExtendAllowed(in->pcrHandle)) return TPM_RC_LOCALITY; // If PCR is state saved and we need to update orderlyState, check NV // availability if(PCRIsStateSaved(in->pcrHandle)) RETURN_IF_ORDERLY; // Internal Data Update // Iterate input digest list to extend for(i = 0; i < in->digests.count; i++) { PCRExtend(in->pcrHandle, in->digests.digests[i].hashAlg, CryptHashGetDigestSize(in->digests.digests[i].hashAlg), (BYTE *)&in->digests.digests[i].digest); } return TPM_RC_SUCCESS; } #endif // CC_PCR_Extend #include "Tpm.h" #include "PCR_Event_fp.h" #if CC_PCR_Event // Conditional expansion of this file TPM_RC TPM2_PCR_Event( PCR_Event_In *in, // IN: input parameter list PCR_Event_Out *out // OUT: output parameter list ) { HASH_STATE hashState; UINT32 i; UINT16 size; // Input Validation // If a PCR extend is required if(in->pcrHandle != TPM_RH_NULL) { // If the PCR is not allow to extend, return error if(!PCRIsExtendAllowed(in->pcrHandle)) return TPM_RC_LOCALITY; // If PCR is state saved and we need to update orderlyState, check NV // availability if(PCRIsStateSaved(in->pcrHandle)) RETURN_IF_ORDERLY; } // Internal Data Update out->digests.count = HASH_COUNT; // Iterate supported PCR bank algorithms to extend for(i = 0; i < HASH_COUNT; i++) { TPM_ALG_ID hash = CryptHashGetAlgByIndex(i); out->digests.digests[i].hashAlg = hash; size = CryptHashStart(&hashState, hash); CryptDigestUpdate2B(&hashState, &in->eventData.b); CryptHashEnd(&hashState, size, (BYTE *)&out->digests.digests[i].digest); if(in->pcrHandle != TPM_RH_NULL) PCRExtend(in->pcrHandle, hash, size, (BYTE *)&out->digests.digests[i].digest); } return TPM_RC_SUCCESS; } #endif // CC_PCR_Event #include "Tpm.h" #include "PCR_Read_fp.h" #if CC_PCR_Read // Conditional expansion of this file TPM_RC TPM2_PCR_Read( PCR_Read_In *in, // IN: input parameter list PCR_Read_Out *out // OUT: output parameter list ) { // Command Output // Call PCR read function. input pcrSelectionIn parameter could be changed // to reflect the actual PCR being returned PCRRead(&in->pcrSelectionIn, &out->pcrValues, &out->pcrUpdateCounter); out->pcrSelectionOut = in->pcrSelectionIn; return TPM_RC_SUCCESS; } #endif // CC_PCR_Read #include "Tpm.h" #include "PCR_Allocate_fp.h" #if CC_PCR_Allocate // Conditional expansion of this file TPM_RC TPM2_PCR_Allocate( PCR_Allocate_In *in, // IN: input parameter list PCR_Allocate_Out *out // OUT: output parameter list ) { TPM_RC result; // The command needs NV update. Check if NV is available. // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at // this point. // Note: These codes are not listed in the return values above because it is // an implementation choice to check in this routine rather than in a common // function that is called before these actions are called. These return values // are described in the Response Code section of Part 3. RETURN_IF_NV_IS_NOT_AVAILABLE; // Command Output // Call PCR Allocation function. result = PCRAllocate(&in->pcrAllocation, &out->maxPCR, &out->sizeNeeded, &out->sizeAvailable); if(result == TPM_RC_PCR) return result; // out->allocationSuccess = (result == TPM_RC_SUCCESS); // if re-configuration succeeds, set the flag to indicate PCR configuration is // going to be changed in next boot if(out->allocationSuccess == YES) g_pcrReConfig = TRUE; return TPM_RC_SUCCESS; } #endif // CC_PCR_Allocate #include "Tpm.h" #include "PCR_SetAuthPolicy_fp.h" #if CC_PCR_SetAuthPolicy // Conditional expansion of this file TPM_RC TPM2_PCR_SetAuthPolicy( PCR_SetAuthPolicy_In *in // IN: input parameter list ) { UINT32 groupIndex; // The command needs NV update. Check if NV is available. // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at // this point RETURN_IF_NV_IS_NOT_AVAILABLE; // Input Validation: // Check the authPolicy consistent with hash algorithm if(in->authPolicy.t.size != CryptHashGetDigestSize(in->hashAlg)) return TPM_RCS_SIZE + RC_PCR_SetAuthPolicy_authPolicy; // If PCR does not belong to a policy group, return TPM_RC_VALUE if(!PCRBelongsPolicyGroup(in->pcrNum, &groupIndex)) return TPM_RCS_VALUE + RC_PCR_SetAuthPolicy_pcrNum; // Internal Data Update // Set PCR policy gp.pcrPolicies.hashAlg[groupIndex] = in->hashAlg; gp.pcrPolicies.policy[groupIndex] = in->authPolicy; // Save new policy to NV NV_SYNC_PERSISTENT(pcrPolicies); return TPM_RC_SUCCESS; } #endif // CC_PCR_SetAuthPolicy #include "Tpm.h" #include "PCR_SetAuthValue_fp.h" #if CC_PCR_SetAuthValue // Conditional expansion of this file // CC_PCR_SetAuthPolicy TPM_RC TPM2_PCR_SetAuthValue( PCR_SetAuthValue_In *in // IN: input parameter list ) { UINT32 groupIndex; // Input Validation: // If PCR does not belong to an auth group, return TPM_RC_VALUE if(!PCRBelongsAuthGroup(in->pcrHandle, &groupIndex)) return TPM_RC_VALUE; // The command may cause the orderlyState to be cleared due to the update of // state clear data. If this is the case, Check if NV is available. // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at // this point RETURN_IF_ORDERLY; // Internal Data Update // Set PCR authValue MemoryRemoveTrailingZeros(&in->auth); gc.pcrAuthValues.auth[groupIndex] = in->auth; return TPM_RC_SUCCESS; } #endif // CC_PCR_SetAuthValue #include "Tpm.h" #include "PCR_Reset_fp.h" #if CC_PCR_Reset // Conditional expansion of this file TPM_RC TPM2_PCR_Reset( PCR_Reset_In *in // IN: input parameter list ) { // Input Validation // Check if the reset operation is allowed by the current command locality if(!PCRIsResetAllowed(in->pcrHandle)) return TPM_RC_LOCALITY; // If PCR is state saved and we need to update orderlyState, check NV // availability if(PCRIsStateSaved(in->pcrHandle)) RETURN_IF_ORDERLY; // Internal Data Update // Reset selected PCR in all banks to 0 PCRSetValue(in->pcrHandle, 0); // Indicate that the PCR changed so that pcrCounter will be incremented if // necessary. PCRChanged(in->pcrHandle); return TPM_RC_SUCCESS; } #endif // CC_PCR_Reset #include "Tpm.h" /* This function is called to process a _TPM_Hash_Start() indication. */ LIB_EXPORT void _TPM_Hash_Start( void ) { TPM_RC result; TPMI_DH_OBJECT handle; // If a DRTM sequence object exists, free it up if(g_DRTMHandle != TPM_RH_UNASSIGNED) { FlushObject(g_DRTMHandle); g_DRTMHandle = TPM_RH_UNASSIGNED; } // Create an event sequence object and store the handle in global // g_DRTMHandle. A TPM_RC_OBJECT_MEMORY error may be returned at this point // The NULL value for the first parameter will cause the sequence structure to // be allocated without being set as present. This keeps the sequence from // being left behind if the sequence is terminated early. result = ObjectCreateEventSequence(NULL, &g_DRTMHandle); // If a free slot was not available, then free up a slot. if(result != TPM_RC_SUCCESS) { // An implementation does not need to have a fixed relationship between // slot numbers and handle numbers. To handle the general case, scan for // a handle that is assigned and free it for the DRTM sequence. // In the reference implementation, the relationship between handles and // slots is fixed. So, if the call to ObjectCreateEvenSequence() // failed indicating that all slots are occupied, then the first handle we // are going to check (TRANSIENT_FIRST) will be occupied. It will be freed // so that it can be assigned for use as the DRTM sequence object. for(handle = TRANSIENT_FIRST; handle < TRANSIENT_LAST; handle++) { // try to flush the first object if(IsObjectPresent(handle)) break; } // If the first call to find a slot fails but none of the slots is occupied // then there's a big problem pAssert(handle < TRANSIENT_LAST); // Free the slot FlushObject(handle); // Try to create an event sequence object again. This time, we must // succeed. result = ObjectCreateEventSequence(NULL, &g_DRTMHandle); if(result != TPM_RC_SUCCESS) FAIL(FATAL_ERROR_INTERNAL); } return; } #include "Tpm.h" /* This function is called to process a _TPM_Hash_Data() indication. */ LIB_EXPORT void _TPM_Hash_Data( uint32_t dataSize, // IN: size of data to be extend unsigned char *data // IN: data buffer ) { UINT32 i; HASH_OBJECT *hashObject; TPMI_DH_PCR pcrHandle = TPMIsStarted() ? PCR_FIRST + DRTM_PCR : PCR_FIRST + HCRTM_PCR; // If there is no DRTM sequence object, then _TPM_Hash_Start // was not called so this function returns without doing // anything. if(g_DRTMHandle == TPM_RH_UNASSIGNED) return; hashObject = (HASH_OBJECT *)HandleToObject(g_DRTMHandle); pAssert(hashObject->attributes.eventSeq); // For each of the implemented hash algorithms, update the digest with the // data provided. for(i = 0; i < HASH_COUNT; i++) { // make sure that the PCR is implemented for this algorithm if(PcrIsAllocated(pcrHandle, hashObject->state.hashState[i].hashAlg)) // Update sequence object CryptDigestUpdate(&hashObject->state.hashState[i], dataSize, data); } return; } #include "Tpm.h" /* This function is called to process a _TPM_Hash_End() indication. */ LIB_EXPORT void _TPM_Hash_End( void ) { UINT32 i; TPM2B_DIGEST digest; HASH_OBJECT *hashObject; TPMI_DH_PCR pcrHandle; // If the DRTM handle is not being used, then either _TPM_Hash_Start has not // been called, _TPM_Hash_End was previously called, or some other command // was executed and the sequence was aborted. if(g_DRTMHandle == TPM_RH_UNASSIGNED) return; // Get DRTM sequence object hashObject = (HASH_OBJECT *)HandleToObject(g_DRTMHandle); // Is this _TPM_Hash_End after Startup or before if(TPMIsStarted()) { // After // Reset the DRTM PCR PCRResetDynamics(); // Extend the DRTM_PCR. pcrHandle = PCR_FIRST + DRTM_PCR; // DRTM sequence increments restartCount gr.restartCount++; } else { pcrHandle = PCR_FIRST + HCRTM_PCR; g_DrtmPreStartup = TRUE; } // Complete hash and extend PCR, or if this is an HCRTM, complete // the hash, reset the H-CRTM register (PCR[0]) to 0...04, and then // extend the H-CRTM data for(i = 0; i < HASH_COUNT; i++) { TPMI_ALG_HASH hash = CryptHashGetAlgByIndex(i); // make sure that the PCR is implemented for this algorithm if(PcrIsAllocated(pcrHandle, hashObject->state.hashState[i].hashAlg)) { // Complete hash digest.t.size = CryptHashGetDigestSize(hash); CryptHashEnd2B(&hashObject->state.hashState[i], &digest.b); PcrDrtm(pcrHandle, hash, &digest); } } // Flush sequence object. FlushObject(g_DRTMHandle); g_DRTMHandle = TPM_RH_UNASSIGNED; return; } libtpms-0.9.3/src/tpm2/InternalRoutines.h000066400000000000000000000126701421143571500203350ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Include Headers for Internal Routines */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: InternalRoutines.h 1594 2020-03-26 22:15:48Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2020 */ /* */ /********************************************************************************/ #ifndef INTERNALROUTINES_H #define INTERNALROUTINES_H #if !defined _LIB_SUPPORT_H_ && !defined _TPM_H_ #error "Should not be called" #endif /* DRTM functions */ #include "_TPM_Hash_Start_fp.h" #include "_TPM_Hash_Data_fp.h" #include "_TPM_Hash_End_fp.h" /* Internal subsystem functions */ #include "Object_fp.h" #include "Context_spt_fp.h" #include "Object_spt_fp.h" #include "Entity_fp.h" #include "Session_fp.h" #include "Hierarchy_fp.h" #include "NVReserved_fp.h" #include "NVDynamic_fp.h" #include "NV_spt_fp.h" #include "ACT_spt_fp.h" #include "PCR_fp.h" #include "DA_fp.h" #include "TpmFail_fp.h" #include "SessionProcess_fp.h" /* Internal support functions */ #include "CommandCodeAttributes_fp.h" #include "Marshal_fp.h" #include "Unmarshal_fp.h" /* kgold */ #include "Time_fp.h" #include "Locality_fp.h" #include "PP_fp.h" #include "CommandAudit_fp.h" #include "Manufacture_fp.h" #include "Handle_fp.h" #include "Power_fp.h" #include "Response_fp.h" #include "CommandDispatcher_fp.h" #if CC_AC_Send # include "AC_spt_fp.h" #endif // CC_AC_Send /* Miscellaneous */ #include "Bits_fp.h" #include "AlgorithmCap_fp.h" #include "PropertyCap_fp.h" #include "IoBuffers_fp.h" #include "Memory_fp.h" #include "ResponseCodeProcessing_fp.h" /* Internal cryptographic functions */ #include "BnConvert_fp.h" #include "BnMath_fp.h" #include "BnMemory_fp.h" #include "Ticket_fp.h" #include "CryptUtil_fp.h" #include "CryptHash_fp.h" #include "CryptSym_fp.h" #include "CryptDes_fp.h" #include "CryptPrime_fp.h" #include "CryptRand_fp.h" #include "CryptSelfTest_fp.h" #include "MathOnByteBuffers_fp.h" #include "CryptSym_fp.h" #include "AlgorithmTests_fp.h" #if ALG_RSA #include "CryptRsa_fp.h" #include "CryptPrimeSieve_fp.h" #endif #if ALG_ECC #include "CryptEccMain_fp.h" #include "CryptEccSignature_fp.h" #include "CryptEccKeyExchange_fp.h" #include "CryptEccCrypt_fp.h" #endif #if CC_MAC || CC_MAC_Start # include "CryptSmac_fp.h" # if ALG_CMAC # include "CryptCmac_fp.h" # endif #endif /* Support library */ #include "SupportLibraryFunctionPrototypes_fp.h" /* Linkage to platform functions */ #include "Platform_fp.h" #endif libtpms-0.9.3/src/tpm2/IoBuffers.c000066400000000000000000000143301421143571500167020ustar00rootroot00000000000000/********************************************************************************/ /* */ /* I/O Buffers */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: IoBuffers.c 1311 2018-08-23 21:39:29Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2018 */ /* */ /********************************************************************************/ /* 9.7 IoBuffers.c */ /* 9.7.1 Includes and Data Definitions */ /* This definition allows this module to see the values that are private to this module but kept in Global.c for ease of state migration. */ #define IO_BUFFER_C #include "Tpm.h" #include "IoBuffers_fp.h" /* 9.7.2 Buffers and Functions */ /* These buffers are set aside to hold command and response values. In this implementation, it is not guaranteed that the code will stop accessing the s_actionInputBuffer before starting to put values in the s_actionOutputBuffer so different buffers are required. */ /* 9.7.2.1 MemoryIoBufferAllocationReset() */ /* This function is used to reset the allocation of buffers. */ void MemoryIoBufferAllocationReset( void ) { s_actionIoAllocation = 0; } /* 9.7.2.2 MemoryIoBufferZero() */ /* Function zeros the action I/O buffer at the end of a command. Calling this is not mandatory for proper functionality. */ void MemoryIoBufferZero( void ) { memset(s_actionIoBuffer, 0, s_actionIoAllocation); } /* 9.7.2.3 MemoryGetInBuffer() */ /* This function returns the address of the buffer into which the command parameters will be unmarshaled in preparation for calling the command actions. */ BYTE * MemoryGetInBuffer( UINT32 size // Size, in bytes, required for the input // unmarshaling ) { pAssert(size <= sizeof(s_actionIoBuffer)); // In this implementation, a static buffer is set aside for the command action // buffers. The buffer is shared between input and output. This is because // there is no need to allocate for the worst case input and worst case output // at the same time. // Round size up #define UoM (sizeof(s_actionIoBuffer[0])) size = (size + (UoM - 1)) & (UINT32_MAX - (UoM - 1)); memset(s_actionIoBuffer, 0, size); s_actionIoAllocation = size; return (BYTE *)&s_actionIoBuffer[0]; } /* 9.7.2.4 MemoryGetOutBuffer() */ /* This function returns the address of the buffer into which the command action code places its output values. */ BYTE * MemoryGetOutBuffer( UINT32 size // required size of the buffer ) { BYTE *retVal = (BYTE *)(&s_actionIoBuffer[s_actionIoAllocation / UoM]); pAssert((size + s_actionIoAllocation) < (sizeof(s_actionIoBuffer))); // In this implementation, a static buffer is set aside for the command action // output buffer. memset(retVal, 0, size); s_actionIoAllocation += size; return retVal; } /* 9.7.2.5 IsLabelProperlyFormatted() */ /* This function checks that a label is a null-terminated string. */ /* NOTE: this function is here because there was no better place for it. */ /* Return Value Meaning */ /* FALSE string is not null terminated */ /* TRUE string is null terminated */ BOOL IsLabelProperlyFormatted( TPM2B *x ) { return (((x)->size == 0) || ((x)->buffer[(x)->size - 1] == 0)); } libtpms-0.9.3/src/tpm2/IoBuffers_fp.h000066400000000000000000000074171421143571500174040ustar00rootroot00000000000000/********************************************************************************/ /* */ /* I/O Buffers */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: IoBuffers_fp.h 1259 2018-07-10 19:11:09Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2018 */ /* */ /********************************************************************************/ #ifndef IOBUFFERS_FP_H #define IOBUFFERS_FP_H void MemoryIoBufferAllocationReset( void ); void MemoryIoBufferZero( void ); BYTE * MemoryGetInBuffer( UINT32 size // Size, in bytes, required for the input // unmarshaling ); BYTE * MemoryGetOutBuffer( UINT32 size // required size of the buffer ); BOOL IsLabelProperlyFormatted( TPM2B *x ); #endif libtpms-0.9.3/src/tpm2/KdfTestData.h000066400000000000000000000120201421143571500171530ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Hash Test Vectors */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: KdfTestData.h 1311 2018-08-23 21:39:29Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2018 */ /* */ /********************************************************************************/ // // Hash Test Vectors // #define TEST_KDF_KEY_SIZE 20 TPM2B_TYPE(KDF_TEST_KEY, TEST_KDF_KEY_SIZE); TPM2B_KDF_TEST_KEY c_kdfTestKeyIn = {{TEST_KDF_KEY_SIZE, { 0x27, 0x1F, 0xA0, 0x8B, 0xBD, 0xC5, 0x06, 0x0E, 0xC3, 0xDF, 0xA9, 0x28, 0xFF, 0x9B, 0x73, 0x12, 0x3A, 0x12, 0xDA, 0x0C }}}; TPM2B_TYPE(KDF_TEST_LABEL, 17); TPM2B_KDF_TEST_LABEL c_kdfTestLabel = {{17, { 0x4B, 0x44, 0x46, 0x53, 0x45, 0x4C, 0x46, 0x54, 0x45, 0x53, 0x54, 0x4C, 0x41, 0x42, 0x45, 0x4C, 0x00 }}}; TPM2B_TYPE(KDF_TEST_CONTEXT, 8); TPM2B_KDF_TEST_CONTEXT c_kdfTestContextU = {{8, { 0xCE, 0x24, 0x4F, 0x39, 0x5D, 0xCA, 0x73, 0x91 }}}; TPM2B_KDF_TEST_CONTEXT c_kdfTestContextV = {{8, { 0xDA, 0x50, 0x40, 0x31, 0xDD, 0xF1, 0x2E, 0x83 }}}; #if ALG_SHA512 == ALG_YES TPM2B_KDF_TEST_KEY c_kdfTestKeyOut = {{20, { 0x8b, 0xe2, 0xc1, 0xb8, 0x5b, 0x78, 0x56, 0x9b, 0x9f, 0xa7, 0x59, 0xf5, 0x85, 0x7c, 0x56, 0xd6, 0x84, 0x81, 0x0f, 0xd3 }}}; #define KDF_TEST_ALG TPM_ALG_SHA512 #elif ALG_SHA384 == ALG_YES TPM2B_KDF_TEST_KEY c_kdfTestKeyOut = {{20, { 0x1d, 0xce, 0x70, 0xc9, 0x11, 0x3e, 0xb2, 0xdb, 0xa4, 0x7b, 0xd9, 0xcf, 0xc7, 0x2b, 0xf4, 0x6f, 0x45, 0xb0, 0x93, 0x12 }}}; #define KDF_TEST_ALG TPM_ALG_SHA384 #elif ALG_SHA256 == ALG_YES TPM2B_KDF_TEST_KEY c_kdfTestKeyOut = {{20, { 0xbb, 0x02, 0x59, 0xe1, 0xc8, 0xba, 0x60, 0x7e, 0x6a, 0x2c, 0xd7, 0x04, 0xb6, 0x9a, 0x90, 0x2e, 0x9a, 0xde, 0x84, 0xc4 }}}; #define KDF_TEST_ALG TPM_ALG_SHA256 #elif ALG_SHA1 == ALG_YES TPM2B_KDF_TEST_KEY c_kdfTestKeyOut = {{20, { 0x55, 0xb5, 0xa7, 0x18, 0x4a, 0xa0, 0x74, 0x23, 0xc4, 0x7d, 0xae, 0x76, 0x6c, 0x26, 0xa2, 0x37, 0x7d, 0x7c, 0xf8, 0x51 }}}; #define KDF_TEST_ALG TPM_ALG_SHA1 #endif libtpms-0.9.3/src/tpm2/LibtpmsCallbacks.c000066400000000000000000000121501421143571500202260ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Libtpms Callbacks */ /* Written by Stefan Berger */ /* IBM Thomas J. Watson Research Center */ /* */ /* (c) Copyright IBM Corporation 2018. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include #include #include "Platform.h" #include "LibtpmsCallbacks.h" #include "NVMarshal.h" #define TPM_HAVE_TPM2_DECLARATIONS #include "tpm_library_intern.h" #include "tpm_error.h" #include "tpm_nvfilename.h" int libtpms_plat__NVEnable(void) { unsigned char *data = NULL; uint32_t length = 0; struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks(); TPM_RC rc; bool is_empty_state; /* try to get state blob set via TPMLIB_SetState() */ GetCachedState(TPMLIB_STATE_PERMANENT, &data, &length, &is_empty_state); if (is_empty_state) { memset(s_NV, 0, NV_MEMORY_SIZE); return 0; } if (data == NULL && cbs->tpm_nvram_loaddata) { uint32_t tpm_number = 0; const char *name = TPM_PERMANENT_ALL_NAME; TPM_RESULT ret; ret = cbs->tpm_nvram_loaddata(&data, &length, tpm_number, name); switch (ret) { case TPM_RETRY: if (!cbs->tpm_nvram_storedata) { return -1; } memset(s_NV, 0, NV_MEMORY_SIZE); return 0; case TPM_SUCCESS: /* got the data -- unmarshal them... */ break; case TPM_FAIL: default: return -1; } } if (data) { unsigned char *buffer = data; INT32 size = length; rc = PERSISTENT_ALL_Unmarshal(&buffer, &size); free(data); if (rc != TPM_RC_SUCCESS) return -1; return 0; } return LIBTPMS_CALLBACK_FALLTHROUGH; /* -2 */ } int libtpms_plat__NVDisable( void ) { struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks(); if (cbs->tpm_nvram_loaddata) return 0; return LIBTPMS_CALLBACK_FALLTHROUGH; /* -2 */ } int libtpms_plat__IsNvAvailable( void ) { struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks(); if (cbs->tpm_nvram_loaddata && cbs->tpm_nvram_storedata) { return 1; } return LIBTPMS_CALLBACK_FALLTHROUGH; /* -2 */ } int libtpms_plat__NvCommit( void ) { struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks(); if (cbs->tpm_nvram_storedata) { uint32_t tpm_number = 0; const char *name = TPM_PERMANENT_ALL_NAME; TPM_RESULT ret; BYTE *buf; uint32_t buflen; ret = TPM2_PersistentAllStore(&buf, &buflen); if (ret != TPM_SUCCESS) return ret; ret = cbs->tpm_nvram_storedata(buf, buflen, tpm_number, name); free(buf); if (ret == TPM_SUCCESS) return 0; return -1; } return LIBTPMS_CALLBACK_FALLTHROUGH; /* -2 */ } int libtpms_plat__PhysicalPresenceAsserted( BOOL *pp ) { struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks(); if (cbs->tpm_io_getphysicalpresence) { uint32_t tpm_number = 0; TPM_RESULT res; unsigned char mypp; res = cbs->tpm_io_getphysicalpresence(&mypp, tpm_number); if (res == TPM_SUCCESS) { *pp = mypp; return 0; } } return LIBTPMS_CALLBACK_FALLTHROUGH; } libtpms-0.9.3/src/tpm2/LibtpmsCallbacks.h000066400000000000000000000045351421143571500202430ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Libtpms Callbacks */ /* Written by Stefan Berger */ /* IBM Thomas J. Watson Research Center */ /* */ /* (c) Copyright IBM Corporation 2018. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef LIBTPMS_CALLBACKS_H #define LIBTPMS_CALLBACKS_H #define LIBTPMS_CALLBACK_FALLTHROUGH -2 int libtpms_plat__NVEnable(void); int libtpms_plat__NVDisable(void); int libtpms_plat__IsNvAvailable(void); int libtpms_plat__NvCommit(void); int libtpms_plat__PhysicalPresenceAsserted(BOOL *pp); #endif /* LIBTPMS_CALLBACKS_H */ libtpms-0.9.3/src/tpm2/LoadExternal_fp.h000066400000000000000000000076711421143571500201040ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: LoadExternal_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef LOADEXTERNAL_FP_H #define LOADEXTERNAL_FP_H typedef struct { TPM2B_SENSITIVE inPrivate; TPM2B_PUBLIC inPublic; TPMI_RH_HIERARCHY hierarchy; } LoadExternal_In; #define RC_LoadExternal_inPrivate (TPM_RC_P + TPM_RC_1) #define RC_LoadExternal_inPublic (TPM_RC_P + TPM_RC_2) #define RC_LoadExternal_hierarchy (TPM_RC_P + TPM_RC_3) typedef struct { TPM_HANDLE objectHandle; TPM2B_NAME name; } LoadExternal_Out; TPM_RC TPM2_LoadExternal( LoadExternal_In *in, // IN: input parameter list LoadExternal_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/Load_fp.h000066400000000000000000000075421421143571500163760ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Load_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef LOAD_FP_H #define LOAD_FP_H typedef struct { TPMI_DH_OBJECT parentHandle; TPM2B_PRIVATE inPrivate; TPM2B_PUBLIC inPublic; } Load_In; #define RC_Load_parentHandle (TPM_RC_H + TPM_RC_1) #define RC_Load_inPrivate (TPM_RC_P + TPM_RC_1) #define RC_Load_inPublic (TPM_RC_P + TPM_RC_2) typedef struct { TPM_HANDLE objectHandle; TPM2B_NAME name; } Load_Out; TPM_RC TPM2_Load( Load_In *in, // IN: input parameter list Load_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/Locality.c000066400000000000000000000106641421143571500166040ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Locality.c 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016, 2017 */ /* */ /********************************************************************************/ /* 9.8 Locality.c */ /* 9.8.1 Includes */ #include "Tpm.h" /* 9.8.2 LocalityGetAttributes() */ /* This function will convert a locality expressed as an integer into TPMA_LOCALITY form. */ /* The function returns the locality attribute. */ TPMA_LOCALITY LocalityGetAttributes( UINT8 locality // IN: locality value ) { TPMA_LOCALITY locality_attributes; BYTE *localityAsByte = (BYTE *)&locality_attributes; MemorySet(&locality_attributes, 0, sizeof(TPMA_LOCALITY)); switch(locality) { case 0: SET_ATTRIBUTE(locality_attributes, TPMA_LOCALITY, TPM_LOC_ZERO); break; case 1: SET_ATTRIBUTE(locality_attributes, TPMA_LOCALITY, TPM_LOC_ONE); break; case 2: SET_ATTRIBUTE(locality_attributes, TPMA_LOCALITY, TPM_LOC_TWO); break; case 3: SET_ATTRIBUTE(locality_attributes, TPMA_LOCALITY, TPM_LOC_THREE); break; case 4: SET_ATTRIBUTE(locality_attributes, TPMA_LOCALITY, TPM_LOC_FOUR); break; default: pAssert(locality > 31); *localityAsByte = locality; break; } return locality_attributes; } libtpms-0.9.3/src/tpm2/LocalityPlat.c000066400000000000000000000077761421143571500174370ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Platform Locality Support */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: LocalityPlat.c 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ /* C.5 LocalityPlat.c */ /* C.5.1. Includes */ #include "Platform.h" /* C.5.2. Functions */ /* C.5.2.1. _plat__LocalityGet() */ /* Get the most recent command locality in locality value form. This is an integer value for locality and not a locality structure The locality can be 0-4 or 32-255. 5-31 is not allowed. */ LIB_EXPORT unsigned char _plat__LocalityGet( void ) { return s_locality; } /* C.5.2.2. _plat__LocalitySet() */ /* Set the most recent command locality in locality value form */ LIB_EXPORT void _plat__LocalitySet( unsigned char locality ) { if(locality > 4 && locality < 32) locality = 0; s_locality = locality; return; } libtpms-0.9.3/src/tpm2/Locality_fp.h000066400000000000000000000067311421143571500172760ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Locality_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 */ /* */ /********************************************************************************/ #ifndef LOCALITY_FP_H #define LOCALITY_FP_H TPMA_LOCALITY LocalityGetAttributes( UINT8 locality // IN: locality value ); #endif libtpms-0.9.3/src/tpm2/MAC_Start_fp.h000066400000000000000000000075461421143571500173000ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: MAC_Start_fp.h 1047 2017-07-20 18:27:34Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2017 */ /* */ /********************************************************************************/ /* rev 146 */ #ifndef MAC_START_FP_H #define MAC_START_FP_H typedef struct { TPMI_DH_OBJECT handle; TPM2B_AUTH auth; TPMI_ALG_MAC_SCHEME inScheme; } MAC_Start_In; typedef struct { TPMI_DH_OBJECT sequenceHandle; } MAC_Start_Out; #define RC_MAC_Start_handle (TPM_RC_H + TPM_RC_1) #define RC_MAC_Start_auth (TPM_RC_P + TPM_RC_1) #define RC_MAC_Start_inScheme (TPM_RC_P + TPM_RC_2) TPM_RC TPM2_MAC_Start( MAC_Start_In *in, // IN: input parameter list MAC_Start_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/MAC_fp.h000066400000000000000000000074751421143571500161240ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: MAC_fp.h 1259 2018-07-10 19:11:09Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2018 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef MAC_FP_H #define MAC_FP_H typedef struct { TPMI_DH_OBJECT handle; TPM2B_MAX_BUFFER buffer; TPMI_ALG_MAC_SCHEME inScheme; } MAC_In; #define RC_MAC_handle (TPM_RC_H + TPM_RC_1) #define RC_MAC_buffer (TPM_RC_P + TPM_RC_1) #define RC_MAC_inScheme (TPM_RC_P + TPM_RC_2) typedef struct { TPM2B_MAX_BUFFER outMAC; } MAC_Out; TPM_RC TPM2_MAC( MAC_In *in, // IN: input parameter list MAC_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/MakeCredential_fp.h000066400000000000000000000077321421143571500203700ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: MakeCredential_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef MAKECREDENTIAL_FP_H #define MAKECREDENTIAL_FP_H typedef struct { TPMI_DH_OBJECT handle; TPM2B_DIGEST credential; TPM2B_NAME objectName; } MakeCredential_In; #define RC_MakeCredential_handle (TPM_RC_H + TPM_RC_1) #define RC_MakeCredential_credential (TPM_RC_P + TPM_RC_1) #define RC_MakeCredential_objectName (TPM_RC_P + TPM_RC_2) typedef struct { TPM2B_ID_OBJECT credentialBlob; TPM2B_ENCRYPTED_SECRET secret; } MakeCredential_Out; TPM_RC TPM2_MakeCredential( MakeCredential_In *in, // IN: input parameter list MakeCredential_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/ManagementCommands.c000066400000000000000000000123221421143571500205530ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Miscellaneous Management Functions */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: ManagementCommands.c 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2018 */ /* */ /********************************************************************************/ #include "Tpm.h" #include "PP_Commands_fp.h" #if CC_PP_Commands // Conditional expansion of this file TPM_RC TPM2_PP_Commands( PP_Commands_In *in // IN: input parameter list ) { UINT32 i; // The command needs NV update. Check if NV is available. // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at // this point RETURN_IF_NV_IS_NOT_AVAILABLE; // Internal Data Update // Process set list for(i = 0; i < in->setList.count; i++) // If command is implemented, set it as PP required. If the input // command is not a PP command, it will be ignored at // PhysicalPresenceCommandSet(). // Note: PhysicalPresenceCommandSet() checks if the command is implemented. PhysicalPresenceCommandSet(in->setList.commandCodes[i]); // Process clear list for(i = 0; i < in->clearList.count; i++) // If command is implemented, clear it as PP required. If the input // command is not a PP command, it will be ignored at // PhysicalPresenceCommandClear(). If the input command is // TPM2_PP_Commands, it will be ignored as well PhysicalPresenceCommandClear(in->clearList.commandCodes[i]); // Save the change of PP list NV_SYNC_PERSISTENT(ppList); return TPM_RC_SUCCESS; } #endif // CC_PP_Commands #include "Tpm.h" #include "SetAlgorithmSet_fp.h" #if CC_SetAlgorithmSet // Conditional expansion of this file TPM_RC TPM2_SetAlgorithmSet( SetAlgorithmSet_In *in // IN: input parameter list ) { // The command needs NV update. Check if NV is available. // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at // this point RETURN_IF_NV_IS_NOT_AVAILABLE; // Internal Data Update gp.algorithmSet = in->algorithmSet; // Write the algorithm set changes to NV NV_SYNC_PERSISTENT(algorithmSet); return TPM_RC_SUCCESS; } #endif // CC_SetAlgorithmSet libtpms-0.9.3/src/tpm2/Manufacture.c000066400000000000000000000202551421143571500172730ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Performs the manufacturing of the TPM */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Manufacture.c 1519 2019-11-15 20:43:51Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ /* 9.9 Manufacture.c */ /* 9.9.1 Description */ /* This file contains the function that performs the manufacturing of the TPM in a simulated environment. These functions should not be used outside of a manufacturing or simulation environment. */ /* 9.9.2 Includes and Data Definitions */ #define MANUFACTURE_C #include "Tpm.h" #include "TpmSizeChecks_fp.h" #define TPM_HAVE_TPM2_DECLARATIONS #include "tpm_library_intern.h" // libtpms added /* 9.9.3 Functions */ /* 9.9.3.1 TPM_Manufacture() */ /* This function initializes the TPM values in preparation for the TPMs first use. This function will fail if previously called. The TPM can be re-manufactured by calling TPM_Teardown() first and then calling this function again. */ /* Return Values Meaning */ /* -1 failure */ /* 0 success */ /* 1 manufacturing process previously performed */ LIB_EXPORT int TPM_Manufacture( int firstTime // IN: indicates if this is the first call from // main() ) { TPM_SU orderlyShutdown; // Initialize the context slot mask for UINT16 s_ContextSlotMask = 0xffff; // libtpms added #if RUNTIME_SIZE_CHECKS // Call the function to verify the sizes of values that result from different // compile options. if(!TpmSizeChecks()) return -1; #endif #if LIBRARY_COMPATIBILITY_CHECK // Make sure that the attached library performs as expected. if(!MathLibraryCompatibilityCheck()) return -1; #endif // If TPM has been manufactured, return indication. if(!firstTime && g_manufactured) return 1; // Do power on initializations of the cryptographic libraries. CryptInit(); s_DAPendingOnNV = FALSE; // initialize NV NvManufacture(); // Clear the magic value in the DRBG state go.drbgState.magic = 0; if (CryptStartup(SU_RESET) == FALSE) { // libtpms added begin TPMLIB_LogTPM2Error( "CryptStartup failed:\n" "IsEntropyBad : %d\n" "IsTestStateSet(TESTING) : %d\n" "IsTestStateSet(TESTED) : %d\n" "IsTestStateSet(ENTROPY) : %d\n" "IsDrbgTested : %d\n", IsEntropyBad(), IsTestStateSet(TESTING), IsTestStateSet(TESTED), IsTestStateSet(ENTROPY), IsDrbgTested()); return -1; } // libtpms added end // default configuration for PCR PCRSimStart(); // initialize pre-installed hierarchy data // This should happen after NV is initialized because hierarchy data is // stored in NV. HierarchyPreInstall_Init(); // initialize dictionary attack parameters DAPreInstall_Init(); // initialize PP list PhysicalPresencePreInstall_Init(); // initialize command audit list CommandAuditPreInstall_Init(); // first start up is required to be Startup(CLEAR) orderlyShutdown = TPM_SU_CLEAR; NV_WRITE_PERSISTENT(orderlyState, orderlyShutdown); // initialize the firmware version gp.firmwareV1 = FIRMWARE_V1; #ifdef FIRMWARE_V2 gp.firmwareV2 = FIRMWARE_V2; #else gp.firmwareV2 = 0; #endif NV_SYNC_PERSISTENT(firmwareV1); NV_SYNC_PERSISTENT(firmwareV2); // initialize the total reset counter to 0 gp.totalResetCount = 0; NV_SYNC_PERSISTENT(totalResetCount); // initialize the clock stuff go.clock = 0; go.clockSafe = YES; NvWrite(NV_ORDERLY_DATA, sizeof(ORDERLY_DATA), &go); // Commit NV writes. Manufacture process is an artificial process existing // only in simulator environment and it is not defined in the specification // that what should be the expected behavior if the NV write fails at this // point. Therefore, it is assumed the NV write here is always success and // no return code of this function is checked. NvCommit(); g_manufactured = TRUE; return 0; } /* 9.9.3.2 TPM_TearDown() */ /* This function prepares the TPM for re-manufacture. It should not be implemented in anything other than a simulated TPM. */ /* In this implementation, all that is needs is to stop the cryptographic units and set a flag to indicate that the TPM can be re-manufactured. This should be all that is necessary to start the manufacturing process again. */ /* Return Values Meaning */ /* 0 success */ /* 1 TPM not previously manufactured */ LIB_EXPORT int TPM_TearDown( void ) { g_manufactured = FALSE; return 0; } #if 0 /* libtpms added */ /* 9.9.3.3 TpmEndSimulation() */ /* This function is called at the end of the simulation run. It is used to provoke printing of any statistics that might be needed. */ LIB_EXPORT void TpmEndSimulation( void ) { #if SIMULATION HashLibSimulationEnd(); SymLibSimulationEnd(); MathLibSimulationEnd(); #if ALG_RSA RsaSimulationEnd(); #endif #if ALG_ECC EccSimulationEnd(); #endif #endif // SIMULATION } #endif /* libtpms added */ libtpms-0.9.3/src/tpm2/Manufacture_fp.h000066400000000000000000000071511421143571500177650ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Performs the manufacturing of the TPM */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Manufacture_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ #ifndef MANUFACTURE_FP_H #define MANUFACTURE_FP_H #include "CompilerDependencies.h" /* kgold */ LIB_EXPORT int TPM_Manufacture( int firstTime ); LIB_EXPORT int TPM_TearDown( void ); LIB_EXPORT void TpmEndSimulation( void ); #endif libtpms-0.9.3/src/tpm2/Marshal.c000066400000000000000000002032171421143571500164110ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Parameter Marshaling */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Marshal.c 1642 2020-08-18 19:42:24Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2020 */ /* */ /********************************************************************************/ #include // libtpms added #include #include "Tpm.h" #include "Marshal_fp.h" UINT16 UINT8_Marshal(UINT8 *source, BYTE **buffer, INT32 *size) { if (buffer != NULL) { if ((size == NULL) || ((UINT32)*size >= sizeof(UINT8))) { (*buffer)[0] = *source; *buffer += sizeof(UINT8); if (size != NULL) { *size -= sizeof(UINT8); } } else { pAssert(FALSE); } } return sizeof(UINT8); } UINT16 UINT16_Marshal(UINT16 *source, BYTE **buffer, INT32 *size) { if (buffer != NULL) { if ((size == NULL) || ((UINT32)*size >= sizeof(UINT16))) { (*buffer)[0] = (BYTE)((*source >> 8) & 0xff); (*buffer)[1] = (BYTE)((*source >> 0) & 0xff); *buffer += sizeof(UINT16); if (size != NULL) { *size -= sizeof(UINT16); } } else { pAssert(FALSE); } } return sizeof(UINT16); } UINT16 UINT32_Marshal(UINT32 *source, BYTE **buffer, INT32 *size) { if (buffer != NULL) { if ((size == NULL) || ((UINT32)*size >= sizeof(UINT32))) { (*buffer)[0] = (BYTE)((*source >> 24) & 0xff); (*buffer)[1] = (BYTE)((*source >> 16) & 0xff); (*buffer)[2] = (BYTE)((*source >> 8) & 0xff); (*buffer)[3] = (BYTE)((*source >> 0) & 0xff); *buffer += sizeof(UINT32); if (size != NULL) { *size -= sizeof(UINT32); } } else { pAssert(FALSE); } } return sizeof(UINT32); } UINT16 UINT64_Marshal(UINT64 *source, BYTE **buffer, INT32 *size) { if (buffer != NULL) { if ((size == NULL) || ((UINT32)*size >= sizeof(UINT64))) { (*buffer)[0] = (BYTE)((*source >> 56) & 0xff); (*buffer)[1] = (BYTE)((*source >> 48) & 0xff); (*buffer)[2] = (BYTE)((*source >> 40) & 0xff); (*buffer)[3] = (BYTE)((*source >> 32) & 0xff); (*buffer)[4] = (BYTE)((*source >> 24) & 0xff); (*buffer)[5] = (BYTE)((*source >> 16) & 0xff); (*buffer)[6] = (BYTE)((*source >> 8) & 0xff); (*buffer)[7] = (BYTE)((*source >> 0) & 0xff); *buffer += sizeof(UINT64); if (size != NULL) { *size -= sizeof(UINT64); } } else { pAssert(FALSE); } } return sizeof(UINT64); } UINT16 Array_Marshal(BYTE *sourceBuffer, UINT16 sourceSize, BYTE **buffer, INT32 *size) { if (buffer != NULL) { if ((size == NULL) || (*size >= sourceSize)) { memcpy(*buffer, sourceBuffer, sourceSize); *buffer += sourceSize; if (size != NULL) { *size -= sourceSize; } } else { pAssert(FALSE); } } return sourceSize; } UINT16 TPM2B_Marshal(TPM2B *source, UINT32 maxSize, BYTE **buffer, INT32 *size) { UINT16 written = 0; assert(source->size <= maxSize); // libtpms added written += UINT16_Marshal(&(source->size), buffer, size); written += Array_Marshal(source->buffer, source->size, buffer, size); return written; } /* Table 2:5 - Definition of Types for Documentation Clarity (TypedefTable()) */ UINT16 TPM_KEY_BITS_Marshal(TPM_KEY_BITS *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += UINT16_Marshal(source, buffer, size); return written; } /* Table 2:7 - Definition of TPM_CONSTANTS32 Constants (EnumTable()) */ UINT16 TPM_CONSTANTS32_Marshal(TPM_CONSTANTS32 *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += UINT32_Marshal(source, buffer, size); return written; } /* Table 9 - Definition of (UINT16) TPM_ALG_ID Constants */ UINT16 TPM_ALG_ID_Marshal(TPM_ALG_ID *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += UINT16_Marshal(source, buffer, size); return written; } /* Table 10 - Definition of (UINT16) {ECC} TPM_ECC_CURVE Constants */ #if ALG_ECC UINT16 TPM_ECC_CURVE_Marshal(TPM_ECC_CURVE *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += UINT16_Marshal(source, buffer, size); return written; } #endif /* Table 12 - Definition of TPM_CC Constants */ UINT16 TPM_CC_Marshal(TPM_CC *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += UINT32_Marshal(source, buffer, size); return written; } /* Table 2:16 - Definition of TPM_RC Constants (EnumTable()) */ UINT16 TPM_RC_Marshal(TPM_RC *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += UINT32_Marshal(source, buffer, size); return written; } /* Table 2:19 - Definition of TPM_ST Constants (EnumTable()) */ UINT16 TPM_ST_Marshal(TPM_ST *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += UINT16_Marshal(source, buffer, size); return written; } /* Table 2:22 - Definition of TPM_CAP Constants (EnumTable()) */ INT16 TPM_CAP_Marshal(TPM_CAP *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += UINT32_Marshal(source, buffer, size); return written; } /* Table 2:23 - Definition of TPM_PT Constants (EnumTable()) */ UINT16 TPM_PT_Marshal(TPM_PT *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += UINT32_Marshal(source, buffer, size); return written; } /* Table 2:24 - Definition of TPM_PT_PCR Constants (EnumTable()) */ UINT16 TPM_PT_PCR_Marshal(TPM_PT_PCR *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += UINT32_Marshal(source, buffer, size); return written; } /* Table 2:26 - Definition of Types for Handles (TypedefTable()) */ UINT16 TPM_HANDLE_Marshal(TPM_HANDLE *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += UINT32_Marshal(source, buffer, size); return written; } /* Table 2:30 - Definition of TPMA_ALGORITHM Bits (BitsTable()) */ UINT16 TPMA_ALGORITHM_Marshal(TPMA_ALGORITHM *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += UINT32_Marshal((UINT32 *)source, buffer, size); return written; } /* Table 2:31 - Definition of TPMA_OBJECT Bits (BitsTable()) */ UINT16 TPMA_OBJECT_Marshal(TPMA_OBJECT *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += UINT32_Marshal((UINT32 *)source, buffer, size); return written; } /* Table 2:32 - Definition of TPMA_SESSION Bits (BitsTable()) */ UINT16 TPMA_SESSION_Marshal(TPMA_SESSION *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += UINT8_Marshal((UINT8 *)source, buffer, size); /* libtpms changed */ return written; } /* Table 2:33 - Definition of TPMA_LOCALITY Bits (BitsTable()) */ UINT16 TPMA_LOCALITY_Marshal(TPMA_LOCALITY *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += UINT8_Marshal((UINT8 *)source, buffer, size); /* libtpms changed */ return written; } /* Table 2:37 - Definition of TPMA_CC Bits (BitsTable()) */ UINT16 TPMA_CC_Marshal(TPMA_CC *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += UINT32_Marshal((UINT32 *)source, buffer, size); return written; } /* Table 2:39 - Definition of TPMI_YES_NO Type (InterfaceTable()) */ UINT16 TPMI_YES_NO_Marshal(TPMI_YES_NO *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += UINT8_Marshal(source, buffer, size); return written; } /* Table 40 - Definition of (UINT32) TPMA_ACT Bits */ UINT16 TPMA_ACT_Marshal(TPMA_ACT *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += UINT32_Marshal((UINT32 *)source, buffer, size); return written; } /* Table 2:49 - Definition of TPMI_DH_SAVED Type (InterfaceTable()) */ UINT16 TPMI_DH_SAVED_Marshal(TPMI_DH_CONTEXT *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM_HANDLE_Marshal(source, buffer, size); return written; } //* Table 2:49 - Definition of TPMI_RH_HIERARCHY Type (InterfaceTable()) */ UINT16 TPMI_RH_HIERARCHY_Marshal(TPMI_RH_HIERARCHY *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM_HANDLE_Marshal(source, buffer, size); return written; } /* Table 2:59 - Definition of TPMI_RH_NV_INDEX Type (InterfaceTable()) */ UINT16 TPMI_RH_NV_INDEX_Marshal(TPMI_RH_NV_INDEX *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM_HANDLE_Marshal(source, buffer, size); return written; } /* Table 2:60 - Definition of TPMI_ALG_HASH Type (InterfaceTable()) */ UINT16 TPMI_ALG_HASH_Marshal(TPMI_ALG_HASH *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM_ALG_ID_Marshal(source, buffer, size); return written; } /* Table 2:63 - Definition of TPMI_ALG_SYM_OBJECT Type (InterfaceTable()) */ UINT16 TPMI_ALG_SYM_OBJECT_Marshal(TPMI_ALG_SYM_OBJECT *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM_ALG_ID_Marshal(source, buffer, size); return written; } /* Table 2:64 - Definition of TPMI_ALG_SYM_MODE Type (InterfaceTable()) */ UINT16 TPMI_ALG_SYM_MODE_Marshal(TPMI_ALG_SYM_MODE *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM_ALG_ID_Marshal(source, buffer, size); return written; } /* Table 2:65 - Definition of TPMI_ALG_KDF Type (InterfaceTable()) */ UINT16 TPMI_ALG_KDF_Marshal(TPMI_ALG_KDF *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM_ALG_ID_Marshal(source, buffer, size); return written; } /* Table 2:66 - Definition of TPMI_ALG_SIG_SCHEME Type (InterfaceTable()) */ UINT16 TPMI_ALG_SIG_SCHEME_Marshal(TPMI_ALG_SIG_SCHEME *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM_ALG_ID_Marshal(source, buffer, size); return written; } /* Table 2:71 - Definition of TPMU_HA Union (StructuresTable()) */ UINT16 TPMU_HA_Marshal(TPMU_HA *source, BYTE **buffer, INT32 *size, UINT32 selector) { UINT16 written = 0; switch (selector) { #if ALG_SHA1 case TPM_ALG_SHA1: written += Array_Marshal(&source->sha1[0], SHA1_DIGEST_SIZE, buffer, size); break; #endif #if ALG_SHA256 case TPM_ALG_SHA256: written += Array_Marshal(&source->sha256[0], SHA256_DIGEST_SIZE, buffer, size); break; #endif #if ALG_SHA384 case TPM_ALG_SHA384: written += Array_Marshal(&source->sha384[0], SHA384_DIGEST_SIZE, buffer, size); break; #endif #if ALG_SHA512 case TPM_ALG_SHA512: written += Array_Marshal(&source->sha512[0], SHA512_DIGEST_SIZE, buffer, size); break; #endif #if ALG_SM3_256 case TPM_ALG_SM3_256: written += Array_Marshal(&source->sm3_256[0], SM3_256_DIGEST_SIZE, buffer, size); break; #endif case TPM_ALG_NULL: break; default: pAssert(FALSE); } return written; } /* Table 2:72 - Definition of TPMT_HA Structure (StructuresTable()) */ UINT16 TPMT_HA_Marshal(TPMT_HA *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPMI_ALG_HASH_Marshal(&source->hashAlg, buffer, size); written += TPMU_HA_Marshal(&source->digest, buffer, size, source->hashAlg); return written; } /* Table 2:73 - Definition of TPM2B_DIGEST Structure (StructuresTable()) */ UINT16 TPM2B_DIGEST_Marshal(TPM2B_DIGEST *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM2B_Marshal(&source->b, sizeof(source->t.buffer), buffer, size); // libtpms changed return written; } /* Table 2:74 - Definition of TPM2B_DATA Structure (StructuresTable()) */ UINT16 TPM2B_DATA_Marshal(TPM2B_DATA *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM2B_Marshal(&source->b, sizeof(source->t.buffer), buffer, size); // libtpms changed return written; } /* Table 2:75 - Definition of Types for TPM2B_NONCE (TypedefTable()) */ UINT16 TPM2B_NONCE_Marshal(TPM2B_NONCE *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM2B_DIGEST_Marshal(source, buffer, size); return written; } /* Table 2:76 - Definition of Types for TPM2B_AUTH (TypedefTable()) */ UINT16 TPM2B_AUTH_Marshal(TPM2B_AUTH *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM2B_DIGEST_Marshal(source, buffer, size); return written; } /* Table 2:79 - Definition of TPM2B_MAX_BUFFER Structure (StructuresTable()) */ UINT16 TPM2B_MAX_BUFFER_Marshal(TPM2B_MAX_BUFFER *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM2B_Marshal(&source->b, sizeof(source->t.buffer), buffer, size); // libtpms changed return written; } /* Table 2:80 - Definition of TPM2B_MAX_NV_BUFFER Structure (StructuresTable()) */ UINT16 TPM2B_MAX_NV_BUFFER_Marshal(TPM2B_MAX_NV_BUFFER *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM2B_Marshal(&source->b, sizeof(source->t.buffer), buffer, size); // libtpms changed return written; } /* Table 80 - Definition of TPM2B_TIMEOUT Structure */ UINT16 TPM2B_TIMEOUT_Marshal(TPM2B_TIMEOUT *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM2B_Marshal(&source->b, sizeof(source->t.buffer), buffer, size); // libtpms changed return written; } /* Table 2:82 - Definition of TPM2B_IV Structure (StructuresTable()) */ UINT16 TPM2B_IV_Marshal(TPM2B_IV *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM2B_Marshal(&source->b, sizeof(source->t.buffer), buffer, size); // libtpms changed return written; } /* Table 2:84 - Definition of TPM2B_NAME Structure (StructuresTable()) */ UINT16 TPM2B_NAME_Marshal(TPM2B_NAME *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM2B_Marshal(&source->b, sizeof(source->t.name), buffer, size); // libtpms changed return written; } /* Table 2:86 - Definition of TPMS_PCR_SELECTION Structure (StructuresTable()) */ UINT16 TPMS_PCR_SELECTION_Marshal(TPMS_PCR_SELECTION *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPMI_ALG_HASH_Marshal(&source->hash, buffer, size); written += UINT8_Marshal(&source->sizeofSelect, buffer, size); written += Array_Marshal(&source->pcrSelect[0], source->sizeofSelect, buffer, size); return written; } /* Table 2:89 - Definition of TPMT_TK_CREATION Structure (StructuresTable()) */ UINT16 TPMT_TK_CREATION_Marshal(TPMT_TK_CREATION *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM_ST_Marshal(&source->tag, buffer, size); written += TPMI_RH_HIERARCHY_Marshal(&source->hierarchy, buffer, size); written += TPM2B_DIGEST_Marshal(&source->digest, buffer, size); return written; } /* Table 2:90 - Definition of TPMT_TK_VERIFIED Structure (StructuresTable()) */ UINT16 TPMT_TK_VERIFIED_Marshal(TPMT_TK_VERIFIED *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM_ST_Marshal(&source->tag, buffer, size); written += TPMI_RH_HIERARCHY_Marshal(&source->hierarchy, buffer, size); written += TPM2B_DIGEST_Marshal(&source->digest, buffer, size); return written; } /* Table 2:91 - Definition of TPMT_TK_AUTH Structure (StructuresTable()) */ UINT16 TPMT_TK_AUTH_Marshal(TPMT_TK_AUTH *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM_ST_Marshal(&source->tag, buffer, size); written += TPMI_RH_HIERARCHY_Marshal(&source->hierarchy, buffer, size); written += TPM2B_DIGEST_Marshal(&source->digest, buffer, size); return written; } /* Table 2:92 - Definition of TPMT_TK_HASHCHECK Structure (StructuresTable()) */ UINT16 TPMT_TK_HASHCHECK_Marshal(TPMT_TK_HASHCHECK *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM_ST_Marshal(&source->tag, buffer, size); written += TPMI_RH_HIERARCHY_Marshal(&source->hierarchy, buffer, size); written += TPM2B_DIGEST_Marshal(&source->digest, buffer, size); return written; } /* Table 2:93 - Definition of TPMS_ALG_PROPERTY Structure (StructuresTable()) */ UINT16 TPMS_ALG_PROPERTY_Marshal(TPMS_ALG_PROPERTY *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM_ALG_ID_Marshal(&source->alg, buffer, size); written += TPMA_ALGORITHM_Marshal(&source->algProperties, buffer, size); return written; } /* Table 2:95 - Definition of TPMS_TAGGED_PCR_SELECT Structure (StructuresTable()) */ UINT16 TPMS_TAGGED_PCR_SELECT_Marshal(TPMS_TAGGED_PCR_SELECT *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM_PT_PCR_Marshal(&source->tag, buffer, size); written += UINT8_Marshal(&source->sizeofSelect, buffer, size); written += Array_Marshal(&source->pcrSelect[0], source->sizeofSelect, buffer, size); return written; } /* Table 2:96 - Definition of TPMS_TAGGED_POLICY Structure (StructuresTable()) */ UINT16 TPMS_TAGGED_POLICY_Marshal(TPMS_TAGGED_POLICY *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM_HANDLE_Marshal(&source->handle, buffer, size); written += TPMT_HA_Marshal(&source->policyHash, buffer, size); return written; } /* Table 105 - Definition of TPMS_ACT_DATA Structure */ UINT16 TPMS_ACT_DATA_Marshal(TPMS_ACT_DATA *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM_HANDLE_Marshal(&source->handle, buffer, size); written += UINT32_Marshal(&source->timeout, buffer, size); written += TPMA_ACT_Marshal(&source->attributes, buffer, size); return written; } /* Table 2:94 - Definition of TPMS_TAGGED_PROPERTY Structure (StructuresTable()) */ UINT16 TPMS_TAGGED_PROPERTY_Marshal(TPMS_TAGGED_PROPERTY *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM_PT_Marshal(&source->property, buffer, size); written += UINT32_Marshal(&source->value, buffer, size); return written; } /* Table 2:97 - Definition of TPML_CC Structure (StructuresTable()) */ UINT16 TPML_CC_Marshal(TPML_CC *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; UINT32 i; written += UINT32_Marshal(&source->count, buffer, size); for (i = 0 ; i < source->count ; i++) { written += TPM_CC_Marshal(&source->commandCodes[i], buffer, size); } return written; } /* Table 2:98 - Definition of TPML_CCA Structure (StructuresTable()) */ UINT16 TPML_CCA_Marshal(TPML_CCA *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; UINT32 i; written += UINT32_Marshal(&source->count, buffer, size); for (i = 0 ; i < source->count ; i++) { written += TPMA_CC_Marshal(&source->commandAttributes[i], buffer, size); } return written; } /* Table 2:99 - Definition of TPML_ALG Structure (StructuresTable()) */ UINT16 TPML_ALG_Marshal(TPML_ALG *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; UINT32 i; written += UINT32_Marshal(&source->count, buffer, size); for (i = 0 ; i < source->count ; i++) { written += TPM_ALG_ID_Marshal(&source->algorithms[i], buffer, size); } return written; } /* Table 2:100 - Definition of TPML_HANDLE Structure (StructuresTable()) */ UINT16 TPML_HANDLE_Marshal(TPML_HANDLE *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; UINT32 i; written += UINT32_Marshal(&source->count, buffer, size); for (i = 0 ; i < source->count ; i++) { written += TPM_HANDLE_Marshal(&source->handle[i], buffer, size); } return written; } /* Table 2:101 - Definition of TPML_DIGEST Structure (StructuresTable()) */ UINT16 TPML_DIGEST_Marshal(TPML_DIGEST *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; UINT32 i; written += UINT32_Marshal(&source->count, buffer, size); for (i = 0 ; i < source->count ; i++) { written += TPM2B_DIGEST_Marshal(&source->digests[i], buffer, size); } return written; } /* Table 2:102 - Definition of TPML_DIGEST_VALUES Structure (StructuresTable()) */ UINT16 TPML_DIGEST_VALUES_Marshal(TPML_DIGEST_VALUES *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; UINT32 i; written += UINT32_Marshal(&source->count, buffer, size); for (i = 0 ; i < source->count ; i++) { written += TPMT_HA_Marshal(&source->digests[i], buffer, size); } return written; } /* Table 2:104 - Definition of TPML_PCR_SELECTION Structure (StructuresTable()) */ UINT16 TPML_PCR_SELECTION_Marshal(TPML_PCR_SELECTION *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; UINT32 i; written += UINT32_Marshal(&source->count, buffer, size); for (i = 0 ; i < source->count ; i++) { written += TPMS_PCR_SELECTION_Marshal(&source->pcrSelections[i], buffer, size); } return written; } /* Table 2:105 - Definition of TPML_ALG_PROPERTY Structure (StructuresTable()) */ UINT16 TPML_ALG_PROPERTY_Marshal(TPML_ALG_PROPERTY *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; UINT32 i; written += UINT32_Marshal(&source->count, buffer, size); for (i = 0 ; i < source->count ; i++) { written += TPMS_ALG_PROPERTY_Marshal(&source->algProperties[i], buffer, size); } return written; } //* Table 2:106 - Definition of TPML_TAGGED_TPM_PROPERTY Structure (StructuresTable()) */ UINT16 TPML_TAGGED_TPM_PROPERTY_Marshal(TPML_TAGGED_TPM_PROPERTY *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; UINT32 i; written += UINT32_Marshal(&source->count, buffer, size); for (i = 0 ; i < source->count ; i++) { written += TPMS_TAGGED_PROPERTY_Marshal(&source->tpmProperty[i], buffer, size); } return written; } /* Table 2:107 - Definition of TPML_TAGGED_PCR_PROPERTY Structure (StructuresTable()) */ UINT16 TPML_TAGGED_PCR_PROPERTY_Marshal(TPML_TAGGED_PCR_PROPERTY *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; UINT32 i; written += UINT32_Marshal(&source->count, buffer, size); for (i = 0 ; i < source->count ; i++) { written += TPMS_TAGGED_PCR_SELECT_Marshal(&source->pcrProperty[i], buffer, size); } return written; } /* Table 2:108 - Definition of TPML_ECC_CURVE Structure (StructuresTable()) */ UINT16 TPML_ECC_CURVE_Marshal(TPML_ECC_CURVE *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; UINT32 i; written += UINT32_Marshal(&source->count, buffer, size); for (i = 0 ; i < source->count ; i++) { written += TPM_ECC_CURVE_Marshal(&source->eccCurves[i], buffer, size); } return written; } /* Table 2:109 - Definition of TPML_TAGGED_POLICY Structure (StructuresTable()) */ UINT16 TPML_TAGGED_POLICY_Marshal(TPML_TAGGED_POLICY *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; UINT32 i; written += UINT32_Marshal(&source->count, buffer, size); for (i = 0 ; i < source->count ; i++) { written += TPMS_TAGGED_POLICY_Marshal(&source->policies[i], buffer, size); } return written; } /* Table 2:118 - Definition of TPML_ACT_DATA Structure (StructuresTable()) */ UINT16 TPML_ACT_DATA_Marshal(TPML_ACT_DATA *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; UINT32 i; written += UINT32_Marshal(&source->count, buffer, size); for (i = 0 ; i < source->count ; i++) { written += TPMS_ACT_DATA_Marshal(&source->actData[i], buffer, size); } return written; } /* Table 2:110 - Definition of TPMU_CAPABILITIES Union (StructuresTable()) */ UINT16 TPMU_CAPABILITIES_Marshal(TPMU_CAPABILITIES *source, BYTE **buffer, INT32 *size, UINT32 selector) { UINT16 written = 0; switch (selector) { case TPM_CAP_ALGS: written += TPML_ALG_PROPERTY_Marshal(&source->algorithms, buffer, size); break; case TPM_CAP_HANDLES: written += TPML_HANDLE_Marshal(&source->handles, buffer, size); break; case TPM_CAP_COMMANDS: written += TPML_CCA_Marshal(&source->command, buffer, size); break; case TPM_CAP_PP_COMMANDS: written += TPML_CC_Marshal(&source->ppCommands, buffer, size); break; case TPM_CAP_AUDIT_COMMANDS: written += TPML_CC_Marshal(&source->auditCommands, buffer, size); break; case TPM_CAP_PCRS: written += TPML_PCR_SELECTION_Marshal(&source->assignedPCR, buffer, size); break; case TPM_CAP_TPM_PROPERTIES: written += TPML_TAGGED_TPM_PROPERTY_Marshal(&source->tpmProperties, buffer, size); break; case TPM_CAP_PCR_PROPERTIES: written += TPML_TAGGED_PCR_PROPERTY_Marshal(&source->pcrProperties, buffer, size); break; case TPM_CAP_ECC_CURVES: written += TPML_ECC_CURVE_Marshal(&source->eccCurves, buffer, size); break; case TPM_CAP_AUTH_POLICIES: written += TPML_TAGGED_POLICY_Marshal(&source->authPolicies, buffer, size); break; case TPM_CAP_ACT: written += TPML_ACT_DATA_Marshal(&source->actData, buffer, size); break; default: pAssert(FALSE); } return written; } /* Table 2:111 - Definition of TPMS_CAPABILITY_DATA Structure (StructuresTable()) */ UINT16 TPMS_CAPABILITY_DATA_Marshal(TPMS_CAPABILITY_DATA *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM_CAP_Marshal(&source->capability, buffer, size); written += TPMU_CAPABILITIES_Marshal(&source->data, buffer, size, source->capability); return written; } /* Table 2:112 - Definition of TPMS_CLOCK_INFO Structure (StructuresTable()) */ UINT16 TPMS_CLOCK_INFO_Marshal(TPMS_CLOCK_INFO *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += UINT64_Marshal(&source->clock, buffer, size); written += UINT32_Marshal(&source->resetCount, buffer, size); written += UINT32_Marshal(&source->restartCount, buffer, size); written += TPMI_YES_NO_Marshal(&source->safe, buffer, size); return written; } /* Table 2:113 - Definition of TPMS_TIME_INFO Structure (StructuresTable()) */ UINT16 TPMS_TIME_INFO_Marshal(TPMS_TIME_INFO *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += UINT64_Marshal(&source->time, buffer, size); written += TPMS_CLOCK_INFO_Marshal(&source->clockInfo, buffer, size); return written; } /* Table 2:114 - Definition of TPMS_TIME_ATTEST_INFO Structure (StructuresTable()) */ UINT16 TPMS_TIME_ATTEST_INFO_Marshal(TPMS_TIME_ATTEST_INFO *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPMS_TIME_INFO_Marshal(&source->time, buffer, size); written += UINT64_Marshal(&source->firmwareVersion, buffer, size); return written; } /* Table 2:115 - Definition of TPMS_CERTIFY_INFO Structure (StructuresTable()) */ UINT16 TPMS_CERTIFY_INFO_Marshal(TPMS_CERTIFY_INFO *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM2B_NAME_Marshal(&source->name, buffer, size); written += TPM2B_NAME_Marshal(&source->qualifiedName, buffer, size); return written; } /* Table 2:116 - Definition of TPMS_QUOTE_INFO Structure (StructuresTable()) */ UINT16 TPMS_QUOTE_INFO_Marshal(TPMS_QUOTE_INFO *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPML_PCR_SELECTION_Marshal(&source->pcrSelect, buffer, size); written += TPM2B_DIGEST_Marshal(&source->pcrDigest, buffer, size); return written; } /* Table 2:117 - Definition of TPMS_COMMAND_AUDIT_INFO Structure (StructuresTable()) */ UINT16 TPMS_COMMAND_AUDIT_INFO_Marshal(TPMS_COMMAND_AUDIT_INFO *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += UINT64_Marshal(&source->auditCounter, buffer, size); written += TPM_ALG_ID_Marshal(&source->digestAlg, buffer, size); written += TPM2B_DIGEST_Marshal(&source->auditDigest, buffer, size); written += TPM2B_DIGEST_Marshal(&source->commandDigest, buffer, size); return written; } /* Table 2:118 - Definition of TPMS_SESSION_AUDIT_INFO Structure (StructuresTable()) */ UINT16 TPMS_SESSION_AUDIT_INFO_Marshal(TPMS_SESSION_AUDIT_INFO *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPMI_YES_NO_Marshal(&source->exclusiveSession, buffer, size); written += TPM2B_DIGEST_Marshal(&source->sessionDigest, buffer, size); return written; } /* Table 2:119 - Definition of TPMS_CREATION_INFO Structure (StructuresTable()) */ UINT16 TPMS_CREATION_INFO_Marshal(TPMS_CREATION_INFO *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM2B_NAME_Marshal(&source->objectName, buffer, size); written += TPM2B_DIGEST_Marshal(&source->creationHash, buffer, size); return written; } /* Table 2:120 - Definition of TPMS_NV_CERTIFY_INFO Structure (StructuresTable()) */ UINT16 TPMS_NV_CERTIFY_INFO_Marshal(TPMS_NV_CERTIFY_INFO *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM2B_NAME_Marshal(&source->indexName, buffer, size); written += UINT16_Marshal(&source->offset, buffer, size); written += TPM2B_MAX_NV_BUFFER_Marshal(&source->nvContents, buffer, size); return written; } /* Table 125 - Definition of TPMS_NV_DIGEST_CERTIFY_INFO Structure */ UINT16 TPMS_NV_DIGEST_CERTIFY_INFO_Marshal(TPMS_NV_DIGEST_CERTIFY_INFO *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM2B_NAME_Marshal(&source->indexName, buffer, size); written += TPM2B_DIGEST_Marshal(&source->nvDigest, buffer, size); return written; } /* Table 2:121 - Definition of TPMI_ST_ATTEST Type (InterfaceTable()) */ UINT16 TPMI_ST_ATTEST_Marshal(TPMI_ST_ATTEST *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM_ST_Marshal(source, buffer, size); return written; } /* Table 2:122 - Definition of TPMU_ATTEST Union (StructuresTable()) */ UINT16 TPMU_ATTEST_Marshal(TPMU_ATTEST *source, BYTE **buffer, INT32 *size, UINT32 selector) { UINT16 written = 0; switch (selector) { case TPM_ST_ATTEST_CERTIFY: written += TPMS_CERTIFY_INFO_Marshal(&source->certify, buffer, size); break; case TPM_ST_ATTEST_CREATION: written += TPMS_CREATION_INFO_Marshal(&source->creation, buffer, size); break; case TPM_ST_ATTEST_QUOTE: written += TPMS_QUOTE_INFO_Marshal(&source->quote, buffer, size); break; case TPM_ST_ATTEST_COMMAND_AUDIT: written += TPMS_COMMAND_AUDIT_INFO_Marshal(&source->commandAudit, buffer, size); break; case TPM_ST_ATTEST_SESSION_AUDIT: written += TPMS_SESSION_AUDIT_INFO_Marshal(&source->sessionAudit, buffer, size); break; case TPM_ST_ATTEST_TIME: written += TPMS_TIME_ATTEST_INFO_Marshal(&source->time, buffer, size); break; case TPM_ST_ATTEST_NV: written += TPMS_NV_CERTIFY_INFO_Marshal(&source->nv, buffer, size); break; case TPM_ST_ATTEST_NV_DIGEST: written += TPMS_NV_DIGEST_CERTIFY_INFO_Marshal(&source->nvDigest, buffer, size); break; default: pAssert(FALSE); } return written; } /* Table 2:123 - Definition of TPMS_ATTEST Structure (StructuresTable()) */ UINT16 TPMS_ATTEST_Marshal(TPMS_ATTEST *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM_CONSTANTS32_Marshal(&source->magic, buffer, size); written += TPMI_ST_ATTEST_Marshal(&source->type, buffer, size); written += TPM2B_NAME_Marshal(&source->qualifiedSigner, buffer, size); written += TPM2B_DATA_Marshal(&source->extraData, buffer, size); written += TPMS_CLOCK_INFO_Marshal(&source->clockInfo, buffer, size); written += UINT64_Marshal(&source->firmwareVersion, buffer, size); written += TPMU_ATTEST_Marshal(&source->attested, buffer, size,source->type); return written; } /* Table 2:124 - Definition of TPM2B_ATTEST Structure (StructuresTable()) */ UINT16 TPM2B_ATTEST_Marshal(TPM2B_ATTEST *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM2B_Marshal(&source->b, sizeof(source->t.attestationData), buffer, size); // libtpms changed return written; } /* Table 2:127 - Definition of TPMI_AES_KEY_BITS Type (InterfaceTable()) */ UINT16 TPMI_AES_KEY_BITS_Marshal(TPMI_AES_KEY_BITS *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM_KEY_BITS_Marshal(source, buffer, size); return written; } UINT16 // libtpms added begin TPMI_TDES_KEY_BITS_Marshal(TPMI_TDES_KEY_BITS *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM_KEY_BITS_Marshal(source, buffer, size); return written; } #if ALG_CAMELLIA UINT16 TPMI_CAMELLIA_KEY_BITS_Marshal(TPMI_CAMELLIA_KEY_BITS *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM_KEY_BITS_Marshal(source, buffer, size); return written; } #endif // libtpms added end /* Table 2:128 - Definition of TPMU_SYM_KEY_BITS Union (StructuresTable()) */ UINT16 TPMU_SYM_KEY_BITS_Marshal(TPMU_SYM_KEY_BITS *source, BYTE **buffer, INT32 *size, UINT32 selector) { UINT16 written = 0; switch(selector) { #if ALG_AES case TPM_ALG_AES: written += TPMI_AES_KEY_BITS_Marshal(&source->aes, buffer, size); break; #endif #if ALG_SM4 case TPM_ALG_SM4: written += TPMI_SM4_KEY_BITS_Marshal(&source->sm4, buffer, size); break; #endif #if ALG_CAMELLIA case TPM_ALG_CAMELLIA: written += TPMI_CAMELLIA_KEY_BITS_Marshal(&source->camellia, buffer, size); break; #endif #if ALG_TDES // libtpms added begin case TPM_ALG_TDES: written += TPMI_TDES_KEY_BITS_Marshal(&source->tdes, buffer, size); break; #endif // libtpms added end #if ALG_XOR case TPM_ALG_XOR: written += TPMI_ALG_HASH_Marshal(&source->xorr, buffer, size); break; #endif case TPM_ALG_NULL: break; default: pAssert(FALSE); } return written; } /* Table 2:129 - Definition of TPMU_SYM_MODE Union (StructuresTable()) */ UINT16 TPMU_SYM_MODE_Marshal(TPMU_SYM_MODE *source, BYTE **buffer, INT32 *size, UINT32 selector) { UINT16 written = 0; switch (selector) { #if ALG_AES case TPM_ALG_AES: written += TPMI_ALG_SYM_MODE_Marshal(&source->aes, buffer, size); break; #endif #if ALG_SM4 case TPM_ALG_SM4: written += TPMI_ALG_SYM_MODE_Marshal(&source->sm4, buffer, size); break; #endif #if ALG_CAMELLIA case TPM_ALG_CAMELLIA: written += TPMI_ALG_SYM_MODE_Marshal(&source->camellia, buffer, size); break; #endif #if ALG_TDES // libtpms added begin case TPM_ALG_TDES: written += TPMI_ALG_SYM_MODE_Marshal(&source->tdes, buffer, size); break; #endif // libtpms added end #if ALG_XOR case TPM_ALG_XOR: #endif case TPM_ALG_NULL: break; default: pAssert(FALSE); } return written; } /* Table 2:132 - Definition of TPMT_SYM_DEF_OBJECT Structure (StructuresTable()) */ UINT16 TPMT_SYM_DEF_OBJECT_Marshal(TPMT_SYM_DEF_OBJECT *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPMI_ALG_SYM_OBJECT_Marshal(&source->algorithm, buffer, size); written += TPMU_SYM_KEY_BITS_Marshal(&source->keyBits, buffer, size, source->algorithm); written += TPMU_SYM_MODE_Marshal(&source->mode, buffer, size, source->algorithm); return written; } /* Table 2:133 - Definition of TPM2B_SYM_KEY Structure (StructuresTable()) */ UINT16 TPM2B_SYM_KEY_Marshal(TPM2B_SYM_KEY *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM2B_Marshal(&source->b, sizeof(source->t.buffer), buffer, size); // libtpms changed return written; } /* Table 2:134 - Definition of TPMS_SYMCIPHER_PARMS Structure (StructuresTable()) */ UINT16 TPMS_SYMCIPHER_PARMS_Marshal(TPMS_SYMCIPHER_PARMS *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPMT_SYM_DEF_OBJECT_Marshal(&source->sym, buffer, size); return written; } /* Table 2:139 - Definition of TPM2B_SENSITIVE_DATA Structure (StructuresTable()) */ UINT16 TPM2B_SENSITIVE_DATA_Marshal(TPM2B_SENSITIVE_DATA *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM2B_Marshal(&source->b, sizeof(source->t.buffer), buffer, size); // libtpms changed return written; } /* Table 2:142 - Definition of TPMS_SCHEME_HASH Structure (StructuresTable()) */ UINT16 TPMS_SCHEME_HASH_Marshal(TPMS_SCHEME_HASH *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPMI_ALG_HASH_Marshal(&source->hashAlg, buffer, size); return written; } /* Table 2:143 - Definition of TPMS_SCHEME_ECDAA Structure (StructuresTable()) */ UINT16 TPMS_SCHEME_ECDAA_Marshal(TPMS_SCHEME_ECDAA *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPMI_ALG_HASH_Marshal(&source->hashAlg, buffer, size); written += UINT16_Marshal(&source->count, buffer, size); return written; } /* Table 2:144 - Definition of TPMI_ALG_KEYEDHASH_SCHEME Type (InterfaceTable()) */ UINT16 TPMI_ALG_KEYEDHASH_SCHEME_Marshal(TPMI_ALG_KEYEDHASH_SCHEME *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM_ALG_ID_Marshal(source, buffer, size); return written; } /* Table 2:145 - Definition of Types for HMAC_SIG_SCHEME (TypedefTable()) */ UINT16 TPMS_SCHEME_HMAC_Marshal(TPMS_SCHEME_HMAC *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPMS_SCHEME_HASH_Marshal(source, buffer, size); return written; } /* Table 2:146 - Definition of TPMS_SCHEME_XOR Structure (StructuresTable()) */ UINT16 TPMS_SCHEME_XOR_Marshal(TPMS_SCHEME_XOR *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPMI_ALG_HASH_Marshal(&source->hashAlg, buffer, size); written += TPMI_ALG_KDF_Marshal(&source->kdf, buffer, size); return written; } /* Table 2:148 - Definition of TPMT_KEYEDHASH_SCHEME Structure (StructuresTable()) */ UINT16 TPMT_KEYEDHASH_SCHEME_Marshal(TPMT_KEYEDHASH_SCHEME *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPMI_ALG_KEYEDHASH_SCHEME_Marshal(&source->scheme, buffer, size); written += TPMU_SCHEME_KEYEDHASH_Marshal(&source->details, buffer, size, source->scheme); return written; } /* Table 2:149 - Definition of Types for RSA Signature Schemes (TypedefTable()) */ UINT16 TPMS_SIG_SCHEME_RSASSA_Marshal(TPMS_SIG_SCHEME_RSASSA *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPMS_SCHEME_HASH_Marshal(source, buffer, size); return written; } UINT16 TPMS_SIG_SCHEME_RSAPSS_Marshal(TPMS_SIG_SCHEME_RSAPSS *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPMS_SCHEME_HASH_Marshal(source, buffer, size); return written; } /* Table 2:150 - Definition of Types for ECC Signature Schemes (TypedefTable()) */ UINT16 TPMS_SIG_SCHEME_ECDSA_Marshal(TPMS_SIG_SCHEME_ECDSA *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPMS_SCHEME_HASH_Marshal(source, buffer, size); return written; } UINT16 TPMS_SIG_SCHEME_SM2_Marshal(TPMS_SIG_SCHEME_SM2 *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPMS_SCHEME_HASH_Marshal(source, buffer, size); return written; } UINT16 TPMS_SIG_SCHEME_ECSCHNORR_Marshal(TPMS_SIG_SCHEME_ECSCHNORR *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPMS_SCHEME_HASH_Marshal(source, buffer, size); return written; } UINT16 TPMS_SIG_SCHEME_ECDAA_Marshal(TPMS_SIG_SCHEME_ECDAA *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPMS_SCHEME_ECDAA_Marshal(source, buffer, size); return written; } /* Table 2:153 - Definition of Types for Encryption Schemes (TypedefTable()) */ UINT16 TPMS_ENC_SCHEME_OAEP_Marshal(TPMS_ENC_SCHEME_OAEP *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPMS_SCHEME_HASH_Marshal(source, buffer, size); return written; } /* Table 146 - Definition of Types for {RSA} Encryption Schemes */ UINT16 TPMS_ENC_SCHEME_RSAES_Marshal(TPMS_ENC_SCHEME_RSAES *source, BYTE **buffer, INT32 *size) { source = source; buffer = buffer; size = size; return 0; } /* Table 2:147 - Definition of TPMU_SCHEME_KEYEDHASH Union (StructuresTable()) */ UINT16 TPMU_SCHEME_KEYEDHASH_Marshal(TPMU_SCHEME_KEYEDHASH *source, BYTE **buffer, INT32 *size, UINT32 selector) { UINT16 written = 0; switch (selector) { #if ALG_HMAC case TPM_ALG_HMAC: written += TPMS_SCHEME_HMAC_Marshal(&source->hmac, buffer, size); break; #endif #if ALG_XOR case TPM_ALG_XOR: written += TPMS_SCHEME_XOR_Marshal(&source->xorr, buffer, size); break; #endif case TPM_ALG_NULL: break; default: pAssert(FALSE); } return written; } /* Table 2:154 - Definition of Types for ECC Key Exchange (TypedefTable()) */ UINT16 TPMS_KEY_SCHEME_ECDH_Marshal(TPMS_KEY_SCHEME_ECDH *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPMS_SCHEME_HASH_Marshal(source, buffer, size); return written; } UINT16 TPMS_KEY_SCHEME_ECMQV_Marshal(TPMS_KEY_SCHEME_ECMQV*source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPMS_SCHEME_HASH_Marshal(source, buffer, size); return written; } /* Table 2:155 - Definition of Types for KDF Schemes (TypedefTable()) */ UINT16 TPMS_KDF_SCHEME_MGF1_Marshal(TPMS_KDF_SCHEME_MGF1 *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPMS_SCHEME_HASH_Marshal(source, buffer, size); return written; } UINT16 TPMS_KDF_SCHEME_KDF1_SP800_56A_Marshal(TPMS_KDF_SCHEME_KDF1_SP800_56A *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPMS_SCHEME_HASH_Marshal(source, buffer, size); return written; } UINT16 TPMS_KDF_SCHEME_KDF2_Marshal(TPMS_KDF_SCHEME_KDF2 *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPMS_SCHEME_HASH_Marshal(source, buffer, size); return written; } UINT16 TPMS_KDF_SCHEME_KDF1_SP800_108_Marshal(TPMS_KDF_SCHEME_KDF1_SP800_108 *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPMS_SCHEME_HASH_Marshal(source, buffer, size); return written; } /* Table 2:156 - Definition of TPMU_KDF_SCHEME Union (StructuresTable()) */ UINT16 TPMU_KDF_SCHEME_Marshal(TPMU_KDF_SCHEME *source, BYTE **buffer, INT32 *size, UINT32 selector) { UINT16 written = 0; switch (selector) { #if ALG_MGF1 case TPM_ALG_MGF1: written += TPMS_KDF_SCHEME_MGF1_Marshal(&source->mgf1, buffer, size); break; #endif #if ALG_KDF1_SP800_56A case TPM_ALG_KDF1_SP800_56A: written += TPMS_KDF_SCHEME_KDF1_SP800_56A_Marshal(&source->kdf1_sp800_56a, buffer, size); break; #endif #if ALG_KDF2 case TPM_ALG_KDF2: written += TPMS_KDF_SCHEME_KDF2_Marshal(&source->kdf2, buffer, size); break; #endif #if ALG_KDF1_SP800_108 case TPM_ALG_KDF1_SP800_108: written += TPMS_KDF_SCHEME_KDF1_SP800_108_Marshal(&source->kdf1_sp800_108, buffer, size); break; #endif case TPM_ALG_NULL: break; default: pAssert(FALSE); } return written; } /* Table 2:157 - Definition of TPMT_KDF_SCHEME Structure (StructuresTable()) */ UINT16 TPMT_KDF_SCHEME_Marshal(TPMT_KDF_SCHEME *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPMI_ALG_KDF_Marshal(&source->scheme, buffer, size); written += TPMU_KDF_SCHEME_Marshal(&source->details, buffer, size, source->scheme); return written; } /* Table 2:159 - Definition of TPMU_ASYM_SCHEME Union (StructuresTable()) */ UINT16 TPMU_ASYM_SCHEME_Marshal(TPMU_ASYM_SCHEME *source, BYTE **buffer, INT32 *size, UINT32 selector) { UINT16 written = 0; switch (selector) { #if ALG_ECDH case TPM_ALG_ECDH: written += TPMS_KEY_SCHEME_ECDH_Marshal(&source->ecdh, buffer, size); break; #endif #if ALG_ECMQV case TPM_ALG_ECMQV: written += TPMS_KEY_SCHEME_ECMQV_Marshal(&source->ecmqv, buffer, size); break; #endif #if ALG_RSASSA case TPM_ALG_RSASSA: written += TPMS_SIG_SCHEME_RSASSA_Marshal(&source->rsassa, buffer, size); break; #endif #if ALG_RSAPSS case TPM_ALG_RSAPSS: written += TPMS_SIG_SCHEME_RSAPSS_Marshal(&source->rsapss, buffer, size); break; #endif #if ALG_ECDSA case TPM_ALG_ECDSA: written += TPMS_SIG_SCHEME_ECDSA_Marshal(&source->ecdsa, buffer, size); break; #endif #if ALG_ECDAA case TPM_ALG_ECDAA: written += TPMS_SIG_SCHEME_ECDAA_Marshal(&source->ecdaa, buffer, size); break; #endif #if ALG_SM2 case TPM_ALG_SM2: written += TPMS_SIG_SCHEME_SM2_Marshal(&source->sm2, buffer, size); break; #endif #if ALG_ECSCHNORR case TPM_ALG_ECSCHNORR: written += TPMS_SIG_SCHEME_ECSCHNORR_Marshal(&source->ecschnorr, buffer, size); break; #endif #if ALG_RSAES case TPM_ALG_RSAES: written += TPMS_ENC_SCHEME_RSAES_Marshal(&source->rsaes, buffer, size); break; #endif #if ALG_OAEP case TPM_ALG_OAEP: written += TPMS_ENC_SCHEME_OAEP_Marshal(&source->oaep, buffer, size); break; #endif case TPM_ALG_NULL: break; default: pAssert(FALSE); } return written; } /* Table 2:161 - Definition of TPMI_ALG_RSA_SCHEME Type (InterfaceTable()) */ UINT16 TPMI_ALG_RSA_SCHEME_Marshal(TPMI_ALG_RSA_SCHEME *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM_ALG_ID_Marshal(source, buffer, size); return written; } /* Table 2:162 - Definition of TPMT_RSA_SCHEME Structure (StructuresTable()) */ UINT16 TPMT_RSA_SCHEME_Marshal(TPMT_RSA_SCHEME *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPMI_ALG_RSA_SCHEME_Marshal(&source->scheme, buffer, size); written += TPMU_ASYM_SCHEME_Marshal(&source->details, buffer, size, source->scheme); return written; } /* Table 2:165 - Definition of TPM2B_PUBLIC_KEY_RSA Structure (StructuresTable()) */ UINT16 TPM2B_PUBLIC_KEY_RSA_Marshal(TPM2B_PUBLIC_KEY_RSA *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM2B_Marshal(&source->b, sizeof(source->t.buffer), buffer, size); // libtpms changed return written; } /* Table 2:166 - Definition of TPMI_RSA_KEY_BITS Type (InterfaceTable()) */ UINT16 TPMI_RSA_KEY_BITS_Marshal(TPMI_RSA_KEY_BITS *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM_KEY_BITS_Marshal(source, buffer, size); return written; } /* Table 2:167 - Definition of TPM2B_PRIVATE_KEY_RSA Structure (StructuresTable()) */ UINT16 TPM2B_PRIVATE_KEY_RSA_Marshal(TPM2B_PRIVATE_KEY_RSA *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM2B_Marshal(&source->b, sizeof(source->t.buffer), buffer, size); // libtpms changed return written; } /* Table 2:168 - Definition of TPM2B_ECC_PARAMETER Structure (StructuresTable()) */ UINT16 TPM2B_ECC_PARAMETER_Marshal(TPM2B_ECC_PARAMETER *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM2B_Marshal(&source->b, sizeof(source->t.buffer), buffer, size); // libtpms changed return written; } /* Table 2:169 - Definition of TPMS_ECC_POINT Structure (StructuresTable()) */ UINT16 TPMS_ECC_POINT_Marshal(TPMS_ECC_POINT *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM2B_ECC_PARAMETER_Marshal(&source->x, buffer, size); written += TPM2B_ECC_PARAMETER_Marshal(&source->y, buffer, size); return written; } /* Table 2:170 - Definition of TPM2B_ECC_POINT Structure (StructuresTable()) */ UINT16 TPM2B_ECC_POINT_Marshal(TPM2B_ECC_POINT *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; BYTE *sizePtr; if (buffer != NULL) { sizePtr = *buffer; *buffer += sizeof(UINT16); } written += TPMS_ECC_POINT_Marshal(&source->point, buffer, size); if (buffer != NULL) { written += UINT16_Marshal(&written, &sizePtr, size); } else { written += sizeof(UINT16); } return written; } /* Table 2:171 - Definition of TPMI_ALG_ECC_SCHEME Type (InterfaceTable()) */ UINT16 TPMI_ALG_ECC_SCHEME_Marshal(TPMI_ALG_ECC_SCHEME *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM_ALG_ID_Marshal(source, buffer, size); return written; } /* Table 2:172 - Definition of TPMI_ECC_CURVE Type (InterfaceTable()) */ UINT16 TPMI_ECC_CURVE_Marshal(TPMI_ECC_CURVE *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM_ECC_CURVE_Marshal(source, buffer, size); return written; } /* Table 2:173 - Definition of TPMT_ECC_SCHEME Structure (StructuresTable()) */ UINT16 TPMT_ECC_SCHEME_Marshal(TPMT_ECC_SCHEME *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPMI_ALG_ECC_SCHEME_Marshal(&source->scheme, buffer, size); written += TPMU_ASYM_SCHEME_Marshal(&source->details, buffer, size, source->scheme); return written; } /* Table 2:174 - Definition of TPMS_ALGORITHM_DETAIL_ECC Structure (StructuresTable()) */ UINT16 TPMS_ALGORITHM_DETAIL_ECC_Marshal(TPMS_ALGORITHM_DETAIL_ECC *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM_ECC_CURVE_Marshal(&source->curveID, buffer, size); written += UINT16_Marshal(&source->keySize, buffer, size); written += TPMT_KDF_SCHEME_Marshal(&source->kdf, buffer, size); written += TPMT_ECC_SCHEME_Marshal(&source->sign, buffer, size); written += TPM2B_ECC_PARAMETER_Marshal(&source->p, buffer, size); written += TPM2B_ECC_PARAMETER_Marshal(&source->a, buffer, size); written += TPM2B_ECC_PARAMETER_Marshal(&source->b, buffer, size); written += TPM2B_ECC_PARAMETER_Marshal(&source->gX, buffer, size); written += TPM2B_ECC_PARAMETER_Marshal(&source->gY, buffer, size); written += TPM2B_ECC_PARAMETER_Marshal(&source->n, buffer, size); written += TPM2B_ECC_PARAMETER_Marshal(&source->h, buffer, size); return written; } /* Table 2:175 - Definition of TPMS_SIGNATURE_RSA Structure (StructuresTable()) */ UINT16 TPMS_SIGNATURE_RSA_Marshal(TPMS_SIGNATURE_RSA *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPMI_ALG_HASH_Marshal(&source->hash, buffer, size); written += TPM2B_PUBLIC_KEY_RSA_Marshal(&source->sig, buffer, size); return written; } /* Table 2:176 - Definition of Types for Signature (TypedefTable()) */ UINT16 TPMS_SIGNATURE_RSASSA_Marshal(TPMS_SIGNATURE_RSASSA *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPMS_SIGNATURE_RSA_Marshal(source, buffer, size); return written; } UINT16 TPMS_SIGNATURE_RSAPSS_Marshal(TPMS_SIGNATURE_RSAPSS *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPMS_SIGNATURE_RSA_Marshal(source, buffer, size); return written; } /* Table 2:177 - Definition of TPMS_SIGNATURE_ECC Structure (StructuresTable()) */ UINT16 TPMS_SIGNATURE_ECC_Marshal(TPMS_SIGNATURE_ECC *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPMI_ALG_HASH_Marshal(&source->hash, buffer, size); written += TPM2B_ECC_PARAMETER_Marshal(&source->signatureR, buffer, size); written += TPM2B_ECC_PARAMETER_Marshal(&source->signatureS, buffer, size); return written; } /* Table 2:178 - Definition of Types for TPMS_SIGNATURE_ECC (TypedefTable()) */ UINT16 TPMS_SIGNATURE_ECDSA_Marshal(TPMS_SIGNATURE_ECDSA *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPMS_SIGNATURE_ECC_Marshal(source, buffer, size); return written; } UINT16 TPMS_SIGNATURE_ECDAA_Marshal(TPMS_SIGNATURE_ECDAA *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPMS_SIGNATURE_ECC_Marshal(source, buffer, size); return written; } UINT16 TPMS_SIGNATURE_SM2_Marshal(TPMS_SIGNATURE_SM2 *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPMS_SIGNATURE_ECC_Marshal(source, buffer, size); return written; } UINT16 TPMS_SIGNATURE_ECSCHNORR_Marshal(TPMS_SIGNATURE_ECSCHNORR *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPMS_SIGNATURE_ECC_Marshal(source, buffer, size); return written; } /* Table 2:179 - Definition of TPMU_SIGNATURE Union (StructuresTable()) */ UINT16 TPMU_SIGNATURE_Marshal(TPMU_SIGNATURE *source, BYTE **buffer, INT32 *size, UINT32 selector) { UINT16 written = 0; switch (selector) { #if ALG_RSASSA case TPM_ALG_RSASSA: written += TPMS_SIGNATURE_RSASSA_Marshal(&source->rsassa, buffer, size); break; #endif #if ALG_RSAPSS case TPM_ALG_RSAPSS: written += TPMS_SIGNATURE_RSAPSS_Marshal(&source->rsapss, buffer, size); break; #endif #if ALG_ECDSA case TPM_ALG_ECDSA: written += TPMS_SIGNATURE_ECDSA_Marshal(&source->ecdsa, buffer, size); break; #endif #if ALG_ECDAA case TPM_ALG_ECDAA: written += TPMS_SIGNATURE_ECDAA_Marshal(&source->ecdaa, buffer, size); break; #endif #if ALG_SM2 case TPM_ALG_SM2: written += TPMS_SIGNATURE_SM2_Marshal(&source->sm2, buffer, size); break; #endif #if ALG_ECSCHNORR case TPM_ALG_ECSCHNORR: written += TPMS_SIGNATURE_ECSCHNORR_Marshal(&source->ecschnorr, buffer, size); break; #endif #if ALG_HMAC case TPM_ALG_HMAC: written += TPMT_HA_Marshal(&source->hmac, buffer, size); break; #endif case TPM_ALG_NULL: break; default: pAssert(FALSE); } return written; } /* Table 2:180 - Definition of TPMT_SIGNATURE Structure (StructuresTable()) */ UINT16 TPMT_SIGNATURE_Marshal(TPMT_SIGNATURE *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPMI_ALG_SIG_SCHEME_Marshal(&source->sigAlg, buffer, size); written += TPMU_SIGNATURE_Marshal(&source->signature, buffer, size, source->sigAlg); return written; } /* Table 2:182 - Definition of TPM2B_ENCRYPTED_SECRET Structure (StructuresTable()) */ UINT16 TPM2B_ENCRYPTED_SECRET_Marshal(TPM2B_ENCRYPTED_SECRET *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM2B_Marshal(&source->b, sizeof(source->t.secret), buffer, size); // libtpms changed return written; } /* Table 2:183 - Definition of TPMI_ALG_PUBLIC Type (InterfaceTable()) */ UINT16 TPMI_ALG_PUBLIC_Marshal(TPMI_ALG_PUBLIC *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM_ALG_ID_Marshal(source, buffer, size); return written; } /* Table 2:184 - Definition of TPMU_PUBLIC_ID Union (StructuresTable()) */ UINT16 TPMU_PUBLIC_ID_Marshal(TPMU_PUBLIC_ID *source, BYTE **buffer, INT32 *size, UINT32 selector) { UINT16 written = 0; switch (selector) { #if ALG_KEYEDHASH case TPM_ALG_KEYEDHASH: written += TPM2B_DIGEST_Marshal(&source->keyedHash, buffer, size); break; #endif #if ALG_SYMCIPHER case TPM_ALG_SYMCIPHER: written += TPM2B_DIGEST_Marshal(&source->sym, buffer, size); break; #endif #if ALG_RSA case TPM_ALG_RSA: written += TPM2B_PUBLIC_KEY_RSA_Marshal(&source->rsa, buffer, size); break; #endif #if ALG_ECC case TPM_ALG_ECC: written += TPMS_ECC_POINT_Marshal(&source->ecc, buffer, size); break; #endif default: pAssert(FALSE); } return written; } /* Table 2:185 - Definition of TPMS_KEYEDHASH_PARMS Structure (StructuresTable()) */ UINT16 TPMS_KEYEDHASH_PARMS_Marshal(TPMS_KEYEDHASH_PARMS *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPMT_KEYEDHASH_SCHEME_Marshal(&source->scheme, buffer, size); return written; } /* Table 2:187 - Definition of TPMS_RSA_PARMS Structure (StructuresTable()) */ UINT16 TPMS_RSA_PARMS_Marshal(TPMS_RSA_PARMS *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPMT_SYM_DEF_OBJECT_Marshal(&source->symmetric, buffer, size); written += TPMT_RSA_SCHEME_Marshal(&source->scheme, buffer, size); written += TPMI_RSA_KEY_BITS_Marshal(&source->keyBits, buffer, size); written += UINT32_Marshal(&source->exponent, buffer, size); return written; } /* Table 2:188 - Definition of TPMS_ECC_PARMS Structure (StructuresTable()) */ UINT16 TPMS_ECC_PARMS_Marshal(TPMS_ECC_PARMS *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPMT_SYM_DEF_OBJECT_Marshal(&source->symmetric, buffer, size); written += TPMT_ECC_SCHEME_Marshal(&source->scheme, buffer, size); written += TPMI_ECC_CURVE_Marshal(&source->curveID, buffer, size); written += TPMT_KDF_SCHEME_Marshal(&source->kdf, buffer, size); return written; } /* Table 2:189 - Definition of TPMU_PUBLIC_PARMS Union (StructuresTable()) */ UINT16 TPMU_PUBLIC_PARMS_Marshal(TPMU_PUBLIC_PARMS *source, BYTE **buffer, INT32 *size, UINT32 selector) { UINT16 written = 0; switch (selector) { #if ALG_KEYEDHASH case TPM_ALG_KEYEDHASH: written += TPMS_KEYEDHASH_PARMS_Marshal(&source->keyedHashDetail, buffer, size); break; #endif #if ALG_SYMCIPHER case TPM_ALG_SYMCIPHER: written += TPMS_SYMCIPHER_PARMS_Marshal(&source->symDetail, buffer, size); break; #endif #if ALG_RSA case TPM_ALG_RSA: written += TPMS_RSA_PARMS_Marshal(&source->rsaDetail, buffer, size); break; #endif #if ALG_ECC case TPM_ALG_ECC: written += TPMS_ECC_PARMS_Marshal(&source->eccDetail, buffer, size); break; #endif default: pAssert(FALSE); } return written; } /* Table 2:191 - Definition of TPMT_PUBLIC Structure (StructuresTable()) */ UINT16 TPMT_PUBLIC_Marshal(TPMT_PUBLIC *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPMI_ALG_PUBLIC_Marshal(&source->type, buffer, size); written += TPMI_ALG_HASH_Marshal(&source->nameAlg, buffer, size); written += TPMA_OBJECT_Marshal(&source->objectAttributes, buffer, size); written += TPM2B_DIGEST_Marshal(&source->authPolicy, buffer, size); written += TPMU_PUBLIC_PARMS_Marshal(&source->parameters, buffer, size, source->type); written += TPMU_PUBLIC_ID_Marshal(&source->unique, buffer, size, source->type); return written; } /* Table 2:192 - Definition of TPM2B_PUBLIC Structure (StructuresTable()) */ UINT16 TPM2B_PUBLIC_Marshal(TPM2B_PUBLIC *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; BYTE *sizePtr = NULL; // libtpms changes for ppc64el gcc-5 -O3 if (buffer != NULL) { sizePtr = *buffer; *buffer += sizeof(UINT16); } written += TPMT_PUBLIC_Marshal(&source->publicArea, buffer, size); if (buffer != NULL) { written += UINT16_Marshal(&written, &sizePtr, size); } else { written += sizeof(UINT16); } return written; } /* Table 2:195 - Definition of TPMU_SENSITIVE_COMPOSITE Union (StructuresTable()) */ UINT16 TPMU_SENSITIVE_COMPOSITE_Marshal(TPMU_SENSITIVE_COMPOSITE *source, BYTE **buffer, INT32 *size, UINT32 selector) { UINT16 written = 0; switch (selector) { #if ALG_RSA case TPM_ALG_RSA: written += TPM2B_PRIVATE_KEY_RSA_Marshal(&source->rsa, buffer, size); break; #endif #if ALG_ECC case TPM_ALG_ECC: written += TPM2B_ECC_PARAMETER_Marshal(&source->ecc, buffer, size); break; #endif #if ALG_KEYEDHASH case TPM_ALG_KEYEDHASH: written += TPM2B_SENSITIVE_DATA_Marshal(&source->bits, buffer, size); break; #endif #if ALG_SYMCIPHER case TPM_ALG_SYMCIPHER: written += TPM2B_SYM_KEY_Marshal(&source->sym, buffer, size); break; #endif default: pAssert(FALSE); } return written; } /* Table 2:196 - Definition of TPMT_SENSITIVE Structure (StructuresTable()) */ UINT16 TPMT_SENSITIVE_Marshal(TPMT_SENSITIVE *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPMI_ALG_PUBLIC_Marshal(&source->sensitiveType, buffer, size); written += TPM2B_AUTH_Marshal(&source->authValue, buffer, size); written += TPM2B_DIGEST_Marshal(&source->seedValue, buffer, size); written += TPMU_SENSITIVE_COMPOSITE_Marshal(&source->sensitive, buffer, size, source->sensitiveType); return written; } /* Table 2:199 - Definition of TPM2B_PRIVATE Structure (StructuresTable()) */ UINT16 TPM2B_PRIVATE_Marshal(TPM2B_PRIVATE *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM2B_Marshal(&source->b, sizeof(source->t.buffer), buffer, size); // libtpms changed return written; } /* Table 2:201 - Definition of TPM2B_ID_OBJECT Structure (StructuresTable()) */ UINT16 TPM2B_ID_OBJECT_Marshal(TPM2B_ID_OBJECT *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM2B_Marshal(&source->b, sizeof(source->t.credential), buffer, size); // libtpms changed return written; } /* Table 2:205 - Definition of TPMA_NV Bits (BitsTable()) */ UINT16 TPMA_NV_Marshal(TPMA_NV *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += UINT32_Marshal((UINT32 *)source, buffer, size); /* libtpms changed */ return written; } /* Table 2:206 - Definition of TPMS_NV_PUBLIC Structure (StructuresTable()) */ UINT16 TPMS_NV_PUBLIC_Marshal(TPMS_NV_PUBLIC *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPMI_RH_NV_INDEX_Marshal(&source->nvIndex, buffer, size); written += TPMI_ALG_HASH_Marshal(&source->nameAlg, buffer, size); written += TPMA_NV_Marshal(&source->attributes, buffer, size); written += TPM2B_DIGEST_Marshal(&source->authPolicy, buffer, size); written += UINT16_Marshal(&source->dataSize, buffer, size); return written; } /* Table 2:207 - Definition of TPM2B_NV_PUBLIC Structure (StructuresTable()) */ UINT16 TPM2B_NV_PUBLIC_Marshal(TPM2B_NV_PUBLIC *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; BYTE *sizePtr; if (buffer != NULL) { sizePtr = *buffer; *buffer += sizeof(UINT16); } written += TPMS_NV_PUBLIC_Marshal(&source->nvPublic, buffer, size); if (buffer != NULL) { written += UINT16_Marshal(&written, &sizePtr, size); } else { written += sizeof(UINT16); } return written; } /* Table 2:210 - Definition of TPM2B_CONTEXT_DATA Structure (StructuresTable()) */ UINT16 TPM2B_CONTEXT_DATA_Marshal(TPM2B_CONTEXT_DATA *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM2B_Marshal(&source->b, sizeof(source->t.buffer), buffer, size); // libtpms changed return written; } /* Table 2:211 - Definition of TPMS_CONTEXT Structure (StructuresTable()) */ UINT16 TPMS_CONTEXT_Marshal(TPMS_CONTEXT *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += UINT64_Marshal(&source->sequence, buffer, size); written += TPMI_DH_SAVED_Marshal(&source->savedHandle, buffer, size); written += TPMI_RH_HIERARCHY_Marshal(&source->hierarchy, buffer, size); written += TPM2B_CONTEXT_DATA_Marshal(&source->contextBlob, buffer, size); return written; } /* Table 2:213 - Definition of TPMS_CREATION_DATA Structure (StructuresTable()) */ UINT16 TPMS_CREATION_DATA_Marshal(TPMS_CREATION_DATA *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPML_PCR_SELECTION_Marshal(&source->pcrSelect, buffer, size); written += TPM2B_DIGEST_Marshal(&source->pcrDigest, buffer, size); written += TPMA_LOCALITY_Marshal(&source->locality, buffer, size); written += TPM_ALG_ID_Marshal(&source->parentNameAlg, buffer, size); written += TPM2B_NAME_Marshal(&source->parentName, buffer, size); written += TPM2B_NAME_Marshal(&source->parentQualifiedName, buffer, size); written += TPM2B_DATA_Marshal(&source->outsideInfo, buffer, size); return written; } /* Table 2:214 - Definition of TPM2B_CREATION_DATA Structure (StructuresTable()) */ UINT16 TPM2B_CREATION_DATA_Marshal(TPM2B_CREATION_DATA *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; BYTE *sizePtr = NULL; // libtpms added for s390x on Fedora 32 if (buffer != NULL) { sizePtr = *buffer; *buffer += sizeof(UINT16); } written += TPMS_CREATION_DATA_Marshal(&source->creationData, buffer, size); if (buffer != NULL) { written += UINT16_Marshal(&written, &sizePtr, size); } else { written += sizeof(UINT16); } return written; } /* Table 225 - Definition of (UINT32) TPM_AT Constants */ UINT16 TPM_AT_Marshal(TPM_AT *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += UINT32_Marshal(source, buffer, size); return written; } /* Table 227 - Definition of TPMS_AC_OUTPUT Structure */ UINT16 TPMS_AC_OUTPUT_Marshal(TPMS_AC_OUTPUT *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM_AT_Marshal(&source->tag, buffer, size); written += UINT32_Marshal(&source->data, buffer, size); return written; } /* Table 228 - Definition of TPML_AC_CAPABILITIES Structure */ UINT16 TPML_AC_CAPABILITIES_Marshal(TPML_AC_CAPABILITIES *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; UINT32 i; written += UINT32_Marshal(&source->count, buffer, size); for (i = 0 ; i < source->count ; i++) { written += TPMS_AC_OUTPUT_Marshal(&source->acCapabilities[i], buffer, size); } return written; } libtpms-0.9.3/src/tpm2/Marshal_fp.h000066400000000000000000000452751421143571500171130ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Parameter Marshaling */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Marshal_fp.h 1635 2020-06-12 21:48:27Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2020 */ /* */ /********************************************************************************/ #ifndef MARSHAL_FP_H #define MARSHAL_FP_H #include "TpmTypes.h" #ifdef __cplusplus extern "C" { #endif UINT16 UINT8_Marshal(UINT8 *source, BYTE **buffer, INT32 *size); UINT16 UINT16_Marshal(UINT16 *source, BYTE **buffer, INT32 *size); UINT16 UINT32_Marshal(UINT32 *source, BYTE **buffer, INT32 *size); UINT16 UINT64_Marshal(UINT64 *source, BYTE **buffer, INT32 *size); UINT16 Array_Marshal(BYTE *sourceBuffer, UINT16 sourceSize, BYTE **buffer, INT32 *size); UINT16 TPM2B_Marshal(TPM2B *source, UINT32 maxSize, BYTE **buffer, INT32 *size); // libtpms changed UINT16 TPM_KEY_BITS_Marshal(TPM_KEY_BITS *source, BYTE **buffer, INT32 *size); UINT16 TPM_CONSTANTS32_Marshal(TPM_CONSTANTS32 *source, BYTE **buffer, INT32 *size); UINT16 TPM_ALG_ID_Marshal(TPM_ALG_ID *source, BYTE **buffer, INT32 *size); UINT16 TPM_ECC_CURVE_Marshal(TPM_ECC_CURVE *source, BYTE **buffer, INT32 *size); UINT16 TPM_CC_Marshal(TPM_CC *source, BYTE **buffer, INT32 *size); UINT16 TPM_RC_Marshal(TPM_RC *source, BYTE **buffer, INT32 *size); UINT16 TPM_ST_Marshal(TPM_ST *source, BYTE **buffer, INT32 *size); INT16 TPM_CAP_Marshal(TPM_CAP *source, BYTE **buffer, INT32 *size); UINT16 TPM_PT_Marshal(TPM_PT *source, BYTE **buffer, INT32 *size); UINT16 TPM_PT_PCR_Marshal(TPM_PT_PCR *source, BYTE **buffer, INT32 *size); UINT16 TPM_HANDLE_Marshal(TPM_HANDLE *source, BYTE **buffer, INT32 *size); UINT16 TPMA_ALGORITHM_Marshal(TPMA_ALGORITHM *source, BYTE **buffer, INT32 *size); UINT16 TPMA_OBJECT_Marshal(TPMA_OBJECT *source, BYTE **buffer, INT32 *size); UINT16 TPMA_SESSION_Marshal(TPMA_SESSION *source, BYTE **buffer, INT32 *size); UINT16 TPMA_LOCALITY_Marshal(TPMA_LOCALITY *source, BYTE **buffer, INT32 *size); UINT16 TPMA_CC_Marshal(TPMA_CC *source, BYTE **buffer, INT32 *size); UINT16 TPMI_YES_NO_Marshal(TPMI_YES_NO *source, BYTE **buffer, INT32 *size); UINT16 TPMA_ACT_Marshal(TPMA_ACT *source, BYTE **buffer, INT32 *size); UINT16 TPMI_DH_SAVED_Marshal(TPMI_DH_CONTEXT *source, BYTE **buffer, INT32 *size); UINT16 TPMI_RH_HIERARCHY_Marshal(TPMI_RH_HIERARCHY *source, BYTE **buffer, INT32 *size); UINT16 TPMI_RH_NV_INDEX_Marshal(TPMI_RH_NV_INDEX *source, BYTE **buffer, INT32 *size); UINT16 TPMI_ALG_HASH_Marshal(TPMI_ALG_HASH *source, BYTE **buffer, INT32 *size); UINT16 TPMI_ALG_SYM_OBJECT_Marshal(TPMI_ALG_SYM_OBJECT *source, BYTE **buffer, INT32 *size); UINT16 TPMU_SYM_KEY_BITS_Marshal(TPMU_SYM_KEY_BITS *source, BYTE **buffer, INT32 *size, UINT32 selector); UINT16 TPMI_ALG_SYM_MODE_Marshal(TPMI_ALG_SYM_MODE *source, BYTE **buffer, INT32 *size); UINT16 TPMI_ALG_KDF_Marshal(TPMI_ALG_KDF *source, BYTE **buffer, INT32 *size); UINT16 TPMI_ALG_SIG_SCHEME_Marshal(TPMI_ALG_SIG_SCHEME *source, BYTE **buffer, INT32 *size); UINT16 TPMU_HA_Marshal(TPMU_HA *source, BYTE **buffer, INT32 *size, UINT32 selector); UINT16 TPMT_HA_Marshal(TPMT_HA *source, BYTE **buffer, INT32 *size); UINT16 TPM2B_DIGEST_Marshal(TPM2B_DIGEST *source, BYTE **buffer, INT32 *size); UINT16 TPM2B_DATA_Marshal(TPM2B_DATA *source, BYTE **buffer, INT32 *size); UINT16 TPM2B_NONCE_Marshal(TPM2B_NONCE *source, BYTE **buffer, INT32 *size); UINT16 TPM2B_AUTH_Marshal(TPM2B_AUTH *source, BYTE **buffer, INT32 *size); UINT16 TPM2B_MAX_BUFFER_Marshal(TPM2B_MAX_BUFFER *source, BYTE **buffer, INT32 *size); UINT16 TPM2B_MAX_NV_BUFFER_Marshal(TPM2B_MAX_NV_BUFFER *source, BYTE **buffer, INT32 *size); UINT16 TPM2B_TIMEOUT_Marshal(TPM2B_TIMEOUT *source, BYTE **buffer, INT32 *size); UINT16 TPM2B_IV_Marshal(TPM2B_IV *source, BYTE **buffer, INT32 *size); UINT16 TPM2B_NAME_Marshal(TPM2B_NAME *source, BYTE **buffer, INT32 *size); UINT16 TPMS_PCR_SELECTION_Marshal(TPMS_PCR_SELECTION *source, BYTE **buffer, INT32 *size); UINT16 TPMT_TK_CREATION_Marshal(TPMT_TK_CREATION *source, BYTE **buffer, INT32 *size); UINT16 TPMT_TK_VERIFIED_Marshal(TPMT_TK_VERIFIED *source, BYTE **buffer, INT32 *size); UINT16 TPMT_TK_AUTH_Marshal(TPMT_TK_AUTH *source, BYTE **buffer, INT32 *size); UINT16 TPMT_TK_HASHCHECK_Marshal(TPMT_TK_HASHCHECK *source, BYTE **buffer, INT32 *size); UINT16 TPMS_ALG_PROPERTY_Marshal(TPMS_ALG_PROPERTY *source, BYTE **buffer, INT32 *size); UINT16 TPMS_TAGGED_PCR_SELECT_Marshal(TPMS_TAGGED_PCR_SELECT *source, BYTE **buffer, INT32 *size); UINT16 TPMS_TAGGED_POLICY_Marshal(TPMS_TAGGED_POLICY *source, BYTE **buffer, INT32 *size); UINT16 TPMS_ACT_DATA_Marshal(TPMS_ACT_DATA *source, BYTE **buffer, INT32 *size); UINT16 TPMS_TAGGED_PROPERTY_Marshal(TPMS_TAGGED_PROPERTY *source, BYTE **buffer, INT32 *size); UINT16 TPML_CC_Marshal(TPML_CC *source, BYTE **buffer, INT32 *size); UINT16 TPML_CCA_Marshal(TPML_CCA *source, BYTE **buffer, INT32 *size); UINT16 TPML_ALG_Marshal(TPML_ALG *source, BYTE **buffer, INT32 *size); UINT16 TPML_DIGEST_Marshal(TPML_DIGEST *source, BYTE **buffer, INT32 *size); UINT16 TPML_HANDLE_Marshal(TPML_HANDLE *source, BYTE **buffer, INT32 *size); UINT16 TPML_DIGEST_VALUES_Marshal(TPML_DIGEST_VALUES *source, BYTE **buffer, INT32 *size); UINT16 TPML_PCR_SELECTION_Marshal(TPML_PCR_SELECTION *source, BYTE **buffer, INT32 *size); UINT16 TPML_ALG_PROPERTY_Marshal(TPML_ALG_PROPERTY *source, BYTE **buffer, INT32 *size); UINT16 TPML_TAGGED_TPM_PROPERTY_Marshal(TPML_TAGGED_TPM_PROPERTY *source, BYTE **buffer, INT32 *size); UINT16 TPML_TAGGED_PCR_PROPERTY_Marshal(TPML_TAGGED_PCR_PROPERTY *source, BYTE **buffer, INT32 *size); UINT16 TPML_ECC_CURVE_Marshal(TPML_ECC_CURVE *source, BYTE **buffer, INT32 *size); UINT16 TPML_TAGGED_POLICY_Marshal(TPML_TAGGED_POLICY *source, BYTE **buffer, INT32 *size); UINT16 TPML_ACT_DATA_Marshal(TPML_ACT_DATA *source, BYTE **buffer, INT32 *size); UINT16 TPMU_CAPABILITIES_Marshal(TPMU_CAPABILITIES *source, BYTE **buffer, INT32 *size, UINT32 selector); UINT16 TPMS_CAPABILITY_DATA_Marshal(TPMS_CAPABILITY_DATA *source, BYTE **buffer, INT32 *size); UINT16 TPMS_CLOCK_INFO_Marshal(TPMS_CLOCK_INFO *source, BYTE **buffer, INT32 *size); UINT16 TPMS_TIME_INFO_Marshal(TPMS_TIME_INFO *source, BYTE **buffer, INT32 *size); UINT16 TPMS_TIME_ATTEST_INFO_Marshal(TPMS_TIME_ATTEST_INFO *source, BYTE **buffer, INT32 *size); UINT16 TPMS_CERTIFY_INFO_Marshal(TPMS_CERTIFY_INFO *source, BYTE **buffer, INT32 *size); UINT16 TPMS_QUOTE_INFO_Marshal(TPMS_QUOTE_INFO *source, BYTE **buffer, INT32 *size); UINT16 TPMS_COMMAND_AUDIT_INFO_Marshal(TPMS_COMMAND_AUDIT_INFO *source, BYTE **buffer, INT32 *size); UINT16 TPMS_SESSION_AUDIT_INFO_Marshal(TPMS_SESSION_AUDIT_INFO *source, BYTE **buffer, INT32 *size); UINT16 TPMS_CREATION_INFO_Marshal(TPMS_CREATION_INFO *source, BYTE **buffer, INT32 *size); UINT16 TPMS_NV_CERTIFY_INFO_Marshal(TPMS_NV_CERTIFY_INFO *source, BYTE **buffer, INT32 *size); UINT16 TPMS_NV_DIGEST_CERTIFY_INFO_Marshal(TPMS_NV_DIGEST_CERTIFY_INFO *source, BYTE **buffer, INT32 *size); UINT16 TPM_ST_ATTEST_NV_DIGEST_Marshal(TPMS_NV_DIGEST_CERTIFY_INFO *source, BYTE **buffer, INT32 *size); UINT16 TPMI_ST_ATTEST_Marshal(TPMI_ST_ATTEST *source, BYTE **buffer, INT32 *size); UINT16 TPMU_ATTEST_Marshal(TPMU_ATTEST *source, BYTE **buffer, INT32 *size, UINT32 selector); UINT16 TPMS_ATTEST_Marshal(TPMS_ATTEST *source, BYTE **buffer, INT32 *size); UINT16 TPM2B_ATTEST_Marshal(TPM2B_ATTEST *source, BYTE **buffer, INT32 *size); UINT16 TPMI_AES_KEY_BITS_Marshal(TPMI_AES_KEY_BITS *source, BYTE **buffer, INT32 *size); UINT16 // libtpms added TPMI_TDES_KEY_BITS_Marshal(TPMI_TDES_KEY_BITS *source, BYTE **buffer, INT32 *size); UINT16 TPMI_CAMELLIA_KEY_BITS_Marshal(TPMI_CAMELLIA_KEY_BITS *source, BYTE **buffer, INT32 *size); UINT16 TPMU_SYM_KEY_BITS_Marshal(TPMU_SYM_KEY_BITS *source, BYTE **buffer, INT32 *size, UINT32 selector); UINT16 TPMU_SYM_MODE_Marshal(TPMU_SYM_MODE *source, BYTE **buffer, INT32 *size, UINT32 selector); UINT16 TPMT_SYM_DEF_OBJECT_Marshal(TPMT_SYM_DEF_OBJECT *source, BYTE **buffer, INT32 *size); UINT16 TPM2B_SYM_KEY_Marshal(TPM2B_SYM_KEY *source, BYTE **buffer, INT32 *size); UINT16 TPMS_SYMCIPHER_PARMS_Marshal(TPMS_SYMCIPHER_PARMS *source, BYTE **buffer, INT32 *size); UINT16 TPM2B_SENSITIVE_DATA_Marshal(TPM2B_SENSITIVE_DATA *source, BYTE **buffer, INT32 *size); UINT16 TPMS_SCHEME_HASH_Marshal(TPMS_SCHEME_HASH *source, BYTE **buffer, INT32 *size); UINT16 TPMS_SCHEME_ECDAA_Marshal(TPMS_SCHEME_ECDAA *source, BYTE **buffer, INT32 *size); UINT16 TPMI_ALG_KEYEDHASH_SCHEME_Marshal(TPMI_ALG_KEYEDHASH_SCHEME *source, BYTE **buffer, INT32 *size); UINT16 TPMS_SCHEME_HMAC_Marshal(TPMS_SCHEME_HMAC *source, BYTE **buffer, INT32 *size); UINT16 TPMS_SCHEME_XOR_Marshal(TPMS_SCHEME_XOR *source, BYTE **buffer, INT32 *size); UINT16 TPMT_KEYEDHASH_SCHEME_Marshal(TPMT_KEYEDHASH_SCHEME *source, BYTE **buffer, INT32 *size); UINT16 TPMS_SIG_SCHEME_RSASSA_Marshal(TPMS_SIG_SCHEME_RSASSA *source, BYTE **buffer, INT32 *size); UINT16 TPMS_SIG_SCHEME_RSAPSS_Marshal(TPMS_SIG_SCHEME_RSAPSS *source, BYTE **buffer, INT32 *size); UINT16 TPMS_SIG_SCHEME_ECDSA_Marshal(TPMS_SIG_SCHEME_ECDSA *source, BYTE **buffer, INT32 *size); UINT16 TPMS_SIG_SCHEME_SM2_Marshal(TPMS_SIG_SCHEME_SM2 *source, BYTE **buffer, INT32 *size); UINT16 TPMS_SIG_SCHEME_ECSCHNORR_Marshal(TPMS_SIG_SCHEME_ECSCHNORR *source, BYTE **buffer, INT32 *size); UINT16 TPMS_SIG_SCHEME_ECDAA_Marshal(TPMS_SIG_SCHEME_ECDAA *source, BYTE **buffer, INT32 *size); UINT16 TPMS_ENC_SCHEME_OAEP_Marshal(TPMS_ENC_SCHEME_OAEP *source, BYTE **buffer, INT32 *size); UINT16 TPMS_ENC_SCHEME_RSAES_Marshal(TPMS_ENC_SCHEME_RSAES *source, BYTE **buffer, INT32 *size); UINT16 TPMU_SCHEME_KEYEDHASH_Marshal(TPMU_SCHEME_KEYEDHASH *source, BYTE **buffer, INT32 *size, UINT32 selector); UINT16 TPMS_KEY_SCHEME_ECDH_Marshal(TPMS_KEY_SCHEME_ECDH *source, BYTE **buffer, INT32 *size); UINT16 TPMS_KEY_SCHEME_ECMQV_Marshal(TPMS_KEY_SCHEME_ECMQV*source, BYTE **buffer, INT32 *size); UINT16 TPMS_KDF_SCHEME_MGF1_Marshal(TPMS_KDF_SCHEME_MGF1 *source, BYTE **buffer, INT32 *size); UINT16 TPMS_KDF_SCHEME_KDF1_SP800_56A_Marshal(TPMS_KDF_SCHEME_KDF1_SP800_56A *source, BYTE **buffer, INT32 *size); UINT16 TPMS_KDF_SCHEME_KDF2_Marshal(TPMS_KDF_SCHEME_KDF2 *source, BYTE **buffer, INT32 *size); UINT16 TPMS_KDF_SCHEME_KDF1_SP800_108_Marshal(TPMS_KDF_SCHEME_KDF1_SP800_108 *source, BYTE **buffer, INT32 *size); UINT16 TPMU_KDF_SCHEME_Marshal(TPMU_KDF_SCHEME *source, BYTE **buffer, INT32 *size, UINT32 selector); UINT16 TPMT_KDF_SCHEME_Marshal(TPMT_KDF_SCHEME *source, BYTE **buffer, INT32 *size); UINT16 TPMU_ASYM_SCHEME_Marshal(TPMU_ASYM_SCHEME *source, BYTE **buffer, INT32 *size, UINT32 selector); UINT16 TPMI_ALG_RSA_SCHEME_Marshal(TPMI_ALG_RSA_SCHEME *source, BYTE **buffer, INT32 *size); UINT16 TPMT_RSA_SCHEME_Marshal(TPMT_RSA_SCHEME *source, BYTE **buffer, INT32 *size); UINT16 TPM2B_PUBLIC_KEY_RSA_Marshal(TPM2B_PUBLIC_KEY_RSA *source, BYTE **buffer, INT32 *size); UINT16 TPMI_RSA_KEY_BITS_Marshal(TPMI_RSA_KEY_BITS *source, BYTE **buffer, INT32 *size); UINT16 TPM2B_PRIVATE_KEY_RSA_Marshal(TPM2B_PRIVATE_KEY_RSA *source, BYTE **buffer, INT32 *size); UINT16 TPM2B_ECC_PARAMETER_Marshal(TPM2B_ECC_PARAMETER *source, BYTE **buffer, INT32 *size); UINT16 TPMS_ECC_POINT_Marshal(TPMS_ECC_POINT *source, BYTE **buffer, INT32 *size); UINT16 TPM2B_ECC_POINT_Marshal(TPM2B_ECC_POINT *source, BYTE **buffer, INT32 *size); UINT16 TPMI_ALG_ECC_SCHEME_Marshal(TPMI_ALG_ECC_SCHEME *source, BYTE **buffer, INT32 *size); UINT16 TPMI_ECC_CURVE_Marshal(TPMI_ECC_CURVE *source, BYTE **buffer, INT32 *size); UINT16 TPMT_ECC_SCHEME_Marshal(TPMT_ECC_SCHEME *source, BYTE **buffer, INT32 *size); UINT16 TPMS_ALGORITHM_DETAIL_ECC_Marshal(TPMS_ALGORITHM_DETAIL_ECC *source, BYTE **buffer, INT32 *size); UINT16 TPMS_SIGNATURE_RSA_Marshal(TPMS_SIGNATURE_RSA *source, BYTE **buffer, INT32 *size); UINT16 TPMS_SIGNATURE_RSASSA_Marshal(TPMS_SIGNATURE_RSASSA *source, BYTE **buffer, INT32 *size); UINT16 TPMS_SIGNATURE_RSAPSS_Marshal(TPMS_SIGNATURE_RSAPSS *source, BYTE **buffer, INT32 *size); UINT16 TPMS_SIGNATURE_ECC_Marshal(TPMS_SIGNATURE_ECC *source, BYTE **buffer, INT32 *size); UINT16 TPMS_SIGNATURE_ECDSA_Marshal(TPMS_SIGNATURE_ECDSA *source, BYTE **buffer, INT32 *size); UINT16 TPMS_SIGNATURE_ECDAA_Marshal(TPMS_SIGNATURE_ECDAA *source, BYTE **buffer, INT32 *size); UINT16 TPMS_SIGNATURE_SM2_Marshal(TPMS_SIGNATURE_SM2 *source, BYTE **buffer, INT32 *size); UINT16 TPMS_SIGNATURE_ECSCHNORR_Marshal(TPMS_SIGNATURE_ECSCHNORR *source, BYTE **buffer, INT32 *size); UINT16 TPMU_SIGNATURE_Marshal(TPMU_SIGNATURE *source, BYTE **buffer, INT32 *size, UINT32 selector); UINT16 TPMT_SIGNATURE_Marshal(TPMT_SIGNATURE *source, BYTE **buffer, INT32 *size); UINT16 TPM2B_ENCRYPTED_SECRET_Marshal(TPM2B_ENCRYPTED_SECRET *source, BYTE **buffer, INT32 *size); UINT16 TPMI_ALG_PUBLIC_Marshal(TPMI_ALG_PUBLIC *source, BYTE **buffer, INT32 *size); UINT16 TPMU_PUBLIC_ID_Marshal(TPMU_PUBLIC_ID *source, BYTE **buffer, INT32 *size, UINT32 selector); UINT16 TPMS_KEYEDHASH_PARMS_Marshal(TPMS_KEYEDHASH_PARMS *source, BYTE **buffer, INT32 *size); UINT16 TPMS_RSA_PARMS_Marshal(TPMS_RSA_PARMS *source, BYTE **buffer, INT32 *size); UINT16 TPMS_ECC_PARMS_Marshal(TPMS_ECC_PARMS *source, BYTE **buffer, INT32 *size); UINT16 TPMU_PUBLIC_PARMS_Marshal(TPMU_PUBLIC_PARMS *source, BYTE **buffer, INT32 *size, UINT32 selector); UINT16 TPMT_PUBLIC_Marshal(TPMT_PUBLIC *source, BYTE **buffer, INT32 *size); UINT16 TPM2B_PUBLIC_Marshal(TPM2B_PUBLIC *source, BYTE **buffer, INT32 *size); UINT16 TPMU_SENSITIVE_COMPOSITE_Marshal(TPMU_SENSITIVE_COMPOSITE *source, BYTE **buffer, INT32 *size, UINT32 selector); UINT16 TPMT_SENSITIVE_Marshal(TPMT_SENSITIVE *source, BYTE **buffer, INT32 *size); UINT16 TPM2B_PRIVATE_Marshal(TPM2B_PRIVATE *source, BYTE **buffer, INT32 *size); UINT16 TPM2B_ID_OBJECT_Marshal(TPM2B_ID_OBJECT *source, BYTE **buffer, INT32 *size); UINT16 TPMA_NV_Marshal(TPMA_NV *source, BYTE **buffer, INT32 *size); UINT16 TPMS_NV_PUBLIC_Marshal(TPMS_NV_PUBLIC *source, BYTE **buffer, INT32 *size); UINT16 TPM2B_NV_PUBLIC_Marshal(TPM2B_NV_PUBLIC *source, BYTE **buffer, INT32 *size); UINT16 TPM2B_CONTEXT_DATA_Marshal(TPM2B_CONTEXT_DATA *source, BYTE **buffer, INT32 *size); UINT16 TPMS_CONTEXT_Marshal(TPMS_CONTEXT *source, BYTE **buffer, INT32 *size); UINT16 TPMS_CREATION_DATA_Marshal(TPMS_CREATION_DATA *source, BYTE **buffer, INT32 *size); UINT16 TPM2B_CREATION_DATA_Marshal(TPM2B_CREATION_DATA *source, BYTE **buffer, INT32 *size); UINT16 TPM_AT_Marshal(TPM_AT *source, BYTE **buffer, INT32 *size); UINT16 TPMS_AC_OUTPUT_Marshal(TPMS_AC_OUTPUT *source, BYTE **buffer, INT32 *size); UINT16 TPML_AC_CAPABILITIES_Marshal(TPML_AC_CAPABILITIES *source, BYTE **buffer, INT32 *size); #ifdef __cplusplus } #endif #endif libtpms-0.9.3/src/tpm2/MathOnByteBuffers.c000066400000000000000000000236741421143571500203600ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Math functions performed with canonical integers in byte buffers */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: MathOnByteBuffers.c 1519 2019-11-15 20:43:51Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ /* 9.11 MathOnByteBuffers.c */ /* 9.11.1 Introduction */ /* This file contains implementation of the math functions that are performed with canonical integers in byte buffers. The canonical integer is big-endian bytes. */ #include "Tpm.h" /* 9.11.2.1 UnsignedCmpB */ /* This function compare two unsigned values. The values are byte-aligned, big-endian numbers (e.g, a hash). */ /* Return Values Meaning */ /* 1 if (a > b) */ /* 0 if (a = b) */ /* -1 if (a < b) */ LIB_EXPORT int UnsignedCompareB( UINT32 aSize, // IN: size of a const BYTE *a, // IN: a UINT32 bSize, // IN: size of b const BYTE *b // IN: b ) { UINT32 i; if(aSize > bSize) return 1; else if(aSize < bSize) return -1; else { for(i = 0; i < aSize; i++) { if(a[i] != b[i]) return (a[i] > b[i]) ? 1 : -1; } } return 0; } /* 9.11.2.2 SignedCompareB() */ /* Compare two signed integers: */ /* Return Values Meaning */ /* 1 if a > b */ /* 0 if a = b */ /* -1 if a < b */ int SignedCompareB( const UINT32 aSize, // IN: size of a const BYTE *a, // IN: a buffer const UINT32 bSize, // IN: size of b const BYTE *b // IN: b buffer ) { int signA, signB; // sign of a and b // For positive or 0, sign_a is 1 // for negative, sign_a is 0 signA = ((a[0] & 0x80) == 0) ? 1 : 0; // For positive or 0, sign_b is 1 // for negative, sign_b is 0 signB = ((b[0] & 0x80) == 0) ? 1 : 0; if(signA != signB) { return signA - signB; } if(signA == 1) // do unsigned compare function return UnsignedCompareB(aSize, a, bSize, b); else // do unsigned compare the other way return 0 - UnsignedCompareB(aSize, a, bSize, b); } /* 9.11.3.3 ModExpB */ /* This function is used to do modular exponentiation in support of RSA. The most typical uses are: c = m^e mod n (RSA encrypt) and m = c^d mod n (RSA decrypt). When doing decryption, the e parameter of the function will contain the private exponent d instead of the public exponent e. */ /* If the results will not fit in the provided buffer, an error is returned (CRYPT_ERROR_UNDERFLOW). If the results is smaller than the buffer, the results is de-normalized. */ /* This version is intended for use with RSA and requires that m be less than n. */ /* Error Returns Meaning */ /* TPM_RC_SIZE number to exponentiate is larger than the modulus */ /* TPM_RC_NO_RESULT result will not fit into the provided buffer */ TPM_RC ModExpB( UINT32 cSize, // IN: the size of the output buffer. It will // need to be the same size as the modulus BYTE *c, // OUT: the buffer to receive the results // (c->size must be set to the maximum size // for the returned value) const UINT32 mSize, const BYTE *m, // IN: number to exponentiate const UINT32 eSize, const BYTE *e, // IN: power const UINT32 nSize, const BYTE *n // IN: modulus ) { BN_MAX(bnC); BN_MAX(bnM); BN_MAX(bnE); BN_MAX(bnN); NUMBYTES tSize = (NUMBYTES)nSize; TPM_RC retVal = TPM_RC_SUCCESS; // Convert input parameters BnFromBytes(bnM, m, (NUMBYTES)mSize); BnFromBytes(bnE, e, (NUMBYTES)eSize); BnFromBytes(bnN, n, (NUMBYTES)nSize); // Make sure that the output is big enough to hold the result // and that 'm' is less than 'n' (the modulus) if(cSize < nSize) ERROR_RETURN(TPM_RC_NO_RESULT); if(BnUnsignedCmp(bnM, bnN) >= 0) ERROR_RETURN(TPM_RC_SIZE); BnModExp(bnC, bnM, bnE, bnN); BnToBytes(bnC, c, &tSize); Exit: return retVal; } /* 9.11.2.4 DivideB() */ /* Divide an integer (n) by an integer (d) producing a quotient (q) and a remainder (r). If q or r is not needed, then the pointer to them may be set to NULL. */ /* Error Returns Meaning */ /* TPM_RC_NO_RESULT q or r is too small to receive the result */ LIB_EXPORT TPM_RC DivideB( const TPM2B *n, // IN: numerator const TPM2B *d, // IN: denominator TPM2B *q, // OUT: quotient TPM2B *r // OUT: remainder ) { BN_MAX_INITIALIZED(bnN, n); BN_MAX_INITIALIZED(bnD, d); BN_MAX(bnQ); BN_MAX(bnR); // // Do divide with converted values BnDiv(bnQ, bnR, bnN, bnD); // Convert the BIGNUM result back to 2B format using the size of the original // number if(q != NULL) if(!BnTo2B(bnQ, q, q->size)) return TPM_RC_NO_RESULT; if(r != NULL) if(!BnTo2B(bnR, r, r->size)) return TPM_RC_NO_RESULT; return TPM_RC_SUCCESS; } /* 9.11.2.5 AdjustNumberB() */ /* Remove/add leading zeros from a number in a TPM2B. Will try to make the number by adding or removing leading zeros. If the number is larger than the requested size, it will make the number as small as possible. Setting requestedSize to zero is equivalent to requesting that the number be normalized. */ UINT16 AdjustNumberB( TPM2B *num, UINT16 requestedSize ) { BYTE *from; UINT16 i; // See if number is already the requested size if(num->size == requestedSize) return requestedSize; from = num->buffer; if (num->size > requestedSize) { // This is a request to shift the number to the left (remove leading zeros) // Find the first non-zero byte. Don't look past the point where removing // more zeros would make the number smaller than requested, and don't throw // away any significant digits. for(i = num->size; *from == 0 && i > requestedSize; from++, i--); if(i < num->size) { num->size = i; MemoryCopy(num->buffer, from, i); } } // This is a request to shift the number to the right (add leading zeros) else { MemoryCopy(&num->buffer[requestedSize - num->size], num->buffer, num->size); MemorySet(num->buffer, 0, requestedSize- num->size); num->size = requestedSize; } return num->size; } /* 9.11.2.6 ShiftLeft() */ /* This function shifts a byte buffer (a TPM2B) one byte to the left. That is, the most significant bit of the most significant byte is lost. */ TPM2B * ShiftLeft( TPM2B *value // IN/OUT: value to shift and shifted value out ) { UINT16 count = value->size; BYTE *buffer = value->buffer; if(count > 0) { for(count -= 1; count > 0; buffer++, count--) { buffer[0] = (buffer[0] << 1) + ((buffer[1] & 0x80) ? 1 : 0); } *buffer <<= 1; } return value; } libtpms-0.9.3/src/tpm2/MathOnByteBuffers_fp.h000066400000000000000000000115631421143571500210440ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Math functions performed with canonical integers in byte buffers */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: MathOnByteBuffers_fp.h 1519 2019-11-15 20:43:51Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ #ifndef MATHONBYTEBUFFERS_FP_H #define MATHONBYTEBUFFERS_FP_H LIB_EXPORT int UnsignedCompareB( UINT32 aSize, // IN: size of a const BYTE *a, // IN: a UINT32 bSize, // IN: size of b const BYTE *b // IN: b ); int SignedCompareB( const UINT32 aSize, // IN: size of a const BYTE *a, // IN: a buffer const UINT32 bSize, // IN: size of b const BYTE *b // IN: b buffer ); TPM_RC ModExpB( UINT32 cSize, // IN: the size of the output buffer. It will // need to be the same size as the modulus BYTE *c, // OUT: the buffer to receive the results // (c->size must be set to the maximum size // for the returned value) const UINT32 mSize, const BYTE *m, // IN: number to exponentiate const UINT32 eSize, const BYTE *e, // IN: power const UINT32 nSize, const BYTE *n // IN: modulus ); LIB_EXPORT TPM_RC DivideB( const TPM2B *n, // IN: numerator const TPM2B *d, // IN: denominator TPM2B *q, // OUT: quotient TPM2B *r // OUT: remainder ); UINT16 AdjustNumberB( TPM2B *num, UINT16 requestedSize ); TPM2B * ShiftLeft( TPM2B *value // IN/OUT: value to shift and shifted value out ); #endif libtpms-0.9.3/src/tpm2/Memory.c000066400000000000000000000231231421143571500162660ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Miscellaneous Memory Manipulation Routines */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Memory.c 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2021 */ /* */ /********************************************************************************/ /* 9.12 Memory.c */ /* 9.12.1 Description */ /* This file contains a set of miscellaneous memory manipulation routines. Many of the functions have the same semantics as functions defined in string.h. Those functions are not used directly in the TPM because they are not safe */ /* This version uses string.h after adding guards. This is because the math libraries invariably use those functions so it is not practical to prevent those library functions from being pulled into the build. */ /* 9.12.2 Includes and Data Definitions */ #include "Tpm.h" #include "Memory_fp.h" /* 9.12.3 Functions */ /* 9.12.3.1 MemoryCopy() */ /* This is an alias for memmove. This is used in place of memcpy because some of the moves may overlap and rather than try to make sure that memmove is used when necessary, it is always used. */ void MemoryCopy( void *dest, const void *src, int sSize ) { if (dest != src) memmove(dest, src, sSize); } /* 9.12.3.2 MemoryEqual() */ /* This function indicates if two buffers have the same values in the indicated number of bytes. */ /* Return Values Meaning */ /* TRUE all octets are the same */ /* FALSE all octets are not the same */ BOOL MemoryEqual( const void *buffer1, // IN: compare buffer1 const void *buffer2, // IN: compare buffer2 unsigned int size // IN: size of bytes being compared ) { BYTE equal = 0; const BYTE *b1 = (BYTE *)buffer1; const BYTE *b2 = (BYTE *)buffer2; // // Compare all bytes so that there is no leakage of information // due to timing differences. for(; size > 0; size--) equal |= (*b1++ ^ *b2++); return (equal == 0); } /* 9.12.3.3 MemoryCopy2B() */ /* This function copies a TPM2B. This can be used when the TPM2B types are the same or different. */ /* This function returns the number of octets in the data buffer of the TPM2B. */ LIB_EXPORT INT16 MemoryCopy2B( TPM2B *dest, // OUT: receiving TPM2B const TPM2B *source, // IN: source TPM2B unsigned int dSize // IN: size of the receiving buffer ) { pAssert(dest != NULL); if(source == NULL) dest->size = 0; else { pAssert(source->size <= dSize); MemoryCopy(dest->buffer, source->buffer, source->size); dest->size = source->size; } return dest->size; } /* 9.12.3.4 MemoryConcat2B() */ /* This function will concatenate the buffer contents of a TPM2B to the buffer contents of another TPM2B and adjust the size accordingly (a := (a | b)). */ void MemoryConcat2B( TPM2B *aInOut, // IN/OUT: destination 2B TPM2B *bIn, // IN: second 2B unsigned int aMaxSize // IN: The size of aInOut.buffer (max values for // aInOut.size) ) { pAssert(bIn->size <= aMaxSize - aInOut->size); MemoryCopy(&aInOut->buffer[aInOut->size], &bIn->buffer, bIn->size); aInOut->size = aInOut->size + bIn->size; return; } /* 9.12.3.5 MemoryEqual2B() */ /* This function will compare two TPM2B structures. To be equal, they need to be the same size and the buffer contexts need to be the same in all octets. */ /* Return Values Meaning */ /* TRUE size and buffer contents are the same */ /* FALSE size or buffer contents are not the same */ BOOL MemoryEqual2B( const TPM2B *aIn, // IN: compare value const TPM2B *bIn // IN: compare value ) { if(aIn->size != bIn->size) return FALSE; return MemoryEqual(aIn->buffer, bIn->buffer, aIn->size); } /* 9.12.3.6 MemorySet() */ /* This function will set all the octets in the specified memory range to the specified octet value. */ /* NOTE: A previous version had an additional parameter (dSize) that was intended to make sure that the destination would not be overrun. The problem is that, in use, all that was happening was that the value of size was used for dSize so there was no benefit in the extra parameter. */ void MemorySet( void *dest, int value, size_t size ) { memset(dest, value, size); } /* 9.12.3.7 MemoryPad2B() */ /* Function to pad a TPM2B with zeros and adjust the size. */ void MemoryPad2B( TPM2B *b, UINT16 newSize ) { MemorySet(&b->buffer[b->size], 0, newSize - b->size); b->size = newSize; } /* 9.12.3.8 Uint16ToByteArray() */ /* Function to write an integer to a byte array */ void Uint16ToByteArray( UINT16 i, BYTE *a ) { a[1] = (BYTE)(i); i >>= 8; a[0] = (BYTE)(i); } /* 9.12.3.9 Uint32ToByteArray() */ /* Function to write an integer to a byte array */ void Uint32ToByteArray( UINT32 i, BYTE *a ) { a[3] = (BYTE)(i); i >>= 8; a[2] = (BYTE)(i); i >>= 8; a[1] = (BYTE)(i); i >>= 8; a[0] = (BYTE)(i); } /* 9.12.3.10 Uint64ToByteArray() */ /* Function to write an integer to a byte array */ void Uint64ToByteArray( UINT64 i, BYTE *a ) { a[7] = (BYTE)(i); i >>= 8; a[6] = (BYTE)(i); i >>= 8; a[5] = (BYTE)(i); i >>= 8; a[4] = (BYTE)(i); i >>= 8; a[3] = (BYTE)(i); i >>= 8; a[2] = (BYTE)(i); i >>= 8; a[1] = (BYTE)(i); i >>= 8; a[0] = (BYTE)(i); } /* 9.12.3.11 ByteArrayToUint8() */ /* Function to write a UINT8 to a byte array. This is included for completeness and to allow certain macro expansions */ #if 0 // libtpms added UINT8 ByteArrayToUint8( BYTE *a ) { return *a; } #endif // libtpms added /* 9.12.3.12 ByteArrayToUint16() */ /* Function to write an integer to a byte array */ UINT16 ByteArrayToUint16( BYTE *a ) { return ((UINT16)a[0] << 8) + a[1]; } /* 9.12.3.13 ByteArrayToUint32() */ /* Function to write an integer to a byte array */ UINT32 ByteArrayToUint32( BYTE *a ) { return (UINT32)((((((UINT32)a[0] << 8) + a[1]) << 8) + (UINT32)a[2]) << 8) + a[3]; } /* 9.12.3.14 ByteArrayToUint64() */ /* Function to write an integer to a byte array */ UINT64 ByteArrayToUint64( BYTE *a ) { return (((UINT64)BYTE_ARRAY_TO_UINT32(a)) << 32) + BYTE_ARRAY_TO_UINT32(&a[4]); } libtpms-0.9.3/src/tpm2/Memory_fp.h000066400000000000000000000117661421143571500167720ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Miscellaneous Memory Manipulation Routines */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Memory_fp.h 1476 2019-06-10 19:32:03Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ #ifndef MEMORY_FP_H #define MEMORY_FP_H void MemoryCopy( void *dest, const void *src, int sSize ); BOOL MemoryEqual( const void *buffer1, // IN: compare buffer1 const void *buffer2, // IN: compare buffer2 unsigned int size // IN: size of bytes being compared ); LIB_EXPORT INT16 MemoryCopy2B( TPM2B *dest, // OUT: receiving TPM2B const TPM2B *source, // IN: source TPM2B unsigned int dSize // IN: size of the receiving buffer ); void MemoryConcat2B( TPM2B *aInOut, // IN/OUT: destination 2B TPM2B *bIn, // IN: second 2B unsigned int aMaxSize // IN: The size of aInOut.buffer (max values for // aInOut.size) ); BOOL MemoryEqual2B( const TPM2B *aIn, // IN: compare value const TPM2B *bIn // IN: compare value ); void MemorySet( void *dest, int value, size_t size ); void MemoryPad2B( TPM2B *b, UINT16 newSize ); void Uint16ToByteArray( UINT16 i, BYTE *a ); void Uint32ToByteArray( UINT32 i, BYTE *a ); void Uint64ToByteArray( UINT64 i, BYTE *a ); UINT8 ByteArrayToUint8( BYTE *a ); UINT16 ByteArrayToUint16( BYTE *a ); UINT32 ByteArrayToUint32( BYTE *a ); UINT64 ByteArrayToUint64( BYTE *a ); #endif libtpms-0.9.3/src/tpm2/MinMax.h000066400000000000000000000070101421143571500162110ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Min Max Macros */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: MinMax.h 1529 2019-11-21 23:29:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2019 */ /* */ /********************************************************************************/ // 5.13 MinMax.h #ifndef _MIN_MAX_H_ #define _MIN_MAX_H_ #ifndef MAX #define MAX(a, b) ((a) > (b) ? (a) : (b)) #endif #ifndef MIN #define MIN(a, b) ((a) < (b) ? (a) : (b)) #endif #endif // _MIN_MAX_H_ libtpms-0.9.3/src/tpm2/NV.h000066400000000000000000000171761421143571500153610ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: NV.h 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ #ifndef NV_H #define NV_H /* 5.14.1 Index Type Definitions */ /* These definitions allow the same code to be used pre and post 1.21. The main action is to redefine the index type values from the bit values. Use TPM_NT_ORDINARY to indicate if the TPM_NT type is defined */ #ifdef TPM_NT_ORDINARY /* If TPM_NT_ORDINARY is defined, then the TPM_NT field is present in a TPMA_NV */ # define GET_TPM_NT(attributes) GET_ATTRIBUTE(attributes, TPMA_NV, TPM_NT) #else /* If TPM_NT_ORDINARY is not defined, then need to synthesize it from the attributes */ # define GetNv_TPM_NV(attributes) \ ( IS_ATTRIBUTE(attributes, TPMA_NV, COUNTER) \ + (IS_ATTRIBUTE(attributes, TPMA_NV, BITS) << 1) \ + (IS_ATTRIBUTE(attributes, TPMA_NV, EXTEND) << 2) \ ) # define TPM_NT_ORDINARY (0) # define TPM_NT_COUNTER (1) # define TPM_NT_BITS (2) # define TPM_NT_EXTEND (4) #endif /* 5.14.2 Attribute Macros */ /* These macros are used to isolate the differences in the way that the index type changed in version 1.21 of the specification */ # define IsNvOrdinaryIndex(attributes) \ (GET_TPM_NT(attributes) == TPM_NT_ORDINARY) # define IsNvCounterIndex(attributes) \ (GET_TPM_NT(attributes) == TPM_NT_COUNTER) # define IsNvBitsIndex(attributes) \ (GET_TPM_NT(attributes) == TPM_NT_BITS) # define IsNvExtendIndex(attributes) \ (GET_TPM_NT(attributes) == TPM_NT_EXTEND) #ifdef TPM_NT_PIN_PASS # define IsNvPinPassIndex(attributes) \ (GET_TPM_NT(attributes) == TPM_NT_PIN_PASS) #endif #ifdef TPM_NT_PIN_FAIL # define IsNvPinFailIndex(attributes) \ (GET_TPM_NT(attributes) == TPM_NT_PIN_FAIL) #endif typedef struct { UINT32 size; TPM_HANDLE handle; } NV_ENTRY_HEADER; #define NV_EVICT_OBJECT_SIZE \ (sizeof(UINT32) + sizeof(TPM_HANDLE) + sizeof(OBJECT)) #define NV_INDEX_COUNTER_SIZE \ (sizeof(UINT32) + sizeof(NV_INDEX) + sizeof(UINT64)) #define NV_RAM_INDEX_COUNTER_SIZE \ (sizeof(NV_RAM_HEADER) + sizeof(UINT64)) typedef struct { UINT32 size; TPM_HANDLE handle; TPMA_NV attributes; } NV_RAM_HEADER; /* Defines the end-of-list marker for NV. The list terminator is a UINT32 of zero, followed by the current value of s_maxCounter which is a 64-bit value. The structure is defined as an array of 3 UINT32 values so that there is no padding between the UINT32 list end marker and the UINT64 maxCounter value. */ typedef UINT32 NV_LIST_TERMINATOR[3]; /* 5.14.3 Orderly RAM Values */ /* The following defines are for accessing orderly RAM values. This is the initialize for the RAM reference iterator. */ #define NV_RAM_REF_INIT 0 /* This is the starting address of the RAM space used for orderly data */ #define RAM_ORDERLY_START \ (&s_indexOrderlyRam[0]) /* This is the offset within NV that is used to save the orderly data on an orderly shutdown. */ #define NV_ORDERLY_START \ (NV_INDEX_RAM_DATA) /* This is the end of the orderly RAM space. It is actually the first byte after the last byte of orderly RAM data */ #define RAM_ORDERLY_END \ (RAM_ORDERLY_START + sizeof(s_indexOrderlyRam)) /* This is the end of the orderly space in NV memory. As with RAM_ORDERLY_END, it is actually the offset of the first byte after the end of the NV orderly data. */ #define NV_ORDERLY_END \ (NV_ORDERLY_START + sizeof(s_indexOrderlyRam)) /* Macro to check that an orderly RAM address is with range. */ #define ORDERLY_RAM_ADDRESS_OK(start, offset) \ ((start >= RAM_ORDERLY_START) && ((start + offset - 1) < RAM_ORDERLY_END)) #define RETURN_IF_NV_IS_NOT_AVAILABLE \ { \ if(g_NvStatus != TPM_RC_SUCCESS) \ return g_NvStatus; \ } /* Routinely have to clear the orderly flag and fail if the NV is not available so that it can be cleared. */ #define RETURN_IF_ORDERLY \ { \ if(NvClearOrderly() != TPM_RC_SUCCESS) \ return g_NvStatus; \ } #define NV_IS_AVAILABLE (g_NvStatus == TPM_RC_SUCCESS) #define IS_ORDERLY(value) (value < SU_DA_USED_VALUE) #define NV_IS_ORDERLY (IS_ORDERLY(gp.orderlyState)) /* Macro to set the NV UPDATE_TYPE. This deals with the fact that the update is possibly a combination of UT_NV and UT_ORDERLY. */ #define SET_NV_UPDATE(type) g_updateNV |= (type) #endif // _NV_H_ libtpms-0.9.3/src/tpm2/NVCommands.c000066400000000000000000000711401421143571500170250ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Non-Volatile Storage */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: NVCommands.c 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ #include "Tpm.h" #include "NV_DefineSpace_fp.h" #if CC_NV_DefineSpace // Conditional expansion of this file TPM_RC TPM2_NV_DefineSpace( NV_DefineSpace_In *in // IN: input parameter list ) { TPMA_NV attributes = in->publicInfo.nvPublic.attributes; UINT16 nameSize; nameSize = CryptHashGetDigestSize(in->publicInfo.nvPublic.nameAlg); // Input Validation // Checks not specific to type // If the UndefineSpaceSpecial command is not implemented, then can't have // an index that can only be deleted with policy #if CC_NV_UndefineSpaceSpecial == NO if(IS_ATTRIBUTE(attributes, TPMA_NV, POLICY_DELETE)) return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo; #endif // check that the authPolicy consistent with hash algorithm if(in->publicInfo.nvPublic.authPolicy.t.size != 0 && in->publicInfo.nvPublic.authPolicy.t.size != nameSize) return TPM_RCS_SIZE + RC_NV_DefineSpace_publicInfo; // make sure that the authValue is not too large if(MemoryRemoveTrailingZeros(&in->auth) > CryptHashGetDigestSize(in->publicInfo.nvPublic.nameAlg)) return TPM_RCS_SIZE + RC_NV_DefineSpace_auth; // If an index is being created by the owner and shEnable is // clear, then we would not reach this point because ownerAuth // can't be given when shEnable is CLEAR. However, if phEnable // is SET but phEnableNV is CLEAR, we have to check here if(in->authHandle == TPM_RH_PLATFORM && gc.phEnableNV == CLEAR) return TPM_RCS_HIERARCHY + RC_NV_DefineSpace_authHandle; // Attribute checks // Eliminate the unsupported types switch(GET_TPM_NT(attributes)) { #if CC_NV_Increment == YES case TPM_NT_COUNTER: #endif #if CC_NV_SetBits == YES case TPM_NT_BITS: #endif #if CC_NV_Extend == YES case TPM_NT_EXTEND: #endif #if CC_PolicySecret == YES && defined TPM_NT_PIN_PASS case TPM_NT_PIN_PASS: case TPM_NT_PIN_FAIL: #endif case TPM_NT_ORDINARY: break; default: return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo; break; } // Check that the sizes are OK based on the type switch(GET_TPM_NT(attributes)) { case TPM_NT_ORDINARY: // Can't exceed the allowed size for the implementation if(in->publicInfo.nvPublic.dataSize > MAX_NV_INDEX_SIZE) return TPM_RCS_SIZE + RC_NV_DefineSpace_publicInfo; break; case TPM_NT_EXTEND: if(in->publicInfo.nvPublic.dataSize != nameSize) return TPM_RCS_SIZE + RC_NV_DefineSpace_publicInfo; break; default: // Everything else needs a size of 8 if(in->publicInfo.nvPublic.dataSize != 8) return TPM_RCS_SIZE + RC_NV_DefineSpace_publicInfo; break; } // Handle other specifics switch(GET_TPM_NT(attributes)) { case TPM_NT_COUNTER: // Counter can't have TPMA_NV_CLEAR_STCLEAR SET (don't clear counters) if(IS_ATTRIBUTE(attributes, TPMA_NV, CLEAR_STCLEAR)) return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo; break; #ifdef TPM_NT_PIN_FAIL case TPM_NT_PIN_FAIL: // NV_NO_DA must be SET and AUTHWRITE must be CLEAR // NOTE: As with a PIN_PASS index, the authValue of the index is not // available until the index is written. If AUTHWRITE is the only way to // write then index, it could never be written. Rather than go through // all of the other possible ways to write the Index, it is simply // prohibited to write the index with the authValue. Other checks // below will insure that there seems to be a way to write the index // (i.e., with platform authorization , owner authorization, // or with policyAuth.) // It is not allowed to create a PIN Index that can't be modified. if(!IS_ATTRIBUTE(attributes, TPMA_NV, NO_DA)) return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo; /* fall through */ #endif #ifdef TPM_NT_PIN_PASS case TPM_NT_PIN_PASS: // AUTHWRITE must be CLEAR (see note above to TPM_NT_PIN_FAIL) if(IS_ATTRIBUTE(attributes, TPMA_NV, AUTHWRITE) || IS_ATTRIBUTE(attributes, TPMA_NV, GLOBALLOCK) || IS_ATTRIBUTE(attributes, TPMA_NV, WRITEDEFINE)) return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo; #endif // this comes before break because PIN_FAIL falls through break; default: break; } // Locks may not be SET and written cannot be SET if(IS_ATTRIBUTE(attributes, TPMA_NV, WRITTEN) || IS_ATTRIBUTE(attributes, TPMA_NV, WRITELOCKED) || IS_ATTRIBUTE(attributes, TPMA_NV, READLOCKED)) return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo; // There must be a way to read the index. if(!IS_ATTRIBUTE(attributes, TPMA_NV, OWNERREAD) && !IS_ATTRIBUTE(attributes, TPMA_NV, PPREAD) && !IS_ATTRIBUTE(attributes, TPMA_NV, AUTHREAD) && !IS_ATTRIBUTE(attributes, TPMA_NV, POLICYREAD)) return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo; // There must be a way to write the index if(!IS_ATTRIBUTE(attributes, TPMA_NV, OWNERWRITE) && !IS_ATTRIBUTE(attributes, TPMA_NV, PPWRITE) && !IS_ATTRIBUTE(attributes, TPMA_NV, AUTHWRITE) && !IS_ATTRIBUTE(attributes, TPMA_NV, POLICYWRITE)) return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo; // An index with TPMA_NV_CLEAR_STCLEAR can't have TPMA_NV_WRITEDEFINE SET if(IS_ATTRIBUTE(attributes, TPMA_NV, CLEAR_STCLEAR) && IS_ATTRIBUTE(attributes, TPMA_NV, WRITEDEFINE)) return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo; // Make sure that the creator of the index can delete the index if((IS_ATTRIBUTE(attributes, TPMA_NV, PLATFORMCREATE) && in->authHandle == TPM_RH_OWNER) || (!IS_ATTRIBUTE(attributes, TPMA_NV, PLATFORMCREATE) && in->authHandle == TPM_RH_PLATFORM)) return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_authHandle; // If TPMA_NV_POLICY_DELETE is SET, then the index must be defined by // the platform if(IS_ATTRIBUTE(attributes, TPMA_NV, POLICY_DELETE) && TPM_RH_PLATFORM != in->authHandle) return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo; // Make sure that the TPMA_NV_WRITEALL is not set if the index size is larger // than the allowed NV buffer size. if(in->publicInfo.nvPublic.dataSize > MAX_NV_BUFFER_SIZE && IS_ATTRIBUTE(attributes, TPMA_NV, WRITEALL)) return TPM_RCS_SIZE + RC_NV_DefineSpace_publicInfo; // And finally, see if the index is already defined. if(NvIndexIsDefined(in->publicInfo.nvPublic.nvIndex)) return TPM_RC_NV_DEFINED; // Internal Data Update // define the space. A TPM_RC_NV_SPACE error may be returned at this point return NvDefineIndex(&in->publicInfo.nvPublic, &in->auth); } #endif // CC_NV_DefineSpace #include "Tpm.h" #include "NV_UndefineSpace_fp.h" #if CC_NV_UndefineSpace // Conditional expansion of this file TPM_RC TPM2_NV_UndefineSpace( NV_UndefineSpace_In *in // IN: input parameter list ) { NV_REF locator; NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, &locator); // Input Validation // This command can't be used to delete an index with TPMA_NV_POLICY_DELETE SET if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, POLICY_DELETE)) return TPM_RCS_ATTRIBUTES + RC_NV_UndefineSpace_nvIndex; // The owner may only delete an index that was defined with ownerAuth. The // platform may delete an index that was created with either authorization. if(in->authHandle == TPM_RH_OWNER && IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, PLATFORMCREATE)) return TPM_RC_NV_AUTHORIZATION; // Internal Data Update // Call implementation dependent internal routine to delete NV index return NvDeleteIndex(nvIndex, locator); } #endif // CC_NV_UndefineSpace #include "Tpm.h" #include "NV_UndefineSpaceSpecial_fp.h" #include "SessionProcess_fp.h" #if CC_NV_UndefineSpaceSpecial // Conditional expansion of this file TPM_RC TPM2_NV_UndefineSpaceSpecial( NV_UndefineSpaceSpecial_In *in // IN: input parameter list ) { TPM_RC result; NV_REF locator; NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, &locator); // Input Validation // This operation only applies when the TPMA_NV_POLICY_DELETE attribute is SET if(!IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, POLICY_DELETE)) return TPM_RCS_ATTRIBUTES + RC_NV_UndefineSpaceSpecial_nvIndex; // Internal Data Update // Call implementation dependent internal routine to delete NV index result = NvDeleteIndex(nvIndex, locator); // If we just removed the index providing the authorization, make sure that the // authorization session computation is modified so that it doesn't try to // access the authValue of the just deleted index if(result == TPM_RC_SUCCESS) SessionRemoveAssociationToHandle(in->nvIndex); return result; } #endif // CC_NV_UndefineSpaceSpecial #include "Tpm.h" #include "NV_ReadPublic_fp.h" #if CC_NV_ReadPublic // Conditional expansion of this file TPM_RC TPM2_NV_ReadPublic( NV_ReadPublic_In *in, // IN: input parameter list NV_ReadPublic_Out *out // OUT: output parameter list ) { NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, NULL); // Command Output // Copy index public data to output out->nvPublic.nvPublic = nvIndex->publicArea; // Compute NV name NvGetIndexName(nvIndex, &out->nvName); return TPM_RC_SUCCESS; } #endif // CC_NV_ReadPublic #include "Tpm.h" #include "NV_Write_fp.h" #if CC_NV_Write // Conditional expansion of this file TPM_RC TPM2_NV_Write( NV_Write_In *in // IN: input parameter list ) { NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, NULL); TPMA_NV attributes = nvIndex->publicArea.attributes; TPM_RC result; // Input Validation // Common access checks, NvWriteAccessCheck() may return TPM_RC_NV_AUTHORIZATION // or TPM_RC_NV_LOCKED result = NvWriteAccessChecks(in->authHandle, in->nvIndex, attributes); if(result != TPM_RC_SUCCESS) return result; // Bits index, extend index or counter index may not be updated by // TPM2_NV_Write if(IsNvCounterIndex(attributes) || IsNvBitsIndex(attributes) || IsNvExtendIndex(attributes)) return TPM_RC_ATTRIBUTES; // Make sure that the offset is not too large if(in->offset > nvIndex->publicArea.dataSize) return TPM_RCS_VALUE + RC_NV_Write_offset; // Make sure that the selection is within the range of the Index if(in->data.t.size > (nvIndex->publicArea.dataSize - in->offset)) return TPM_RC_NV_RANGE; // If this index requires a full sized write, make sure that input range is // full sized. // Note: if the requested size is the same as the Index data size, then offset // will have to be zero. Otherwise, the range check above would have failed. if(IS_ATTRIBUTE(attributes, TPMA_NV, WRITEALL) && in->data.t.size < nvIndex->publicArea.dataSize) return TPM_RC_NV_RANGE; // Internal Data Update // Perform the write. This called routine will SET the TPMA_NV_WRITTEN // attribute if it has not already been SET. If NV isn't available, an error // will be returned. return NvWriteIndexData(nvIndex, in->offset, in->data.t.size, in->data.t.buffer); } #endif // CC_NV_Write #include "Tpm.h" #include "NV_Increment_fp.h" #if CC_NV_Increment // Conditional expansion of this file TPM_RC TPM2_NV_Increment( NV_Increment_In *in // IN: input parameter list ) { TPM_RC result; NV_REF locator; NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, &locator); UINT64 countValue; // Input Validation // Common access checks, NvWriteAccessCheck() may return TPM_RC_NV_AUTHORIZATION // or TPM_RC_NV_LOCKED result = NvWriteAccessChecks(in->authHandle, in->nvIndex, nvIndex->publicArea.attributes); if(result != TPM_RC_SUCCESS) return result; // Make sure that this is a counter if(!IsNvCounterIndex(nvIndex->publicArea.attributes)) return TPM_RCS_ATTRIBUTES + RC_NV_Increment_nvIndex; // Internal Data Update // If counter index is not been written, initialize it if(!IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITTEN)) countValue = NvReadMaxCount(); else // Read NV data in native format for TPM CPU. countValue = NvGetUINT64Data(nvIndex, locator); // Do the increment countValue++; // Write NV data back. A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may // be returned at this point. If necessary, this function will set the // TPMA_NV_WRITTEN attribute result = NvWriteUINT64Data(nvIndex, countValue); if(result == TPM_RC_SUCCESS) { // If a counter just rolled over, then force the NV update. // Note, if this is an orderly counter, then the write-back needs to be // forced, for other counters, the write-back will happen anyway if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, ORDERLY) && (countValue & MAX_ORDERLY_COUNT) == 0 ) { // Need to force an NV update of orderly data SET_NV_UPDATE(UT_ORDERLY); } } return result; } #endif // CC_NV_Increment #include "Tpm.h" #include "NV_Extend_fp.h" #if CC_NV_Extend // Conditional expansion of this file TPM_RC TPM2_NV_Extend( NV_Extend_In *in // IN: input parameter list ) { TPM_RC result; NV_REF locator; NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, &locator); TPM2B_DIGEST oldDigest; TPM2B_DIGEST newDigest; HASH_STATE hashState; // Input Validation // Common access checks, NvWriteAccessCheck() may return TPM_RC_NV_AUTHORIZATION // or TPM_RC_NV_LOCKED result = NvWriteAccessChecks(in->authHandle, in->nvIndex, nvIndex->publicArea.attributes); if(result != TPM_RC_SUCCESS) return result; // Make sure that this is an extend index if(!IsNvExtendIndex(nvIndex->publicArea.attributes)) return TPM_RCS_ATTRIBUTES + RC_NV_Extend_nvIndex; // Internal Data Update // Perform the write. oldDigest.t.size = CryptHashGetDigestSize(nvIndex->publicArea.nameAlg); pAssert(oldDigest.t.size <= sizeof(oldDigest.t.buffer)); if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITTEN)) { NvGetIndexData(nvIndex, locator, 0, oldDigest.t.size, oldDigest.t.buffer); } else { MemorySet(oldDigest.t.buffer, 0, oldDigest.t.size); } // Start hash newDigest.t.size = CryptHashStart(&hashState, nvIndex->publicArea.nameAlg); // Adding old digest CryptDigestUpdate2B(&hashState, &oldDigest.b); // Adding new data CryptDigestUpdate2B(&hashState, &in->data.b); // Complete hash CryptHashEnd2B(&hashState, &newDigest.b); // Write extended hash back. // Note, this routine will SET the TPMA_NV_WRITTEN attribute if necessary return NvWriteIndexData(nvIndex, 0, newDigest.t.size, newDigest.t.buffer); } #endif // CC_NV_Extend #include "Tpm.h" #include "NV_SetBits_fp.h" #if CC_NV_SetBits // Conditional expansion of this file TPM_RC TPM2_NV_SetBits( NV_SetBits_In *in // IN: input parameter list ) { TPM_RC result; NV_REF locator; NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, &locator); UINT64 oldValue; UINT64 newValue; // Input Validation // Common access checks, NvWriteAccessCheck() may return TPM_RC_NV_AUTHORIZATION // or TPM_RC_NV_LOCKED result = NvWriteAccessChecks(in->authHandle, in->nvIndex, nvIndex->publicArea.attributes); if(result != TPM_RC_SUCCESS) return result; // Make sure that this is a bit field if(!IsNvBitsIndex(nvIndex->publicArea.attributes)) return TPM_RCS_ATTRIBUTES + RC_NV_SetBits_nvIndex; // If index is not been written, initialize it if(!IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITTEN)) oldValue = 0; else // Read index data oldValue = NvGetUINT64Data(nvIndex, locator); // Figure out what the new value is going to be newValue = oldValue | in->bits; // Internal Data Update return NvWriteUINT64Data(nvIndex, newValue); } #endif // CC_NV_SetBits #include "Tpm.h" #include "NV_WriteLock_fp.h" #if CC_NV_WriteLock // Conditional expansion of this file TPM_RC TPM2_NV_WriteLock( NV_WriteLock_In *in // IN: input parameter list ) { TPM_RC result; NV_REF locator; NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, &locator); TPMA_NV nvAttributes = nvIndex->publicArea.attributes; // Input Validation: // Common access checks, NvWriteAccessCheck() may return TPM_RC_NV_AUTHORIZATION // or TPM_RC_NV_LOCKED result = NvWriteAccessChecks(in->authHandle, in->nvIndex, nvAttributes); if(result != TPM_RC_SUCCESS) { if(result == TPM_RC_NV_AUTHORIZATION) return result; // If write access failed because the index is already locked, then it is // no error. return TPM_RC_SUCCESS; } // if neither TPMA_NV_WRITEDEFINE nor TPMA_NV_WRITE_STCLEAR is set, the index // can not be write-locked if(!IS_ATTRIBUTE(nvAttributes, TPMA_NV, WRITEDEFINE) && !IS_ATTRIBUTE(nvAttributes, TPMA_NV, WRITE_STCLEAR)) return TPM_RCS_ATTRIBUTES + RC_NV_WriteLock_nvIndex; // Internal Data Update // Set the WRITELOCK attribute. // Note: if TPMA_NV_WRITELOCKED were already SET, then the write access check // above would have failed and this code isn't executed. SET_ATTRIBUTE(nvAttributes, TPMA_NV, WRITELOCKED); // Write index info back return NvWriteIndexAttributes(nvIndex->publicArea.nvIndex, locator, nvAttributes); } #endif // CC_NV_WriteLock #include "Tpm.h" #include "NV_GlobalWriteLock_fp.h" #if CC_NV_GlobalWriteLock // Conditional expansion of this file TPM_RC TPM2_NV_GlobalWriteLock( NV_GlobalWriteLock_In *in // IN: input parameter list ) { // Input parameter (the authorization handle) is not reference in command action. NOT_REFERENCED(in); // Internal Data Update // Implementation dependent method of setting the global lock return NvSetGlobalLock(); } #endif // CC_NV_GlobalWriteLock #include "Tpm.h" #include "NV_Read_fp.h" #if CC_NV_Read // Conditional expansion of this file /* TPM_RC_NV_AUTHORIZATION the authorization was valid but the authorizing entity (authHandle) is not allowed to read from the Index referenced by nvIndex */ /* TPM_RC_NV_LOCKED the Index referenced by nvIndex is read locked */ /* TPM_RC_NV_RANGE read range defined by size and offset is outside the range of the Index referenced by nvIndex */ /* TPM_RC_NV_UNINITIALIZED the Index referenced by nvIndex has not been initialized (written) */ /* TPM_RC_VALUE the read size is larger than the MAX_NV_BUFFER_SIZE */ TPM_RC TPM2_NV_Read( NV_Read_In *in, // IN: input parameter list NV_Read_Out *out // OUT: output parameter list ) { NV_REF locator; NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, &locator); TPM_RC result; // Input Validation // Common read access checks. NvReadAccessChecks() may return // TPM_RC_NV_AUTHORIZATION, TPM_RC_NV_LOCKED, or TPM_RC_NV_UNINITIALIZED result = NvReadAccessChecks(in->authHandle, in->nvIndex, nvIndex->publicArea.attributes); if(result != TPM_RC_SUCCESS) return result; // Make sure the data will fit the return buffer if(in->size > MAX_NV_BUFFER_SIZE) return TPM_RCS_VALUE + RC_NV_Read_size; // Verify that the offset is not too large if(in->offset > nvIndex->publicArea.dataSize) return TPM_RCS_VALUE + RC_NV_Read_offset; // Make sure that the selection is within the range of the Index if(in->size > (nvIndex->publicArea.dataSize - in->offset)) return TPM_RC_NV_RANGE; // Command Output // Set the return size out->data.t.size = in->size; // Perform the read NvGetIndexData(nvIndex, locator, in->offset, in->size, out->data.t.buffer); return TPM_RC_SUCCESS; } #endif // CC_NV_Read #include "Tpm.h" #include "NV_ReadLock_fp.h" #if CC_NV_ReadLock // Conditional expansion of this file TPM_RC TPM2_NV_ReadLock( NV_ReadLock_In *in // IN: input parameter list ) { TPM_RC result; NV_REF locator; // The referenced index has been checked multiple times before this is called // so it must be present and will be loaded into cache NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, &locator); TPMA_NV nvAttributes = nvIndex->publicArea.attributes; // Input Validation // Common read access checks. NvReadAccessChecks() may return // TPM_RC_NV_AUTHORIZATION, TPM_RC_NV_LOCKED, or TPM_RC_NV_UNINITIALIZED result = NvReadAccessChecks(in->authHandle, in->nvIndex, nvAttributes); if(result == TPM_RC_NV_AUTHORIZATION) return TPM_RC_NV_AUTHORIZATION; // Index is already locked for write else if(result == TPM_RC_NV_LOCKED) return TPM_RC_SUCCESS; // If NvReadAccessChecks return TPM_RC_NV_UNINITALIZED, then continue. // It is not an error to read lock an uninitialized Index. // if TPMA_NV_READ_STCLEAR is not set, the index can not be read-locked if(!IS_ATTRIBUTE(nvAttributes, TPMA_NV, READ_STCLEAR)) return TPM_RCS_ATTRIBUTES + RC_NV_ReadLock_nvIndex; // Internal Data Update // Set the READLOCK attribute SET_ATTRIBUTE(nvAttributes, TPMA_NV, READLOCKED); // Write NV info back return NvWriteIndexAttributes(nvIndex->publicArea.nvIndex, locator, nvAttributes); } #endif // CC_NV_ReadLock #include "Tpm.h" #include "NV_ChangeAuth_fp.h" #if CC_NV_ChangeAuth // Conditional expansion of this file TPM_RC TPM2_NV_ChangeAuth( NV_ChangeAuth_In *in // IN: input parameter list ) { NV_REF locator; NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, &locator); // Input Validation // Remove trailing zeros and make sure that the result is not larger than the // digest of the nameAlg. if(MemoryRemoveTrailingZeros(&in->newAuth) > CryptHashGetDigestSize(nvIndex->publicArea.nameAlg)) return TPM_RCS_SIZE + RC_NV_ChangeAuth_newAuth; // Internal Data Update // Change authValue return NvWriteIndexAuth(locator, &in->newAuth); } #endif // CC_NV_ChangeAuth #include "Tpm.h" #include "Attest_spt_fp.h" #include "NV_Certify_fp.h" #if CC_NV_Certify // Conditional expansion of this file TPM_RC TPM2_NV_Certify( NV_Certify_In *in, // IN: input parameter list NV_Certify_Out *out // OUT: output parameter list ) { TPM_RC result; NV_REF locator; NV_INDEX *nvIndex = NvGetIndexInfo(in->nvIndex, &locator); TPMS_ATTEST certifyInfo; OBJECT *signObject = HandleToObject(in->signHandle); // Input Validation if(!IsSigningObject(signObject)) return TPM_RCS_KEY + RC_NV_Certify_signHandle; if(!CryptSelectSignScheme(signObject, &in->inScheme)) return TPM_RCS_SCHEME + RC_NV_Certify_inScheme; // Common access checks, NvWriteAccessCheck() may return TPM_RC_NV_AUTHORIZATION // or TPM_RC_NV_LOCKED result = NvReadAccessChecks(in->authHandle, in->nvIndex, nvIndex->publicArea.attributes); if(result != TPM_RC_SUCCESS) return result; // make sure that the selection is within the range of the Index (cast to avoid // any wrap issues with addition) if((UINT32)in->size + (UINT32)in->offset > (UINT32)nvIndex->publicArea.dataSize) return TPM_RC_NV_RANGE; // Make sure the data will fit the return buffer // NOTE: This check may be modified if the output buffer will not hold the // maximum sized NV buffer as part of the certified data. The difference in // size could be substantial if the signature scheme was produced a large // signature (e.g., RSA 4096). if(in->size > MAX_NV_BUFFER_SIZE) return TPM_RCS_VALUE + RC_NV_Certify_size; // Command Output // Fill in attest information common fields FillInAttestInfo(in->signHandle, &in->inScheme, &in->qualifyingData, &certifyInfo); // Get the name of the index NvGetIndexName(nvIndex, &certifyInfo.attested.nv.indexName); // See if this is old format or new format if ((in->size != 0) || (in->offset != 0)) { // NV certify specific fields // Attestation type certifyInfo.type = TPM_ST_ATTEST_NV; // Set the return size certifyInfo.attested.nv.nvContents.t.size = in->size; // Set the offset certifyInfo.attested.nv.offset = in->offset; // Perform the read NvGetIndexData(nvIndex, locator, in->offset, in->size, certifyInfo.attested.nv.nvContents.t.buffer); } else { HASH_STATE hashState; // This is to sign a digest of the data certifyInfo.type = TPM_ST_ATTEST_NV_DIGEST; // Initialize the hash before calling the function to add the Index data to // the hash. certifyInfo.attested.nvDigest.nvDigest.t.size = CryptHashStart(&hashState, in->inScheme.details.any.hashAlg); NvHashIndexData(&hashState, nvIndex, locator, 0, nvIndex->publicArea.dataSize); CryptHashEnd2B(&hashState, &certifyInfo.attested.nvDigest.nvDigest.b); } // Sign attestation structure. A NULL signature will be returned if // signObject is NULL. return SignAttestInfo(signObject, &in->inScheme, &certifyInfo, &in->qualifyingData, &out->certifyInfo, &out->signature); } #endif // CC_NV_Certify libtpms-0.9.3/src/tpm2/NVDynamic.c000066400000000000000000001756011421143571500166570ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Dynamic space for user defined NV */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: NVDynamic.c 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2021 */ /* */ /********************************************************************************/ /* 8.4 NVDynamic.c */ /* 8.4.2 Includes, Defines and Data Definitions */ #define NV_C #include "Tpm.h" /* 8.4.3 Local Functions */ /* 8.4.3.1 NvNext() */ /* This function provides a method to traverse every data entry in NV dynamic area. */ /* To begin with, parameter iter should be initialized to NV_REF_INIT indicating the first element. Every time this function is called, the value in iter would be adjusted pointing to the next element in traversal. If there is no next element, iter value would be 0. This function returns the address of the 'data entry' pointed by the iter. If there is no more elements in the set, a 0 value is returned indicating the end of traversal. */ static NV_REF NvNext( NV_REF *iter, // IN/OUT: the list iterator TPM_HANDLE *handle // OUT: the handle of the next item. ) { NV_REF currentAddr; NV_ENTRY_HEADER header; // // If iterator is at the beginning of list if(*iter == NV_REF_INIT) { // Initialize iterator *iter = NV_USER_DYNAMIC; } // Step over the size field and point to the handle currentAddr = *iter + sizeof(UINT32); // read the header of the next entry NvRead(&header, *iter, sizeof(NV_ENTRY_HEADER)); // if the size field is zero, then we have hit the end of the list if(header.size == 0) // leave the *iter pointing at the end of the list return 0; // advance the header by the size of the entry *iter += header.size; if(handle != NULL) *handle = header.handle; return currentAddr; } /* 8.4.3.2 NvNextByType() */ /* This function returns a reference to the next NV entry of the desired type */ /* Return Values Meaning */ /* 0 end of list */ /* != 0 the next entry of the indicated type */ static NV_REF NvNextByType( TPM_HANDLE *handle, // OUT: the handle of the found type or 0 NV_REF *iter, // IN: the iterator TPM_HT type // IN: the handle type to look for ) { NV_REF addr; TPM_HANDLE nvHandle = 0; while((addr = NvNext(iter, &nvHandle)) != 0) { // addr: the address of the location containing the handle of the value // iter: the next location. if(HandleGetType(nvHandle) == type) break; } if(handle != NULL) *handle = nvHandle; return addr; } /* 8.4.3.3 NvNextIndex() */ /* This function returns the reference to the next NV Index entry. A value of 0 indicates the end of the list. */ /* Return Values Meaning */ /* 0 end of list */ /* != 0 the next */ #define NvNextIndex(handle, iter) \ NvNextByType(handle, iter, TPM_HT_NV_INDEX) /* 8.4.3.4 NvNextEvict() */ /* This function returns the offset in NV of the next evict object entry. A value of 0 indicates the end of the list. */ #define NvNextEvict(handle, iter) \ NvNextByType(handle, iter, TPM_HT_PERSISTENT) /* 8.4.3.5 NvGetEnd() */ /* Function to find the end of the NV dynamic data list */ static NV_REF NvGetEnd( void ) { NV_REF iter = NV_REF_INIT; NV_REF currentAddr; // Scan until the next address is 0 while((currentAddr = NvNext(&iter, NULL)) != 0); return iter; } /* 8.4.3.6 NvGetFreeBytes */ /* This function returns the number of free octets in NV space. */ static UINT32 NvGetFreeBytes( void ) { // This does not have an overflow issue because NvGetEnd() cannot return a value // that is larger than s_evictNvEnd. This is because there is always a 'stop' // word in the NV memory that terminates the search for the end before the // value can go past s_evictNvEnd. return s_evictNvEnd - NvGetEnd(); } /* 8.4.3.7 NvTestSpace() */ /* This function will test if there is enough space to add a new entity. */ /* Return Values Meaning */ /* TRUE space available */ /* FALSE no enough space */ static BOOL NvTestSpace( UINT32 size, // IN: size of the entity to be added BOOL isIndex, // IN: TRUE if the entity is an index BOOL isCounter // IN: TRUE if the index is a counter ) { UINT32 remainBytes = NvGetFreeBytes(); UINT32 reserved = sizeof(UINT32) // size of the forward pointer + sizeof(NV_LIST_TERMINATOR); // Do a compile time sanity check on the setting for NV_MEMORY_SIZE #if NV_MEMORY_SIZE < 1024 #error "NV_MEMORY_SIZE probably isn't large enough" #endif // For NV Index, need to make sure that we do not allocate an Index if this // would mean that the TPM cannot allocate the minimum number of evict // objects. if(isIndex) { // Get the number of persistent objects allocated UINT32 persistentNum = NvCapGetPersistentNumber(); // If we have not allocated the requisite number of evict objects, then we // need to reserve space for them. // NOTE: some of this is not written as simply as it might seem because // the values are all unsigned and subtracting needs to be done carefully // so that an underflow doesn't cause problems. if(persistentNum < MIN_EVICT_OBJECTS) reserved += (MIN_EVICT_OBJECTS - persistentNum) * NV_EVICT_OBJECT_SIZE; } // If this is not an index or is not a counter, reserve space for the // required number of counter indexes if(!isIndex || !isCounter) { // Get the number of counters UINT32 counterNum = NvCapGetCounterNumber(); // If the required number of counters have not been allocated, reserved // space for the extra needed counters if(counterNum < MIN_COUNTER_INDICES) reserved += (MIN_COUNTER_INDICES - counterNum) * NV_INDEX_COUNTER_SIZE; } // Check that the requested allocation will fit after making sure that there // will be no chance of overflow return ((reserved < remainBytes) && (size <= remainBytes) && (size + reserved <= remainBytes)); } /* 8.4.3.8 NvWriteNvListEnd() */ /* Function to write the list terminator. */ NV_REF NvWriteNvListEnd( NV_REF end ) { // Marker is initialized with zeros BYTE listEndMarker[sizeof(NV_LIST_TERMINATOR)] = {0}; UINT64 maxCount = NvReadMaxCount(); // // This is a constant check that can be resolved at compile time. cAssert(sizeof(UINT64) <= sizeof(NV_LIST_TERMINATOR) - sizeof(UINT32)); // Copy the maxCount value to the marker buffer MemoryCopy(&listEndMarker[sizeof(UINT32)], &maxCount, sizeof(UINT64)); pAssert(end + sizeof(NV_LIST_TERMINATOR) <= s_evictNvEnd); // Write it to memory NvWrite(end, sizeof(NV_LIST_TERMINATOR), &listEndMarker); return end + sizeof(NV_LIST_TERMINATOR); } /* 8.4.3.9 NvAdd() */ /* This function adds a new entity to NV. */ /* This function requires that there is enough space to add a new entity (i.e., that NvTestSpace() has been called and the available space is at least as large as the required space). */ /* The totalSize will be the size of entity. If a handle is added, this function will increase the size accordingly. */ static TPM_RC NvAdd( UINT32 totalSize, // IN: total size needed for this entity For // evict object, totalSize is the same as // bufferSize. For NV Index, totalSize is // bufferSize plus index data size UINT32 bufferSize, // IN: size of initial buffer TPM_HANDLE handle, // IN: optional handle BYTE *entity // IN: initial buffer ) { NV_REF newAddr; // IN: where the new entity will start NV_REF nextAddr; RETURN_IF_NV_IS_NOT_AVAILABLE; // Get the end of data list newAddr = NvGetEnd(); // Step over the forward pointer nextAddr = newAddr + sizeof(UINT32); // Optionally write the handle. For indexes, the handle is TPM_RH_UNASSIGNED // so that the handle in the nvIndex is used instead of writing this value if(handle != TPM_RH_UNASSIGNED) { NvWrite((UINT32)nextAddr, sizeof(TPM_HANDLE), &handle); nextAddr += sizeof(TPM_HANDLE); } // Write entity data NvWrite((UINT32)nextAddr, bufferSize, entity); // Advance the pointer by the amount of the total nextAddr += totalSize; // Finish by writing the link value // Write the next offset (relative addressing) totalSize = nextAddr - newAddr; // Write link value NvWrite((UINT32)newAddr, sizeof(UINT32), &totalSize); // Write the list terminator NvWriteNvListEnd(nextAddr); return TPM_RC_SUCCESS; } /* 8.4.3.10 NvDelete() */ /* This function is used to delete an NV Index or persistent object from NV memory. */ static TPM_RC NvDelete( NV_REF entityRef // IN: reference to entity to be deleted ) { UINT32 entrySize; // adjust entityAddr to back up and point to the forward pointer NV_REF entryRef = entityRef - sizeof(UINT32); NV_REF endRef = NvGetEnd(); NV_REF nextAddr; // address of the next entry RETURN_IF_NV_IS_NOT_AVAILABLE; // Get the offset of the next entry. That is, back up and point to the size // field of the entry NvRead(&entrySize, entryRef, sizeof(UINT32)); // The next entry after the one being deleted is at a relative offset // from the current entry nextAddr = entryRef + entrySize; // If this is not the last entry, move everything up if(nextAddr < endRef) { pAssert(nextAddr > entryRef); _plat__NvMemoryMove(nextAddr, entryRef, (endRef - nextAddr)); } // The end of the used space is now moved up by the amount of space we just // reclaimed endRef -= entrySize; // Write the end marker, and make the new end equal to the first byte after // the just added end value. This will automatically update the NV value for // maxCounter // NOTE: This is the call that sets flag to cause NV to be updated endRef = NvWriteNvListEnd(endRef); // Clear the reclaimed memory _plat__NvMemoryClear(endRef, entrySize); return TPM_RC_SUCCESS; } /* 8.4.4 RAM-based NV Index Data Access Functions */ /* 8.4.4.1 Introduction */ /* The data layout in ram buffer is {size of(NV_handle() + attributes + data NV_handle(), attributes, data} for each NV Index data stored in RAM. */ /* NV storage associated with orderly data is updated when a NV Index is added but NOT when the data or attributes are changed. Orderly data is only updated to NV on an orderly shutdown (TPM2_Shutdown()) */ /* 8.4.4.2 NvRamNext() */ /* This function is used to iterate trough the list of Ram Index values. *iter needs to be initialized by calling */ static NV_RAM_REF NvRamNext( NV_RAM_REF *iter, // IN/OUT: the list iterator TPM_HANDLE *handle // OUT: the handle of the next item. ) { NV_RAM_REF currentAddr; NV_RAM_HEADER header; // // If iterator is at the beginning of list if(*iter == NV_RAM_REF_INIT) { // Initialize iterator *iter = &s_indexOrderlyRam[0]; } // if we are going to return what the iter is currently pointing to... currentAddr = *iter; // If iterator reaches the end of NV space, then don't advance and return // that we are at the end of the list. The end of the list occurs when // we don't have space for a size and a handle if(currentAddr + sizeof(NV_RAM_HEADER) > RAM_ORDERLY_END) return NULL; // read the header of the next entry memcpy(&header, currentAddr, sizeof(NV_RAM_HEADER)); // libtpms: do not use MemoryCopy to avoid gcc warning // if the size field is zero, then we have hit the end of the list if(header.size == 0) // leave the *iter pointing at the end of the list return NULL; // advance the header by the size of the entry *iter = currentAddr + header.size; // pAssert(*iter <= RAM_ORDERLY_END); if(handle != NULL) *handle = header.handle; return currentAddr; } /* 8.4.4.2 NvRamGetEnd() */ /* This routine performs the same function as NvGetEnd() but for the RAM data. */ static NV_RAM_REF NvRamGetEnd( void ) { NV_RAM_REF iter = NV_RAM_REF_INIT; NV_RAM_REF currentAddr; // Scan until the next address is 0 while((currentAddr = NvRamNext(&iter, NULL)) != 0); return iter; } /* 8.4.4.3 NvRamTestSpaceIndex() */ /* This function indicates if there is enough RAM space to add a data for a new NV Index. */ /* Return Values Meaning */ /* TRUE space available */ /* FALSE no enough space */ static BOOL NvRamTestSpaceIndex( UINT32 size // IN: size of the data to be added to RAM ) { UINT32 remaining = (UINT32)(RAM_ORDERLY_END - NvRamGetEnd()); UINT32 needed = sizeof(NV_RAM_HEADER) + size; // NvRamGetEnd points to the next available byte. return remaining >= needed; } /* 8.4.4.4 NvRamGetIndex() */ /* This function returns the offset of NV data in the RAM buffer */ /* This function requires that NV Index is in RAM. That is, the index must be known to exist. */ static NV_RAM_REF NvRamGetIndex( TPMI_RH_NV_INDEX handle // IN: NV handle ) { NV_RAM_REF iter = NV_RAM_REF_INIT; NV_RAM_REF currentAddr; TPM_HANDLE foundHandle; while((currentAddr = NvRamNext(&iter, &foundHandle)) != 0) { if(handle == foundHandle) break; } return currentAddr; } /* 8.4.4.5 NvUpdateIndexOrderlyData() */ /* This function is used to cause an update of the orderly data to the NV backing store. */ void NvUpdateIndexOrderlyData( void ) { // Write reserved RAM space to NV NvWrite(NV_INDEX_RAM_DATA, sizeof(s_indexOrderlyRam), s_indexOrderlyRam); } /* 8.4.4.6 NvAddRAM() */ /* This function adds a new data area to RAM. */ /* This function requires that enough free RAM space is available to add the new data. */ /* This function should be called after the NV Index space has been updated and the index removed. This insures that NV is available so that checking for NV availability is not required during this function. */ static void NvAddRAM( TPMS_NV_PUBLIC *index // IN: the index descriptor ) { NV_RAM_HEADER header; NV_RAM_REF end = NvRamGetEnd(); header.size = sizeof(NV_RAM_HEADER) + index->dataSize; header.handle = index->nvIndex; MemoryCopy(&header.attributes, &index->attributes, sizeof(TPMA_NV)); pAssert(ORDERLY_RAM_ADDRESS_OK(end, header.size)); // Copy the header to the memory MemoryCopy(end, &header, sizeof(NV_RAM_HEADER)); // Clear the data area (just in case) MemorySet(end + sizeof(NV_RAM_HEADER), 0, index->dataSize); // Step over this new entry end += header.size; // If the end marker will fit, add it if(end + sizeof(UINT32) < RAM_ORDERLY_END) MemorySet(end, 0, sizeof(UINT32)); // Write reserved RAM space to NV to reflect the newly added NV Index SET_NV_UPDATE(UT_ORDERLY); return; } /* 8.4.4.7 NvDeleteRAM() */ /* This function is used to delete a RAM-backed NV Index data area. The space used by the entry are overwritten by the contents of the Index data that comes after (the data is moved up to fill the hole left by removing this index. The reclaimed space is cleared to zeros. This function assumes the data of NV Index exists in RAM. */ /* This function should be called after the NV Index space has been updated and the index removed. This insures that NV is available so that checking for NV availability is not required during this function. */ static void NvDeleteRAM( TPMI_RH_NV_INDEX handle // IN: NV handle ) { NV_RAM_REF nodeAddress; NV_RAM_REF nextNode; UINT32 size; NV_RAM_REF lastUsed = NvRamGetEnd(); nodeAddress = NvRamGetIndex(handle); pAssert(nodeAddress != 0); // Get node size MemoryCopy(&size, nodeAddress, sizeof(size)); // Get the offset of next node nextNode = nodeAddress + size; // Copy the data MemoryCopy(nodeAddress, nextNode, (int)(lastUsed - nextNode)); // Clear out the reclaimed space MemorySet(lastUsed - size, 0, size); // Write reserved RAM space to NV to reflect the newly delete NV Index SET_NV_UPDATE(UT_ORDERLY); return; } /* 8.4.4.9 NvReadIndex() */ /* This function is used to read the NV Index NV_INDEX. This is used so that the index information can be compressed and only this function would be needed to decompress it. Mostly, compression would only be able to save the space needed by the policy. */ void NvReadNvIndexInfo( NV_REF ref, // IN: points to NV where index is located NV_INDEX *nvIndex // OUT: place to receive index data ) { pAssert(nvIndex != NULL); NvRead(nvIndex, ref, sizeof(NV_INDEX)); return; } /* 8.4.4.9 NvReadObject() */ /* This function is used to read a persistent object. This is used so that the object information can be compressed and only this function would be needed to uncompress it. */ void NvReadObject( NV_REF ref, // IN: points to NV where index is located OBJECT *object // OUT: place to receive the object data ) { NvRead(object, (ref + sizeof(TPM_HANDLE)), sizeof(OBJECT)); return; } /* 8.4.4.10 NvFindEvict() */ /* This function will return the NV offset of an evict object */ /* Return Values Meaning */ /* 0 evict object not found */ /* != 0 offset of evict object */ static NV_REF NvFindEvict( TPM_HANDLE nvHandle, OBJECT *object ) { NV_REF found = NvFindHandle(nvHandle); // If we found the handle and the request included an object pointer, fill it in if(found != 0 && object != NULL) NvReadObject(found, object); return found; } /* 8.4.4.11 NvIndexIsDefined() */ /* See if an index is already defined */ BOOL NvIndexIsDefined( TPM_HANDLE nvHandle // IN: Index to look for ) { return (NvFindHandle(nvHandle) != 0); } /* 8.4.4.12 NvConditionallyWrite() */ /* Function to check if the data to be written has changed and write it if it has */ /* Error Returns Meaning */ /* TPM_RC_NV_RATE NV is unavailable because of rate limit */ /* TPM_RC_NV_UNAVAILABLE NV is inaccessible */ static TPM_RC NvConditionallyWrite( NV_REF entryAddr, // IN: stating address UINT32 size, // IN: size of the data to write void *data // IN: the data to write ) { // If the index data is actually changed, then a write to NV is required if(_plat__NvIsDifferent(entryAddr, size, data)) { // Write the data if NV is available if(g_NvStatus == TPM_RC_SUCCESS) { NvWrite(entryAddr, size, data); } return g_NvStatus; } return TPM_RC_SUCCESS; } /* 8.4.4.13 NvReadNvIndexAttributes() */ /* This function returns the attributes of an NV Index. */ static TPMA_NV NvReadNvIndexAttributes( NV_REF locator // IN: reference to an NV index ) { TPMA_NV attributes; NvRead(&attributes, locator + offsetof(NV_INDEX, publicArea.attributes), sizeof(TPMA_NV)); return attributes; } /* 8.4.4.14 NvReadRamIndexAttributes() */ /* This function returns the attributes from the RAM header structure. This function is used to deal with the fact that the header structure is only byte aligned. */ static TPMA_NV NvReadRamIndexAttributes( NV_RAM_REF ref // IN: pointer to a NV_RAM_HEADER ) { TPMA_NV attributes; MemoryCopy(&attributes, ref + offsetof(NV_RAM_HEADER, attributes), sizeof(TPMA_NV)); return attributes; } /* 8.4.4.15 NvWriteNvIndexAttributes() */ /* This function is used to write just the attributes of an index to NV. */ /* Error Returns Meaning */ /* TPM_RC_NV_RATE NV is rate limiting so retry */ /* TPM_RC_NV_UNAVAILABLE NV is not available */ static TPM_RC NvWriteNvIndexAttributes( NV_REF locator, // IN: location of the index TPMA_NV attributes // IN: attributes to write ) { return NvConditionallyWrite( locator + offsetof(NV_INDEX, publicArea.attributes), sizeof(TPMA_NV), &attributes); } /* 8.4.4.16 NvWriteRamIndexAttributes() */ /* This function is used to write the index attributes into an unaligned structure */ static void NvWriteRamIndexAttributes( NV_RAM_REF ref, // IN: address of the header TPMA_NV attributes // IN: the attributes to write ) { MemoryCopy(ref + offsetof(NV_RAM_HEADER, attributes), &attributes, sizeof(TPMA_NV)); return; } /* 8.4.5 Externally Accessible Functions */ /* 8.4.5.1 NvIsPlatformPersistentHandle() */ /* This function indicates if a handle references a persistent object in the range belonging to the platform. */ /* Return Values Meaning */ /* TRUE handle references a platform persistent object */ /* FALSE handle does not reference platform persistent object */ BOOL NvIsPlatformPersistentHandle( TPM_HANDLE handle // IN: handle ) { return (handle >= PLATFORM_PERSISTENT && handle <= PERSISTENT_LAST); } /* 8.4.5.2 NvIsOwnerPersistentHandle() */ /* This function indicates if a handle references a persistent object in the range belonging to the owner. */ /* Return Values Meaning */ /* TRUE handle is owner persistent handle */ /* FALSE handle is not owner persistent handle and may not be a persistent handle at all */ BOOL NvIsOwnerPersistentHandle( TPM_HANDLE handle // IN: handle ) { return (handle >= PERSISTENT_FIRST && handle < PLATFORM_PERSISTENT); } /* 8.4.5.3 NvIndexIsAccessible() */ /* This function validates that a handle references a defined NV Index and that the Index is currently accessible. */ /* Error Returns Meaning */ /* TPM_RC_HANDLE the handle points to an undefined NV Index If shEnable is CLEAR, this would include an index created using ownerAuth. If phEnableNV is CLEAR, this would include and index created using platformAuth */ /* TPM_RC_NV_READLOCKED Index is present but locked for reading and command does not write to the index */ /* TPM_RC_NV_WRITELOCKED Index is present but locked for writing and command writes to the index */ TPM_RC NvIndexIsAccessible( TPMI_RH_NV_INDEX handle // IN: handle ) { NV_INDEX *nvIndex = NvGetIndexInfo(handle, NULL); // if(nvIndex == NULL) // If index is not found, return TPM_RC_HANDLE return TPM_RC_HANDLE; if(gc.shEnable == FALSE || gc.phEnableNV == FALSE) { // if shEnable is CLEAR, an ownerCreate NV Index should not be // indicated as present if(!IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, PLATFORMCREATE)) { if(gc.shEnable == FALSE) return TPM_RC_HANDLE; } // if phEnableNV is CLEAR, a platform created Index should not // be visible else if(gc.phEnableNV == FALSE) return TPM_RC_HANDLE; } #if 0 // Writelock test for debug // If the Index is write locked and this is an NV Write operation... if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITELOCKED) && IsWriteOperation(commandIndex)) { // then return a locked indication unless the command is TPM2_NV_WriteLock if(GetCommandCode(commandIndex) != TPM_CC_NV_WriteLock) return TPM_RC_NV_LOCKED; return TPM_RC_SUCCESS; } #endif #if 0 // Readlock Test for debug // If the Index is read locked and this is an NV Read operation... if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, READLOCKED) && IsReadOperation(commandIndex)) { // then return a locked indication unless the command is TPM2_NV_ReadLock if(GetCommandCode(commandIndex) != TPM_CC_NV_ReadLock) return TPM_RC_NV_LOCKED; } #endif // NV Index is accessible return TPM_RC_SUCCESS; } /* 8.4.5.4 NvGetEvictObject() */ /* This function is used to dereference an evict object handle and get a pointer to the object. */ /* Error Returns Meaning */ /* TPM_RC_HANDLE the handle does not point to an existing persistent object */ TPM_RC NvGetEvictObject( TPM_HANDLE handle, // IN: handle OBJECT *object // OUT: object data ) { NV_REF entityAddr; // offset points to the entity // Find the address of evict object and copy to object entityAddr = NvFindEvict(handle, object); // whether there is an error or not, make sure that the evict // status of the object is set so that the slot will get freed on exit // Must do this after NvFindEvict loads the object object->attributes.evict = SET; // If handle is not found, return an error if(entityAddr == 0) return TPM_RC_HANDLE; return TPM_RC_SUCCESS; } /* 8.4.5.5 NvIndexCacheInit() */ /* Function to initialize the Index cache */ void NvIndexCacheInit( void ) { s_cachedNvRef = NV_REF_INIT; s_cachedNvRamRef = NV_RAM_REF_INIT; s_cachedNvIndex.publicArea.nvIndex = TPM_RH_UNASSIGNED; return; } /* 8.4.5.6 NvGetIndexData() */ /* This function is used to access the data in an NV Index. The data is returned as a byte sequence. */ /* This function requires that the NV Index be defined, and that the required data is within the data range. It also requires that TPMA_NV_WRITTEN of the Index is SET. */ void NvGetIndexData( NV_INDEX *nvIndex, // IN: the in RAM index descriptor NV_REF locator, // IN: where the data is located UINT32 offset, // IN: offset of NV data UINT16 size, // IN: size of NV data void *data // OUT: data buffer ) { TPMA_NV nvAttributes; // pAssert(nvIndex != NULL); nvAttributes = nvIndex->publicArea.attributes; pAssert(IS_ATTRIBUTE(nvAttributes, TPMA_NV, WRITTEN)); if(IS_ATTRIBUTE(nvAttributes, TPMA_NV, ORDERLY)) { // Get data from RAM buffer NV_RAM_REF ramAddr = NvRamGetIndex(nvIndex->publicArea.nvIndex); pAssert(ramAddr != 0 && (size <= ((NV_RAM_HEADER *)ramAddr)->size - sizeof(NV_RAM_HEADER) - offset)); MemoryCopy(data, ramAddr + sizeof(NV_RAM_HEADER) + offset, size); } else { // Validate that read falls within range of the index pAssert(offset <= nvIndex->publicArea.dataSize && size <= (nvIndex->publicArea.dataSize - offset)); NvRead(data, locator + sizeof(NV_INDEX) + offset, size); } return; } /* 8.4.5.7 NvHashIndexData() */ /* This function adds Index data to a hash. It does this in parts to avoid large stack buffers. */ void NvHashIndexData( HASH_STATE *hashState, // IN: Initialized hash state NV_INDEX *nvIndex, // IN: Index NV_REF locator, // IN: where the data is located UINT32 offset, // IN: starting offset UINT16 size // IN: amount to hash ) { #define BUFFER_SIZE 64 BYTE buffer[BUFFER_SIZE]; if (offset > nvIndex->publicArea.dataSize) return; // Make sure that we don't try to read off the end. if ((offset + size) > nvIndex->publicArea.dataSize) size = nvIndex->publicArea.dataSize - (UINT16)offset; #if BUFFER_SIZE >= MAX_NV_INDEX_SIZE NvGetIndexData(nvIndex, locator, offset, size, buffer); CryptDigestUpdate(hashState, size, buffer); #else { INT16 i; UINT16 readSize; // for (i = size; i > 0; offset += readSize, i -= readSize) { readSize = (i < BUFFER_SIZE) ? i : BUFFER_SIZE; NvGetIndexData(nvIndex, locator, offset, readSize, buffer); CryptDigestUpdate(hashState, readSize, buffer); } } #endif // BUFFER_SIZE >= MAX_NV_INDEX_SIZE #undef BUFFER_SIZE } /* 8.4.5.7 NvGetUINT64Data() */ /* Get data in integer format of a bit or counter NV Index. */ /* This function requires that the NV Index is defined and that the NV Index previously has been written. */ UINT64 NvGetUINT64Data( NV_INDEX *nvIndex, // IN: the in RAM index descriptor NV_REF locator // IN: where index exists in NV ) { UINT64 intVal; // Read the value and convert it to internal format NvGetIndexData(nvIndex, locator, 0, 8, &intVal); return BYTE_ARRAY_TO_UINT64(((BYTE *)&intVal)); } /* 8.4.5.8 NvWriteIndexAttributes() */ /* This function is used to write just the attributes of an index. */ /* Error Returns Meaning */ /* TPM_RC_NV_RATE NV is rate limiting so retry */ /* TPM_RC_NV_UNAVAILABLE NV is not available */ TPM_RC NvWriteIndexAttributes( TPM_HANDLE handle, NV_REF locator, // IN: location of the index TPMA_NV attributes // IN: attributes to write ) { TPM_RC result; // if(IS_ATTRIBUTE(attributes, TPMA_NV, ORDERLY)) { NV_RAM_REF ram = NvRamGetIndex(handle); NvWriteRamIndexAttributes(ram, attributes); result = TPM_RC_SUCCESS; } else { result = NvWriteNvIndexAttributes(locator, attributes); } return result; } /* 8.4.5.9 NvWriteIndexAuth() */ /* This function is used to write the authValue of an index. It is used by TPM2_NV_ChangeAuth() */ /* Error Returns Meaning */ /* TPM_RC_NV_RATE NV is rate limiting so retry */ /* TPM_RC_NV_UNAVAILABLE NV is not available */ TPM_RC NvWriteIndexAuth( NV_REF locator, // IN: location of the index TPM2B_AUTH *authValue // IN: the authValue to write ) { { TPM_RC result; // // If the locator is pointing to the cached index value... if(locator == s_cachedNvRef) { // copy the authValue to the cached index so it will be there if we // look for it. This is a safety thing. MemoryCopy2B(&s_cachedNvIndex.authValue.b, &authValue->b, sizeof(s_cachedNvIndex.authValue.t.buffer)); } result = NvConditionallyWrite( locator + offsetof(NV_INDEX, authValue), sizeof(UINT16) + authValue->t.size, authValue); return result; } } /* 8.4.5.10 NvGetIndexInfo() */ /* This function loads the nvIndex Info into the NV cache and returns a pointer to the NV_INDEX. If the returned value is zero, the index was not found. The locator parameter, if not NULL, will be set to the offset in NV of the Index (the location of the handle of the Index). */ /* This function will set the index cache. If the index is orderly, the attributes from RAM are substituted for the attributes in the cached index */ NV_INDEX * NvGetIndexInfo( TPM_HANDLE nvHandle, // IN: the index handle NV_REF *locator // OUT: location of the index ) { if(s_cachedNvIndex.publicArea.nvIndex != nvHandle) { s_cachedNvIndex.publicArea.nvIndex = TPM_RH_UNASSIGNED; s_cachedNvRamRef = 0; s_cachedNvRef = NvFindHandle(nvHandle); if(s_cachedNvRef == 0) return NULL; NvReadNvIndexInfo(s_cachedNvRef, &s_cachedNvIndex); if(IS_ATTRIBUTE(s_cachedNvIndex.publicArea.attributes, TPMA_NV, ORDERLY)) { s_cachedNvRamRef = NvRamGetIndex(nvHandle); s_cachedNvIndex.publicArea.attributes = NvReadRamIndexAttributes(s_cachedNvRamRef); } } if(locator != NULL) *locator = s_cachedNvRef; return &s_cachedNvIndex; } /* 8.4.5.11 NvWriteIndexData() */ /* This function is used to write NV index data. It is intended to be used to update the data associated with the default index. */ /* This function requires that the NV Index is defined, and the data is within the defined data range for the index. */ /* Index data is only written due to a command that modifies the data in a single index. There is no case where changes are made to multiple indexes data at the same time. Multiple attributes may be change but not multiple index data. This is important because we will normally be handling the index for which we have the cached pointer values. */ /* Error Returns Meaning */ /* TPM_RC_NV_RATE NV is rate limiting so retry */ /* TPM_RC_NV_UNAVAILABLE NV is not available */ TPM_RC NvWriteIndexData( NV_INDEX *nvIndex, // IN: the description of the index UINT32 offset, // IN: offset of NV data UINT32 size, // IN: size of NV data void *data // IN: data buffer ) { TPM_RC result = TPM_RC_SUCCESS; // pAssert(nvIndex != NULL); // Make sure that this is dealing with the 'default' index. // Note: it is tempting to change the calling sequence so that the 'default' is // presumed. pAssert(nvIndex->publicArea.nvIndex == s_cachedNvIndex.publicArea.nvIndex); // Validate that write falls within range of the index pAssert(offset <= nvIndex->publicArea.dataSize && size <= (nvIndex->publicArea.dataSize - offset)); // Update TPMA_NV_WRITTEN bit if necessary if(!IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITTEN)) { // Update the in memory version of the attributes SET_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITTEN); // If this is not orderly, then update the NV version of // the attributes if(!IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, ORDERLY)) { result = NvWriteNvIndexAttributes(s_cachedNvRef, nvIndex->publicArea.attributes); if(result != TPM_RC_SUCCESS) return result; // If this is a partial write of an ordinary index, clear the whole // index. if(IsNvOrdinaryIndex(nvIndex->publicArea.attributes) && (nvIndex->publicArea.dataSize > size)) _plat__NvMemoryClear(s_cachedNvRef + sizeof(NV_INDEX), nvIndex->publicArea.dataSize); } else { // This is orderly so update the RAM version MemoryCopy(s_cachedNvRamRef + offsetof(NV_RAM_HEADER, attributes), &nvIndex->publicArea.attributes, sizeof(TPMA_NV)); // If setting WRITTEN for an orderly counter, make sure that the // state saved version of the counter is saved if(IsNvCounterIndex(nvIndex->publicArea.attributes)) SET_NV_UPDATE(UT_ORDERLY); // If setting the written attribute on an ordinary index, make sure that // the data is all cleared out in case there is a partial write. This // is only necessary for ordinary indexes because all of the other types // are always written in total. else if(IsNvOrdinaryIndex(nvIndex->publicArea.attributes)) MemorySet(s_cachedNvRamRef + sizeof(NV_RAM_HEADER), 0, nvIndex->publicArea.dataSize); } } // If this is orderly data, write it to RAM if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, ORDERLY)) { // Note: if this is the first write to a counter, the code above will queue // the write to NV of the RAM data in order to update TPMA_NV_WRITTEN. In // process of doing that write, it will also write the initial counter value // Update RAM MemoryCopy(s_cachedNvRamRef + sizeof(NV_RAM_HEADER) + offset, data, size); // And indicate that the TPM is no longer orderly g_clearOrderly = TRUE; } else { // Offset into the index to the first byte of the data to be written to NV result = NvConditionallyWrite(s_cachedNvRef + sizeof(NV_INDEX) + offset, size, data); } return result; } /* 8.4.5.12 NvWriteUINT64Data() */ /* This function to write back a UINT64 value. The various UINT64 values (bits, counters, and PINs()) are kept in canonical format but manipulate in native format. This takes a native format value converts it and saves it back as in canonical format. */ /* This function will return the value from NV or RAM depending on the type of the index (orderly or not) */ TPM_RC NvWriteUINT64Data( NV_INDEX *nvIndex, // IN: the description of the index UINT64 intValue // IN: the value to write ) { BYTE bytes[8]; UINT64_TO_BYTE_ARRAY(intValue, bytes); return NvWriteIndexData(nvIndex, 0, 8, &bytes); } /* 8.4.5.13 NvGetIndexName() */ /* This function computes the Name of an index The name buffer receives the bytes of the Name and the return value is the number of octets in the Name. */ /* This function requires that the NV Index is defined. */ TPM2B_NAME * NvGetIndexName( NV_INDEX *nvIndex, // IN: the index over which the name is to be // computed TPM2B_NAME *name // OUT: name of the index ) { UINT16 dataSize, digestSize; BYTE marshalBuffer[sizeof(TPMS_NV_PUBLIC)]; BYTE *buffer; HASH_STATE hashState; // Marshal public area buffer = marshalBuffer; dataSize = TPMS_NV_PUBLIC_Marshal(&nvIndex->publicArea, &buffer, NULL); // hash public area digestSize = CryptHashStart(&hashState, nvIndex->publicArea.nameAlg); CryptDigestUpdate(&hashState, dataSize, marshalBuffer); // Complete digest leaving room for the nameAlg CryptHashEnd(&hashState, digestSize, &name->b.buffer[2]); // Include the nameAlg UINT16_TO_BYTE_ARRAY(nvIndex->publicArea.nameAlg, name->b.buffer); name->t.size = digestSize + 2; return name; } /* 8.4.5.14 NvGetNameByIndexHandle() */ /* This function is used to compute the Name of an NV Index referenced by handle. */ /* The name buffer receives the bytes of the Name and the return value is the number of octets in the Name. */ /* This function requires that the NV Index is defined. */ TPM2B_NAME * NvGetNameByIndexHandle( TPMI_RH_NV_INDEX handle, // IN: handle of the index TPM2B_NAME *name // OUT: name of the index ) { NV_INDEX *nvIndex = NvGetIndexInfo(handle, NULL); return NvGetIndexName(nvIndex, name); } /* 8.4.5.15 NvDefineIndex() */ /* This function is used to assign NV memory to an NV Index. */ /* Error Returns Meaning */ /* TPM_RC_NV_SPACE insufficient NV space */ TPM_RC NvDefineIndex( TPMS_NV_PUBLIC *publicArea, // IN: A template for an area to create. TPM2B_AUTH *authValue // IN: The initial authorization value ) { // The buffer to be written to NV memory NV_INDEX nvIndex; // the index data UINT16 entrySize; // size of entry TPM_RC result; // entrySize = sizeof(NV_INDEX); // only allocate data space for indexes that are going to be written to NV. // Orderly indexes don't need space. if(!IS_ATTRIBUTE(publicArea->attributes, TPMA_NV, ORDERLY)) entrySize += publicArea->dataSize; // Check if we have enough space to create the NV Index // In this implementation, the only resource limitation is the available NV // space (and possibly RAM space.) Other implementation may have other // limitation on counter or on NV slots if(!NvTestSpace(entrySize, TRUE, IsNvCounterIndex(publicArea->attributes))) return TPM_RC_NV_SPACE; // if the index to be defined is RAM backed, check RAM space availability // as well if(IS_ATTRIBUTE(publicArea->attributes, TPMA_NV, ORDERLY) && !NvRamTestSpaceIndex(publicArea->dataSize)) return TPM_RC_NV_SPACE; // Copy input value to nvBuffer nvIndex.publicArea = *publicArea; // Copy the authValue nvIndex.authValue = *authValue; // Add index to NV memory result = NvAdd(entrySize, sizeof(NV_INDEX), TPM_RH_UNASSIGNED, (BYTE *)&nvIndex); if(result == TPM_RC_SUCCESS) { // If the data of NV Index is RAM backed, add the data area in RAM as well if(IS_ATTRIBUTE(publicArea->attributes, TPMA_NV, ORDERLY)) NvAddRAM(publicArea); } return result; } /* 8.4.5.16 NvAddEvictObject() */ /* This function is used to assign NV memory to a persistent object. */ /* Error Returns Meaning */ /* TPM_RC_NV_HANDLE the requested handle is already in use */ /* TPM_RC_NV_SPACE insufficient NV space */ TPM_RC NvAddEvictObject( TPMI_DH_OBJECT evictHandle, // IN: new evict handle OBJECT *object // IN: object to be added ) { TPM_HANDLE temp = object->evictHandle; TPM_RC result; // Check if we have enough space to add the evict object // An evict object needs 8 bytes in index table + sizeof OBJECT // In this implementation, the only resource limitation is the available NV // space. Other implementation may have other limitation on evict object // handle space if(!NvTestSpace(sizeof(OBJECT) + sizeof(TPM_HANDLE), FALSE, FALSE)) return TPM_RC_NV_SPACE; // Set evict attribute and handle object->attributes.evict = SET; object->evictHandle = evictHandle; // Now put this in NV result = NvAdd(sizeof(OBJECT), sizeof(OBJECT), evictHandle, (BYTE *)object); // Put things back the way they were object->attributes.evict = CLEAR; object->evictHandle = temp; return result; } /* 8.4.5.17 NvDeleteIndex() */ /* This function is used to delete an NV Index. */ /* Error Returns Meaning */ /* TPM_RC_NV_UNAVAILABLE NV is not accessible */ /* TPM_RC_NV_RATE NV is rate limiting */ TPM_RC NvDeleteIndex( NV_INDEX *nvIndex, // IN: an in RAM index descriptor NV_REF entityAddr // IN: location in NV ) { TPM_RC result; // if(nvIndex != NULL) { // Whenever a counter is deleted, make sure that the MaxCounter value is // updated to reflect the value if(IsNvCounterIndex(nvIndex->publicArea.attributes) && IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITTEN)) NvUpdateMaxCount(NvGetUINT64Data(nvIndex, entityAddr)); result = NvDelete(entityAddr); if(result != TPM_RC_SUCCESS) return result; // If the NV Index is RAM backed, delete the RAM data as well if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, ORDERLY)) NvDeleteRAM(nvIndex->publicArea.nvIndex); NvIndexCacheInit(); } return TPM_RC_SUCCESS; } /* 8.4.5.18 NvDeleteEvict() */ /* This function will delete a NV evict object. Will return success if object deleted or if it does not exist */ TPM_RC NvDeleteEvict( TPM_HANDLE handle // IN: handle of entity to be deleted ) { NV_REF entityAddr = NvFindEvict(handle, NULL); // pointer to entity TPM_RC result = TPM_RC_SUCCESS; if(entityAddr != 0) result = NvDelete(entityAddr); return result; } /* 8.4.5.19 NvFlushHierarchy() */ /* This function will delete persistent objects belonging to the indicated hierarchy. If the storage hierarchy is selected, the function will also delete any NV Index defined using ownerAuth. */ /* Error Returns Meaning */ /* TPM_RC_NV_RATE NV is unavailable because of rate limit */ /* TPM_RC_NV_UNAVAILABLE NV is inaccessible */ TPM_RC NvFlushHierarchy( TPMI_RH_HIERARCHY hierarchy // IN: hierarchy to be flushed. ) { NV_REF iter = NV_REF_INIT; NV_REF currentAddr; TPM_HANDLE entityHandle; TPM_RC result = TPM_RC_SUCCESS; // while((currentAddr = NvNext(&iter, &entityHandle)) != 0) { if(HandleGetType(entityHandle) == TPM_HT_NV_INDEX) { NV_INDEX nvIndex; // // If flush endorsement or platform hierarchy, no NV Index would be // flushed if(hierarchy == TPM_RH_ENDORSEMENT || hierarchy == TPM_RH_PLATFORM) continue; // Get the index information NvReadNvIndexInfo(currentAddr, &nvIndex); // For storage hierarchy, flush OwnerCreated index if(!IS_ATTRIBUTE(nvIndex.publicArea.attributes, TPMA_NV, PLATFORMCREATE)) { // Delete the index (including RAM for orderly) result = NvDeleteIndex(&nvIndex, currentAddr); if(result != TPM_RC_SUCCESS) break; // Re-iterate from beginning after a delete iter = NV_REF_INIT; } } else if(HandleGetType(entityHandle) == TPM_HT_PERSISTENT) { OBJECT_ATTRIBUTES attributes; // NvRead(&attributes, (UINT32)(currentAddr + sizeof(TPM_HANDLE) + offsetof(OBJECT, attributes)), sizeof(OBJECT_ATTRIBUTES)); // If the evict object belongs to the hierarchy to be flushed... if((hierarchy == TPM_RH_PLATFORM && attributes.ppsHierarchy == SET) || (hierarchy == TPM_RH_OWNER && attributes.spsHierarchy == SET) || (hierarchy == TPM_RH_ENDORSEMENT && attributes.epsHierarchy == SET)) { // ...then delete the evict object result = NvDelete(currentAddr); if(result != TPM_RC_SUCCESS) break; // Re-iterate from beginning after a delete iter = NV_REF_INIT; } } else { FAIL(FATAL_ERROR_INTERNAL); } } return result; } /* 8.4.5.20 NvSetGlobalLock() */ /* This function is used to SET the TPMA_NV_WRITELOCKED attribute for all NV Indexes that have TPMA_NV_GLOBALLOCK SET. This function is use by TPM2_NV_GlobalWriteLock(). */ /* Error Returns Meaning */ /* TPM_RC_NV_RATE NV is unavailable because of rate limit */ /* TPM_RC_NV_UNAVAILABLE NV is inaccessible */ TPM_RC NvSetGlobalLock( void ) { NV_REF iter = NV_REF_INIT; NV_RAM_REF ramIter = NV_RAM_REF_INIT; NV_REF currentAddr; NV_RAM_REF currentRamAddr; TPM_RC result = TPM_RC_SUCCESS; // // Check all normal indexes while((currentAddr = NvNextIndex(NULL, &iter)) != 0) { TPMA_NV attributes = NvReadNvIndexAttributes(currentAddr); // // See if it should be locked if(!IS_ATTRIBUTE(attributes, TPMA_NV, ORDERLY) && IS_ATTRIBUTE(attributes, TPMA_NV, GLOBALLOCK)) { SET_ATTRIBUTE(attributes, TPMA_NV, WRITELOCKED); result = NvWriteNvIndexAttributes(currentAddr, attributes); if(result != TPM_RC_SUCCESS) return result; } } // Now search all the orderly attributes while((currentRamAddr = NvRamNext(&ramIter, NULL)) != 0) { // See if it should be locked TPMA_NV attributes = NvReadRamIndexAttributes(currentRamAddr); if(IS_ATTRIBUTE(attributes, TPMA_NV, GLOBALLOCK)) { SET_ATTRIBUTE(attributes, TPMA_NV, WRITELOCKED); NvWriteRamIndexAttributes(currentRamAddr, attributes); } } return result; } /* 8.4.5.21 InsertSort() */ /* Sort a handle into handle list in ascending order. The total handle number in the list should not exceed MAX_CAP_HANDLES */ static void InsertSort( TPML_HANDLE *handleList, // IN/OUT: sorted handle list UINT32 count, // IN: maximum count in the handle list TPM_HANDLE entityHandle // IN: handle to be inserted ) { UINT32 i, j; UINT32 originalCount; // For a corner case that the maximum count is 0, do nothing if(count == 0) return; // For empty list, add the handle at the beginning and return if(handleList->count == 0) { handleList->handle[0] = entityHandle; handleList->count++; return; } // Check if the maximum of the list has been reached originalCount = handleList->count; if(originalCount < count) handleList->count++; // Insert the handle to the list for(i = 0; i < originalCount; i++) { if(handleList->handle[i] > entityHandle) { for(j = handleList->count - 1; j > i; j--) { handleList->handle[j] = handleList->handle[j - 1]; } break; } } // If a slot was found, insert the handle in this position if(i < originalCount || handleList->count > originalCount) handleList->handle[i] = entityHandle; return; } /* 8.4.5.22 NvCapGetPersistent() */ /* This function is used to get a list of handles of the persistent objects, starting at handle. */ /* Handle must be in valid persistent object handle range, but does not have to reference an existing persistent object. */ /* Return Values Meaning */ /* YES if there are more handles available */ /* NO all the available handles has been returned */ TPMI_YES_NO NvCapGetPersistent( TPMI_DH_OBJECT handle, // IN: start handle UINT32 count, // IN: maximum number of returned handles TPML_HANDLE *handleList // OUT: list of handle ) { TPMI_YES_NO more = NO; NV_REF iter = NV_REF_INIT; NV_REF currentAddr; TPM_HANDLE entityHandle; pAssert(HandleGetType(handle) == TPM_HT_PERSISTENT); // Initialize output handle list handleList->count = 0; // The maximum count of handles we may return is MAX_CAP_HANDLES if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES; while((currentAddr = NvNextEvict(&entityHandle, &iter)) != 0) { // Ignore persistent handles that have values less than the input handle if(entityHandle < handle) continue; // if the handles in the list have reached the requested count, and there // are still handles need to be inserted, indicate that there are more. if(handleList->count == count) more = YES; // A handle with a value larger than start handle is a candidate // for return. Insert sort it to the return list. Insert sort algorithm // is chosen here for simplicity based on the assumption that the total // number of NV Indexes is small. For an implementation that may allow // large number of NV Indexes, a more efficient sorting algorithm may be // used here. InsertSort(handleList, count, entityHandle); } return more; } /* 8.4.5.23 NvCapGetIndex() */ /* This function returns a list of handles of NV Indexes, starting from handle. Handle must be in the range of NV Indexes, but does not have to reference an existing NV Index. */ /* Return Values Meaning */ /* YES if there are more handles to report */ /* NO all the available handles has been reported */ TPMI_YES_NO NvCapGetIndex( TPMI_DH_OBJECT handle, // IN: start handle UINT32 count, // IN: max number of returned handles TPML_HANDLE *handleList // OUT: list of handle ) { TPMI_YES_NO more = NO; NV_REF iter = NV_REF_INIT; NV_REF currentAddr; TPM_HANDLE nvHandle; pAssert(HandleGetType(handle) == TPM_HT_NV_INDEX); // Initialize output handle list handleList->count = 0; // The maximum count of handles we may return is MAX_CAP_HANDLES if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES; while((currentAddr = NvNextIndex(&nvHandle, &iter)) != 0) { // Ignore index handles that have values less than the 'handle' if(nvHandle < handle) continue; // if the count of handles in the list has reached the requested count, // and there are still handles to report, set more. if(handleList->count == count) more = YES; // A handle with a value larger than start handle is a candidate // for return. Insert sort it to the return list. Insert sort algorithm // is chosen here for simplicity based on the assumption that the total // number of NV Indexes is small. For an implementation that may allow // large number of NV Indexes, a more efficient sorting algorithm may be // used here. InsertSort(handleList, count, nvHandle); } return more; } /* 8.4.5.24 NvCapGetIndexNumber() */ /* This function returns the count of NV Indexes currently defined. */ UINT32 NvCapGetIndexNumber( void ) { UINT32 num = 0; NV_REF iter = NV_REF_INIT; while(NvNextIndex(NULL, &iter) != 0) num++; return num; } /* 8.4.5.25 NvCapGetPersistentNumber() */ /* Function returns the count of persistent objects currently in NV memory. */ UINT32 NvCapGetPersistentNumber( void ) { UINT32 num = 0; NV_REF iter = NV_REF_INIT; TPM_HANDLE handle; while(NvNextEvict(&handle, &iter) != 0) num++; return num; } /* 8.4.5.26 NvCapGetPersistentAvail() */ /* This function returns an estimate of the number of additional persistent objects that could be loaded into NV memory. */ UINT32 NvCapGetPersistentAvail( void ) { UINT32 availNVSpace; UINT32 counterNum = NvCapGetCounterNumber(); UINT32 reserved = sizeof(NV_LIST_TERMINATOR); // Get the available space in NV storage availNVSpace = NvGetFreeBytes(); if(counterNum < MIN_COUNTER_INDICES) { // Some space has to be reserved for counter objects. reserved += (MIN_COUNTER_INDICES - counterNum) * NV_INDEX_COUNTER_SIZE; if(reserved > availNVSpace) availNVSpace = 0; else availNVSpace -= reserved; } return availNVSpace / NV_EVICT_OBJECT_SIZE; } /* 8.4.5.27 NvCapGetCounterNumber() */ /* Get the number of defined NV Indexes that are counter indexes. */ UINT32 NvCapGetCounterNumber( void ) { NV_REF iter = NV_REF_INIT; NV_REF currentAddr; UINT32 num = 0; while((currentAddr = NvNextIndex(NULL, &iter)) != 0) { TPMA_NV attributes = NvReadNvIndexAttributes(currentAddr); if(IsNvCounterIndex(attributes)) num++; } return num; } /* 8.4.5.28 NvSetStartupAttributes() */ /* Local function to set the attributes of an Index at TPM Reset and TPM Restart. */ static TPMA_NV NvSetStartupAttributes( TPMA_NV attributes, // IN: attributes to change STARTUP_TYPE type // IN: start up type ) { // Clear read lock CLEAR_ATTRIBUTE(attributes, TPMA_NV, READLOCKED); // Will change a non counter index to the unwritten state if: // a) TPMA_NV_CLEAR_STCLEAR is SET // b) orderly and TPM Reset if(!IsNvCounterIndex(attributes)) { if(IS_ATTRIBUTE(attributes, TPMA_NV, CLEAR_STCLEAR) || (IS_ATTRIBUTE(attributes, TPMA_NV, ORDERLY) && (type == SU_RESET))) CLEAR_ATTRIBUTE(attributes, TPMA_NV, WRITTEN); } // Unlock any index that is not written or that does not have // TPMA_NV_WRITEDEFINE SET. if(!IS_ATTRIBUTE(attributes, TPMA_NV, WRITTEN) || !IS_ATTRIBUTE(attributes, TPMA_NV, WRITEDEFINE)) CLEAR_ATTRIBUTE(attributes, TPMA_NV, WRITELOCKED); return attributes; } /* 8.4.5.29 NvEntityStartup() */ /* This function is called at TPM_Startup(). If the startup completes a TPM Resume cycle, no action is taken. If the startup is a TPM Reset or a TPM Restart, then this function will: */ /* a) clear read/write lock; */ /* b) reset NV Index data that has TPMA_NV_CLEAR_STCLEAR SET; and */ /* c) set the lower bits in orderly counters to 1 for a non-orderly startup */ /* It is a prerequisite that NV be available for writing before this function is called. */ BOOL NvEntityStartup( STARTUP_TYPE type // IN: start up type ) { NV_REF iter = NV_REF_INIT; NV_RAM_REF ramIter = NV_RAM_REF_INIT; NV_REF currentAddr; // offset points to the current entity NV_RAM_REF currentRamAddr; TPM_HANDLE nvHandle; TPMA_NV attributes; // Restore RAM index data NvRead(s_indexOrderlyRam, NV_INDEX_RAM_DATA, sizeof(s_indexOrderlyRam)); // Initialize the max NV counter value NvSetMaxCount(NvGetMaxCount()); // If recovering from state save, do nothing else if(type == SU_RESUME) return TRUE; // Iterate all the NV Index to clear the locks while((currentAddr = NvNextIndex(&nvHandle, &iter)) != 0) { attributes = NvReadNvIndexAttributes(currentAddr); // If this is an orderly index, defer processing until loop below if(IS_ATTRIBUTE(attributes, TPMA_NV, ORDERLY)) continue; // Set the attributes appropriate for this startup type attributes = NvSetStartupAttributes(attributes, type); NvWriteNvIndexAttributes(currentAddr, attributes); } // Iterate all the orderly indexes to clear the locks and initialize counters while((currentRamAddr = NvRamNext(&ramIter, NULL)) != 0) { attributes = NvReadRamIndexAttributes(currentRamAddr); attributes = NvSetStartupAttributes(attributes, type); // update attributes in RAM NvWriteRamIndexAttributes(currentRamAddr, attributes); // Set the lower bits in an orderly counter to 1 for a non-orderly startup if(IsNvCounterIndex(attributes) && (g_prevOrderlyState == SU_NONE_VALUE)) { UINT64 counter; // Read the counter value last saved to NV. counter = BYTE_ARRAY_TO_UINT64(currentRamAddr + sizeof(NV_RAM_HEADER)); // Set the lower bits of counter to 1's counter |= MAX_ORDERLY_COUNT; // Write back to RAM // NOTE: Do not want to force a write to NV here. The counter value will // stay in RAM until the next shutdown or rollover. UINT64_TO_BYTE_ARRAY(counter, currentRamAddr + sizeof(NV_RAM_HEADER)); } } return TRUE; } /* 8.4.5.30 NvCapGetCounterAvail() */ /* This function returns an estimate of the number of additional counter type NV Indexes that can be defined. */ UINT32 NvCapGetCounterAvail( void ) { UINT32 availNVSpace; UINT32 availRAMSpace; UINT32 persistentNum = NvCapGetPersistentNumber(); UINT32 reserved = sizeof(NV_LIST_TERMINATOR); // Get the available space in NV storage availNVSpace = NvGetFreeBytes(); if(persistentNum < MIN_EVICT_OBJECTS) { // Some space has to be reserved for evict object. Adjust availNVSpace. reserved += (MIN_EVICT_OBJECTS - persistentNum) * NV_EVICT_OBJECT_SIZE; if(reserved > availNVSpace) availNVSpace = 0; else availNVSpace -= reserved; } // Compute the available space in RAM availRAMSpace = (RAM_ORDERLY_END - NvRamGetEnd()); /* kgold - removed cast */ // Return the min of counter number in NV and in RAM if(availNVSpace / NV_INDEX_COUNTER_SIZE > availRAMSpace / NV_RAM_INDEX_COUNTER_SIZE) return availRAMSpace / NV_RAM_INDEX_COUNTER_SIZE; else return availNVSpace / NV_INDEX_COUNTER_SIZE; } /* 8.4.5.31 NvFindHandle() */ /* this function returns the offset in NV memory of the entity associated with the input handle. A value of zero indicates that handle does not exist reference an existing persistent object or defined NV Index. */ NV_REF NvFindHandle( TPM_HANDLE handle ) { NV_REF addr; NV_REF iter = NV_REF_INIT; TPM_HANDLE nextHandle; while((addr = NvNext(&iter, &nextHandle)) != 0) { if(nextHandle == handle) break; } return addr; } /* 8.4.6 NV Max Counter */ /* 8.4.6.1 Introduction */ /* The TPM keeps track of the highest value of a deleted counter index. When an index is deleted, this value is updated if the deleted counter index is greater than the previous value. When a new index is created and first incremented, it will get a value that is at least one greater than any other index than any previously deleted index. This ensures that it is not possible to roll back an index. */ /* The highest counter value is kept in NV in a special end-of-list marker. This marker is only updated when an index is deleted. Otherwise it just moves. */ /* When the TPM starts up, it searches NV for the end of list marker and initializes an in memory value (s_maxCounter). */ /* 8.4.6.2 NvReadMaxCount() */ /* This function returns the max NV counter value. */ UINT64 NvReadMaxCount( void ) { return s_maxCounter; } /* 8.4.6.3 NvUpdateMaxCount() */ /* This function updates the max counter value to NV memory. This is just staging for the actual write that will occur when the NV index memory is modified. */ void NvUpdateMaxCount( UINT64 count ) { if(count > s_maxCounter) s_maxCounter = count; } /* 8.4.6.4 NvSetMaxCount() */ /* This function is used at NV initialization time to set the initial value of the maximum counter. */ void NvSetMaxCount( UINT64 value ) { s_maxCounter = value; } /* 8.4.6.5 NvGetMaxCount() */ /* Function to get the NV max counter value from the end-of-list marker */ UINT64 NvGetMaxCount( void ) { NV_REF iter = NV_REF_INIT; NV_REF currentAddr; UINT64 maxCount; // Find the end of list marker and initialize the NV Max Counter value. while((currentAddr = NvNext(&iter, NULL )) != 0); // 'iter' should be pointing at the end of list marker so read in the current // value of the s_maxCounter. NvRead(&maxCount, iter + sizeof(UINT32), sizeof(maxCount)); return maxCount; } libtpms-0.9.3/src/tpm2/NVDynamic_fp.h000066400000000000000000000205751421143571500173500ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Dynamic space for user defined NV */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: NVDynamic_fp.h 1476 2019-06-10 19:32:03Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ #ifndef NVDYNAMIC_FP_H #define NVDYNAMIC_FP_H NV_REF NvWriteNvListEnd( NV_REF end ); void NvUpdateIndexOrderlyData( void ); void NvReadNvIndexInfo( NV_REF ref, // IN: points to NV where index is located NV_INDEX *nvIndex // OUT: place to receive index data ); void NvReadObject( NV_REF ref, // IN: points to NV where index is located OBJECT *object // OUT: place to receive the object data ); BOOL NvIndexIsDefined( TPM_HANDLE nvHandle // IN: Index to look for ); BOOL NvIsPlatformPersistentHandle( TPM_HANDLE handle // IN: handle ); BOOL NvIsOwnerPersistentHandle( TPM_HANDLE handle // IN: handle ); TPM_RC NvIndexIsAccessible( TPMI_RH_NV_INDEX handle // IN: handle ); TPM_RC NvGetEvictObject( TPM_HANDLE handle, // IN: handle OBJECT *object // OUT: object data ); void NvIndexCacheInit( void ); void NvGetIndexData( NV_INDEX *nvIndex, // IN: the in RAM index descriptor NV_REF locator, // IN: where the data is located UINT32 offset, // IN: offset of NV data UINT16 size, // IN: size of NV data void *data // OUT: data buffer ); void NvHashIndexData( HASH_STATE *hashState, // IN: Initialized hash state NV_INDEX *nvIndex, // IN: Index NV_REF locator, // IN: where the data is located UINT32 offset, // IN: starting offset UINT16 size // IN: amount to hash ); UINT64 NvGetUINT64Data( NV_INDEX *nvIndex, // IN: the in RAM index descriptor NV_REF locator // IN: where index exists in NV ); TPM_RC NvWriteIndexAttributes( TPM_HANDLE handle, NV_REF locator, // IN: location of the index TPMA_NV attributes // IN: attributes to write ); TPM_RC NvWriteIndexAuth( NV_REF locator, // IN: location of the index TPM2B_AUTH *authValue // IN: the authValue to write ); NV_INDEX * NvGetIndexInfo( TPM_HANDLE nvHandle, // IN: the index handle NV_REF *locator // OUT: location of the index ); TPM_RC NvWriteIndexData( NV_INDEX *nvIndex, // IN: the description of the index UINT32 offset, // IN: offset of NV data UINT32 size, // IN: size of NV data void *data // IN: data buffer ); TPM_RC NvWriteUINT64Data( NV_INDEX *nvIndex, // IN: the description of the index UINT64 intValue // IN: the value to write ); TPM2B_NAME * NvGetIndexName( NV_INDEX *nvIndex, // IN: the index over which the name is to be // computed TPM2B_NAME *name // OUT: name of the index ); TPM2B_NAME * NvGetNameByIndexHandle( TPMI_RH_NV_INDEX handle, // IN: handle of the index TPM2B_NAME *name // OUT: name of the index ); TPM_RC NvDefineIndex( TPMS_NV_PUBLIC *publicArea, // IN: A template for an area to create. TPM2B_AUTH *authValue // IN: The initial authorization value ); TPM_RC NvAddEvictObject( TPMI_DH_OBJECT evictHandle, // IN: new evict handle OBJECT *object // IN: object to be added ); TPM_RC NvDeleteIndex( NV_INDEX *nvIndex, // IN: an in RAM index descriptor NV_REF entityAddr // IN: location in NV ); TPM_RC NvDeleteEvict( TPM_HANDLE handle // IN: handle of entity to be deleted ); TPM_RC NvFlushHierarchy( TPMI_RH_HIERARCHY hierarchy // IN: hierarchy to be flushed. ); TPM_RC NvSetGlobalLock( void ); TPMI_YES_NO NvCapGetPersistent( TPMI_DH_OBJECT handle, // IN: start handle UINT32 count, // IN: maximum number of returned handles TPML_HANDLE *handleList // OUT: list of handle ); TPMI_YES_NO NvCapGetIndex( TPMI_DH_OBJECT handle, // IN: start handle UINT32 count, // IN: max number of returned handles TPML_HANDLE *handleList // OUT: list of handle ); UINT32 NvCapGetIndexNumber( void ); UINT32 NvCapGetPersistentNumber( void ); UINT32 NvCapGetPersistentAvail( void ); UINT32 NvCapGetCounterNumber( void ); BOOL NvEntityStartup( STARTUP_TYPE type // IN: start up type ); UINT32 NvCapGetCounterAvail( void ); NV_REF NvFindHandle( TPM_HANDLE handle ); UINT64 NvReadMaxCount( void ); void NvUpdateMaxCount( UINT64 count ); void NvSetMaxCount( UINT64 value ); UINT64 NvGetMaxCount( void ); #endif libtpms-0.9.3/src/tpm2/NVMarshal.c000066400000000000000000004750461421143571500166700ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Marshalling and unmarshalling of state */ /* Written by Stefan Berger */ /* IBM Thomas J. Watson Research Center */ /* */ /* (c) Copyright IBM Corporation 2017,2018. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include #include #include "assert.h" #define _CRYPT_HASH_C_ #define SESSION_PROCESS_C #define NV_C #define OBJECT_C #define PCR_C #define SESSION_C #include "Platform.h" #include "NVMarshal.h" #include "Marshal_fp.h" #include "Unmarshal_fp.h" #include "Global.h" #include "TpmTcpProtocol.h" #include "Simulator_fp.h" #define TPM_HAVE_TPM2_DECLARATIONS #include "tpm_library_intern.h" /* * The TPM2 maintains a pcrAllocated shadow variable; the current active one is * in gp.pcrAllocated and the one to be active after reboot is in NVRAM. So, * this means we have to restore two of these variables when we resume. The * tricky part is that the global gp will be restored by reading from NVRAM. * Once that has been done the gp.pcrAllocated needs to be restored with the * one that is supposed to be active. All of this is only supposed to happen * when we resume a VM's volatile state. */ static struct shadow { TPML_PCR_SELECTION pcrAllocated; BOOL pcrAllocatedIsNew; } shadow; /* prevent misconfiguration: */ typedef char assertion_failed_nvram[ (NV_USER_DYNAMIC_END < NV_USER_DYNAMIC) ? -1 : 0]; typedef struct { UINT16 version; UINT32 magic; UINT16 min_version; /* min. implementation version to accept the blob */ } NV_HEADER; static UINT8 BOOL_Marshal(BOOL *boolean, BYTE **buffer, INT32 *size); static TPM_RC BOOL_Unmarshal(BOOL *boolean, BYTE **buffer, INT32 *size); /* * There are compile-time optional variables that we marshal. To allow * for some flexibility, we marshal them in such a way that these * variables can be skipped if they are in the byte stream but are not * needed by the implementation. The following block_skip data structure * and related functions address this issue. */ typedef struct { size_t idx; size_t sz; struct position { BYTE *buffer; INT32 size; } pos[5]; /* more only needed for nested compile-time #ifdef's */ } block_skip; /* * This function is to be called when an optional block follows. It inserts * a BOOL into the byte stream indicating whether the block is there or not. * Then it leaves a 16bit zero in the byt stream and remembers the location * of that zero. We will update the location with the number of optional * bytes written when block_skip_write_pop() is called. */ static UINT16 block_skip_write_push(block_skip *bs, BOOL has_block, BYTE **buffer, INT32 *size) { UINT16 written , w; UINT16 zero = 0; written = BOOL_Marshal(&has_block, buffer, size); bs->pos[bs->idx].buffer = *buffer; bs->pos[bs->idx].size = *size; w = UINT16_Marshal(&zero, buffer, size); if (w) { bs->idx++; pAssert(bs->idx < bs->sz); written += w; } return written; } /* * This function must be called for every block_skip_write_push() call. * It has to be called once a compile-time optional block has been * processed. It must be called after the #endif. * In this function we updated the previously remembered location with * the numbers of bytes to skip in case a block is there but it is not * needed. */ static void block_skip_write_pop(block_skip *bs, INT32 *size) { UINT16 skip; unsigned i = --bs->idx; pAssert((int)bs->idx >= 0); skip = bs->pos[i].size - *size - sizeof(UINT16); UINT16_Marshal(&skip, &bs->pos[i].buffer, &bs->pos[i].size); } /* * This function must be called when unmarshalling a byte stream and * a compile-time optional block follows. In case the compile-time * optional block is there but not in the byte stream, we log an error. * In case the bytes stream contains the block, but we don't need it * we skip it. In the other cases we don't need to do anything since * the code is 'in sync' with the byte stream. */ static TPM_RC block_skip_read(BOOL needs_block, BYTE **buffer, INT32 *size, const char *name, const char *field, BOOL *skip_code) { TPM_RC rc = TPM_RC_SUCCESS; BOOL has_block; UINT16 blocksize; if (rc == TPM_RC_SUCCESS) { rc = BOOL_Unmarshal(&has_block, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(&blocksize, buffer, size); } if (rc == TPM_RC_SUCCESS) { if (!has_block && needs_block) { TPMLIB_LogTPM2Error("%s needs missing %s\n", name, field); rc = TPM_RC_BAD_PARAMETER; } else if (has_block && !needs_block) { /* byte stream has the data but we don't need them */ *buffer += blocksize; *size -= blocksize; *skip_code = TRUE; } } return rc; } #define BLOCK_SKIP_INIT \ block_skip block_skip = { \ .idx = 0, \ .sz = ARRAY_SIZE(block_skip.pos), \ } #define BLOCK_SKIP_WRITE_PUSH(HAS_BLOCK, BUFFER, POS) \ block_skip_write_push(&block_skip, HAS_BLOCK, BUFFER, POS) #define BLOCK_SKIP_WRITE_POP(SIZE) \ block_skip_write_pop(&block_skip, SIZE) #define BLOCK_SKIP_WRITE_CHECK \ pAssert(block_skip.idx == 0) #define BLOCK_SKIP_READ(SKIP_MARK, NEEDS_BLOCK, BUFFER, SIZE, NAME, FIELD) \ { \ BOOL skip_code = FALSE; \ rc = block_skip_read(NEEDS_BLOCK, buffer, size, \ NAME, FIELD, &skip_code); \ if (rc == TPM_RC_SUCCESS && skip_code) \ goto SKIP_MARK; \ } static unsigned int _ffsll(long long bits) { size_t i = 0; for (i = 0; i < 8 * sizeof(bits); i++) { if (bits & (1ULL << i)) return i + 1; } return 0; } /* BOOL is 'int' but we store a single byte */ static UINT8 BOOL_Marshal(BOOL *boolean, BYTE **buffer, INT32 *size) { UINT8 _bool = (*boolean != 0); UINT16 written = 0; written += UINT8_Marshal(&_bool, buffer, size); return written; } static TPM_RC BOOL_Unmarshal(BOOL *boolean, BYTE **buffer, INT32 *size) { UINT8 _bool; TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = UINT8_Unmarshal(&_bool, buffer, size); } if (rc == TPM_RC_SUCCESS) { *boolean = (_bool != 0); } return rc; } static UINT16 SEED_COMPAT_LEVEL_Marshal(SEED_COMPAT_LEVEL *source, BYTE **buffer, INT32 *size) { return UINT8_Marshal((UINT8 *)source, buffer, size); } static TPM_RC SEED_COMPAT_LEVEL_Unmarshal(SEED_COMPAT_LEVEL *source, BYTE **buffer, INT32 *size, const char *name) { TPM_RC rc; rc = UINT8_Unmarshal((UINT8 *)source, buffer, size); if (rc == TPM_RC_SUCCESS && *source > SEED_COMPAT_LEVEL_LAST) { TPMLIB_LogTPM2Error("%s compatLevel '%u' higher than supported '%u'\n", name, *source, SEED_COMPAT_LEVEL_LAST); rc = TPM_RC_BAD_VERSION; } return rc; } static int TPM2B_Cmp(const TPM2B *t1, const TPM2B *t2) { if (t1->size != t2->size) return 1; return memcmp(t1->buffer, t2->buffer, t1->size); } static UINT16 TPM2B_PROOF_Marshal(TPM2B_PROOF *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM2B_Marshal(&source->b, sizeof(source->t.buffer), buffer, size); return written; } static TPM_RC TPM2B_PROOF_Unmarshal(TPM2B_PROOF *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPM2B_Unmarshal(&target->b, sizeof(target->t.buffer), buffer, size); } return rc; } static TPM_RC UINT32_Unmarshal_Check(UINT32 *data, UINT32 exp, BYTE **buffer, INT32 *size, const char *msg) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(data, buffer, size); } if (rc == TPM_RC_SUCCESS && exp != *data) { TPMLIB_LogTPM2Error("%s: Expected value: 0x%08x, found: 0x%08x\n", __func__, exp, *data); rc = TPM_RC_BAD_TAG; } return rc; } static void NV_HEADER_INIT(NV_HEADER *t, UINT16 version, UINT32 magic, UINT16 min_version) { t->version = version; t->magic = magic; t->min_version = min_version; } static UINT16 NV_HEADER_Marshal(BYTE **buffer, INT32 *size, UINT16 version, UINT32 magic, UINT16 min_version) { UINT16 written; NV_HEADER hdr; NV_HEADER_INIT(&hdr, version, magic, min_version); written = UINT16_Marshal(&hdr.version, buffer, size); written += UINT32_Marshal(&hdr.magic, buffer, size); if (version >= 2) written += UINT16_Marshal(&hdr.min_version, buffer, size); return written; } static TPM_RC NV_HEADER_UnmarshalVerbose(NV_HEADER *data, BYTE **buffer, INT32 *size, UINT16 cur_version, UINT32 exp_magic, BOOL verbose) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(&data->version, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&data->magic, buffer, size); } if (rc == TPM_RC_SUCCESS && exp_magic != data->magic) { if (verbose) TPMLIB_LogTPM2Error("%s: Invalid magic. Expected 0x%08x, got 0x%08x\n", __func__, exp_magic, data->magic); rc = TPM_RC_BAD_TAG; } data->min_version = 0; if (rc == TPM_RC_SUCCESS && data->version >= 2) { rc = UINT16_Unmarshal(&data->min_version, buffer, size); if (rc == TPM_RC_SUCCESS && data->min_version > cur_version) { if (verbose) TPMLIB_LogTPM2Error("%s: Minimum version %u higher than " "implementation version %u for type 0x%08x\n", __func__, data->min_version, cur_version, exp_magic); rc = TPM_RC_BAD_VERSION; } } return rc; } static TPM_RC NV_HEADER_Unmarshal(NV_HEADER *data, BYTE **buffer, INT32 *size, UINT16 cur_version, UINT32 exp_magic) { return NV_HEADER_UnmarshalVerbose(data, buffer, size, cur_version, exp_magic, true); } #define NV_INDEX_MAGIC 0x2547265a #define NV_INDEX_VERSION 2 static UINT16 NV_INDEX_Marshal(NV_INDEX *data, BYTE **buffer, INT32 *size) { UINT16 written; BLOCK_SKIP_INIT; written = NV_HEADER_Marshal(buffer, size, NV_INDEX_VERSION, NV_INDEX_MAGIC, 1); written += TPMS_NV_PUBLIC_Marshal(&data->publicArea, buffer, size); written += TPM2B_AUTH_Marshal(&data->authValue, buffer, size); written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); /* future versions append below this line */ BLOCK_SKIP_WRITE_POP(size); BLOCK_SKIP_WRITE_CHECK; return written; } static TPM_RC NV_INDEX_Unmarshal(NV_INDEX *data, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; NV_HEADER hdr; if (rc == TPM_RC_SUCCESS) { rc = NV_HEADER_Unmarshal(&hdr, buffer, size, NV_INDEX_VERSION, NV_INDEX_MAGIC); } if (rc == TPM_RC_SUCCESS) { rc = TPMS_NV_PUBLIC_Unmarshal(&data->publicArea, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_AUTH_Unmarshal(&data->authValue, buffer, size); } /* version 2 starts having indicator for next versions that we can skip; this allows us to downgrade state */ if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, "NV_INDEX", "version 3 or later"); /* future versions nest-append here */ } skip_future_versions: return rc; } #define DRBG_STATE_MAGIC 0x6fe83ea1 #define DRBG_STATE_VERSION 2 static UINT16 DRBG_STATE_Marshal(DRBG_STATE *data, BYTE **buffer, INT32 *size) { UINT16 written; size_t i; UINT16 array_size; BLOCK_SKIP_INIT; written = NV_HEADER_Marshal(buffer, size, DRBG_STATE_VERSION, DRBG_STATE_MAGIC, 1); written += UINT64_Marshal(&data->reseedCounter, buffer, size); written += UINT32_Marshal(&data->magic, buffer, size); array_size = sizeof(data->seed.bytes); written += UINT16_Marshal(&array_size, buffer, size); written += Array_Marshal(&data->seed.bytes[0], array_size, buffer, size); array_size = ARRAY_SIZE(data->lastValue); written += UINT16_Marshal(&array_size, buffer, size); for (i = 0; i < array_size; i++) { written += UINT32_Marshal(&data->lastValue[i], buffer, size); } written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); /* future versions append below this line */ BLOCK_SKIP_WRITE_POP(size); BLOCK_SKIP_WRITE_CHECK; return written; } static TPM_RC DRBG_STATE_Unmarshal(DRBG_STATE *data, BYTE **buffer, INT32 *size) { TPM_RC rc= TPM_RC_SUCCESS; size_t i; NV_HEADER hdr; UINT16 array_size = 0; if (rc == TPM_RC_SUCCESS) { rc = NV_HEADER_Unmarshal(&hdr, buffer, size, DRBG_STATE_VERSION, DRBG_STATE_MAGIC); } if (rc == TPM_RC_SUCCESS) { rc = UINT64_Unmarshal(&data->reseedCounter, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&data->magic, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(&array_size, buffer, size); } if (rc == TPM_RC_SUCCESS) { if (array_size != ARRAY_SIZE(data->seed.bytes)) { TPMLIB_LogTPM2Error("Non-matching DRBG_STATE seed array size. " "Expected %zu, got %u\n", ARRAY_SIZE(data->seed.bytes), array_size); rc = TPM_RC_SIZE; } } if (rc == TPM_RC_SUCCESS) { rc = Array_Unmarshal(&data->seed.bytes[0], array_size, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(&array_size, buffer, size); } if (rc == TPM_RC_SUCCESS) { if (array_size != ARRAY_SIZE(data->lastValue)) { TPMLIB_LogTPM2Error("Non-matching DRBG_STATE lastValue array size. " "Expected %zu, got %u\n", ARRAY_SIZE(data->lastValue), array_size); rc = TPM_RC_SIZE; } } if (rc == TPM_RC_SUCCESS) { for (i = 0; i < ARRAY_SIZE(data->lastValue) && rc == TPM_RC_SUCCESS; i++) { rc = UINT32_Unmarshal(&data->lastValue[i], buffer, size); } } /* version 2 starts having indicator for next versions that we can skip; this allows us to downgrade state */ if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, "DRBG_STATE", "version 3 or later"); /* future versions nest-append here */ } skip_future_versions: return rc; } #define PCR_POLICY_MAGIC 0x176be626 #define PCR_POLICY_VERSION 2 static UINT16 PCR_POLICY_Marshal(PCR_POLICY *data, BYTE **buffer, INT32 *size) { UINT16 written; unsigned i; UINT16 array_size = ARRAY_SIZE(data->hashAlg); BLOCK_SKIP_INIT; written = NV_HEADER_Marshal(buffer, size, PCR_POLICY_VERSION, PCR_POLICY_MAGIC, 1); written += UINT16_Marshal(&array_size, buffer, size); for (i = 0; i < array_size; i++) { /* TPMI_ALG_HASH_Unmarshal errors on algid 0 */ written += TPM_ALG_ID_Marshal(&data->hashAlg[i], buffer, size); written += TPM2B_DIGEST_Marshal(&data->policy[i], buffer, size); } written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); /* future versions append below this line */ BLOCK_SKIP_WRITE_POP(size); BLOCK_SKIP_WRITE_CHECK; return written; } static TPM_RC PCR_POLICY_Unmarshal(PCR_POLICY *data, BYTE **buffer, INT32 *size) { TPM_RC rc= TPM_RC_SUCCESS; unsigned i; UINT16 array_size; NV_HEADER hdr; if (rc == TPM_RC_SUCCESS) { rc = NV_HEADER_Unmarshal(&hdr, buffer, size, PCR_POLICY_VERSION, PCR_POLICY_MAGIC); } if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(&array_size, buffer, size); } if (rc == TPM_RC_SUCCESS) { if (array_size != ARRAY_SIZE(data->hashAlg)) { TPMLIB_LogTPM2Error("Non-matching PCR_POLICY array size. " "Expected %zu, got %u\n", ARRAY_SIZE(data->hashAlg), array_size); rc = TPM_RC_SIZE; } } for (i = 0; rc == TPM_RC_SUCCESS && i < ARRAY_SIZE(data->hashAlg); i++) { /* TPMI_ALG_HASH_Unmarshal errors on algid 0 */ if (rc == TPM_RC_SUCCESS) { rc = TPM_ALG_ID_Unmarshal(&data->hashAlg[i], buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_DIGEST_Unmarshal(&data->policy[i], buffer, size); } } /* version 2 starts having indicator for next versions that we can skip; this allows us to downgrade state */ if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, "PCR_POLICY", "version 3 or later"); /* future versions nest-append here */ } skip_future_versions: return rc; } #define ORDERLY_DATA_MAGIC 0x56657887 #define ORDERLY_DATA_VERSION 2 static UINT16 ORDERLY_DATA_Marshal(ORDERLY_DATA *data, BYTE **buffer, INT32 *size) { UINT16 written; BOOL has_block; BLOCK_SKIP_INIT; written = NV_HEADER_Marshal(buffer, size, ORDERLY_DATA_VERSION, ORDERLY_DATA_MAGIC, 1); written += UINT64_Marshal(&data->clock, buffer, size); written += UINT8_Marshal(&data->clockSafe, buffer, size); written += DRBG_STATE_Marshal(&data->drbgState, buffer, size); #if ACCUMULATE_SELF_HEAL_TIMER has_block = TRUE; #else has_block = FALSE; #endif written += BLOCK_SKIP_WRITE_PUSH(has_block, buffer, size); #if ACCUMULATE_SELF_HEAL_TIMER written += UINT64_Marshal(&data->selfHealTimer, buffer, size); written += UINT64_Marshal(&data->lockoutTimer, buffer, size); written += UINT64_Marshal(&data->time, buffer, size); #endif // ACCUMULATE_SELF_HEAL_TIMER BLOCK_SKIP_WRITE_POP(size); written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); /* future versions append below this line */ BLOCK_SKIP_WRITE_POP(size); BLOCK_SKIP_WRITE_CHECK; return written; } static TPM_RC ORDERLY_DATA_Unmarshal(ORDERLY_DATA *data, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; BOOL needs_block; NV_HEADER hdr; if (rc == TPM_RC_SUCCESS) { rc = NV_HEADER_Unmarshal(&hdr, buffer, size, ORDERLY_DATA_VERSION, ORDERLY_DATA_MAGIC); } if (rc == TPM_RC_SUCCESS) { rc = UINT64_Unmarshal(&data->clock, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT8_Unmarshal(&data->clockSafe, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = DRBG_STATE_Unmarshal(&data->drbgState, buffer, size); } #if ACCUMULATE_SELF_HEAL_TIMER needs_block = TRUE; #else needs_block = FALSE; #endif if (rc == TPM_RC_SUCCESS) { BLOCK_SKIP_READ(skip_self_heal_timer, needs_block, buffer, size, "ORDERLY_DATA", "selfHealTimer"); } #if ACCUMULATE_SELF_HEAL_TIMER if (rc == TPM_RC_SUCCESS) { rc = UINT64_Unmarshal(&data->selfHealTimer, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT64_Unmarshal(&data->lockoutTimer, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT64_Unmarshal(&data->time, buffer, size); } #endif // ACCUMULATE_SELF_HEAL_TIMER skip_self_heal_timer: /* version 2 starts having indicator for next versions that we can skip; this allows us to downgrade state */ if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, "ORDERLY_DATA", "version 3 or later"); /* future versions nest-append here */ } skip_future_versions: return rc; } #define PCR_SAVE_MAGIC 0x7372eabc #define PCR_SAVE_VERSION 2 static UINT16 PCR_SAVE_Marshal(PCR_SAVE *data, BYTE **buffer, INT32 *size) { UINT16 written = 0; TPM_ALG_ID algid; UINT16 array_size; BLOCK_SKIP_INIT; written = NV_HEADER_Marshal(buffer, size, PCR_SAVE_VERSION, PCR_SAVE_MAGIC, 1); array_size = NUM_STATIC_PCR; written += UINT16_Marshal(&array_size, buffer, size); #if ALG_SHA1 algid = TPM_ALG_SHA1; written += TPM_ALG_ID_Marshal(&algid, buffer, size); array_size = sizeof(data->Sha1); written += UINT16_Marshal(&array_size, buffer, size); written += Array_Marshal((BYTE *)&data->Sha1, array_size, buffer, size); #endif #if ALG_SHA256 algid = TPM_ALG_SHA256; written += TPM_ALG_ID_Marshal(&algid, buffer, size); array_size = sizeof(data->Sha256); written += UINT16_Marshal(&array_size, buffer, size); written += Array_Marshal((BYTE *)&data->Sha256, array_size, buffer, size); #endif #if ALG_SHA384 algid = TPM_ALG_SHA384; written += TPM_ALG_ID_Marshal(&algid, buffer, size); array_size = sizeof(data->Sha384); written += UINT16_Marshal(&array_size, buffer, size); written += Array_Marshal((BYTE *)&data->Sha384, array_size, buffer, size); #endif #if ALG_SHA512 algid = TPM_ALG_SHA512; written += TPM_ALG_ID_Marshal(&algid, buffer, size); array_size = sizeof(data->Sha512); written += UINT16_Marshal(&array_size, buffer, size); written += Array_Marshal((BYTE *)&data->Sha512, array_size, buffer, size); #endif #if ALG_SM3_256 algid = TPM_ALG_SM3_256; written += TPM_ALG_ID_Marshal(&algid, buffer, size); array_size = sizeof(data->Sm3_256); written += UINT16_Marshal(&array_size, buffer, size); written += Array_Marshal((BYTE *)&data->Sm3_256, array_size, buffer, size); #endif #if ALG_SHA3_256 || ALG_SHA3_384 || ALG_SHA3_512 || ALG_SM3_256 #error SHA3 and SM3 are not supported #endif /* end marker */ algid = TPM_ALG_NULL; written += TPM_ALG_ID_Marshal(&algid, buffer, size); written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); /* future versions append below this line */ BLOCK_SKIP_WRITE_POP(size); BLOCK_SKIP_WRITE_CHECK; return written; } /* * Get the PCR banks that are active so that we know what PCRs need to be * restored. Only data for active PCR banks needs to restored, inactive PCR * banks need no data restored. */ static UINT64 pcrbanks_algs_active(const TPML_PCR_SELECTION *pcrAllocated) { UINT64 algs_active = 0; unsigned i, j; for(i = 0; i < pcrAllocated->count; i++) { for (j = 0; j < pcrAllocated->pcrSelections[i].sizeofSelect; j++) { if (pcrAllocated->pcrSelections[i].pcrSelect[j]) { algs_active |= 1 << pcrAllocated->pcrSelections[i].hash; break; } } } return algs_active; } static TPM_RC PCR_SAVE_Unmarshal(PCR_SAVE *data, BYTE **buffer, INT32 *size, const TPML_PCR_SELECTION *pcrAllocated) { TPM_RC rc = TPM_RC_SUCCESS; UINT16 array_size, needed_size = 0; NV_HEADER hdr; TPM_ALG_ID algid; BOOL end = FALSE; BYTE *t = NULL; UINT64 algs_needed = pcrbanks_algs_active(pcrAllocated); if (rc == TPM_RC_SUCCESS) { rc = NV_HEADER_Unmarshal(&hdr, buffer, size, PCR_SAVE_VERSION, PCR_SAVE_MAGIC); } if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(&array_size, buffer, size); } if (rc == TPM_RC_SUCCESS && array_size != NUM_STATIC_PCR) { TPMLIB_LogTPM2Error("Non-matching PCR_SAVE NUM_STATIC_PCR. " "Expected %zu, got %u\n", sizeof(NUM_STATIC_PCR), array_size); rc = TPM_RC_SIZE; } while (rc == TPM_RC_SUCCESS && !end) { if (rc == TPM_RC_SUCCESS) { rc = TPM_ALG_ID_Unmarshal(&algid, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (algid) { #if ALG_SHA1 case TPM_ALG_SHA1: needed_size = sizeof(data->Sha1); t = (BYTE *)&data->Sha1; break; #endif #if ALG_SHA256 case TPM_ALG_SHA256: needed_size = sizeof(data->Sha256); t = (BYTE *)&data->Sha256; break; #endif #if ALG_SHA384 case TPM_ALG_SHA384: needed_size = sizeof(data->Sha384); t = (BYTE *)&data->Sha384; break; #endif #if ALG_SHA512 case TPM_ALG_SHA512: needed_size = sizeof(data->Sha512); t = (BYTE *)&data->Sha512; break; #endif #if ALG_SM3_256 case TPM_ALG_SM3_256: needed_size = sizeof(data->Sm3_256); t = (BYTE *)&data->Sm3_256; break; #endif #if ALG_SHA3_256 || ALG_SHA3_384 || ALG_SHA3_512 || ALG_SM3_256 #error SHA3 and SM3 are not supported #endif case TPM_ALG_NULL: /* end marker */ end = TRUE; t = NULL; break; default: TPMLIB_LogTPM2Error("PCR_SAVE: Unsupported algid %d.", algid); rc = TPM_RC_BAD_PARAMETER; t = NULL; } } if (t) { if (rc == TPM_RC_SUCCESS) { algs_needed &= ~(1 << algid); rc = UINT16_Unmarshal(&array_size, buffer, size); } if (rc == TPM_RC_SUCCESS && array_size != needed_size) { TPMLIB_LogTPM2Error("PCR_SAVE: Bad size for PCRs for hash 0x%x; " "Expected %u, got %d\n", algid, needed_size, array_size); rc = TPM_RC_BAD_PARAMETER; } if (rc == TPM_RC_SUCCESS) { rc = Array_Unmarshal(t, array_size, buffer, size); } } } if (rc == TPM_RC_SUCCESS && algs_needed) { TPMLIB_LogTPM2Error("PCR_SAVE: Missing data for hash algorithm %d.\n", _ffsll(algs_needed) - 1); rc = TPM_RC_BAD_PARAMETER; } /* version 2 starts having indicator for next versions that we can skip; this allows us to downgrade state */ if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, "PCR_SAVE", "version 3 or later"); /* future versions nest-append here */ } skip_future_versions: return rc; } #ifdef PCR_C #define PCR_MAGIC 0xe95f0387 #define PCR_VERSION 2 static UINT16 PCR_Marshal(PCR *data, BYTE **buffer, INT32 *size) { UINT16 written; TPM_ALG_ID algid; UINT16 array_size; BLOCK_SKIP_INIT; written = NV_HEADER_Marshal(buffer, size, PCR_VERSION, PCR_MAGIC, 1); #if ALG_SHA1 algid = TPM_ALG_SHA1; written += TPM_ALG_ID_Marshal(&algid, buffer, size); array_size = sizeof(data->Sha1Pcr); written += UINT16_Marshal(&array_size, buffer, size); written += Array_Marshal((BYTE *)&data->Sha1Pcr, array_size, buffer, size); #endif #if ALG_SHA256 algid = TPM_ALG_SHA256; written += TPM_ALG_ID_Marshal(&algid, buffer, size); array_size = sizeof(data->Sha256Pcr); written += UINT16_Marshal(&array_size, buffer, size); written += Array_Marshal((BYTE *)&data->Sha256Pcr, array_size, buffer, size); #endif #if ALG_SHA384 algid = TPM_ALG_SHA384; written += TPM_ALG_ID_Marshal(&algid, buffer, size); array_size = sizeof(data->Sha384Pcr); written += UINT16_Marshal(&array_size, buffer, size); written += Array_Marshal((BYTE *)&data->Sha384Pcr, array_size, buffer, size); #endif #if ALG_SHA512 algid = TPM_ALG_SHA512; written += TPM_ALG_ID_Marshal(&algid, buffer, size); array_size = sizeof(data->Sha512Pcr); written += UINT16_Marshal(&array_size, buffer, size); written += Array_Marshal((BYTE *)&data->Sha512Pcr, array_size, buffer, size); #endif #if ALG_SM3_256 algid = TPM_ALG_SM3_256; written += TPM_ALG_ID_Marshal(&algid, buffer, size); array_size = sizeof(data->Sm3_256Pcr); written += UINT16_Marshal(&array_size, buffer, size); written += Array_Marshal((BYTE *)&data->Sm3_256Pcr, array_size, buffer, size); #endif #if ALG_SHA3_256 || ALG_SHA3_384 || ALG_SHA3_512 || ALG_SM3_256 #error SHA3 and SM3 are not supported #endif /* end marker */ algid = TPM_ALG_NULL; written += TPM_ALG_ID_Marshal(&algid, buffer, size); written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); /* future versions append below this line */ BLOCK_SKIP_WRITE_POP(size); BLOCK_SKIP_WRITE_CHECK; return written; } static TPM_RC PCR_Unmarshal(PCR *data, BYTE **buffer, INT32 *size, const TPML_PCR_SELECTION *pcrAllocated) { TPM_RC rc = TPM_RC_SUCCESS; NV_HEADER hdr; BOOL end = FALSE; BYTE *t = NULL; UINT16 needed_size = 0, array_size; TPM_ALG_ID algid; UINT64 algs_needed = pcrbanks_algs_active(pcrAllocated); if (rc == TPM_RC_SUCCESS) { rc = NV_HEADER_Unmarshal(&hdr, buffer, size, PCR_VERSION, PCR_MAGIC); } while (rc == TPM_RC_SUCCESS && !end) { if (rc == TPM_RC_SUCCESS) { rc = TPM_ALG_ID_Unmarshal(&algid, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (algid) { #if ALG_SHA1 case TPM_ALG_SHA1: needed_size = sizeof(data->Sha1Pcr); t = (BYTE *)&data->Sha1Pcr; break; #endif #if ALG_SHA256 case TPM_ALG_SHA256: needed_size = sizeof(data->Sha256Pcr); t = (BYTE *)&data->Sha256Pcr; break; #endif #if ALG_SHA384 case TPM_ALG_SHA384: needed_size = sizeof(data->Sha384Pcr); t = (BYTE *)&data->Sha384Pcr; break; #endif #if ALG_SHA512 case TPM_ALG_SHA512: needed_size = sizeof(data->Sha512Pcr); t = (BYTE *)&data->Sha512Pcr; break; #endif #if ALG_SM3_256 case TPM_ALG_SM3_256: needed_size = sizeof(data->Sm3_256Pcr); t = (BYTE *)&data->Sm3_256Pcr; break; #endif #if ALG_SHA3_256 || ALG_SHA3_384 || ALG_SHA3_512 || ALG_SM3_256 #error SHA3 and SM3 are not supported #endif case TPM_ALG_NULL: /* end marker */ end = TRUE; t = NULL; break; default: TPMLIB_LogTPM2Error("PCR: Unsupported algid %d.", algid); rc = TPM_RC_BAD_PARAMETER; t = NULL; } } if (t) { if (rc == TPM_RC_SUCCESS) { algs_needed &= ~(1 << algid); rc = UINT16_Unmarshal(&array_size, buffer, size); } if (rc == TPM_RC_SUCCESS && array_size != needed_size) { TPMLIB_LogTPM2Error("PCR: Bad size for PCR for hash 0x%x; " "Expected %u, got %d\n", algid, needed_size, array_size); rc = TPM_RC_BAD_PARAMETER; } if (rc == TPM_RC_SUCCESS) { rc = Array_Unmarshal(t, array_size, buffer, size); } } } if (rc == TPM_RC_SUCCESS && algs_needed) { TPMLIB_LogTPM2Error("PCR: Missing data for hash algorithm %d.\n", _ffsll(algs_needed) - 1); rc = TPM_RC_BAD_PARAMETER; } /* version 2 starts having indicator for next versions that we can skip; this allows us to downgrade state */ if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, "PCR", "version 3 or later"); /* future versions nest-append here */ } skip_future_versions: return rc; } #endif #define PCR_AUTHVALUE_MAGIC 0x6be82eaf #define PCR_AUTHVALUE_VERSION 2 static UINT16 PCR_AUTHVALUE_Marshal(PCR_AUTHVALUE *data, BYTE **buffer, INT32 *size) { UINT16 written; size_t i; UINT16 array_size; BLOCK_SKIP_INIT; written = NV_HEADER_Marshal(buffer, size, PCR_AUTHVALUE_VERSION, PCR_AUTHVALUE_MAGIC, 1); array_size = ARRAY_SIZE(data->auth); written += UINT16_Marshal(&array_size, buffer, size); for (i = 0; i < array_size; i++) { written += TPM2B_DIGEST_Marshal(&data->auth[i], buffer, size); } written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); /* future versions append below this line */ BLOCK_SKIP_WRITE_POP(size); BLOCK_SKIP_WRITE_CHECK; return written; } static TPM_RC PCR_AUTHVALUE_Unmarshal(PCR_AUTHVALUE *data, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; size_t i; NV_HEADER hdr; UINT16 array_size = 0; if (rc == TPM_RC_SUCCESS) { rc = NV_HEADER_Unmarshal(&hdr, buffer, size, PCR_AUTHVALUE_VERSION, PCR_AUTHVALUE_MAGIC); } if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(&array_size, buffer, size); } if (rc == TPM_RC_SUCCESS && array_size != ARRAY_SIZE(data->auth)) { TPMLIB_LogTPM2Error("PCR_AUTHVALUE: Bad array size for auth; " "expected %zu, got %u\n", ARRAY_SIZE(data->auth), array_size); rc = TPM_RC_BAD_PARAMETER; } if (rc == TPM_RC_SUCCESS) { for (i = 0; i < ARRAY_SIZE(data->auth) && rc == TPM_RC_SUCCESS; i++) { rc = TPM2B_DIGEST_Unmarshal(&data->auth[i], buffer, size); } } /* version 2 starts having indicator for next versions that we can skip; this allows us to downgrade state */ if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, "PCR_AUTHVALUE", "version 3 or later"); /* future versions nest-append here */ } skip_future_versions: return rc; } #define STATE_CLEAR_DATA_MAGIC 0x98897667 #define STATE_CLEAR_DATA_VERSION 2 static UINT16 STATE_CLEAR_DATA_Marshal(STATE_CLEAR_DATA *data, BYTE **buffer, INT32 *size) { UINT16 written; BLOCK_SKIP_INIT; written = NV_HEADER_Marshal(buffer, size, STATE_CLEAR_DATA_VERSION, STATE_CLEAR_DATA_MAGIC, 1); written += BOOL_Marshal(&data->shEnable, buffer, size); written += BOOL_Marshal(&data->ehEnable, buffer, size); written += BOOL_Marshal(&data->phEnableNV, buffer, size); written += UINT16_Marshal(&data->platformAlg, buffer, size); written += TPM2B_DIGEST_Marshal(&data->platformPolicy, buffer, size); written += TPM2B_AUTH_Marshal(&data->platformAuth, buffer, size); written += PCR_SAVE_Marshal(&data->pcrSave, buffer, size); written += PCR_AUTHVALUE_Marshal(&data->pcrAuthValues, buffer, size); written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); /* future versions append below this line */ BLOCK_SKIP_WRITE_POP(size); BLOCK_SKIP_WRITE_CHECK; return written; } static TPM_RC STATE_CLEAR_DATA_Unmarshal(STATE_CLEAR_DATA *data, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; NV_HEADER hdr; if (rc == TPM_RC_SUCCESS) { rc = NV_HEADER_Unmarshal(&hdr, buffer, size, STATE_CLEAR_DATA_VERSION, STATE_CLEAR_DATA_MAGIC); } if (rc == TPM_RC_SUCCESS) { rc = BOOL_Unmarshal(&data->shEnable, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = BOOL_Unmarshal(&data->ehEnable, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = BOOL_Unmarshal(&data->phEnableNV, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(&data->platformAlg, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_DIGEST_Unmarshal(&data->platformPolicy, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_AUTH_Unmarshal(&data->platformAuth, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = PCR_SAVE_Unmarshal(&data->pcrSave, buffer, size, &shadow.pcrAllocated); } if (rc == TPM_RC_SUCCESS) { rc = PCR_AUTHVALUE_Unmarshal(&data->pcrAuthValues, buffer, size); } /* version 2 starts having indicator for next versions that we can skip; this allows us to downgrade state */ if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, "STATE_CLEAR_DATA", "version 3 or later"); /* future versions nest-append here */ } skip_future_versions: return rc; } #define STATE_RESET_DATA_MAGIC 0x01102332 #define STATE_RESET_DATA_VERSION 4 static TPM_RC STATE_RESET_DATA_Unmarshal(STATE_RESET_DATA *data, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; BOOL needs_block; UINT16 array_size; NV_HEADER hdr; if (rc == TPM_RC_SUCCESS) { rc = NV_HEADER_Unmarshal(&hdr, buffer, size, STATE_RESET_DATA_VERSION, STATE_RESET_DATA_MAGIC); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_PROOF_Unmarshal(&data->nullProof, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_Unmarshal(&data->nullSeed.b, PRIMARY_SEED_SIZE, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&data->clearCount, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT64_Unmarshal(&data->objectContextID, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(&array_size, buffer, size); } if (rc == TPM_RC_SUCCESS && array_size != ARRAY_SIZE(data->contextArray)) { TPMLIB_LogTPM2Error("STATE_RESET_DATA: Bad array size for contextArray; " "expected %zu, got %u\n", ARRAY_SIZE(data->contextArray), array_size); rc = TPM_RC_BAD_PARAMETER; } if (rc == TPM_RC_SUCCESS) { size_t i; if (hdr.version <= 3) { /* version <= 3 was writing an array of UINT8 */ UINT8 element; for (i = 0; i < array_size && rc == TPM_RC_SUCCESS; i++) { rc = UINT8_Unmarshal(&element, buffer, size); data->contextArray[i] = element; } s_ContextSlotMask = 0xff; } else { /* version 4 and later an array of UINT16 */ for (i = 0; i < array_size && rc == TPM_RC_SUCCESS; i++) { rc = UINT16_Unmarshal(&data->contextArray[i], buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(&s_ContextSlotMask, buffer, size); } if (rc == TPM_RC_SUCCESS) { if (s_ContextSlotMask != 0xffff && s_ContextSlotMask != 0x00ff) { TPMLIB_LogTPM2Error("STATE_RESET_DATA: s_ContextSlotMask has bad value: 0x%04x\n", s_ContextSlotMask); rc = TPM_RC_BAD_PARAMETER; } } } } if (rc == TPM_RC_SUCCESS) { rc = UINT64_Unmarshal(&data->contextCounter, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_DIGEST_Unmarshal(&data->commandAuditDigest, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&data->restartCount, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&data->pcrCounter, buffer, size); } #if ALG_ECC needs_block = TRUE; #else needs_block = FALSE; #endif if (rc == TPM_RC_SUCCESS) { BLOCK_SKIP_READ(skip_alg_ecc, needs_block, buffer, size, "STATE_RESET_DATA", "commitCounter"); } #if ALG_ECC if (rc == TPM_RC_SUCCESS) { rc = UINT64_Unmarshal(&data->commitCounter, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_AUTH_Unmarshal(&data->commitNonce, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(&array_size, buffer, size); } if (rc == TPM_RC_SUCCESS && array_size != sizeof(data->commitArray)) { TPMLIB_LogTPM2Error("STATE_RESET_DATA: Bad array size for commitArray; " "expected %zu, got %u\n", sizeof(data->commitArray), array_size); rc = TPM_RC_BAD_PARAMETER; } if (rc == TPM_RC_SUCCESS) { rc = Array_Unmarshal((BYTE *)&data->commitArray, array_size, buffer, size); } #endif skip_alg_ecc: /* default values before conditional block */ data->nullSeedCompatLevel = SEED_COMPAT_LEVEL_ORIGINAL; /* version 2 starts having indicator for next versions that we can skip; this allows us to downgrade state */ if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { BLOCK_SKIP_READ(skip_future_versions, hdr.version >= 3, buffer, size, "STATE_RESET_DATA", "version 3 or later"); if (rc == TPM_RC_SUCCESS) { rc = SEED_COMPAT_LEVEL_Unmarshal(&gr.nullSeedCompatLevel, buffer, size, "nullSeed"); } if (rc == TPM_RC_SUCCESS) { BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, "STATE_RESET_DATA", "version 4 or later"); } /* future versions nest-append here */ } skip_future_versions: return rc; } static UINT16 STATE_RESET_DATA_Marshal(STATE_RESET_DATA *data, BYTE **buffer, INT32 *size) { UINT16 written; BOOL has_block; UINT16 array_size; BLOCK_SKIP_INIT; size_t i; written = NV_HEADER_Marshal(buffer, size, STATE_RESET_DATA_VERSION, STATE_RESET_DATA_MAGIC, 4); written += TPM2B_PROOF_Marshal(&data->nullProof, buffer, size); written += TPM2B_Marshal(&data->nullSeed.b, sizeof(data->nullSeed.t.buffer), buffer, size); written += UINT32_Marshal(&data->clearCount, buffer, size); written += UINT64_Marshal(&data->objectContextID, buffer, size); array_size = ARRAY_SIZE(data->contextArray); written += UINT16_Marshal(&array_size, buffer, size); for (i = 0; i < array_size; i++) written += UINT16_Marshal(&data->contextArray[i], buffer, size); if (s_ContextSlotMask != 0x00ff && s_ContextSlotMask != 0xffff) { /* TPM wasn't initialized, so s_ContextSlotMask wasn't set */ s_ContextSlotMask = 0xffff; } written += UINT16_Marshal(&s_ContextSlotMask, buffer, size); written += UINT64_Marshal(&data->contextCounter, buffer, size); written += TPM2B_DIGEST_Marshal(&data->commandAuditDigest, buffer, size); written += UINT32_Marshal(&data->restartCount, buffer, size); written += UINT32_Marshal(&data->pcrCounter, buffer, size); #if ALG_ECC has_block = TRUE; #else has_block = FALSE; #endif written += BLOCK_SKIP_WRITE_PUSH(has_block, buffer, size); #if ALG_ECC written += UINT64_Marshal(&data->commitCounter, buffer, size); written += TPM2B_AUTH_Marshal(&data->commitNonce, buffer, size); array_size = sizeof(data->commitArray); written += UINT16_Marshal(&array_size, buffer, size); written += Array_Marshal((BYTE *)&data->commitArray, array_size, buffer, size); #endif BLOCK_SKIP_WRITE_POP(size); written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); written += SEED_COMPAT_LEVEL_Marshal(&data->nullSeedCompatLevel, buffer, size); written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); /* future versions append below this line */ BLOCK_SKIP_WRITE_POP(size); BLOCK_SKIP_WRITE_POP(size); BLOCK_SKIP_WRITE_CHECK; return written; } #define BN_PRIME_T_MAGIC 0x2fe736ab #define BN_PRIME_T_VERSION 2 static UINT16 bn_prime_t_Marshal(bn_prime_t *data, BYTE **buffer, INT32 *size) { UINT16 written, numbytes; size_t i, idx; BLOCK_SKIP_INIT; written = NV_HEADER_Marshal(buffer, size, BN_PRIME_T_VERSION, BN_PRIME_T_MAGIC, 1); /* we do not write 'allocated' */ numbytes = data->size * sizeof(crypt_uword_t); written += UINT16_Marshal(&numbytes, buffer, size); for (i = 0, idx = 0; i < numbytes; i += sizeof(crypt_uword_t), idx += 1) { #if RADIX_BITS == 64 written += UINT64_Marshal(&data->d[idx], buffer, size); #elif RADIX_BITS == 32 written += UINT32_Marshal(&data->d[idx], buffer, size); #else #error RADIX_BYTES it no defined #endif } written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); /* future versions append below this line */ BLOCK_SKIP_WRITE_POP(size); BLOCK_SKIP_WRITE_CHECK; return written; } static TPM_RC bn_prime_t_Unmarshal(bn_prime_t *data, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; size_t i, idx; UINT16 numbytes = 0; UINT32 word; NV_HEADER hdr; if (rc == TPM_RC_SUCCESS) { rc = NV_HEADER_Unmarshal(&hdr, buffer, size, BN_PRIME_T_VERSION, BN_PRIME_T_MAGIC); } data->allocated = ARRAY_SIZE(data->d); if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(&numbytes, buffer, size); } if (rc == TPM_RC_SUCCESS) { /* coverity: num_bytes is sanitized here! */ data->size = (numbytes + sizeof(crypt_uword_t) - 1) / sizeof(crypt_word_t); if (data->size > data->allocated) { TPMLIB_LogTPM2Error("bn_prime_t: Require size larger %zu than " "allocated %zu\n", (size_t)data->size, (size_t)data->allocated); rc = TPM_RC_SIZE; data->size = 0; } } if (rc == TPM_RC_SUCCESS) { for (i = 0, idx = 0; i < numbytes && rc == TPM_RC_SUCCESS; i += sizeof(UINT32), idx += 1) { rc = UINT32_Unmarshal(&word, buffer, size); #if RADIX_BITS == 64 data->d[idx / 2] <<= 32; data->d[idx / 2] |= word; #elif RADIX_BITS == 32 data->d[idx] = word; #endif } } #if RADIX_BITS == 64 if (rc == TPM_RC_SUCCESS) { if (idx & 1) data->d[idx / 2] <<= 32; } #endif /* version 2 starts having indicator for next versions that we can skip; this allows us to downgrade state */ if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, "BN_PRIME_T", "version 3 or later"); /* future versions nest-append here */ } skip_future_versions: return rc; } #define PRIVATE_EXPONENT_T_MAGIC 0x854eab2 #define PRIVATE_EXPONENT_T_VERSION 2 static UINT16 privateExponent_t_Marshal(privateExponent_t *data, BYTE **buffer, INT32 *size) { UINT16 written; BLOCK_SKIP_INIT; written = NV_HEADER_Marshal(buffer, size, PRIVATE_EXPONENT_T_VERSION, PRIVATE_EXPONENT_T_MAGIC, 1); #if CRT_FORMAT_RSA == NO #error Missing code #else written += bn_prime_t_Marshal(&data->Q, buffer, size); written += bn_prime_t_Marshal(&data->dP, buffer, size); written += bn_prime_t_Marshal(&data->dQ, buffer, size); written += bn_prime_t_Marshal(&data->qInv, buffer, size); #endif written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); /* future versions append below this line */ BLOCK_SKIP_WRITE_POP(size); BLOCK_SKIP_WRITE_CHECK; return written; } static TPM_RC privateExponent_t_Unmarshal(privateExponent_t *data, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; NV_HEADER hdr; if (rc == TPM_RC_SUCCESS) { rc = NV_HEADER_Unmarshal(&hdr, buffer, size, PRIVATE_EXPONENT_T_VERSION, PRIVATE_EXPONENT_T_MAGIC); } #if CRT_FORMAT_RSA == NO #error Missing code #else if (rc == TPM_RC_SUCCESS) { rc = bn_prime_t_Unmarshal(&data->Q, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = bn_prime_t_Unmarshal(&data->dP, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = bn_prime_t_Unmarshal(&data->dQ, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = bn_prime_t_Unmarshal(&data->qInv, buffer, size); } #endif /* version 2 starts having indicator for next versions that we can skip; this allows us to downgrade state */ if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, "PRIVATE_EXPONENT_T", "version 3 or later"); /* future versions nest-append here */ } skip_future_versions: return rc; } static UINT16 HASH_STATE_TYPE_Marshal(HASH_STATE_TYPE *data, BYTE **buffer, INT32 *size) { UINT16 written; written = UINT8_Marshal(data, buffer, size); return written; } static UINT16 HASH_STATE_TYPE_Unmarshal(HASH_STATE_TYPE *data, BYTE **buffer, INT32 *size) { return UINT8_Unmarshal(data, buffer, size); } static inline UINT16 SHA_LONG_Marshal(SHA_LONG *data, BYTE **buffer, INT32 *size) { return UINT32_Marshal(data, buffer, size); } static inline UINT16 SHA_LONG_Unmarshal(SHA_LONG *data, BYTE **buffer, INT32 *size) { return UINT32_Unmarshal(data, buffer, size); } static inline UINT16 SHA_LONG64_Marshal(SHA_LONG64 *data, BYTE **buffer, INT32 *size) { assert(sizeof(*data) == 8); return UINT64_Marshal((UINT64 *)data, buffer, size); } static inline UINT16 SHA_LONG64_Unmarshal(SHA_LONG64 *data, BYTE **buffer, INT32 *size) { assert(sizeof(*data) == 8); return UINT64_Unmarshal((UINT64 *)data, buffer, size); } #if ALG_SHA1 #define HASH_STATE_SHA1_MAGIC 0x19d46f50 #define HASH_STATE_SHA1_VERSION 2 static UINT16 tpmHashStateSHA1_Marshal(tpmHashStateSHA1_t *data, BYTE **buffer, INT32 *size) { UINT16 written; UINT16 array_size; BLOCK_SKIP_INIT; written = NV_HEADER_Marshal(buffer, size, HASH_STATE_SHA1_VERSION, HASH_STATE_SHA1_MAGIC,1); written += SHA_LONG_Marshal(&data->h0, buffer, size); written += SHA_LONG_Marshal(&data->h1, buffer, size); written += SHA_LONG_Marshal(&data->h2, buffer, size); written += SHA_LONG_Marshal(&data->h3, buffer, size); written += SHA_LONG_Marshal(&data->h4, buffer, size); written += SHA_LONG_Marshal(&data->Nl, buffer, size); written += SHA_LONG_Marshal(&data->Nh, buffer, size); /* data must be written as array */ array_size = sizeof(data->data); written += UINT16_Marshal(&array_size, buffer, size); written += Array_Marshal((BYTE *)&data->data[0], array_size, buffer, size); written += UINT32_Marshal(&data->num, buffer, size); written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); /* future versions append below this line */ BLOCK_SKIP_WRITE_POP(size); BLOCK_SKIP_WRITE_CHECK; return written; } static UINT16 tpmHashStateSHA1_Unmarshal(tpmHashStateSHA1_t *data, BYTE **buffer, INT32 *size) { UINT16 rc = TPM_RC_SUCCESS; NV_HEADER hdr; UINT16 array_size; if (rc == TPM_RC_SUCCESS) { rc = NV_HEADER_Unmarshal(&hdr, buffer, size, HASH_STATE_SHA1_VERSION, HASH_STATE_SHA1_MAGIC); } if (rc == TPM_RC_SUCCESS) { rc = SHA_LONG_Unmarshal(&data->h0, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = SHA_LONG_Unmarshal(&data->h1, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = SHA_LONG_Unmarshal(&data->h2, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = SHA_LONG_Unmarshal(&data->h3, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = SHA_LONG_Unmarshal(&data->h4, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = SHA_LONG_Unmarshal(&data->Nl, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = SHA_LONG_Unmarshal(&data->Nh, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(&array_size, buffer, size); } if (rc == TPM_RC_SUCCESS && array_size != sizeof(data->data)) { TPMLIB_LogTPM2Error("HASH_STATE_SHA1: Bad array size for data; " "expected %zu, got %u\n", sizeof(data->data), array_size); rc = TPM_RC_BAD_PARAMETER; } if (rc == TPM_RC_SUCCESS) { rc = Array_Unmarshal((BYTE *)&data->data[0], array_size, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&data->num, buffer, size); } /* version 2 starts having indicator for next versions that we can skip; this allows us to downgrade state */ if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, "HASH_STATE_SHA1", "version 3 or later"); /* future versions nest-append here */ } skip_future_versions: return rc; } #endif #if ALG_SHA256 #define HASH_STATE_SHA256_MAGIC 0x6ea059d0 #define HASH_STATE_SHA256_VERSION 2 static UINT16 tpmHashStateSHA256_Marshal(tpmHashStateSHA256_t *data, BYTE **buffer, INT32 *size) { UINT16 written = 0; UINT16 array_size; size_t i; BLOCK_SKIP_INIT; written = NV_HEADER_Marshal(buffer, size, HASH_STATE_SHA256_VERSION, HASH_STATE_SHA256_MAGIC, 1); array_size = ARRAY_SIZE(data->h); written += UINT16_Marshal(&array_size, buffer, size); for (i = 0; i < array_size; i++) { written += SHA_LONG_Marshal(&data->h[i], buffer, size); } written += SHA_LONG_Marshal(&data->Nl, buffer, size); written += SHA_LONG_Marshal(&data->Nh, buffer, size); /* data must be written as array */ array_size = sizeof(data->data); written += UINT16_Marshal(&array_size, buffer, size); written += Array_Marshal((BYTE *)&data->data[0], array_size, buffer, size); written += UINT32_Marshal(&data->num, buffer, size); written += UINT32_Marshal(&data->md_len, buffer, size); written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); /* future versions append below this line */ BLOCK_SKIP_WRITE_POP(size); BLOCK_SKIP_WRITE_CHECK; return written; } static UINT16 tpmHashStateSHA256_Unmarshal(tpmHashStateSHA256_t *data, BYTE **buffer, INT32 *size) { UINT16 rc = TPM_RC_SUCCESS; size_t i; UINT16 array_size; NV_HEADER hdr; if (rc == TPM_RC_SUCCESS) { rc = NV_HEADER_Unmarshal(&hdr, buffer, size, HASH_STATE_SHA256_VERSION, HASH_STATE_SHA256_MAGIC); } if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(&array_size, buffer, size); } if (rc == TPM_RC_SUCCESS && array_size != ARRAY_SIZE(data->h)) { TPMLIB_LogTPM2Error("HASH_STATE_SHA256: Bad array size for h; " "expected %zu, got %u\n", ARRAY_SIZE(data->h), array_size); rc = TPM_RC_BAD_PARAMETER; } for (i = 0; rc == TPM_RC_SUCCESS && i < array_size; i++) { rc = SHA_LONG_Unmarshal(&data->h[i], buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = SHA_LONG_Unmarshal(&data->Nl, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = SHA_LONG_Unmarshal(&data->Nh, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(&array_size, buffer, size); } if (rc == TPM_RC_SUCCESS && array_size != sizeof(data->data)) { TPMLIB_LogTPM2Error("HASH_STATE_SHA256: Bad array size for data; " "expected %zu, got %u\n", sizeof(data->data), array_size); rc = TPM_RC_BAD_PARAMETER; } if (rc == TPM_RC_SUCCESS) { rc = Array_Unmarshal((BYTE *)&data->data[0], array_size, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&data->num, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&data->md_len, buffer, size); } /* version 2 starts having indicator for next versions that we can skip; this allows us to downgrade state */ if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, "HASH_STATE_SHA256", "version 3 or later"); /* future versions nest-append here */ } skip_future_versions: return rc; } #endif #if ALG_SHA384 || ALG_SHA512 #define HASH_STATE_SHA384_MAGIC 0x14814b08 #define HASH_STATE_SHA384_VERSION 2 #define HASH_STATE_SHA512_MAGIC 0x269e8ae0 #define HASH_STATE_SHA512_VERSION 2 static UINT16 tpmHashStateSHA512_Marshal(SHA512_CTX *data, BYTE **buffer, INT32 *size, UINT16 hashAlg) { UINT16 written = 0; UINT16 array_size; size_t i; BLOCK_SKIP_INIT; UINT16 version = HASH_STATE_SHA512_VERSION; UINT32 magic = HASH_STATE_SHA512_MAGIC; if (hashAlg == ALG_SHA384_VALUE) { version = HASH_STATE_SHA384_VERSION; magic = HASH_STATE_SHA384_MAGIC; } written = NV_HEADER_Marshal(buffer, size, version, magic, 1); array_size = ARRAY_SIZE(data->h); written += UINT16_Marshal(&array_size, buffer, size); for (i = 0; i < array_size; i++) { written += SHA_LONG64_Marshal(&data->h[i], buffer, size); } written += SHA_LONG64_Marshal(&data->Nl, buffer, size); written += SHA_LONG64_Marshal(&data->Nh, buffer, size); array_size = sizeof(data->u.p); written += UINT16_Marshal(&array_size, buffer, size); written += Array_Marshal(&data->u.p[0], array_size, buffer, size); written += UINT32_Marshal(&data->num, buffer, size); written += UINT32_Marshal(&data->md_len, buffer, size); written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); /* future versions append below this line */ BLOCK_SKIP_WRITE_POP(size); BLOCK_SKIP_WRITE_CHECK; return written; } static UINT16 tpmHashStateSHA512_Unmarshal(SHA512_CTX *data, BYTE **buffer, INT32 *size, UINT16 hashAlg) { UINT16 rc = TPM_RC_SUCCESS; size_t i; UINT16 array_size; NV_HEADER hdr; UINT16 version = HASH_STATE_SHA512_VERSION; UINT32 magic = HASH_STATE_SHA512_MAGIC; if (hashAlg == ALG_SHA384_VALUE) { version = HASH_STATE_SHA384_VERSION; magic = HASH_STATE_SHA384_MAGIC; } if (rc == TPM_RC_SUCCESS) { rc = NV_HEADER_Unmarshal(&hdr, buffer, size, version, magic); } if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(&array_size, buffer, size); } if (rc == TPM_RC_SUCCESS && array_size != ARRAY_SIZE(data->h)) { TPMLIB_LogTPM2Error("HASH_STATE_SHA512: Bad array size for h; " "expected %zu, got %u\n", ARRAY_SIZE(data->h), array_size); rc = TPM_RC_BAD_PARAMETER; } for (i = 0; rc == TPM_RC_SUCCESS && i < array_size; i++) { rc = SHA_LONG64_Unmarshal(&data->h[i], buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = SHA_LONG64_Unmarshal(&data->Nl, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = SHA_LONG64_Unmarshal(&data->Nh, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(&array_size, buffer, size); } if (rc == TPM_RC_SUCCESS && array_size != sizeof(data->u.p)) { TPMLIB_LogTPM2Error("HASH_STATE_SHA512: Bad array size for u.p; " "expected %zu, got %u\n", sizeof(data->u.p), array_size); rc = TPM_RC_BAD_PARAMETER; } if (rc == TPM_RC_SUCCESS) { rc = Array_Unmarshal(&data->u.p[0], array_size, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&data->num, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&data->md_len, buffer, size); } /* version 2 starts having indicator for next versions that we can skip; this allows us to downgrade state */ if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, "HASH_STATE_SHA512", "version 3 or later"); /* future versions nest-append here */ } skip_future_versions: return rc; } #endif #define ANY_HASH_STATE_MAGIC 0x349d494b #define ANY_HASH_STATE_VERSION 2 static UINT16 ANY_HASH_STATE_Marshal(ANY_HASH_STATE *data, BYTE **buffer, INT32 *size, UINT16 hashAlg) { UINT16 written; BLOCK_SKIP_INIT; written = NV_HEADER_Marshal(buffer, size, ANY_HASH_STATE_VERSION, ANY_HASH_STATE_MAGIC, 1); switch (hashAlg) { #if ALG_SHA1 case ALG_SHA1_VALUE: written += tpmHashStateSHA1_Marshal(&data->Sha1, buffer, size); break; #endif #if ALG_SHA256 case ALG_SHA256_VALUE: written += tpmHashStateSHA256_Marshal(&data->Sha256, buffer, size); break; #endif #if ALG_SHA384 case ALG_SHA384_VALUE: written += tpmHashStateSHA512_Marshal(&data->Sha384, buffer, size, ALG_SHA384_VALUE); break; #endif #if ALG_SHA512 case ALG_SHA512_VALUE: written += tpmHashStateSHA512_Marshal(&data->Sha512, buffer, size, ALG_SHA512_VALUE); break; #endif default: break; } written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); /* future versions append below this line */ BLOCK_SKIP_WRITE_POP(size); BLOCK_SKIP_WRITE_CHECK; return written; } static UINT16 ANY_HASH_STATE_Unmarshal(ANY_HASH_STATE *data, BYTE **buffer, INT32 *size, UINT16 hashAlg) { UINT16 rc = TPM_RC_SUCCESS; NV_HEADER hdr; if (rc == TPM_RC_SUCCESS) { rc = NV_HEADER_Unmarshal(&hdr, buffer, size, ANY_HASH_STATE_VERSION, ANY_HASH_STATE_MAGIC); } switch (hashAlg) { #if ALG_SHA1 case ALG_SHA1_VALUE: rc = tpmHashStateSHA1_Unmarshal(&data->Sha1, buffer, size); break; #endif #if ALG_SHA256 case ALG_SHA256_VALUE: rc = tpmHashStateSHA256_Unmarshal(&data->Sha256, buffer, size); break; #endif #if ALG_SHA384 case ALG_SHA384_VALUE: rc = tpmHashStateSHA512_Unmarshal(&data->Sha384, buffer, size, ALG_SHA384_VALUE); break; #endif #if ALG_SHA512 case ALG_SHA512_VALUE: rc = tpmHashStateSHA512_Unmarshal(&data->Sha512, buffer, size, ALG_SHA512_VALUE); break; #endif } /* version 2 starts having indicator for next versions that we can skip; this allows us to downgrade state */ if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, "ANY_HASH_STATE", "version 3 or later"); /* future versions nest-append here */ } skip_future_versions: return rc; } #define HASH_STATE_MAGIC 0x562878a2 #define HASH_STATE_VERSION 2 static UINT16 HASH_STATE_Marshal(HASH_STATE *data, BYTE **buffer, INT32 *size) { UINT16 written; BLOCK_SKIP_INIT; written = NV_HEADER_Marshal(buffer, size, HASH_STATE_VERSION, HASH_STATE_MAGIC, 1); written += HASH_STATE_TYPE_Marshal(&data->type, buffer, size); written += TPM_ALG_ID_Marshal(&data->hashAlg, buffer, size); /* def does not need to be written */ written += ANY_HASH_STATE_Marshal(&data->state, buffer, size, data->hashAlg); written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); /* future versions append below this line */ BLOCK_SKIP_WRITE_POP(size); BLOCK_SKIP_WRITE_CHECK; return written; } static UINT16 HASH_STATE_Unmarshal(HASH_STATE *data, BYTE **buffer, INT32 *size) { UINT16 rc = TPM_RC_SUCCESS; NV_HEADER hdr; if (rc == TPM_RC_SUCCESS) { rc = NV_HEADER_Unmarshal(&hdr, buffer, size, HASH_STATE_VERSION, HASH_STATE_MAGIC); } if (rc == TPM_RC_SUCCESS) { rc = HASH_STATE_TYPE_Unmarshal(&data->type, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM_ALG_ID_Unmarshal(&data->hashAlg, buffer, size); } if (rc == TPM_RC_SUCCESS) { data->def = CryptGetHashDef(data->hashAlg); if (!data->def) { TPMLIB_LogTPM2Error("Could not get hash function interface for " "hashAlg 0x%02x\n", data->hashAlg); rc = TPM_RC_BAD_PARAMETER; } } if (rc == TPM_RC_SUCCESS) { rc = ANY_HASH_STATE_Unmarshal(&data->state, buffer, size, data->hashAlg); } /* version 2 starts having indicator for next versions that we can skip; this allows us to downgrade state */ if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, "HASH_STATE", "version 3 or later"); /* future versions nest-append here */ } skip_future_versions: return rc; } static inline UINT16 TPM2B_HASH_BLOCK_Marshal(TPM2B_HASH_BLOCK *data, BYTE **buffer, INT32 *size) { UINT16 written; written = TPM2B_Marshal(&data->b, sizeof(data->t.buffer), buffer, size); return written; } static inline UINT16 TPM2B_HASH_BLOCK_Unmarshal(TPM2B_HASH_BLOCK *data, BYTE **buffer, INT32 *size) { UINT16 rc; rc = TPM2B_Unmarshal(&data->b, sizeof(data->t.buffer), buffer, size); return rc; } static UINT16 HMAC_STATE_Marshal(HMAC_STATE *data, BYTE **buffer, INT32 *size) { UINT16 written; written = HASH_STATE_Marshal(&data->hashState, buffer, size); written += TPM2B_HASH_BLOCK_Marshal(&data->hmacKey, buffer, size); return written; } static UINT16 HMAC_STATE_Unmarshal(HMAC_STATE *data, BYTE **buffer, INT32 *size) { UINT16 rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = HASH_STATE_Unmarshal(&data->hashState, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_HASH_BLOCK_Unmarshal(&data->hmacKey, buffer, size); } return rc; } #define HASH_OBJECT_MAGIC 0xb874fe38 #define HASH_OBJECT_VERSION 3 static UINT16 HASH_OBJECT_Marshal(HASH_OBJECT *data, BYTE **buffer, INT32 *size) { UINT16 written; size_t i; UINT16 array_size; BLOCK_SKIP_INIT; written = NV_HEADER_Marshal(buffer, size, HASH_OBJECT_VERSION, HASH_OBJECT_MAGIC, 1); written += TPMI_ALG_PUBLIC_Marshal(&data->type, buffer, size); written += TPMI_ALG_HASH_Marshal(&data->nameAlg, buffer, size); written += TPMA_OBJECT_Marshal(&data->objectAttributes, buffer, size); written += TPM2B_AUTH_Marshal(&data->auth, buffer, size); if (data->attributes.hashSeq == SET || data->attributes.eventSeq == SET /* since v3 */) { array_size = ARRAY_SIZE(data->state.hashState); written += UINT16_Marshal(&array_size, buffer, size); for (i = 0; i < array_size; i++) { written += HASH_STATE_Marshal(&data->state.hashState[i], buffer, size); } } else if (data->attributes.hmacSeq == SET) { written += HMAC_STATE_Marshal(&data->state.hmacState, buffer, size); } written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); /* future versions append below this line */ BLOCK_SKIP_WRITE_POP(size); BLOCK_SKIP_WRITE_CHECK; return written; } static UINT16 HASH_OBJECT_Unmarshal(HASH_OBJECT *data, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; size_t i; UINT16 array_size; NV_HEADER hdr; if (rc == TPM_RC_SUCCESS) { rc = NV_HEADER_Unmarshal(&hdr, buffer, size, HASH_OBJECT_VERSION, HASH_OBJECT_MAGIC); } if (rc == TPM_RC_SUCCESS) { rc = TPMI_ALG_PUBLIC_Unmarshal(&data->type, buffer, size); if (rc == TPM_RC_TYPE) rc = TPM_RC_SUCCESS; } if (rc == TPM_RC_SUCCESS) { rc = TPMI_ALG_HASH_Unmarshal(&data->nameAlg, buffer, size, TRUE); } if (rc == TPM_RC_SUCCESS) { rc = TPMA_OBJECT_Unmarshal(&data->objectAttributes, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_AUTH_Unmarshal(&data->auth, buffer, size); } if (rc == TPM_RC_SUCCESS) { /* hashSeq was always written correctly; eventSeq only appeared in v3 */ if (data->attributes.hashSeq == SET || (data->attributes.eventSeq == SET && hdr.version >= 3)) { if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(&array_size, buffer, size); } if (rc == TPM_RC_SUCCESS) { if (array_size != ARRAY_SIZE(data->state.hashState)) { TPMLIB_LogTPM2Error("HASH_OBJECT: Bad array size for state.hashState; " "expected %zu, got %u\n", ARRAY_SIZE(data->state.hashState), array_size); rc = TPM_RC_SIZE; } } for (i = 0; rc == TPM_RC_SUCCESS && i < array_size; i++) { rc = HASH_STATE_Unmarshal(&data->state.hashState[i], buffer, size); } } else if (data->attributes.hmacSeq == SET) { rc = HMAC_STATE_Unmarshal(&data->state.hmacState, buffer, size); } } /* version 2 starts having indicator for next versions that we can skip; this allows us to downgrade state */ if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, "HASH_OBJECT", "version 3 or later"); /* future versions nest-append here */ } skip_future_versions: return rc; } /* Local version of TPMT_SENSITIVE_Marshal handling public keys that don't have much in TPM_SENSITIVE */ static UINT16 NV_TPMT_SENSITIVE_Marshal(TPMT_SENSITIVE *source, BYTE **buffer, INT32 *size) { UINT16 written = 0; written += TPM_ALG_ID_Marshal(&source->sensitiveType, buffer, size); written += TPM2B_AUTH_Marshal(&source->authValue, buffer, size); written += TPM2B_DIGEST_Marshal(&source->seedValue, buffer, size); switch (source->sensitiveType) { case TPM_ALG_RSA: case TPM_ALG_ECC: case TPM_ALG_KEYEDHASH: case TPM_ALG_SYMCIPHER: written += TPMU_SENSITIVE_COMPOSITE_Marshal(&source->sensitive, buffer, size, source->sensitiveType); break; default: /* we wrote these but they must have been 0 in this case */ pAssert(source->authValue.t.size == 0); pAssert(source->seedValue.t.size == 0); pAssert(source->sensitiveType == TPM_ALG_ERROR) /* public keys */ } return written; } /* local version of TPM_SENSITIVE_Unmarshal handling public keys that don't have much in TPMT_SENSITVE */ static TPM_RC NV_TPMT_SENSITIVE_Unmarshal(TPMT_SENSITIVE *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { /* TPMI_ALG_PUBLIC_Unmarshal would test the sensitiveType; we don't want this */ rc = TPM_ALG_ID_Unmarshal(&target->sensitiveType, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_AUTH_Unmarshal(&target->authValue, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_DIGEST_Unmarshal(&target->seedValue, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (target->sensitiveType) { case TPM_ALG_RSA: case TPM_ALG_ECC: case TPM_ALG_KEYEDHASH: case TPM_ALG_SYMCIPHER: rc = TPMU_SENSITIVE_COMPOSITE_Unmarshal(&target->sensitive, buffer, size, target->sensitiveType); break; default: pAssert(target->authValue.t.size == 0); pAssert(target->seedValue.t.size == 0); pAssert(target->sensitiveType == TPM_ALG_ERROR) /* nothing do to do */ } } return rc; } #define OBJECT_MAGIC 0x75be73af #define OBJECT_VERSION 3 static UINT16 OBJECT_Marshal(OBJECT *data, BYTE **buffer, INT32 *size) { UINT16 written; BOOL has_block; BLOCK_SKIP_INIT; written = NV_HEADER_Marshal(buffer, size, OBJECT_VERSION, OBJECT_MAGIC, 3); /* * attributes are written in ANY_OBJECT_Marshal */ written += TPMT_PUBLIC_Marshal(&data->publicArea, buffer, size); written += NV_TPMT_SENSITIVE_Marshal(&data->sensitive, buffer, size); #if ALG_RSA has_block = TRUE; #else has_block = FALSE; #endif written += BLOCK_SKIP_WRITE_PUSH(has_block, buffer, size); #if ALG_RSA written += privateExponent_t_Marshal(&data->privateExponent, buffer, size); #endif BLOCK_SKIP_WRITE_POP(size); written += TPM2B_NAME_Marshal(&data->qualifiedName, buffer, size); written += TPM_HANDLE_Marshal(&data->evictHandle, buffer, size); written += TPM2B_NAME_Marshal(&data->name, buffer, size); written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); written += SEED_COMPAT_LEVEL_Marshal(&data->seedCompatLevel, buffer, size); written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); /* future versions append below this line */ BLOCK_SKIP_WRITE_POP(size); BLOCK_SKIP_WRITE_POP(size); BLOCK_SKIP_WRITE_CHECK; return written; } static TPM_RC OBJECT_Unmarshal(OBJECT *data, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; NV_HEADER hdr; BOOL needs_block; /* * attributes are read in ANY_OBJECT_Unmarshal */ if (rc == TPM_RC_SUCCESS) { rc = NV_HEADER_Unmarshal(&hdr, buffer, size, OBJECT_VERSION, OBJECT_MAGIC); } if (rc == TPM_RC_SUCCESS) { rc = TPMT_PUBLIC_Unmarshal(&data->publicArea, buffer, size, TRUE); } if (rc == TPM_RC_SUCCESS) { rc = NV_TPMT_SENSITIVE_Unmarshal(&data->sensitive, buffer, size); } #if ALG_RSA needs_block = TRUE; #else needs_block = FALSE; #endif if (rc == TPM_RC_SUCCESS) { BLOCK_SKIP_READ(skip_alg_rsa, needs_block, buffer, size, "OBJECT", "privateExponent"); } #if ALG_RSA if (rc == TPM_RC_SUCCESS) { rc = privateExponent_t_Unmarshal(&data->privateExponent, buffer, size); } #endif skip_alg_rsa: if (rc == TPM_RC_SUCCESS) { rc = TPM2B_NAME_Unmarshal(&data->qualifiedName, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM_HANDLE_Unmarshal(&data->evictHandle, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_NAME_Unmarshal(&data->name, buffer, size); } /* default values before conditional block */ data->seedCompatLevel = SEED_COMPAT_LEVEL_ORIGINAL; /* version 2 starts having indicator for next versions that we can skip; this allows us to downgrade state */ if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { BLOCK_SKIP_READ(skip_future_versions, hdr.version >= 3, buffer, size, "OBJECT", "version 3 or later"); if (rc == TPM_RC_SUCCESS) { rc = SEED_COMPAT_LEVEL_Unmarshal(&data->seedCompatLevel, buffer, size, "OBJECT seedCompatLevel"); } if (rc == TPM_RC_SUCCESS) { BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, "OBJECT", "version 4 or later"); } /* future versions nest-append here */ } skip_future_versions: return rc; } #define ANY_OBJECT_MAGIC 0xfe9a3974 #define ANY_OBJECT_VERSION 2 UINT16 ANY_OBJECT_Marshal(OBJECT *data, BYTE **buffer, INT32 *size) { UINT16 written; UINT32 *ptr = (UINT32 *)&data->attributes; BLOCK_SKIP_INIT; written = NV_HEADER_Marshal(buffer, size, ANY_OBJECT_VERSION, ANY_OBJECT_MAGIC, 1); written += UINT32_Marshal(ptr, buffer, size); /* the slot must be occupied, otherwise the rest may not be initialized */ if (data->attributes.occupied) { if (ObjectIsSequence(data)) written += HASH_OBJECT_Marshal((HASH_OBJECT *)data, buffer, size); else written += OBJECT_Marshal(data, buffer, size); } written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); /* future versions append below this line */ BLOCK_SKIP_WRITE_POP(size); BLOCK_SKIP_WRITE_CHECK; return written; } TPM_RC ANY_OBJECT_Unmarshal(OBJECT *data, BYTE **buffer, INT32 *size, BOOL verbose) { TPM_RC rc = TPM_RC_SUCCESS; UINT32 *ptr = (UINT32 *)&data->attributes; NV_HEADER hdr; if (rc == TPM_RC_SUCCESS) { rc = NV_HEADER_UnmarshalVerbose(&hdr, buffer, size, ANY_OBJECT_VERSION, ANY_OBJECT_MAGIC, verbose); } if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(ptr, buffer, size); } if (rc == TPM_RC_SUCCESS && data->attributes.occupied) { if (ObjectIsSequence(data)) rc = HASH_OBJECT_Unmarshal((HASH_OBJECT *)data, buffer, size); else rc = OBJECT_Unmarshal(data, buffer, size); } /* version 2 starts having indicator for next versions that we can skip; this allows us to downgrade state */ if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, "ANY_OBJECT", "version 3 or later"); /* future versions nest-append here */ } skip_future_versions: return rc; } static UINT16 TPMT_SYM_DEF_Marshal(TPMT_SYM_DEF *data, BYTE **buffer, INT32 *size) { UINT16 written; written = UINT16_Marshal(&data->algorithm, buffer, size); written += TPMU_SYM_KEY_BITS_Marshal(&data->keyBits, buffer, size, data->algorithm); written += TPMU_SYM_MODE_Marshal(&data->mode, buffer, size, data->algorithm); return written; } #define SESSION_MAGIC 0x44be9f45 #define SESSION_VERSION 2 static UINT16 SESSION_Marshal(SESSION *data, BYTE **buffer, INT32 *size) { UINT16 written; UINT8 clocksize; BLOCK_SKIP_INIT; written = NV_HEADER_Marshal(buffer, size, SESSION_VERSION, SESSION_MAGIC, 1); written += UINT32_Marshal((UINT32 *)&data->attributes, buffer, size); written += UINT32_Marshal(&data->pcrCounter, buffer, size); written += UINT64_Marshal(&data->startTime, buffer, size); written += UINT64_Marshal(&data->timeout, buffer, size); #if CLOCK_STOPS clocksize = sizeof(UINT64); written += UINT8_Marshal(&clocksize, buffer, size); written += UINT64_Marshal(&data->epoch, buffer, size); #else clocksize = sizeof(UINT32); written += UINT8_Marshal(&clocksize, buffer, size); written += UINT32_Marshal(&data->epoch, buffer, size); #endif written += UINT32_Marshal(&data->commandCode, buffer, size); written += UINT16_Marshal(&data->authHashAlg, buffer, size); written += UINT8_Marshal(&data->commandLocality, buffer, size); written += TPMT_SYM_DEF_Marshal(&data->symmetric, buffer, size); written += TPM2B_AUTH_Marshal(&data->sessionKey, buffer, size); written += TPM2B_NONCE_Marshal(&data->nonceTPM, buffer, size); // TPM2B_NAME or TPM2B_DIGEST could be used for marshalling written += TPM2B_NAME_Marshal(&data->u1.boundEntity, buffer, size); written += TPM2B_DIGEST_Marshal(&data->u2.auditDigest, buffer, size); written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); /* future versions append below this line */ BLOCK_SKIP_WRITE_POP(size); BLOCK_SKIP_WRITE_CHECK; return written; } static TPM_RC SESSION_Unmarshal(SESSION *data, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; NV_HEADER hdr; UINT8 clocksize; if (rc == TPM_RC_SUCCESS) { rc = NV_HEADER_Unmarshal(&hdr, buffer, size, SESSION_VERSION, SESSION_MAGIC); } if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal((UINT32 *)&data->attributes, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&data->pcrCounter, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT64_Unmarshal(&data->startTime, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT64_Unmarshal(&data->timeout, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT8_Unmarshal(&clocksize, buffer, size); } if (rc == TPM_RC_SUCCESS) { #if CLOCK_STOPS if (clocksize != sizeof(UINT64)) { TPMLIB_LogTPM2Error("Unexpected clocksize for epoch; " "Expected %zu, got %u\n", sizeof(UINT64), clocksize); rc = TPM_RC_BAD_PARAMETER; } if (rc == TPM_RC_SUCCESS) { rc = UINT64_Unmarshal(&data->epoch, buffer, size); } #else if (clocksize != sizeof(UINT32)) { TPMLIB_LogTPM2Error("Unexpected clocksize for epoch; " "Expected %zu, got %u\n", sizeof(UINT32), clocksize); rc = TPM_RC_BAD_PARAMETER; } if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&data->epoch, buffer, size); } #endif } if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&data->commandCode, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(&data->authHashAlg, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT8_Unmarshal(&data->commandLocality, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPMT_SYM_DEF_Unmarshal(&data->symmetric, buffer, size, YES); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_AUTH_Unmarshal(&data->sessionKey, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_NONCE_Unmarshal(&data->nonceTPM, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_NAME_Unmarshal(&data->u1.boundEntity, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_DIGEST_Unmarshal(&data->u2.auditDigest, buffer, size); } /* version 2 starts having indicator for next versions that we can skip; this allows us to downgrade state */ if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, "SESSION", "version 3 or later"); /* future versions nest-append here */ } skip_future_versions: return rc; } #define SESSION_SLOT_MAGIC 0x3664aebc #define SESSION_SLOT_VERSION 2 static UINT16 SESSION_SLOT_Marshal(SESSION_SLOT *data, BYTE **buffer, INT32* size) { UINT16 written; BLOCK_SKIP_INIT; written = NV_HEADER_Marshal(buffer, size, SESSION_SLOT_VERSION, SESSION_SLOT_MAGIC, 1); written += BOOL_Marshal(&data->occupied, buffer, size); if (!data->occupied) return written; written += SESSION_Marshal(&data->session, buffer, size); written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); /* future versions append below this line */ BLOCK_SKIP_WRITE_POP(size); BLOCK_SKIP_WRITE_CHECK; return written; } static TPM_RC SESSION_SLOT_Unmarshal(SESSION_SLOT *data, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; NV_HEADER hdr; if (rc == TPM_RC_SUCCESS) { rc = NV_HEADER_Unmarshal(&hdr, buffer, size, SESSION_SLOT_VERSION, SESSION_SLOT_MAGIC); } if (rc == TPM_RC_SUCCESS) { rc = BOOL_Unmarshal(&data->occupied, buffer, size); } if (!data->occupied) return rc; if (rc == TPM_RC_SUCCESS) { rc = SESSION_Unmarshal(&data->session, buffer, size); } /* version 2 starts having indicator for next versions that we can skip; this allows us to downgrade state */ if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, "SESSION_SLOT", "version 3 or later"); /* future versions nest-append here */ } skip_future_versions: return rc; } #define VOLATILE_STATE_VERSION 4 #define VOLATILE_STATE_MAGIC 0x45637889 UINT16 VolatileState_Marshal(BYTE **buffer, INT32 *size) { UINT16 written; size_t i; BOOL tpmEst; UINT64 tmp_uint64; UINT32 tmp_uint32; BOOL has_block; UINT16 array_size; BLOCK_SKIP_INIT; PERSISTENT_DATA pd; written = NV_HEADER_Marshal(buffer, size, VOLATILE_STATE_VERSION, VOLATILE_STATE_MAGIC, 1); /* skip g_rcIndex: these are 'constants' */ written += TPM_HANDLE_Marshal(&g_exclusiveAuditSession, buffer, size); /* line 423 */ /* g_time: may not be necessary */ written += UINT64_Marshal(&g_time, buffer, size); /* line 426 */ /* g_timeEpoch: skipped so far -- needs investigation */ /* g_phEnable: since we won't call TPM2_Starup, we need to write it */ written += BOOL_Marshal(&g_phEnable, buffer, size); /* line 439 */ /* g_pcrReconfig: must write */ written += BOOL_Marshal(&g_pcrReConfig, buffer, size); /* line 443 */ /* g_DRTMHandle: must write */ written += TPM_HANDLE_Marshal(&g_DRTMHandle, buffer, size); /* line 448 */ /* g_DrtmPreStartup: must write */ written += BOOL_Marshal(&g_DrtmPreStartup, buffer, size); /* line 453 */ /* g_StartupLocality3: must write */ written += BOOL_Marshal(&g_StartupLocality3, buffer, size); /* line 458 */ #if USE_DA_USED has_block = TRUE; #else has_block = FALSE; #endif written += BLOCK_SKIP_WRITE_PUSH(has_block, buffer, size); #if USE_DA_USED /* g_daUsed: must write */ written += BOOL_Marshal(&g_daUsed, buffer, size); /* line 484 */ #endif BLOCK_SKIP_WRITE_POP(size); /* g_updateNV: can skip since it seems to only be valid during execution of a command*/ /* g_powerWasLost: must write */ written += BOOL_Marshal(&g_powerWasLost, buffer, size); /* line 504 */ /* g_clearOrderly: can skip since it seems to only be valid during execution of a command */ /* g_prevOrderlyState: must write */ written += UINT16_Marshal(&g_prevOrderlyState, buffer, size); /* line 516 */ /* g_nvOk: must write */ written += BOOL_Marshal(&g_nvOk, buffer, size); /* line 522 */ /* g_NvStatus: can skip since it seems to only be valid during execution of a command */ #if 0 /* does not exist */ written += TPM2B_AUTH_Marshal(&g_platformUniqueAuthorities, buffer, size); /* line 535 */ #endif written += TPM2B_AUTH_Marshal(&g_platformUniqueDetails, buffer, size); /* line 536 */ /* gp (persistent_data): skip; we assume its latest states in the persistent data file */ /* we store the next 3 because they may not have been written to NVRAM */ written += ORDERLY_DATA_Marshal(&go, buffer, size); /* line 707 */ written += STATE_CLEAR_DATA_Marshal(&gc, buffer, size); /* line 738 */ written += STATE_RESET_DATA_Marshal(&gr, buffer, size); /* line 826 */ /* g_manufactured: must write */ written += BOOL_Marshal(&g_manufactured, buffer, size); /* line 928 */ /* g_initialized: must write */ written += BOOL_Marshal(&g_initialized, buffer, size); /* line 932 */ #if defined SESSION_PROCESS_C || defined GLOBAL_C || defined MANUFACTURE_C has_block = TRUE; #else has_block = FALSE; #endif written += BLOCK_SKIP_WRITE_PUSH(has_block, buffer, size); #if defined SESSION_PROCESS_C || defined GLOBAL_C || defined MANUFACTURE_C /* * The session related variables may only be valid during the execution * of a single command; safer to store */ array_size = ARRAY_SIZE(s_sessionHandles); written += UINT16_Marshal(&array_size, buffer, size); for (i = 0; i < array_size; i++) { written += TPM_HANDLE_Marshal(&s_sessionHandles[i], buffer, size); written += TPMA_SESSION_Marshal(&s_attributes[i], buffer, size); written += TPM_HANDLE_Marshal(&s_associatedHandles[i], buffer, size); written += TPM2B_NONCE_Marshal(&s_nonceCaller[i], buffer, size); written += TPM2B_AUTH_Marshal(&s_inputAuthValues[i], buffer, size); /* s_usedSessions: cannot serialize this since it is a pointer; also, isn't used */ } written += TPM_HANDLE_Marshal(&s_encryptSessionIndex, buffer, size); written += TPM_HANDLE_Marshal(&s_decryptSessionIndex, buffer, size); written += TPM_HANDLE_Marshal(&s_auditSessionIndex, buffer, size); #if CC_GetCommandAuditDigest has_block = TRUE; #else has_block = FALSE; #endif written += BLOCK_SKIP_WRITE_PUSH(has_block, buffer, size); #if CC_GetCommandAuditDigest /* s_cpHashForCommandAudit: seems not used; better to write it */ written += TPM2B_DIGEST_Marshal(&s_cpHashForCommandAudit, buffer, size); #endif BLOCK_SKIP_WRITE_POP(size); /* s_DAPendingOnNV: needs investigation ... */ written += BOOL_Marshal(&s_DAPendingOnNV, buffer, size); #endif // SESSION_PROCESS_C BLOCK_SKIP_WRITE_POP(size); #if defined DA_C || defined GLOBAL_C || defined MANUFACTURE_C has_block = TRUE; #else has_block = FALSE; #endif written += BLOCK_SKIP_WRITE_PUSH(has_block, buffer, size); #if defined DA_C || defined GLOBAL_C || defined MANUFACTURE_C #if !ACCUMULATE_SELF_HEAL_TIMER has_block = TRUE; #else has_block = FALSE; #endif written += BLOCK_SKIP_WRITE_PUSH(has_block, buffer, size); #if !ACCUMULATE_SELF_HEAL_TIMER written += UINT64_Marshal(&s_selfHealTimer, buffer, size); /* line 975 */ written += UINT64_Marshal(&s_lockoutTimer, buffer, size); /* line 977 */ #endif // ACCUMULATE_SELF_HEAL_TIMER BLOCK_SKIP_WRITE_POP(size); #endif // DA_C BLOCK_SKIP_WRITE_POP(size); #if defined NV_C || defined GLOBAL_C has_block = TRUE; #else has_block = FALSE; #endif written += BLOCK_SKIP_WRITE_PUSH(has_block, buffer, size); /* s_evictNvEnd set in NvInitStatic called by NvPowerOn in case g_powerWasLost * Unless we set g_powerWasLost=TRUE and call NvPowerOn, we have to include it. */ #if defined NV_C || defined GLOBAL_C written += UINT32_Marshal(&s_evictNvEnd, buffer, size); /* line 984 */ /* s_indexOrderlyRam read from NVRAM in NvEntityStartup and written to it * in NvUpdateIndexOrderlyData called by TPM2_Shutdown and initialized * in NvManufacture -- since we don't call TPM2_Shutdown we serialize it here */ array_size = sizeof(s_indexOrderlyRam); written += UINT16_Marshal(&array_size, buffer, size); written += Array_Marshal(s_indexOrderlyRam, array_size, buffer, size); written += UINT64_Marshal(&s_maxCounter, buffer, size); /* line 992 */ /* the following need not be written; NvIndexCacheInit initializes them partly * and NvIndexCacheInit() is called during ExecuteCommand() * - s_cachedNvIndex * - s_cachedNvRef * - s_cachedNvRamRef */ #endif BLOCK_SKIP_WRITE_POP(size); #if defined OBJECT_C || defined GLOBAL_C has_block = TRUE; #else has_block = FALSE; #endif written += BLOCK_SKIP_WRITE_PUSH(has_block, buffer, size); #if defined OBJECT_C || defined GLOBAL_C /* used in many places; it doesn't look like TPM2_Shutdown writes this into * persistent memory, so what is lost upon TPM2_Shutdown? */ array_size = ARRAY_SIZE(s_objects); written += UINT16_Marshal(&array_size, buffer, size); for (i = 0; i < array_size; i++) { written += ANY_OBJECT_Marshal(&s_objects[i], buffer, size); } #endif BLOCK_SKIP_WRITE_POP(size); #if defined PCR_C || defined GLOBAL_C has_block = TRUE; #else has_block = FALSE; #endif written += BLOCK_SKIP_WRITE_PUSH(has_block, buffer, size); #if defined PCR_C || defined GLOBAL_C /* s_pcrs: Marshal *all* PCRs, even those for which stateSave bit is not set */ array_size = ARRAY_SIZE(s_pcrs); written += UINT16_Marshal(&array_size, buffer, size); for (i = 0; i < array_size; i++) { written += PCR_Marshal(&s_pcrs[i], buffer, size); } #endif BLOCK_SKIP_WRITE_POP(size); #if defined SESSION_C || defined GLOBAL_C has_block = TRUE; #else has_block = FALSE; #endif written += BLOCK_SKIP_WRITE_PUSH(has_block, buffer, size); #if defined SESSION_C || defined GLOBAL_C /* s_sessions: */ array_size = ARRAY_SIZE(s_sessions); written += UINT16_Marshal(&array_size, buffer, size); for (i = 0; i < array_size; i++) { written += SESSION_SLOT_Marshal(&s_sessions[i], buffer, size); } /* s_oldestSavedSession: */ written += UINT32_Marshal(&s_oldestSavedSession, buffer, size); /* s_freeSessionSlots: */ written += UINT32_Marshal((UINT32 *)&s_freeSessionSlots, buffer, size); #endif BLOCK_SKIP_WRITE_POP(size); #if defined IO_BUFFER_C || defined GLOBAL_C /* s_actionInputBuffer: skip; only used during a single command */ /* s_actionOutputBuffer: skip; only used during a single command */ #endif written += BOOL_Marshal(&g_inFailureMode, buffer, size); /* line 1078 */ /* TPM established bit */ tpmEst = _rpc__Signal_GetTPMEstablished(); written += BOOL_Marshal(&tpmEst, buffer, size); #if defined TPM_FAIL_C || defined GLOBAL_C || 1 has_block = TRUE; #else has_block = FALSE; #endif written += BLOCK_SKIP_WRITE_PUSH(has_block, buffer, size); #if defined TPM_FAIL_C || defined GLOBAL_C || 1 written += UINT32_Marshal(&s_failFunction, buffer, size); written += UINT32_Marshal(&s_failLine, buffer, size); written += UINT32_Marshal(&s_failCode, buffer, size); #endif // TPM_FAIL_C BLOCK_SKIP_WRITE_POP(size); #ifndef HARDWARE_CLOCK has_block = TRUE; #else has_block = FALSE; #endif written += BLOCK_SKIP_WRITE_PUSH(has_block, buffer, size); #ifndef HARDWARE_CLOCK tmp_uint64 = s_realTimePrevious; written += UINT64_Marshal(&tmp_uint64, buffer, size); tmp_uint64 = s_tpmTime; written += UINT64_Marshal(&tmp_uint64, buffer, size); #endif BLOCK_SKIP_WRITE_POP(size); written += BOOL_Marshal(&s_timerReset, buffer, size); written += BOOL_Marshal(&s_timerStopped, buffer, size); written += UINT32_Marshal(&s_adjustRate, buffer, size); tmp_uint64 = ClockGetTime(CLOCK_REALTIME); written += UINT64_Marshal(&tmp_uint64, buffer, size); written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); /* v3 */ /* tie the volatile state to the EP,SP, and PPSeed */ NvRead(&pd, NV_PERSISTENT_DATA, sizeof(pd)); written += TPM2B_Marshal(&pd.EPSeed.b, sizeof(pd.EPSeed.t.buffer), buffer, size); written += TPM2B_Marshal(&pd.SPSeed.b, sizeof(pd.SPSeed.t.buffer), buffer, size); written += TPM2B_Marshal(&pd.PPSeed.b, sizeof(pd.PPSeed.t.buffer), buffer, size); written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); /* v4 */ tmp_uint64 = ClockGetTime(CLOCK_MONOTONIC) + s_hostMonotonicAdjustTime; written += UINT64_Marshal(&tmp_uint64, buffer, size); written += UINT64_Marshal(&s_suspendedElapsedTime, buffer, size); written += UINT64_Marshal(&s_lastSystemTime, buffer, size); written += UINT64_Marshal(&s_lastReportedTime, buffer, size); written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); /* v5 */ /* future versions append below this line */ BLOCK_SKIP_WRITE_POP(size); /* v5 */ BLOCK_SKIP_WRITE_POP(size); /* v4 */ BLOCK_SKIP_WRITE_POP(size); /* v3 */ /* keep marker at end */ tmp_uint32 = VOLATILE_STATE_MAGIC; written += UINT32_Marshal(&tmp_uint32, buffer, size); BLOCK_SKIP_WRITE_CHECK; return written; } static TPM_RC VolatileState_TailV4_Unmarshal(BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; UINT64 tmp_uint64; if (rc == TPM_RC_SUCCESS) { rc = UINT64_Unmarshal(&tmp_uint64, buffer, size); s_hostMonotonicAdjustTime = tmp_uint64 - ClockGetTime(CLOCK_MONOTONIC); } if (rc == TPM_RC_SUCCESS) { rc = UINT64_Unmarshal(&s_suspendedElapsedTime, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT64_Unmarshal(&s_lastSystemTime, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT64_Unmarshal(&s_lastReportedTime, buffer, size); } return rc; } static TPM_RC VolatileState_TailV3_Unmarshal(BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; PERSISTENT_DATA pd; TPM2B_SEED seed = { .b.size = 0, }; NvRead(&pd, NV_PERSISTENT_DATA, sizeof(pd)); if (rc == TPM_RC_SUCCESS) { rc = TPM2B_Unmarshal(&seed.b, PRIMARY_SEED_SIZE, buffer, size); } if (rc == TPM_RC_SUCCESS) { if (seed.b.size > PRIMARY_SEED_SIZE) /* coverity */ rc = TPM_RC_SIZE; } if (rc == TPM_RC_SUCCESS) { if (TPM2B_Cmp(&seed.b, &pd.EPSeed.b)) { TPMLIB_LogTPM2Error("%s: EPSeed does not match\n", __func__); rc = TPM_RC_VALUE; } } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_Unmarshal(&seed.b, PRIMARY_SEED_SIZE, buffer, size); } if (rc == TPM_RC_SUCCESS) { if (seed.b.size > PRIMARY_SEED_SIZE) /* coverity */ rc = TPM_RC_SIZE; } if (rc == TPM_RC_SUCCESS) { if (TPM2B_Cmp(&seed.b, &pd.SPSeed.b)) { TPMLIB_LogTPM2Error("%s: SPSeed does not match\n", __func__); rc = TPM_RC_VALUE; } } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_Unmarshal(&seed.b, PRIMARY_SEED_SIZE, buffer, size); } if (rc == TPM_RC_SUCCESS) { if (seed.b.size > PRIMARY_SEED_SIZE) /* coverity */ rc = TPM_RC_SIZE; } if (rc == TPM_RC_SUCCESS) { if (TPM2B_Cmp(&seed.b, &pd.PPSeed.b)) { TPMLIB_LogTPM2Error("%s: PPSeed does not match\n", __func__); rc = TPM_RC_VALUE; } } return rc; } TPM_RC VolatileState_Unmarshal(BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; size_t i; UINT64 tmp_uint64; UINT32 tmp_uint32; NV_HEADER hdr; BOOL needs_block; UINT16 array_size = 0; UINT64 backthen; if (rc == TPM_RC_SUCCESS) { rc = NV_HEADER_Unmarshal(&hdr, buffer, size, VOLATILE_STATE_VERSION, VOLATILE_STATE_MAGIC); } if (rc == TPM_RC_SUCCESS) { rc = TPM_HANDLE_Unmarshal(&g_exclusiveAuditSession, buffer, size); /* line 423 */ } if (rc == TPM_RC_SUCCESS) { rc = UINT64_Unmarshal(&g_time, buffer, size); /* line 426 */ } if (rc == TPM_RC_SUCCESS) { rc = BOOL_Unmarshal(&g_phEnable, buffer, size); /* line 439 */ } if (rc == TPM_RC_SUCCESS) { rc = BOOL_Unmarshal(&g_pcrReConfig, buffer, size); /* line 443 */ } if (rc == TPM_RC_SUCCESS) { rc = TPM_HANDLE_Unmarshal(&g_DRTMHandle, buffer, size); /* line 448 */ } if (rc == TPM_RC_SUCCESS) { rc = BOOL_Unmarshal(&g_DrtmPreStartup, buffer, size); /* line 453 */ } if (rc == TPM_RC_SUCCESS) { rc = BOOL_Unmarshal(&g_StartupLocality3, buffer, size); /* line 458 */ } #if USE_DA_USED needs_block = TRUE; #else needs_block = FALSE; #endif if (rc == TPM_RC_SUCCESS) { BLOCK_SKIP_READ(skip_da, needs_block, buffer, size, "Volatile state", "g_daUsed"); } #if USE_DA_USED if (rc == TPM_RC_SUCCESS) { rc = BOOL_Unmarshal(&g_daUsed, buffer, size); /* line 484 */ } #endif skip_da: if (rc == TPM_RC_SUCCESS) { rc = BOOL_Unmarshal(&g_powerWasLost, buffer, size); /* line 504 */ } if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(&g_prevOrderlyState, buffer, size); /* line 516 */ } if (rc == TPM_RC_SUCCESS) { rc = BOOL_Unmarshal(&g_nvOk, buffer, size); /* line 522 */ } #if 0 /* does not exist */ if (rc == TPM_RC_SUCCESS) { rc = TPM2B_AUTH_Unmarshal(&g_platformUniqueAuthorities, buffer, size); /* line 535 */ } #endif if (rc == TPM_RC_SUCCESS) { rc = TPM2B_AUTH_Unmarshal(&g_platformUniqueDetails, buffer, size); /* line 536 */ } if (rc == TPM_RC_SUCCESS) { rc = ORDERLY_DATA_Unmarshal(&go, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = STATE_CLEAR_DATA_Unmarshal(&gc, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = STATE_RESET_DATA_Unmarshal(&gr, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = BOOL_Unmarshal(&g_manufactured, buffer, size); /* line 928 */ } if (rc == TPM_RC_SUCCESS) { rc = BOOL_Unmarshal(&g_initialized, buffer, size); /* line 932 */ } #if defined SESSION_PROCESS_C || defined GLOBAL_C || defined MANUFACTURE_C needs_block = TRUE; #else needs_block = FALSE; #endif if (rc == TPM_RC_SUCCESS) { BLOCK_SKIP_READ(skip_session_process, needs_block, buffer, size, "Volatile state", "s_sessionHandles"); } #if defined SESSION_PROCESS_C || defined GLOBAL_C || defined MANUFACTURE_C if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(&array_size, buffer, size); } if (rc == TPM_RC_SUCCESS && array_size != ARRAY_SIZE(s_sessionHandles)) { TPMLIB_LogTPM2Error("Volatile state: Bad array size for s_sessionHandles; " "expected %zu, got %u\n", ARRAY_SIZE(s_sessionHandles), array_size); rc = TPM_RC_BAD_PARAMETER; } for (i = 0; i < array_size && rc == TPM_RC_SUCCESS; i++) { if (rc == TPM_RC_SUCCESS) { rc = TPM_HANDLE_Unmarshal(&s_sessionHandles[i], buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPMA_SESSION_Unmarshal(&s_attributes[i], buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM_HANDLE_Unmarshal(&s_associatedHandles[i], buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_NONCE_Unmarshal(&s_nonceCaller[i], buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_AUTH_Unmarshal(&s_inputAuthValues[i], buffer, size); } } if (rc == TPM_RC_SUCCESS) { rc = TPM_HANDLE_Unmarshal(&s_encryptSessionIndex, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM_HANDLE_Unmarshal(&s_decryptSessionIndex, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM_HANDLE_Unmarshal(&s_auditSessionIndex, buffer, size); } #if CC_GetCommandAuditDigest needs_block = TRUE; #else needs_block = FALSE; #endif if (rc == TPM_RC_SUCCESS) { BLOCK_SKIP_READ(skip_cc_getcommandauditdigest, needs_block, buffer, size, "Volatile state", "s_cpHashForCommandAudit"); } #if CC_GetCommandAuditDigest if (rc == TPM_RC_SUCCESS) { rc = TPM2B_DIGEST_Unmarshal(&s_cpHashForCommandAudit, buffer, size); } #endif skip_cc_getcommandauditdigest: if (rc == TPM_RC_SUCCESS) { rc = BOOL_Unmarshal(&s_DAPendingOnNV, buffer, size); } #endif /* SESSION_PROCESS_C */ skip_session_process: #if defined DA_C || defined GLOBAL_C || defined MANUFACTURE_C needs_block = TRUE; #else needs_block = FALSE; #endif if (rc == TPM_RC_SUCCESS) { BLOCK_SKIP_READ(skip_accumulate_self_heal_timer_1, needs_block, buffer, size, "Volatile state", "s_selfHealTimer.1"); } #if defined DA_C || defined GLOBAL_C || defined MANUFACTURE_C #if !ACCUMULATE_SELF_HEAL_TIMER needs_block = TRUE; #else needs_block = FALSE; #endif if (rc == TPM_RC_SUCCESS) { BLOCK_SKIP_READ(skip_accumulate_self_heal_timer_2, needs_block, buffer, size, "Volatile state", "s_selfHealTimer.2"); } #if !ACCUMULATE_SELF_HEAL_TIMER if (rc == TPM_RC_SUCCESS) { rc = UINT64_Unmarshal(&s_selfHealTimer, buffer, size); /* line 975 */ } if (rc == TPM_RC_SUCCESS) { rc = UINT64_Unmarshal(&s_lockoutTimer, buffer, size); /* line 977 */ } #endif skip_accumulate_self_heal_timer_2: #endif skip_accumulate_self_heal_timer_1: #if defined NV_C || defined GLOBAL_C needs_block = TRUE; #else needs_block = FALSE; #endif if (rc == TPM_RC_SUCCESS) { BLOCK_SKIP_READ(skip_nv, needs_block, buffer, size, "Volatile state", "s_evictNvEnd"); } #if defined NV_C || defined GLOBAL_C if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&s_evictNvEnd, buffer, size); /* line 984 */ } if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(&array_size, buffer, size); } if (rc == TPM_RC_SUCCESS && array_size != ARRAY_SIZE(s_indexOrderlyRam)) { TPMLIB_LogTPM2Error("Volatile state: Bad array size for s_indexOrderlyRam; " "expected %zu, got %u\n", ARRAY_SIZE(s_indexOrderlyRam), array_size); rc = TPM_RC_BAD_PARAMETER; } if (rc == TPM_RC_SUCCESS) { rc = Array_Unmarshal(s_indexOrderlyRam, array_size, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT64_Unmarshal(&s_maxCounter, buffer, size); /* line 992 */ } /* The following are not included: * - s_cachedNvIndex * - s_cachedNvRef * - s_cachedNvRamRef */ #endif skip_nv: #if defined OBJECT_C || defined GLOBAL_C needs_block = TRUE; #else needs_block = FALSE; #endif if (rc == TPM_RC_SUCCESS) { BLOCK_SKIP_READ(skip_object, needs_block, buffer, size, "Volatile state", "s_objects"); } #if defined OBJECT_C || defined GLOBAL_C if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(&array_size, buffer, size); } if (rc == TPM_RC_SUCCESS && array_size != ARRAY_SIZE(s_objects)) { TPMLIB_LogTPM2Error("Volatile state: Bad array size for s_objects; " "expected %zu, got %u\n", ARRAY_SIZE(s_objects), array_size); rc = TPM_RC_BAD_PARAMETER; } for (i = 0; i < array_size && rc == TPM_RC_SUCCESS; i++) { rc = ANY_OBJECT_Unmarshal(&s_objects[i], buffer, size, true); } #endif skip_object: #if defined PCR_C || defined GLOBAL_C needs_block = TRUE; #else needs_block = FALSE; #endif if (rc == TPM_RC_SUCCESS) { BLOCK_SKIP_READ(skip_pcr, needs_block, buffer, size, "Volatile state", "s_pcrs"); } #if defined PCR_C || defined GLOBAL_C if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(&array_size, buffer, size); } if (rc == TPM_RC_SUCCESS && array_size != ARRAY_SIZE(s_pcrs)) { TPMLIB_LogTPM2Error("Volatile state: Bad array size for s_pcrs; " "expected %zu, got %u\n", ARRAY_SIZE(s_pcrs), array_size); rc = TPM_RC_BAD_PARAMETER; } for (i = 0; i < array_size && rc == TPM_RC_SUCCESS; i++) { rc = PCR_Unmarshal(&s_pcrs[i], buffer, size, &shadow.pcrAllocated); } #endif skip_pcr: #if defined SESSION_C || defined GLOBAL_C needs_block = TRUE; #else needs_block = FALSE; #endif if (rc == TPM_RC_SUCCESS) { BLOCK_SKIP_READ(skip_session, needs_block, buffer, size, "Volatile state", "s_sessions"); } #if defined SESSION_C || defined GLOBAL_C if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(&array_size, buffer, size); } if (rc == TPM_RC_SUCCESS && array_size != ARRAY_SIZE(s_sessions)) { TPMLIB_LogTPM2Error("Volatile state: Bad array size for s_sessions; " "expected %zu, got %u\n", ARRAY_SIZE(s_sessions), array_size); rc = TPM_RC_BAD_PARAMETER; } /* s_sessions: */ for (i = 0; i < array_size && rc == TPM_RC_SUCCESS; i++) { rc = SESSION_SLOT_Unmarshal(&s_sessions[i], buffer, size); } /* s_oldestSavedSession: */ if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&s_oldestSavedSession, buffer, size); } /* s_freeSessionSlots: */ if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal((UINT32 *)&s_freeSessionSlots, buffer, size); } #endif skip_session: if (rc == TPM_RC_SUCCESS) { rc = BOOL_Unmarshal(&g_inFailureMode, buffer, size); /* line 1078 */ } /* TPM established bit */ if (rc == TPM_RC_SUCCESS) { BOOL tpmEst; rc = BOOL_Unmarshal(&tpmEst, buffer, size); if (rc == TPM_RC_SUCCESS) { if (tpmEst) _rpc__Signal_SetTPMEstablished(); else _rpc__Signal_ResetTPMEstablished(); } } #if defined TPM_FAIL_C || defined GLOBAL_C || 1 needs_block = TRUE; #else needs_block = FALSE; #endif if (rc == TPM_RC_SUCCESS) { BLOCK_SKIP_READ(skip_fail, needs_block, buffer, size, "Volatile state", "s_failFunction"); } #if defined TPM_FAIL_C || defined GLOBAL_C || 1 /* appended in v2 */ if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&s_failFunction, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&s_failLine, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&s_failCode, buffer, size); } #endif skip_fail: #ifndef HARDWARE_CLOCK needs_block = TRUE; #else needs_block = FALSE; #endif if (rc == TPM_RC_SUCCESS) { BLOCK_SKIP_READ(skip_hardware_clock, needs_block, buffer, size, "Volatile state", "s_realTimePrevious"); } #ifndef HARDWARE_CLOCK if (rc == TPM_RC_SUCCESS) { rc = UINT64_Unmarshal(&tmp_uint64, buffer, size); s_realTimePrevious = tmp_uint64; } if (rc == TPM_RC_SUCCESS) { rc = UINT64_Unmarshal(&tmp_uint64, buffer, size); s_tpmTime = tmp_uint64; } #endif skip_hardware_clock: if (rc == TPM_RC_SUCCESS) { rc = BOOL_Unmarshal(&s_timerReset, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = BOOL_Unmarshal(&s_timerStopped, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&s_adjustRate, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT64_Unmarshal(&backthen, buffer, size); } /* version 2 starts having indicator for next versions that we can skip; this allows us to downgrade state */ if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { BLOCK_SKIP_READ(skip_future_versions, hdr.version >= 3, buffer, size, "Volatile State", "version 3 or later"); if (rc == TPM_RC_SUCCESS) { rc = VolatileState_TailV3_Unmarshal(buffer, size); } if (rc == TPM_RC_SUCCESS) { BLOCK_SKIP_READ(skip_future_versions, hdr.version >= 4, buffer, size, "Volatile State", "version 4 or later"); } if (rc == TPM_RC_SUCCESS) { rc = VolatileState_TailV4_Unmarshal(buffer, size); } if (rc == TPM_RC_SUCCESS) { BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, "Volatile State", "version 5 or later"); } /* future versions append here */ } skip_future_versions: /* keep marker at end: */ if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&tmp_uint32, buffer, size); if (rc == TPM_RC_SUCCESS) { if (tmp_uint32 != VOLATILE_STATE_MAGIC) { TPMLIB_LogTPM2Error("Invalid volatile state magic. " "Expected 0x%08x, got 0x%08x\n", VOLATILE_STATE_MAGIC, tmp_uint32); rc = TPM_RC_BAD_TAG; } } } if (rc == TPM_RC_SUCCESS) { BOOL timesAreRealtime = hdr.version <= 3; /* Before Rev148 (header version <= 3), times were reported in realtime; we need to account for this now */ ClockAdjustPostResume(backthen, timesAreRealtime); } return rc; } /******************************************************************** * The following is a list of compile-time constants that we verify against * when state is presented to us. Comparison operators allow us to verify * compile time constants' values against what we would accept when reading * state. So for example a value of 1024 for a buffer size that is read can * be compared against the value that this implementation has been compiled * with. In some case a 'less or equal' [LE] (1024 < 2048) may be acceptable * but that depends on the purpose of the compile time constant. The most * conservative approach is to force that the unmarshalled values are equal * [EQ] to the ones of this implementation. * * Meanings of comparison operators: * EQ: The read state must match the state the implementation would produce * The algorithm must have been enabled at the previously implementation * and at the current implementation; or it must have been disabled at * both * * LE: The read state may have been written by a version that did not * implement an algorithm ('0') but the current implementation does * implement it ('1'); this does NOT allow an implementation to accept * the state anymore if the state was written by an implementation that * implemented it ('1') but the current implementation does not im- * plement it * * DONTCARE: Implementation that wrote the state can either have implemented * an algorithm or not and implementation reading the state may * also either implement it or not */ static const struct _entry { UINT32 constant; char *name; enum CompareOp { EQ, LE, GE, DONTCARE } cmp; } pa_compile_constants[] = { #define COMPILE_CONSTANT(CONST, CMP) \ .constant = CONST, .name = #CONST, .cmp = CMP { COMPILE_CONSTANT(ALG_RSA, EQ) }, { COMPILE_CONSTANT(ALG_SHA1, EQ) }, { COMPILE_CONSTANT(ALG_HMAC, EQ) }, { COMPILE_CONSTANT(ALG_TDES, LE) }, { COMPILE_CONSTANT(ALG_AES, EQ) }, { COMPILE_CONSTANT(ALG_MGF1, EQ) }, { COMPILE_CONSTANT(ALG_XOR, EQ) }, { COMPILE_CONSTANT(ALG_KEYEDHASH, EQ) }, { COMPILE_CONSTANT(ALG_SHA256, EQ) }, { COMPILE_CONSTANT(ALG_SHA384, EQ) }, { COMPILE_CONSTANT(ALG_SHA512, EQ) }, { COMPILE_CONSTANT(ALG_SM3_256, EQ) }, { COMPILE_CONSTANT(ALG_SM4, EQ) }, { COMPILE_CONSTANT(ALG_RSASSA, EQ) }, { COMPILE_CONSTANT(ALG_RSAES, EQ) }, { COMPILE_CONSTANT(ALG_RSAPSS, EQ) }, { COMPILE_CONSTANT(ALG_OAEP, EQ) }, { COMPILE_CONSTANT(ALG_ECC, EQ) }, { COMPILE_CONSTANT(ALG_ECDH, EQ) }, { COMPILE_CONSTANT(ALG_ECDSA, EQ) }, { COMPILE_CONSTANT(ALG_ECDAA, EQ) }, { COMPILE_CONSTANT(ALG_SM2, LE) }, { COMPILE_CONSTANT(ALG_ECSCHNORR, EQ) }, { COMPILE_CONSTANT(ALG_ECMQV, LE) }, { COMPILE_CONSTANT(ALG_SYMCIPHER, EQ) }, { COMPILE_CONSTANT(ALG_KDF1_SP800_56A, EQ) }, { COMPILE_CONSTANT(ALG_KDF2, LE) }, { COMPILE_CONSTANT(ALG_KDF1_SP800_108, EQ) }, { COMPILE_CONSTANT(ALG_CMAC, LE) }, { COMPILE_CONSTANT(ALG_CTR, EQ) }, { COMPILE_CONSTANT(ALG_OFB, EQ) }, { COMPILE_CONSTANT(ALG_CBC, EQ) }, { COMPILE_CONSTANT(ALG_CFB, EQ) }, { COMPILE_CONSTANT(ALG_ECB, EQ) }, { COMPILE_CONSTANT(MAX_RSA_KEY_BITS, LE) }, /* old: 2048 */ { COMPILE_CONSTANT(MAX_TDES_KEY_BITS, EQ) }, { COMPILE_CONSTANT(MAX_AES_KEY_BITS, EQ) }, { COMPILE_CONSTANT(128, EQ) }, /* MAX_SM4_KEY_BITS in older code was 128 also with SM4 not active */ { COMPILE_CONSTANT(128, EQ) }, /* MAX_CAMELLIA_KEY_BITS in older code was 128 also with CAMELLIA not active */ { COMPILE_CONSTANT(ECC_NIST_P192, LE) }, { COMPILE_CONSTANT(ECC_NIST_P224, LE) }, { COMPILE_CONSTANT(ECC_NIST_P256, LE) }, { COMPILE_CONSTANT(ECC_NIST_P384, LE) }, { COMPILE_CONSTANT(ECC_NIST_P521, LE) }, { COMPILE_CONSTANT(ECC_BN_P256, LE) }, { COMPILE_CONSTANT(ECC_BN_P638, LE) }, { COMPILE_CONSTANT(ECC_SM2_P256, LE) }, { COMPILE_CONSTANT(MAX_ECC_KEY_BITS, LE) }, { COMPILE_CONSTANT(4, EQ) }, /* was: HASH_ALIGNMENT, which is not relevant */ { COMPILE_CONSTANT(SYM_ALIGNMENT, EQ) }, { COMPILE_CONSTANT(IMPLEMENTATION_PCR, EQ) }, { COMPILE_CONSTANT(PLATFORM_PCR, EQ) }, { COMPILE_CONSTANT(DRTM_PCR, EQ) }, { COMPILE_CONSTANT(HCRTM_PCR, EQ) }, { COMPILE_CONSTANT(NUM_LOCALITIES, EQ) }, { COMPILE_CONSTANT(MAX_HANDLE_NUM, EQ) }, { COMPILE_CONSTANT(MAX_ACTIVE_SESSIONS, EQ) }, { COMPILE_CONSTANT(MAX_LOADED_SESSIONS, EQ) }, { COMPILE_CONSTANT(MAX_SESSION_NUM, EQ) }, { COMPILE_CONSTANT(MAX_LOADED_OBJECTS, EQ) }, { COMPILE_CONSTANT(MIN_EVICT_OBJECTS, LE) }, { COMPILE_CONSTANT(NUM_POLICY_PCR_GROUP, EQ) }, { COMPILE_CONSTANT(NUM_AUTHVALUE_PCR_GROUP, EQ) }, { COMPILE_CONSTANT(MAX_CONTEXT_SIZE, LE) }, /* old: 2474 */ { COMPILE_CONSTANT(MAX_DIGEST_BUFFER, EQ) }, { COMPILE_CONSTANT(MAX_NV_INDEX_SIZE, EQ) }, { COMPILE_CONSTANT(MAX_NV_BUFFER_SIZE, EQ) }, { COMPILE_CONSTANT(MAX_CAP_BUFFER, EQ) }, { COMPILE_CONSTANT(NV_MEMORY_SIZE, LE) }, { COMPILE_CONSTANT(MIN_COUNTER_INDICES, EQ) }, { COMPILE_CONSTANT(NUM_STATIC_PCR, EQ) }, { COMPILE_CONSTANT(MAX_ALG_LIST_SIZE, EQ) }, { COMPILE_CONSTANT(PRIMARY_SEED_SIZE, EQ) }, #if CONTEXT_ENCRYPT_ALGORITHM == AES #define CONTEXT_ENCRYPT_ALGORITHM_ TPM_ALG_AES #endif { COMPILE_CONSTANT(CONTEXT_ENCRYPT_ALGORITHM_, EQ) }, { COMPILE_CONSTANT(NV_CLOCK_UPDATE_INTERVAL, EQ) }, { COMPILE_CONSTANT(NUM_POLICY_PCR, EQ) }, { COMPILE_CONSTANT(ORDERLY_BITS, EQ) }, { COMPILE_CONSTANT(MAX_SYM_DATA, EQ) }, { COMPILE_CONSTANT(MAX_RNG_ENTROPY_SIZE, EQ) }, { COMPILE_CONSTANT(RAM_INDEX_SPACE, EQ) }, { COMPILE_CONSTANT(RSA_DEFAULT_PUBLIC_EXPONENT, EQ) }, { COMPILE_CONSTANT(ENABLE_PCR_NO_INCREMENT, EQ) }, { COMPILE_CONSTANT(CRT_FORMAT_RSA, EQ) }, { COMPILE_CONSTANT(VENDOR_COMMAND_COUNT, EQ) }, { COMPILE_CONSTANT(MAX_VENDOR_BUFFER_SIZE, EQ) }, { COMPILE_CONSTANT(TPM_MAX_DERIVATION_BITS, EQ) }, { COMPILE_CONSTANT(PROOF_SIZE, EQ) }, { COMPILE_CONSTANT(HASH_COUNT, EQ) }, /* added for PA_COMPILE_CONSTANTS_VERSION == 3 */ { COMPILE_CONSTANT(AES_128, LE) }, { COMPILE_CONSTANT(AES_192, LE) }, { COMPILE_CONSTANT(AES_256, LE) }, { COMPILE_CONSTANT(SM4_128, LE) }, { COMPILE_CONSTANT(ALG_CAMELLIA, LE) }, { COMPILE_CONSTANT(CAMELLIA_128, LE) }, { COMPILE_CONSTANT(CAMELLIA_192, LE) }, { COMPILE_CONSTANT(CAMELLIA_256, LE) }, { COMPILE_CONSTANT(ALG_SHA3_256, LE) }, { COMPILE_CONSTANT(ALG_SHA3_384, LE) }, { COMPILE_CONSTANT(ALG_SHA3_512, LE) }, { COMPILE_CONSTANT(RSA_1024, LE) }, { COMPILE_CONSTANT(RSA_2048, LE) }, { COMPILE_CONSTANT(RSA_3072, LE) }, { COMPILE_CONSTANT(RSA_4096, LE) }, { COMPILE_CONSTANT(RSA_16384, LE) }, { COMPILE_CONSTANT(RH_ACT_0, LE) }, { COMPILE_CONSTANT(RH_ACT_1, LE) }, { COMPILE_CONSTANT(RH_ACT_2, LE) }, { COMPILE_CONSTANT(RH_ACT_3, LE) }, { COMPILE_CONSTANT(RH_ACT_4, LE) }, { COMPILE_CONSTANT(RH_ACT_5, LE) }, { COMPILE_CONSTANT(RH_ACT_6, LE) }, { COMPILE_CONSTANT(RH_ACT_7, LE) }, { COMPILE_CONSTANT(RH_ACT_8, LE) }, { COMPILE_CONSTANT(RH_ACT_9, LE) }, { COMPILE_CONSTANT(RH_ACT_A, LE) }, { COMPILE_CONSTANT(RH_ACT_B, LE) }, { COMPILE_CONSTANT(RH_ACT_C, LE) }, { COMPILE_CONSTANT(RH_ACT_D, LE) }, { COMPILE_CONSTANT(RH_ACT_E, LE) }, { COMPILE_CONSTANT(RH_ACT_F, LE) }, }; static TPM_RC UINT32_Unmarshal_CheckConstant(BYTE **buffer, INT32 *size, UINT32 constant, const char *name, enum CompareOp cmp, UINT16 struct_version) { TPM_RC rc = TPM_RC_SUCCESS; UINT32 value; const char *op = NULL; if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&value, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (cmp) { case EQ: if (!(constant == value)) op = "="; break; case LE: if (!(value <= constant)) op = "<="; break; case GE: if (!(value >= constant)) op = ">="; break; case DONTCARE: break; } if (op) { TPMLIB_LogTPM2Error("Unexpected value for %s; " "its value %d is not %s %d; " "(version: %u)\n", name, value, op, constant, struct_version); rc = TPM_RC_BAD_PARAMETER; } } return rc; } #define PA_COMPILE_CONSTANTS_MAGIC 0xc9ea6431 #define PA_COMPILE_CONSTANTS_VERSION 3 /* Marshal compile-time constants related to persistent-all state */ static UINT32 PACompileConstants_Marshal(BYTE **buffer, INT32 *size) { unsigned i; UINT32 written, tmp_uint32; UINT32 array_size = ARRAY_SIZE(pa_compile_constants); BLOCK_SKIP_INIT; written = NV_HEADER_Marshal(buffer, size, PA_COMPILE_CONSTANTS_VERSION, PA_COMPILE_CONSTANTS_MAGIC, 1); written += UINT32_Marshal(&array_size, buffer, size); for (i = 0; i < array_size; i++) { tmp_uint32 = pa_compile_constants[i].constant; written += UINT32_Marshal(&tmp_uint32, buffer, size); } written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); /* future versions append below this line */ BLOCK_SKIP_WRITE_POP(size); BLOCK_SKIP_WRITE_CHECK; return written; } static TPM_RC PACompileConstants_Unmarshal(BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; unsigned i; NV_HEADER hdr; UINT32 array_size; UINT32 exp_array_size = 0; if (rc == TPM_RC_SUCCESS) { rc = NV_HEADER_Unmarshal(&hdr, buffer, size, PA_COMPILE_CONSTANTS_VERSION, PA_COMPILE_CONSTANTS_MAGIC); } if (rc == TPM_RC_SUCCESS) { switch (hdr.version) { case 1: case 2: /* PA_COMPILE_CONSTANTS_VERSION 1 and 2 had 88 entries */ exp_array_size = 88; break; case 3: /* PA_COMPILE_CONSTANTS_VERSION 3 had 104 entries */ exp_array_size = 120; break; default: /* we don't suport anything newer - no downgrade */ TPMLIB_LogTPM2Error("Unsupported PA_COMPILE_CONSTANTS version %d. " "Supporting up to version %d.\n", hdr.version, PA_COMPILE_CONSTANTS_VERSION); rc = TPM_RC_BAD_VERSION; } } if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&array_size, buffer, size); } if (rc == TPM_RC_SUCCESS && array_size != exp_array_size) { TPMLIB_LogTPM2Error("PA_COMPILE_CONSTANTS v%d has non-matching number of " "elements; found %u, expected %u\n", hdr.version, array_size, exp_array_size); } for (i = 0; rc == TPM_RC_SUCCESS && i < exp_array_size; i++) rc = UINT32_Unmarshal_CheckConstant( buffer, size, pa_compile_constants[i].constant, pa_compile_constants[i].name, pa_compile_constants[i].cmp, hdr.version); /* version 2 starts having indicator for next versions that we can skip; this allows us to downgrade state */ if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, "PA_COMPILE_CONSTANTS", "version 3 or later"); /* future versions nest-append here */ } skip_future_versions: /* keep marker at end: */ return rc; } #define PERSISTENT_DATA_MAGIC 0x12213443 #define PERSISTENT_DATA_VERSION 4 static UINT16 PERSISTENT_DATA_Marshal(PERSISTENT_DATA *data, BYTE **buffer, INT32 *size) { UINT16 written; UINT16 array_size; UINT8 clocksize; BOOL has_block; BLOCK_SKIP_INIT; written = NV_HEADER_Marshal(buffer, size, PERSISTENT_DATA_VERSION, PERSISTENT_DATA_MAGIC, 4); written += BOOL_Marshal(&data->disableClear, buffer, size); written += TPM_ALG_ID_Marshal(&data->ownerAlg, buffer, size); written += TPM_ALG_ID_Marshal(&data->endorsementAlg, buffer, size); written += TPM_ALG_ID_Marshal(&data->lockoutAlg, buffer, size); written += TPM2B_DIGEST_Marshal(&data->ownerPolicy, buffer, size); written += TPM2B_DIGEST_Marshal(&data->endorsementPolicy, buffer, size); written += TPM2B_DIGEST_Marshal(&data->lockoutPolicy, buffer, size); written += TPM2B_AUTH_Marshal(&data->ownerAuth, buffer, size); written += TPM2B_AUTH_Marshal(&data->endorsementAuth, buffer, size); written += TPM2B_AUTH_Marshal(&data->lockoutAuth, buffer, size); written += TPM2B_Marshal(&data->EPSeed.b, sizeof(data->EPSeed.t.buffer), buffer, size); written += TPM2B_Marshal(&data->SPSeed.b, sizeof(data->SPSeed.t.buffer), buffer, size); written += TPM2B_Marshal(&data->PPSeed.b, sizeof(data->PPSeed.t.buffer), buffer, size); written += TPM2B_PROOF_Marshal(&data->phProof, buffer, size); written += TPM2B_PROOF_Marshal(&data->shProof, buffer, size); written += TPM2B_PROOF_Marshal(&data->ehProof, buffer, size); written += UINT64_Marshal(&data->totalResetCount, buffer, size); written += UINT32_Marshal(&data->resetCount, buffer, size); #if defined NUM_POLICY_PCR_GROUP && NUM_POLICY_PCR_GROUP > 0 has_block = TRUE; #else has_block = FALSE; #endif written += BLOCK_SKIP_WRITE_PUSH(has_block, buffer, size); #if defined NUM_POLICY_PCR_GROUP && NUM_POLICY_PCR_GROUP > 0 written += PCR_POLICY_Marshal(&data->pcrPolicies, buffer, size); #endif BLOCK_SKIP_WRITE_POP(size); written += TPML_PCR_SELECTION_Marshal(&data->pcrAllocated, buffer, size); /* ppList may grow */ array_size = sizeof(data->ppList); written += UINT16_Marshal(&array_size, buffer, size); written += Array_Marshal(&data->ppList[0], array_size, buffer, size); written += UINT32_Marshal(&data->failedTries, buffer, size); written += UINT32_Marshal(&data->maxTries, buffer, size); written += UINT32_Marshal(&data->recoveryTime, buffer, size); written += UINT32_Marshal(&data->lockoutRecovery, buffer, size); written += BOOL_Marshal(&data->lockOutAuthEnabled, buffer, size); written += UINT16_Marshal(&data->orderlyState, buffer, size); /* auditCommands may grow */ array_size = sizeof(data->auditCommands); written += UINT16_Marshal(&array_size, buffer, size); written += Array_Marshal(&data->auditCommands[0], array_size, buffer, size); written += TPM_ALG_ID_Marshal(&data->auditHashAlg, buffer, size); written += UINT64_Marshal(&data->auditCounter, buffer, size); written += UINT32_Marshal(&data->algorithmSet, buffer, size); written += UINT32_Marshal(&data->firmwareV1, buffer, size); written += UINT32_Marshal(&data->firmwareV2, buffer, size); #if CLOCK_STOPS clocksize = sizeof(UINT64); written += UINT8_Marshal(&clocksize, buffer, size); written += UINT64_Marshal(&data->timeEpoch, buffer, size); #else clocksize = sizeof(UINT32); written += UINT8_Marshal(&clocksize, buffer, size); written += UINT32_Marshal(&data->timeEpoch, buffer, size); #endif written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); /* there's a 'shadow' pcrAllocated as well */ written += TPML_PCR_SELECTION_Marshal(&gp.pcrAllocated, buffer, size); written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); written += SEED_COMPAT_LEVEL_Marshal(&data->EPSeedCompatLevel, buffer, size); written += SEED_COMPAT_LEVEL_Marshal(&data->SPSeedCompatLevel, buffer, size); written += SEED_COMPAT_LEVEL_Marshal(&data->PPSeedCompatLevel, buffer, size); written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); /* future versions append below this line */ BLOCK_SKIP_WRITE_POP(size); BLOCK_SKIP_WRITE_POP(size); BLOCK_SKIP_WRITE_POP(size); BLOCK_SKIP_WRITE_CHECK; return written; } static TPM_RC PERSISTENT_DATA_Unmarshal(PERSISTENT_DATA *data, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; NV_HEADER hdr; UINT16 array_size; UINT8 clocksize; BOOL needs_block; if (rc == TPM_RC_SUCCESS) { rc = NV_HEADER_Unmarshal(&hdr, buffer, size, PERSISTENT_DATA_VERSION, PERSISTENT_DATA_MAGIC); } if (rc == TPM_RC_SUCCESS) { rc = BOOL_Unmarshal(&data->disableClear, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM_ALG_ID_Unmarshal(&data->ownerAlg, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM_ALG_ID_Unmarshal(&data->endorsementAlg, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM_ALG_ID_Unmarshal(&data->lockoutAlg, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_DIGEST_Unmarshal(&data->ownerPolicy, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_DIGEST_Unmarshal(&data->endorsementPolicy, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_DIGEST_Unmarshal(&data->lockoutPolicy, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_AUTH_Unmarshal(&data->ownerAuth, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_AUTH_Unmarshal(&data->endorsementAuth, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_AUTH_Unmarshal(&data->lockoutAuth, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_Unmarshal(&data->EPSeed.b, PRIMARY_SEED_SIZE, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_Unmarshal(&data->SPSeed.b, PRIMARY_SEED_SIZE, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_Unmarshal(&data->PPSeed.b, PRIMARY_SEED_SIZE, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_PROOF_Unmarshal(&data->phProof, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_PROOF_Unmarshal(&data->shProof, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_PROOF_Unmarshal(&data->ehProof, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT64_Unmarshal(&data->totalResetCount, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&data->resetCount, buffer, size); } #if defined NUM_POLICY_PCR_GROUP && NUM_POLICY_PCR_GROUP > 0 needs_block = TRUE; #else needs_block = FALSE; #endif if (rc == TPM_RC_SUCCESS) { BLOCK_SKIP_READ(skip_num_policy_pcr_group, needs_block, buffer, size, "PERSISTENT_DATA", "pcrPolicies"); } #if defined NUM_POLICY_PCR_GROUP && NUM_POLICY_PCR_GROUP > 0 if (rc == TPM_RC_SUCCESS) { rc = PCR_POLICY_Unmarshal(&data->pcrPolicies, buffer, size); } #endif skip_num_policy_pcr_group: if (rc == TPM_RC_SUCCESS) { rc = TPML_PCR_SELECTION_Unmarshal(&data->pcrAllocated, buffer, size); shadow.pcrAllocated = data->pcrAllocated; shadow.pcrAllocatedIsNew = TRUE; } /* ppList array may not be our size */ if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(&array_size, buffer, size); } if (rc == TPM_RC_SUCCESS) { BYTE buf[array_size]; rc = Array_Unmarshal(buf, array_size, buffer, size); memcpy(data->ppList, buf, MIN(array_size, sizeof(data->ppList))); } if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&data->failedTries, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&data->maxTries, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&data->recoveryTime, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&data->lockoutRecovery, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = BOOL_Unmarshal(&data->lockOutAuthEnabled, buffer, size); } if (rc == TPM_RC_SUCCESS) { /* TPM_SU_Unmarshal returns error if value is 0 */ rc = UINT16_Unmarshal(&data->orderlyState, buffer, size); } /* auditCommands array may not be our size */ if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(&array_size, buffer, size); } if (rc == TPM_RC_SUCCESS) { BYTE buf[array_size]; rc = Array_Unmarshal(buf, array_size, buffer, size); memcpy(data->auditCommands, buf, MIN(array_size, sizeof(data->auditCommands))); } if (rc == TPM_RC_SUCCESS) { rc = TPM_ALG_ID_Unmarshal(&data->auditHashAlg, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT64_Unmarshal(&data->auditCounter, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&data->algorithmSet, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&data->firmwareV1, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&data->firmwareV2, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT8_Unmarshal(&clocksize, buffer, size); } if (rc == TPM_RC_SUCCESS) { #if CLOCK_STOPS if (clocksize != sizeof(UINT64)) { TPMLIB_LogTPM2Error("Unexpected clocksize for epoch; " "Expected %u, got %u\n", sizeof(UINT64), clocksize); rc = TPM_RC_BAD_PARAMETER; } if (rc == TPM_RC_SUCCESS) { rc = UINT64_Unmarshal(&data->timeEpoch, buffer, size); } #else if (clocksize != sizeof(UINT32)) { TPMLIB_LogTPM2Error("Unexpected clocksize for epoch; " "Expected %zu, got %u\n", sizeof(UINT32), clocksize); rc = TPM_RC_BAD_PARAMETER; } if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&data->timeEpoch, buffer, size); } #endif } /* default values before conditional block */ data->EPSeedCompatLevel = SEED_COMPAT_LEVEL_ORIGINAL; data->SPSeedCompatLevel = SEED_COMPAT_LEVEL_ORIGINAL; data->PPSeedCompatLevel = SEED_COMPAT_LEVEL_ORIGINAL; /* version 2 starts having indicator for next versions that we can skip; this allows us to downgrade state */ if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { BLOCK_SKIP_READ(skip_future_versions, hdr.version >= 3, buffer, size, "PERSISTENT_DATA", "version 3 or later"); if (rc == TPM_RC_SUCCESS) { rc = TPML_PCR_SELECTION_Unmarshal(&shadow.pcrAllocated, buffer, size); } if (rc == TPM_RC_SUCCESS) { BLOCK_SKIP_READ(skip_future_versions, hdr.version >= 4, buffer, size, "PERSISTENT_DATA", "version 4 or later"); } if (rc == TPM_RC_SUCCESS) { rc = SEED_COMPAT_LEVEL_Unmarshal(&data->EPSeedCompatLevel, buffer, size, "EPSeed"); } if (rc == TPM_RC_SUCCESS) { rc = SEED_COMPAT_LEVEL_Unmarshal(&data->SPSeedCompatLevel, buffer, size, "SPSeed"); } if (rc == TPM_RC_SUCCESS) { rc = SEED_COMPAT_LEVEL_Unmarshal(&data->PPSeedCompatLevel, buffer, size, "PPSeed"); } if (rc == TPM_RC_SUCCESS) { BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, "PERSISTENT_DATA", "version 5 or later"); } /* future versions nest-append here */ } skip_future_versions: if (rc != TPM_RC_SUCCESS) { TPMLIB_LogTPM2Error("Failed to unmarshal PERSISTENT_DATA version %u\n", hdr.version); } return rc; } #define INDEX_ORDERLY_RAM_VERSION 2 #define INDEX_ORDERLY_RAM_MAGIC 0x5346feab static UINT32 INDEX_ORDERLY_RAM_Marshal(void *array, size_t array_size, BYTE **buffer, INT32 *size) { UINT16 written; NV_RAM_HEADER nrh, *nrhp; UINT16 offset = 0; UINT16 datasize; UINT32 sourceside_size = array_size; BLOCK_SKIP_INIT; written = NV_HEADER_Marshal(buffer, size, INDEX_ORDERLY_RAM_VERSION, INDEX_ORDERLY_RAM_MAGIC, 1); /* the size of the array we are using here */ written += UINT32_Marshal(&sourceside_size, buffer, size); while (TRUE) { nrhp = array + offset; /* nrhp may point to misaligned address (ubsan), so use 'nrh'; first access only 'size' */ memcpy(&nrh, nrhp, sizeof(nrh.size)); /* write the NVRAM header; nrh->size holds the complete size including data; nrh->size = 0 indicates the end */ written += UINT32_Marshal(&nrh.size, buffer, size); if (nrh.size == 0) break; /* copy the entire structure now; ubsan does not allow 'nrh = *nrhp' */ memcpy(&nrh, nrhp, sizeof(nrh)); written += TPM_HANDLE_Marshal(&nrh.handle, buffer, size); written += TPMA_NV_Marshal(&nrh.attributes, buffer, size); if (offset + nrh.size > array_size) { TPMLIB_LogTPM2Error("INDEX_ORDERLY_RAM: nrh->size corrupted: %d\n", nrh.size); break; } /* write data size before array */ if (nrh.size < sizeof(NV_RAM_HEADER)) { TPMLIB_LogTPM2Error( "INDEX_ORDERLY_RAM: nrh->size < sizeof(NV_RAM_HEADER): %d < %zu\n", (int)nrh.size, sizeof(NV_RAM_HEADER)); break; } datasize = nrh.size - sizeof(NV_RAM_HEADER); written += UINT16_Marshal(&datasize, buffer, size); if (datasize > 0) { /* append the data */ written += Array_Marshal(array + offset + sizeof(NV_RAM_HEADER), datasize, buffer, size); } offset += nrh.size; if (offset + sizeof(NV_RAM_HEADER) > array_size) { /* nothing will fit anymore and there won't be a 0-sized * terminating node (@1). */ break; } } written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); /* future versions append below this line */ BLOCK_SKIP_WRITE_POP(size); BLOCK_SKIP_WRITE_CHECK; return written; } static TPM_RC INDEX_ORDERLY_RAM_Unmarshal(void *array, size_t array_size, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; NV_HEADER hdr; NV_RAM_HEADER nrh, *nrhp; UINT16 offset = 0; UINT16 datasize = 0; UINT32 sourceside_size; if (rc == TPM_RC_SUCCESS) { rc = NV_HEADER_Unmarshal(&hdr, buffer, size, INDEX_ORDERLY_RAM_VERSION, INDEX_ORDERLY_RAM_MAGIC); } if (rc == TPM_RC_SUCCESS) { /* get the size of the array on the source side we can accommodate different sizes when rebuilding but if it doesn't fit we'll error out and report the sizes */ rc = UINT32_Unmarshal(&sourceside_size, buffer, size); } while (rc == TPM_RC_SUCCESS) { memset(&nrh, 0, sizeof(nrh)); /* coverity */ /* nrhp may point to misaligned address (ubsan) * we read 'into' nrh and copy to nrhp at end */ nrhp = array + offset; if (offset + sizeof(NV_RAM_HEADER) > sourceside_size) { /* this case can occur with the previous entry filling up the * space; in this case there will not be a 0-sized terminating * node (see @1 above). We clear the rest of our space. */ if (array_size > offset) memset(nrhp, 0, array_size - offset); break; } /* write the NVRAM header; nrh->size holds the complete size including data; nrh->size = 0 indicates the end */ if (offset + sizeof(nrh.size) > array_size) { offset += sizeof(nrh.size); goto exit_size; } if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&nrh.size, buffer, size); if (rc == TPM_RC_SUCCESS && nrh.size == 0) { memcpy(nrhp, &nrh, sizeof(nrh.size)); break; } } if (offset + sizeof(NV_RAM_HEADER) > array_size) { offset += sizeof(NV_RAM_HEADER); goto exit_size; } if (rc == TPM_RC_SUCCESS) { rc = TPM_HANDLE_Unmarshal(&nrh.handle, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPMA_NV_Unmarshal(&nrh.attributes, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(&datasize, buffer, size); } if (offset + sizeof(NV_RAM_HEADER) + datasize > array_size) { offset += sizeof(NV_RAM_HEADER) + datasize; goto exit_size; } if (rc == TPM_RC_SUCCESS && datasize > 0) { /* append the data */ rc = Array_Unmarshal(array + offset + sizeof(NV_RAM_HEADER), datasize, buffer, size); } if (rc == TPM_RC_SUCCESS) { /* fix up size in case it is architecture-dependent */ nrh.size = sizeof(nrh) + datasize; offset += nrh.size; /* copy header into possibly misaligned address in NVRAM */ *nrhp = nrh; } } /* version 2 starts having indicator for next versions that we can skip; this allows us to downgrade state */ if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, "INDEX_ORDERLY_RAM", "version 3 or later"); /* future versions nest-append here */ } skip_future_versions: return rc; exit_size: TPMLIB_LogTPM2Error("INDEX_ORDERLY_RAM:" "Insufficient space to write to offset %u;" "Source had %u bytes, we have %zu bytes.\n", offset, sourceside_size, array_size); return TPM_RC_SIZE; } static void USER_NVRAM_Display(const char *msg) { NV_REF entryRef = NV_USER_DYNAMIC; UINT32 entrysize; UINT64 offset = 0; TPM_HANDLE handle; UINT32 datasize; NV_INDEX nvi; OBJECT obj; UINT64 maxCount; fprintf(stderr, "USER_NVRAM contents %s:\n", msg); while (TRUE) { /* 1st: entrysize */ NvRead(&entrysize, entryRef, sizeof(entrysize)); fprintf(stderr, " offset: %5"PRIu32" entry size: %5u ", (UINT32)(entryRef - NV_USER_DYNAMIC), entrysize); offset = sizeof(UINT32); if (entrysize == 0) break; /* 2nd: the handle -- it will tell us what datatype this is */ NvRead(&handle, entryRef + offset, sizeof(handle)); fprintf(stderr, "handle: 0x%08x ", handle); switch (HandleGetType(handle)) { case TPM_HT_NV_INDEX: fprintf(stderr, " (NV_INDEX) "); /* NV_INDEX has the index again at offset 0! */ NvReadNvIndexInfo(entryRef + offset, &nvi); offset += sizeof(nvi); datasize = entrysize - sizeof(UINT32) - sizeof(nvi); fprintf(stderr, " datasize: %u\n",datasize); break; break; case TPM_HT_PERSISTENT: fprintf(stderr, " (PERSISTENT)"); offset += sizeof(handle); NvRead(&obj, entryRef + offset, sizeof(obj)); offset += sizeof(obj); fprintf(stderr, " sizeof(obj): %zu\n", sizeof(obj)); break; default: TPMLIB_LogTPM2Error("USER_NVRAM: Corrupted handle: %08x\n", handle); } /* advance to next entry */ entryRef += entrysize; } fprintf(stderr, "\n"); NvRead(&maxCount, entryRef + offset, sizeof(maxCount)); fprintf(stderr, " maxCount: %"PRIu64"\n", maxCount); fprintf(stderr, "-----------------------------\n"); } #define USER_NVRAM_VERSION 2 #define USER_NVRAM_MAGIC 0x094f22c3 static UINT32 USER_NVRAM_Marshal(BYTE **buffer, INT32 *size) { UINT32 written; UINT32 entrysize; UINT64 offset; NV_REF entryRef = NV_USER_DYNAMIC; NV_INDEX nvi; UINT64 maxCount; TPM_HANDLE handle; OBJECT obj; UINT32 datasize; UINT64 sourceside_size = NV_USER_DYNAMIC_END - NV_USER_DYNAMIC; BLOCK_SKIP_INIT; if (FALSE) USER_NVRAM_Display("before marshalling"); written = NV_HEADER_Marshal(buffer, size, USER_NVRAM_VERSION, USER_NVRAM_MAGIC, 1); written += UINT64_Marshal(&sourceside_size, buffer, size); while (TRUE) { /* 1st: entrysize */ NvRead(&entrysize, entryRef, sizeof(entrysize)); offset = sizeof(UINT32); /* entrysize is in native format now */ written += UINT32_Marshal(&entrysize, buffer, size); if (entrysize == 0) break; /* 2nd: the handle -- it will tell us what datatype this is */ NvRead(&handle, entryRef + offset, sizeof(handle)); written += TPM_HANDLE_Marshal(&handle, buffer, size); switch (HandleGetType(handle)) { case TPM_HT_NV_INDEX: /* NV_INDEX has the index again at offset 0! */ NvReadNvIndexInfo(entryRef + offset, &nvi); offset += sizeof(nvi); written += NV_INDEX_Marshal(&nvi, buffer, size); /* after that: bulk data */ datasize = entrysize - sizeof(UINT32) - sizeof(nvi); written += UINT32_Marshal(&datasize, buffer, size); if (datasize > 0) { BYTE buf[datasize]; NvRead(buf, entryRef + offset, datasize); written += Array_Marshal(buf, datasize, buffer, size); } break; case TPM_HT_PERSISTENT: offset += sizeof(handle); NvRead(&obj, entryRef + offset, sizeof(obj)); offset += sizeof(obj); written += ANY_OBJECT_Marshal(&obj, buffer, size); break; default: TPMLIB_LogTPM2Error("USER_NVRAM: Corrupted handle: %08x\n", handle); } /* advance to next entry */ entryRef += entrysize; } NvRead(&maxCount, entryRef + offset, sizeof(maxCount)); written += UINT64_Marshal(&maxCount, buffer, size); written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); /* future versions append below this line */ BLOCK_SKIP_WRITE_POP(size); BLOCK_SKIP_WRITE_CHECK; return written; } /* * USER_NVRAM_Unmarshal: * * Unmarshal the byte stream directly into the NVRAM. Ensure that the * the data fit into the user NVRAM before writing them. * * This function fails if there's not enough NVRAM to write the data into * or if an unknown handle type was encountered. */ static TPM_RC USER_NVRAM_Unmarshal(BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; NV_HEADER hdr; NV_REF entryRef = NV_USER_DYNAMIC; UINT32 entrysize; UINT64 offset, o = 0; NV_INDEX nvi; UINT64 maxCount; TPM_HANDLE handle; OBJECT obj; UINT32 datasize = 0; UINT64 sourceside_size; UINT64 array_size = NV_USER_DYNAMIC_END - NV_USER_DYNAMIC; UINT64 entrysize_offset; if (rc == TPM_RC_SUCCESS) { rc = NV_HEADER_Unmarshal(&hdr, buffer, size, USER_NVRAM_VERSION, USER_NVRAM_MAGIC); } if (rc == TPM_RC_SUCCESS) { rc = UINT64_Unmarshal(&sourceside_size, buffer, size); } while (rc == TPM_RC_SUCCESS) { /* 1st: entrysize */ if (o + sizeof(UINT32) > array_size) { o += sizeof(UINT32); goto exit_size; } if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&entrysize, buffer, size); /* the entrysize also depends on the sizeof(nvi); we may have to update it if sizeof(nvi) changed between versions */ entrysize_offset = o; NvWrite(entryRef + o, sizeof(entrysize), &entrysize); offset = sizeof(UINT32); if (entrysize == 0) break; } /* 2nd: handle */ if (rc == TPM_RC_SUCCESS) { rc = TPM_HANDLE_Unmarshal(&handle, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (HandleGetType(handle)) { case TPM_HT_NV_INDEX: /* we need to read the handle again */ if (rc == TPM_RC_SUCCESS && o + offset + sizeof(nvi) > array_size) { o += offset + sizeof(nvi); goto exit_size; } if (rc == TPM_RC_SUCCESS) { rc = NV_INDEX_Unmarshal(&nvi, buffer, size); NvWrite(entryRef + o + offset, sizeof(nvi), &nvi); offset += sizeof(nvi); } if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&datasize, buffer, size); } if (rc == TPM_RC_SUCCESS) { /* datasize cannot exceed 64k + a few bytes */ if (datasize > (0x10000 + 0x100)) { TPMLIB_LogTPM2Error("datasize for NV_INDEX too " "large: %u\n", datasize); rc = TPM_RC_SIZE; } } if (rc == TPM_RC_SUCCESS && o + offset + datasize > array_size) { o += offset + datasize; goto exit_size; } if (rc == TPM_RC_SUCCESS && datasize > 0) { BYTE buf[datasize]; rc = Array_Unmarshal(buf, datasize, buffer, size); NvWrite(entryRef + o + offset, datasize, buf); offset += datasize; /* update the entry size; account for expanding nvi */ entrysize = sizeof(UINT32) + sizeof(nvi) + datasize; } break; case TPM_HT_PERSISTENT: if (rc == TPM_RC_SUCCESS && o + offset + sizeof(TPM_HANDLE) + sizeof(obj) > array_size) { o += offset + sizeof(TPM_HANDLE) + sizeof(obj); goto exit_size; } if (rc == TPM_RC_SUCCESS) { NvWrite(entryRef + o + offset, sizeof(handle), &handle); offset += sizeof(TPM_HANDLE); memset(&obj, 0, sizeof(obj)); rc = ANY_OBJECT_Unmarshal(&obj, buffer, size, true); NvWrite(entryRef + o + offset, sizeof(obj), &obj); offset += sizeof(obj); } entrysize = sizeof(UINT32) + sizeof(TPM_HANDLE) + sizeof(obj); break; default: TPMLIB_LogTPM2Error("USER_NVRAM: " "Read handle 0x%08x of unknown type\n", handle); rc = TPM_RC_HANDLE; } if (rc == TPM_RC_SUCCESS) { NvWrite(entryRef + entrysize_offset, sizeof(entrysize), &entrysize); } } if (rc == TPM_RC_SUCCESS) { o += offset; } } if (rc == TPM_RC_SUCCESS && o + offset + sizeof(UINT64) > array_size) { o += offset + sizeof(UINT64); goto exit_size; } if (rc == TPM_RC_SUCCESS) { rc = UINT64_Unmarshal(&maxCount, buffer, size); NvWrite(entryRef + o + offset, sizeof(maxCount), &maxCount); } /* version 2 starts having indicator for next versions that we can skip; this allows us to downgrade state */ if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, "USER_NVRAM", "version 3 or later"); /* future versions nest-append here */ } skip_future_versions: if (FALSE) USER_NVRAM_Display("after unmarshalling"); return rc; exit_size: TPMLIB_LogTPM2Error("USER_NVRAM:" "Insufficient space to write to offset %"PRIu64";" "Source had %"PRIu64" bytes, we have %"PRIu64" " "bytes.\n", o, sourceside_size, array_size); return TPM_RC_SIZE; } /* * Write out all persistent data by reading them from the NVRAM * and then writing them out. * * - PERSISTENT_DATA (NV_PERSISTENT_DATA) * - ORDERLY_DATA (NV_STATE_RESET_DATA) * - STATE_RESET_DATA (NV_STATE_RESET_DATA) * - STATE_CLEAR_DATA (NV_STATE_CLEAR_DATA) * - indexOrderlyRAM (NV_INDEX_RAM_DATA) * - NVRAM locations (NV_USER_DYNAMIC) */ #define PERSISTENT_ALL_VERSION 3 #define PERSISTENT_ALL_MAGIC 0xab364723 UINT32 PERSISTENT_ALL_Marshal(BYTE **buffer, INT32 *size) { UINT32 magic; PERSISTENT_DATA pd; ORDERLY_DATA od; STATE_RESET_DATA srd; STATE_CLEAR_DATA scd; UINT32 written = 0; BYTE indexOrderlyRam[sizeof(s_indexOrderlyRam)]; BLOCK_SKIP_INIT; BOOL writeSuState; NvRead(&pd, NV_PERSISTENT_DATA, sizeof(pd)); NvRead(&od, NV_ORDERLY_DATA, sizeof(od)); NvRead(&srd, NV_STATE_RESET_DATA, sizeof(srd)); NvRead(&scd, NV_STATE_CLEAR_DATA, sizeof(scd)); /* indexOrderlyRam was never endianess-converted; so it's native */ NvRead(indexOrderlyRam, NV_INDEX_RAM_DATA, sizeof(indexOrderlyRam)); written = NV_HEADER_Marshal(buffer, size, PERSISTENT_ALL_VERSION, PERSISTENT_ALL_MAGIC, 3); written += PACompileConstants_Marshal(buffer, size); written += PERSISTENT_DATA_Marshal(&pd, buffer, size); written += ORDERLY_DATA_Marshal(&od, buffer, size); writeSuState = (pd.orderlyState & TPM_SU_STATE_MASK) == TPM_SU_STATE; /* starting with v3 we only write STATE_RESET and STATE_CLEAR if needed */ if (writeSuState) { written += STATE_RESET_DATA_Marshal(&srd, buffer, size); written += STATE_CLEAR_DATA_Marshal(&scd, buffer, size); } written += INDEX_ORDERLY_RAM_Marshal(indexOrderlyRam, sizeof(indexOrderlyRam), buffer, size); written += USER_NVRAM_Marshal(buffer, size); written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); /* future versions append below this line */ BLOCK_SKIP_WRITE_POP(size); magic = PERSISTENT_ALL_MAGIC; written += UINT32_Marshal(&magic, buffer, size); BLOCK_SKIP_WRITE_CHECK; return written; } TPM_RC PERSISTENT_ALL_Unmarshal(BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; NV_HEADER hdr; PERSISTENT_DATA pd; ORDERLY_DATA od; STATE_RESET_DATA srd; STATE_CLEAR_DATA scd; BYTE indexOrderlyRam[sizeof(s_indexOrderlyRam)]; BOOL readSuState = false; memset(&pd, 0, sizeof(pd)); memset(&od, 0, sizeof(od)); memset(&srd, 0, sizeof(srd)); memset(&scd, 0, sizeof(scd)); memset(indexOrderlyRam, 0, sizeof(indexOrderlyRam)); if (rc == TPM_RC_SUCCESS) { rc = NV_HEADER_Unmarshal(&hdr, buffer, size, PERSISTENT_ALL_VERSION, PERSISTENT_ALL_MAGIC); } if (rc == TPM_RC_SUCCESS) { rc = PACompileConstants_Unmarshal(buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = PERSISTENT_DATA_Unmarshal(&pd, buffer, size); } if (rc == TPM_RC_SUCCESS) { if (hdr.version < 3) { /* STATE_RESET and STATE_CLEAR were always written before version 3 */ readSuState = true; } else { readSuState = (pd.orderlyState & TPM_SU_STATE_MASK) == TPM_SU_STATE; } rc = ORDERLY_DATA_Unmarshal(&od, buffer, size); } if (rc == TPM_RC_SUCCESS && readSuState) { rc = STATE_RESET_DATA_Unmarshal(&srd, buffer, size); } if (rc == TPM_RC_SUCCESS && readSuState) { rc = STATE_CLEAR_DATA_Unmarshal(&scd, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = INDEX_ORDERLY_RAM_Unmarshal(indexOrderlyRam, sizeof(indexOrderlyRam), buffer, size); } if (rc == TPM_RC_SUCCESS) { /* this will write it into NVRAM right away */ rc = USER_NVRAM_Unmarshal(buffer, size); /* if rc == TPM_RC_SUCCESS, we know that there is enough NVRAM to fit everything. */ } /* version 2 starts having indicator for next versions that we can skip; this allows us to downgrade state */ if (rc == TPM_RC_SUCCESS && hdr.version >= 2) { BLOCK_SKIP_READ(skip_future_versions, FALSE, buffer, size, "USER NVRAM", "version 3 or later"); /* future versions nest-append here */ } skip_future_versions: if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal_Check(&hdr.magic, PERSISTENT_ALL_MAGIC, buffer, size, "PERSISTENT_ALL_MAGIC after USER_NVRAM"); } if (rc == TPM_RC_SUCCESS) { NvWrite(NV_PERSISTENT_DATA, sizeof(pd), &pd); NvWrite(NV_ORDERLY_DATA, sizeof(od), &od); NvWrite(NV_STATE_RESET_DATA, sizeof(srd), &srd); NvWrite(NV_STATE_CLEAR_DATA, sizeof(scd), &scd); NvWrite(NV_INDEX_RAM_DATA, sizeof(indexOrderlyRam), indexOrderlyRam); } return rc; } void NVShadowRestore(void) { if (shadow.pcrAllocatedIsNew) { gp.pcrAllocated = shadow.pcrAllocated; shadow.pcrAllocatedIsNew = FALSE; } } libtpms-0.9.3/src/tpm2/NVMarshal.h000066400000000000000000000052261421143571500166620ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Marshalling and unmarshalling of state */ /* Written by Stefan Berger */ /* IBM Thomas J. Watson Research Center */ /* */ /* (c) Copyright IBM Corporation 2017,2018. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef NVMARSHAL_H #define NVMARSHAL_H #include #include "Tpm.h" #include "TpmTypes.h" #define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) UINT16 VolatileState_Marshal(BYTE **buffer, INT32 *size); TPM_RC VolatileState_Unmarshal(BYTE **buffer, INT32 *size); UINT32 PERSISTENT_ALL_Marshal(BYTE **buffer, INT32 *size); TPM_RC PERSISTENT_ALL_Unmarshal(BYTE **buffer, INT32 *size); void NVShadowRestore(void); UINT16 ANY_OBJECT_Marshal(OBJECT *data, BYTE **buffer, INT32 *size); TPM_RC ANY_OBJECT_Unmarshal(OBJECT *data, BYTE **buffer, INT32 *size, BOOL verbose); #endif /* NVMARSHAL_H */ libtpms-0.9.3/src/tpm2/NVMem.c000066400000000000000000000374041421143571500160070ustar00rootroot00000000000000/********************************************************************************/ /* */ /* NV read and write access methods */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: NVMem.c 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2021 */ /* */ /********************************************************************************/ /* C.6 NVMem.c */ /* C.6.1. Description */ /* This file contains the NV read and write access methods. This implementation uses RAM/file and does not manage the RAM/file as NV blocks. The implementation may become more sophisticated over time. */ /* C.6.2. Includes and Local */ #include #include #include #include "Platform.h" /* libtpms added begin */ #include "NVMarshal.h" #include "LibtpmsCallbacks.h" #include #define TPM_HAVE_TPM2_DECLARATIONS #include "tpm_library_intern.h" /* libtpms added end */ #if FILE_BACKED_NV # include static FILE *s_NvFile = NULL; /* kgold made these static */ static int s_NeedsManufacture = FALSE; #endif /* C.6.2. Functions */ /* C.6.2.1. NvFileOpen() */ #if FILE_BACKED_NV /* This function opens the file used to hold the NV image. Return Type: int */ /* Return Value Meaning */ /* >=0 success */ /* -1 error */ static int NvFileOpen( const char *mode ) { #if defined(NV_FILE_PATH) # define TO_STRING(s) TO_STRING_IMPL(s) # define TO_STRING_IMPL(s) #s const char* s_NvFilePath = TO_STRING(NV_FILE_PATH); # undef TO_STRING # undef TO_STRING_IMPL #else const char* s_NvFilePath = "NVChip"; #endif // Try to open an exist NVChip file for read/write # if defined _MSC_VER && 1 if(fopen_s(&s_NvFile, s_NvFilePath, mode) != 0) s_NvFile = NULL; # else s_NvFile = fopen(s_NvFilePath, mode); # endif return (s_NvFile == NULL) ? -1 : 0; } /* C.6.2.2. NvFileCommit() */ /* Write all of the contents of the NV image to a file. */ /* Return Value Meaning */ /* TRUE success */ /* FALSE failure */ static int NvFileCommit( void ) { int OK; // If NV file is not available, return failure if(s_NvFile == NULL) return 1; // Write RAM data to NV fseek(s_NvFile, 0, SEEK_SET); OK = (NV_MEMORY_SIZE == fwrite(s_NV, 1, NV_MEMORY_SIZE, s_NvFile)); OK = OK && (0 == fflush(s_NvFile)); assert(OK); return OK; } /* C.6.2.3. NvFileSize() */ /* This function gets the size of the NV file and puts the file pointer where desired using the seek method values. SEEK_SET => beginning; SEEK_CUR => current position and SEEK_END => to the end of the file. */ static long NvFileSize( int leaveAt ) { int irc; /* kgold, added return code checks */ long fileSize; long filePos; // assert(NULL != s_NvFile); filePos = ftell(s_NvFile); // libtpms changed begin if (filePos < 0) return -1; // libtpms changed end int fseek_result = fseek(s_NvFile, 0, SEEK_END); NOT_REFERENCED(fseek_result); // Fix compiler warning for NDEBUG assert(fseek_result == 0); fileSize = ftell(s_NvFile); assert(fileSize >= 0); switch(leaveAt) { case SEEK_SET: filePos = 0; /* fall through */ case SEEK_CUR: irc = fseek(s_NvFile, filePos, SEEK_SET); assert(irc == 0); break; case SEEK_END: break; default: assert(FALSE); break; } return fileSize; } #endif #if 0 /* libtpms added */ /* C.6.2.4. _plat__NvErrors() */ /* This function is used by the simulator to set the error flags in the NV subsystem to simulate an error in the NV loading process */ LIB_EXPORT void _plat__NvErrors( int recoverable, int unrecoverable ) { s_NV_unrecoverable = unrecoverable; s_NV_recoverable = recoverable; } #endif /* libtpms added */ /* C.6.2.5. _plat__NVEnable() */ /* Enable NV memory. */ /* This version just pulls in data from a file. In a real TPM, with NV on chip, this function would verify the integrity of the saved context. If the NV memory was not on chip but was in something like RPMB, the NV state would be read in, decrypted and integrity checked. */ /* The recovery from an integrity failure depends on where the error occurred. It it was in the state that is discarded by TPM Reset, then the error is recoverable if the TPM is reset. Otherwise, the TPM must go into failure mode. */ /* Return Values Meaning */ /* 0 if success */ /* > 0 if receive recoverable error */ /* <0 if unrecoverable error */ LIB_EXPORT int _plat__NVEnable( void *platParameter // IN: platform specific parameters ) { #ifdef TPM_LIBTPMS_CALLBACKS int ret; #endif // // Start assuming everything is OK s_NV_unrecoverable = FALSE; s_NV_recoverable = FALSE; #ifdef TPM_LIBTPMS_CALLBACKS ret = libtpms_plat__NVEnable(); if (ret != LIBTPMS_CALLBACK_FALLTHROUGH) return ret; #endif /* TPM_LIBTPMS_CALLBACKS */ return _plat__NVEnable_NVChipFile(platParameter); } int _plat__NVEnable_NVChipFile( void *platParameter // IN: platform specific parameters ) { NOT_REFERENCED(platParameter); // to keep compiler quiet // // Start assuming everything is OK s_NV_unrecoverable = FALSE; s_NV_recoverable = FALSE; #if FILE_BACKED_NV if(s_NvFile != NULL) return 0; // Initialize all the bytes in the ram copy of the NV _plat__NvMemoryClear(0, NV_MEMORY_SIZE); // If the file exists if(NvFileOpen("r+b") >= 0) { long fileSize = NvFileSize(SEEK_SET); // get the file size and leave the // file pointer at the start // // If the size is right, read the data if(NV_MEMORY_SIZE == fileSize) { s_NeedsManufacture = fread(s_NV, 1, NV_MEMORY_SIZE, s_NvFile) != NV_MEMORY_SIZE; if (s_NeedsManufacture) { // libtpms changes start: set s_NV_unrecoverable on error s_NV_unrecoverable = TRUE; TPMLIB_LogTPM2Error("Could not read NVChip file: %s\n", strerror(errno)); // libtpms changes end } } else { NvFileCommit(); // for any other size, initialize it s_NeedsManufacture = TRUE; } } // If NVChip file does not exist, try to create it for read/write. else if(NvFileOpen("w+b") >= 0) { NvFileCommit(); // Initialize the file s_NeedsManufacture = TRUE; } assert(NULL != s_NvFile); // Just in case we are broken for some reason. #endif // NV contents have been initialized and the error checks have been performed. For // simulation purposes, use the signaling interface to indicate if an error is // to be simulated and the type of the error. if(s_NV_unrecoverable) return -1; return s_NV_recoverable; } /* C.6.2.6. _plat__NVDisable() */ /* Disable NV memory */ LIB_EXPORT void _plat__NVDisable( int delete // IN: If TRUE, delete the NV contents. ) { #ifdef TPM_LIBTPMS_CALLBACKS int ret = libtpms_plat__NVDisable(); if (ret != LIBTPMS_CALLBACK_FALLTHROUGH) return; #endif /* TPM_LIBTPMS_CALLBACKS */ #if FILE_BACKED_NV if(NULL != s_NvFile) { fclose(s_NvFile); // Close NV file // Alternative to deleting the file is to set its size to 0. This will not // match the NV size so the TPM will need to be remanufactured. if(delete) { // Open for writing at the start. Sets the size to zero. if(NvFileOpen("w") >= 0) { fflush(s_NvFile); fclose(s_NvFile); } } } s_NvFile = NULL; // Set file handle to NULL #endif return; } /* C.6.2.7. _plat__IsNvAvailable() */ /* Check if NV is available */ /* Return Values Meaning */ /* 0 NV is available */ /* 1 NV is not available due to write failure */ /* 2 NV is not available due to rate limit */ LIB_EXPORT int _plat__IsNvAvailable( void ) { int retVal = 0; #ifdef TPM_LIBTPMS_CALLBACKS if (libtpms_plat__IsNvAvailable() == 1) return 0; #endif /* TPM_LIBTPMS_CALLBACKS */ // NV is not available if the TPM is in failure mode if(!s_NvIsAvailable) retVal = 1; #if FILE_BACKED_NV else retVal = (s_NvFile == NULL); #endif return retVal; } /* C.6.2.8. _plat__NvMemoryRead() */ /* Function: Read a chunk of NV memory */ LIB_EXPORT void _plat__NvMemoryRead( unsigned int startOffset, // IN: read start unsigned int size, // IN: size of bytes to read void *data // OUT: data buffer ) { assert(startOffset + size <= NV_MEMORY_SIZE); memcpy(data, &s_NV[startOffset], size); // Copy data from RAM return; } /* C.6.2.9. _plat__NvIsDifferent() */ /* This function checks to see if the NV is different from the test value. This is so that NV will not be written if it has not changed. */ /* Return Values Meaning */ /* TRUE(1) the NV location is different from the test value */ /* FALSE(0) the NV location is the same as the test value */ LIB_EXPORT int _plat__NvIsDifferent( unsigned int startOffset, // IN: read start unsigned int size, // IN: size of bytes to read void *data // IN: data buffer ) { return (memcmp(&s_NV[startOffset], data, size) != 0); } /* C.6.2.10. _plat__NvMemoryWrite() */ /* This function is used to update NV memory. The write is to a memory copy of NV. At the end of the current command, any changes are written to the actual NV memory. */ /* NOTE: A useful optimization would be for this code to compare the current contents of NV with the local copy and note the blocks that have changed. Then only write those blocks when _plat__NvCommit() is called. */ LIB_EXPORT int _plat__NvMemoryWrite( unsigned int startOffset, // IN: write start unsigned int size, // IN: size of bytes to write void *data // OUT: data buffer ) { if(startOffset + size <= NV_MEMORY_SIZE) { memcpy(&s_NV[startOffset], data, size); // Copy the data to the NV image return TRUE; } return FALSE; } /* C.6.2.11. _plat__NvMemoryClear() */ /* Function is used to set a range of NV memory bytes to an implementation-dependent value. The value represents the erase state of the memory. */ LIB_EXPORT void _plat__NvMemoryClear( unsigned int start, // IN: clear start unsigned int size // IN: number of bytes to clear ) { assert(start + size <= NV_MEMORY_SIZE); // In this implementation, assume that the erase value for NV is all 1s memset(&s_NV[start], 0xff, size); } /* C.6.2.12. _plat__NvMemoryMove() */ /* Function: Move a chunk of NV memory from source to destination This function should ensure that if there overlap, the original data is copied before it is written */ LIB_EXPORT void _plat__NvMemoryMove( unsigned int sourceOffset, // IN: source offset unsigned int destOffset, // IN: destination offset unsigned int size // IN: size of data being moved ) { assert(sourceOffset + size <= NV_MEMORY_SIZE); assert(destOffset + size <= NV_MEMORY_SIZE); memmove(&s_NV[destOffset], &s_NV[sourceOffset], size); // Move data in RAM #if 1 /* libtpms added begin */ if (destOffset > sourceOffset) memset(&s_NV[sourceOffset], 0, destOffset-sourceOffset); else memset(&s_NV[destOffset+size], 0, sourceOffset-destOffset); #endif /* libtpms added end */ return; } /* C.6.2.13. _plat__NvCommit() */ /* This function writes the local copy of NV to NV for permanent store. It will write NV_MEMORY_SIZE bytes to NV. If a file is use, the entire file is written. */ /* Return Values Meaning */ /* 0 NV write success */ /* non-0 NV write fail */ LIB_EXPORT int _plat__NvCommit( void ) { #ifdef TPM_LIBTPMS_CALLBACKS int ret = libtpms_plat__NvCommit(); if (ret != LIBTPMS_CALLBACK_FALLTHROUGH) return ret; #endif /* TPM_LIBTPMS_CALLBACKS */ #if FILE_BACKED_NV return (NvFileCommit() ? 0 : 1); #else return 0; #endif } /* C.6.2.14. _plat__SetNvAvail() */ /* Set the current NV state to available. This function is for testing purpose only. It is not part of the platform NV logic */ LIB_EXPORT void _plat__SetNvAvail( void ) { s_NvIsAvailable = TRUE; return; } #if 0 /* libtpms added */ /* C.6.2.15. _plat__ClearNvAvail() */ /* Set the current NV state to unavailable. This function is for testing purpose only. It is not part of the platform NV logic */ LIB_EXPORT void _plat__ClearNvAvail( void ) { s_NvIsAvailable = FALSE; return; } /* C.6.2.15. _plat__NVNeedsManufacture() */ /* This function is used by the simulator to determine when the TPM's NV state needs to be manufactured. */ LIB_EXPORT int _plat__NVNeedsManufacture( void ) { #if FILE_BACKED_NV return s_NeedsManufacture; #else return FALSE; #endif } #endif /* libtpms added */ libtpms-0.9.3/src/tpm2/NVReserved.c000066400000000000000000000210451421143571500170420ustar00rootroot00000000000000/********************************************************************************/ /* */ /* NV TPM persistent and state save data */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: NVReserved.c 1476 2019-06-10 19:32:03Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ // 8.5 NVReserved.c /* 8.5.2 Includes, Defines and Data Definitions */ #define NV_C #include "Tpm.h" /* 8.5.3 Functions */ /* 8.5.3.1 NvInitStatic() */ /* This function initializes the static variables used in the NV subsystem. */ static void NvInitStatic( void ) { // In some implementations, the end of NV is variable and is set at boot time. // This value will be the same for each boot, but is not necessarily known // at compile time. s_evictNvEnd = (NV_REF)NV_MEMORY_SIZE; return; } /* 8.5.3.2 NvCheckState() */ /* Function to check the NV state by accessing the platform-specific function to get the NV state. The result state is registered in s_NvIsAvailable that will be reported by NvIsAvailable(). */ /* This function is called at the beginning of ExecuteCommand() before any potential check of g_NvStatus. */ void NvCheckState( void ) { int func_return; // func_return = _plat__IsNvAvailable(); if(func_return == 0) g_NvStatus = TPM_RC_SUCCESS; else if(func_return == 1) g_NvStatus = TPM_RC_NV_UNAVAILABLE; else g_NvStatus = TPM_RC_NV_RATE; return; } /* 8.5.3.3 NvCommit */ /* This is a wrapper for the platform function to commit pending NV writes. */ BOOL NvCommit( void ) { return (_plat__NvCommit() == 0); } /* 8.5.3.4 NvPowerOn() */ /* This function is called at _TPM_Init() to initialize the NV environment. */ /* Return Values Meaning */ /* TRUE all NV was initialized */ /* FALSE the NV containing saved state had an error and TPM2_Startup(CLEAR) is required */ BOOL NvPowerOn( void ) { int nvError = 0; // If power was lost, need to re-establish the RAM data that is loaded from // NV and initialize the static variables if(g_powerWasLost) { if((nvError = _plat__NVEnable(0)) < 0) LOG_FAILURE(FATAL_ERROR_NV_UNRECOVERABLE); /* libtpms changed */ NvInitStatic(); } return nvError == 0; } /* 8.5.3.5 NvManufacture() */ /* This function initializes the NV system at pre-install time. */ /* This function should only be called in a manufacturing environment or in a simulation. */ /* The layout of NV memory space is an implementation choice. */ void NvManufacture( void ) { #if SIMULATION // Simulate the NV memory being in the erased state. _plat__NvMemoryClear(0, NV_MEMORY_SIZE); #endif // Initialize static variables NvInitStatic(); // Clear the RAM used for Orderly Index data MemorySet(s_indexOrderlyRam, 0, RAM_INDEX_SPACE); // Write that Orderly Index data to NV NvUpdateIndexOrderlyData(); // Initialize the next offset of the first entry in evict/index list to 0 (the // end of list marker) and the initial s_maxCounterValue; NvSetMaxCount(0); // Put the end of list marker at the end of memory. This contains the MaxCount // value as well as the end marker. NvWriteNvListEnd(NV_USER_DYNAMIC); return; } /* 8.5.3.6 NvRead() */ /* This function is used to move reserved data from NV memory to RAM. */ void NvRead( void *outBuffer, // OUT: buffer to receive data UINT32 nvOffset, // IN: offset in NV of value UINT32 size // IN: size of the value to read ) { // Input type should be valid pAssert(nvOffset + size < NV_MEMORY_SIZE); _plat__NvMemoryRead(nvOffset, size, outBuffer); return; } /* 8.5.3.7 NvWrite() */ /* This function is used to post reserved data for writing to NV memory. Before the TPM completes the operation, the value will be written. */ BOOL NvWrite( UINT32 nvOffset, // IN: location in NV to receive data UINT32 size, // IN: size of the data to move void *inBuffer // IN: location containing data to write ) { // Input type should be valid if(nvOffset + size <= NV_MEMORY_SIZE) { // Set the flag that a NV write happened SET_NV_UPDATE(UT_NV); return _plat__NvMemoryWrite(nvOffset, size, inBuffer); } return FALSE; } #if 0 // libtpms added being (for Coverity) /* 8.5.3.8 NvUpdatePersistent() */ /* This function is used to update a value in the PERSISTENT_DATA structure and commits the value to NV. */ void NvUpdatePersistent( UINT32 offset, // IN: location in PERMANENT_DATA to be updated UINT32 size, // IN: size of the value void *buffer // IN: the new data ) { pAssert(offset + size <= sizeof(gp)); MemoryCopy(&gp + offset, buffer, size); NvWrite(offset, size, buffer); } /* 8.5.3.9 NvClearPersistent() */ /* This function is used to clear a persistent data entry and commit it to NV */ void NvClearPersistent( UINT32 offset, // IN: the offset in the PERMANENT_DATA // structure to be cleared (zeroed) UINT32 size // IN: number of bytes to clear ) { pAssert(offset + size <= sizeof(gp)); MemorySet((&gp) + offset, 0, size); NvWrite(offset, size, (&gp) + offset); } #endif // libtpms added end /* 8.5.3.10 NvReadPersistent() */ /* This function reads persistent data to the RAM copy of the gp structure. */ void NvReadPersistent( void ) { NvRead(&gp, NV_PERSISTENT_DATA, sizeof(gp)); return; } libtpms-0.9.3/src/tpm2/NVReserved_fp.h000066400000000000000000000107471421143571500175430ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: NVReserved_fp.h 1476 2019-06-10 19:32:03Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ #ifndef NVRESERVED_FP_H #define NVRESERVED_FP_H #include "NVMarshal.h" /* libtpms added */ void NvCheckState( void ); BOOL NvCommit( void ); BOOL NvPowerOn( void ); void NvManufacture( void ); void NvRead( void *outBuffer, // OUT: buffer to receive data UINT32 nvOffset, // IN: offset in NV of value UINT32 size // IN: size of the value to read ); BOOL NvWrite( UINT32 nvOffset, // IN: location in NV to receive data UINT32 size, // IN: size of the data to move void *inBuffer // IN: location containing data to write ); void NvUpdatePersistent( UINT32 offset, // IN: location in PERMANENT_DATA to be updated UINT32 size, // IN: size of the value void *buffer // IN: the new data ); void NvClearPersistent( UINT32 offset, // IN: the offset in the PERMANENT_DATA // structure to be cleared (zeroed) UINT32 size // IN: number of bytes to clear ); void NvReadPersistent( void ); #endif libtpms-0.9.3/src/tpm2/NV_Certify_fp.h000066400000000000000000000103361421143571500175220ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: NV_Certify_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef NV_CERTIFY_FP_H #define NV_CERTIFY_FP_H typedef struct { TPMI_DH_OBJECT signHandle; TPMI_RH_NV_AUTH authHandle; TPMI_RH_NV_INDEX nvIndex; TPM2B_DATA qualifyingData; TPMT_SIG_SCHEME inScheme; UINT16 size; UINT16 offset; } NV_Certify_In; #define RC_NV_Certify_signHandle (TPM_RC_H + TPM_RC_1) #define RC_NV_Certify_authHandle (TPM_RC_H + TPM_RC_2) #define RC_NV_Certify_nvIndex (TPM_RC_H + TPM_RC_3) #define RC_NV_Certify_qualifyingData (TPM_RC_P + TPM_RC_1) #define RC_NV_Certify_inScheme (TPM_RC_P + TPM_RC_2) #define RC_NV_Certify_size (TPM_RC_P + TPM_RC_3) #define RC_NV_Certify_offset (TPM_RC_P + TPM_RC_4) typedef struct { TPM2B_ATTEST certifyInfo; TPMT_SIGNATURE signature; } NV_Certify_Out; TPM_RC TPM2_NV_Certify( NV_Certify_In *in, // IN: input parameter list NV_Certify_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/NV_ChangeAuth_fp.h000066400000000000000000000072771421143571500201360ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: NV_ChangeAuth_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef NV_CHANGEAUTH_FP_H #define NV_CHANGEAUTH_FP_H typedef struct { TPMI_RH_NV_INDEX nvIndex; TPM2B_AUTH newAuth; } NV_ChangeAuth_In; #define RC_NV_ChangeAuth_nvIndex (TPM_RC_H + TPM_RC_1) #define RC_NV_ChangeAuth_newAuth (TPM_RC_P + TPM_RC_1) TPM_RC TPM2_NV_ChangeAuth( NV_ChangeAuth_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/NV_DefineSpace_fp.h000066400000000000000000000074471421143571500202740ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: NV_DefineSpace_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef NV_DEFINESPACE_FP_H #define NV_DEFINESPACE_FP_H typedef struct { TPMI_RH_PROVISION authHandle; TPM2B_AUTH auth; TPM2B_NV_PUBLIC publicInfo; } NV_DefineSpace_In; #define RC_NV_DefineSpace_authHandle (TPM_RC_H + TPM_RC_1) #define RC_NV_DefineSpace_auth (TPM_RC_P + TPM_RC_1) #define RC_NV_DefineSpace_publicInfo (TPM_RC_P + TPM_RC_2) TPM_RC TPM2_NV_DefineSpace( NV_DefineSpace_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/NV_Extend_fp.h000066400000000000000000000073761421143571500173560ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: NV_Extend_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef NV_EXTEND_FP_H #define NV_EXTEND_FP_H typedef struct { TPMI_RH_NV_AUTH authHandle; TPMI_RH_NV_INDEX nvIndex; TPM2B_MAX_NV_BUFFER data; } NV_Extend_In; #define RC_NV_Extend_authHandle (TPM_RC_H + TPM_RC_1) #define RC_NV_Extend_nvIndex (TPM_RC_H + TPM_RC_2) #define RC_NV_Extend_data (TPM_RC_P + TPM_RC_1) TPM_RC TPM2_NV_Extend( NV_Extend_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/NV_GlobalWriteLock_fp.h000066400000000000000000000072231421143571500211420ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: NV_GlobalWriteLock_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef NV_GLOBALWRITELOCK_FP_H #define NV_GLOBALWRITELOCK_FP_H typedef struct { TPMI_RH_PROVISION authHandle; } NV_GlobalWriteLock_In; #define RC_NV_GlobalWriteLock_authHandle (TPM_RC_H + TPM_RC_1) TPM_RC TPM2_NV_GlobalWriteLock( NV_GlobalWriteLock_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/NV_Increment_fp.h000066400000000000000000000073021421143571500200400ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: NV_Increment_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef NV_INCREMENT_FP_H #define NV_INCREMENT_FP_H typedef struct { TPMI_RH_NV_AUTH authHandle; TPMI_RH_NV_INDEX nvIndex; } NV_Increment_In;; #define RC_NV_Increment_authHandle (TPM_RC_H + TPM_RC_1) #define RC_NV_Increment_nvIndex (TPM_RC_H + TPM_RC_2) TPM_RC TPM2_NV_Increment( NV_Increment_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/NV_ReadLock_fp.h000066400000000000000000000072651421143571500176100ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: NV_ReadLock_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef NV_READLOCK_FP_H #define NV_READLOCK_FP_H typedef struct { TPMI_RH_NV_AUTH authHandle; TPMI_RH_NV_INDEX nvIndex; } NV_ReadLock_In; #define RC_NV_ReadLock_authHandle (TPM_RC_H + TPM_RC_1) #define RC_NV_ReadLock_nvIndex (TPM_RC_H + TPM_RC_2) TPM_RC TPM2_NV_ReadLock( NV_ReadLock_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/NV_ReadPublic_fp.h000066400000000000000000000074221421143571500201310ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: NV_ReadPublic_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef NV_READPUBLIC_FP_H #define NV_READPUBLIC_FP_H typedef struct { TPMI_RH_NV_INDEX nvIndex; } NV_ReadPublic_In; #define RC_NV_ReadPublic_nvIndex (TPM_RC_P + TPM_RC_1) typedef struct { TPM2B_NV_PUBLIC nvPublic; TPM2B_NAME nvName; } NV_ReadPublic_Out; TPM_RC TPM2_NV_ReadPublic( NV_ReadPublic_In *in, // IN: input parameter list NV_ReadPublic_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/NV_Read_fp.h000066400000000000000000000076451421143571500170010ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: NV_Read_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef NV_READ_FP_H #define NV_READ_FP_H typedef struct { TPMI_RH_NV_AUTH authHandle; TPMI_RH_NV_INDEX nvIndex; UINT16 size; UINT16 offset; } NV_Read_In; #define RC_NV_Read_authHandle (TPM_RC_H + TPM_RC_1) #define RC_NV_Read_nvIndex (TPM_RC_H + TPM_RC_2) #define RC_NV_Read_size (TPM_RC_P + TPM_RC_1) #define RC_NV_Read_offset (TPM_RC_P + TPM_RC_2) typedef struct { TPM2B_MAX_NV_BUFFER data; } NV_Read_Out; TPM_RC TPM2_NV_Read( NV_Read_In *in, // IN: input parameter list NV_Read_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/NV_SetBits_fp.h000066400000000000000000000073601421143571500174750ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: NV_SetBits_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef NV_SETBITS_FP_H #define NV_SETBITS_FP_H typedef struct { TPMI_RH_NV_AUTH authHandle; TPMI_RH_NV_INDEX nvIndex; UINT64 bits; } NV_SetBits_In; #define RC_NV_SetBits_authHandle (TPM_RC_H + TPM_RC_1) #define RC_NV_SetBits_nvIndex (TPM_RC_H + TPM_RC_2) #define RC_NV_SetBits_bits (TPM_RC_P + TPM_RC_1) TPM_RC TPM2_NV_SetBits( NV_SetBits_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/NV_UndefineSpaceSpecial_fp.h000066400000000000000000000074171421143571500221350ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: NV_UndefineSpaceSpecial_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef NV_UNDEFINESPACESPECIAL_FP_H #define NV_UNDEFINESPACESPECIAL_FP_H typedef struct { TPMI_RH_NV_INDEX nvIndex; TPMI_RH_PLATFORM platform; } NV_UndefineSpaceSpecial_In; #define RC_NV_UndefineSpaceSpecial_nvIndex (TPM_RC_H + TPM_RC_1) #define RC_NV_UndefineSpaceSpecial_platform (TPM_RC_H + TPM_RC_2) TPM_RC TPM2_NV_UndefineSpaceSpecial( NV_UndefineSpaceSpecial_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/NV_UndefineSpace_fp.h000066400000000000000000000073521421143571500206320ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: NV_UndefineSpace_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef NV_UNDEFINESPACE_FP_H #define NV_UNDEFINESPACE_FP_H typedef struct { TPMI_RH_PROVISION authHandle; TPMI_RH_NV_INDEX nvIndex; } NV_UndefineSpace_In; #define RC_NV_UndefineSpace_authHandle (TPM_RC_H + TPM_RC_1) #define RC_NV_UndefineSpace_nvIndex (TPM_RC_H + TPM_RC_2) TPM_RC TPM2_NV_UndefineSpace( NV_UndefineSpace_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/NV_WriteLock_fp.h000066400000000000000000000073011421143571500200160ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: NV_WriteLock_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef NV_WRITELOCK_FP_H #define NV_WRITELOCK_FP_H typedef struct { TPMI_RH_NV_AUTH authHandle; TPMI_RH_NV_INDEX nvIndex; } NV_WriteLock_In; #define RC_NV_WriteLock_authHandle (TPM_RC_H + TPM_RC_1) #define RC_NV_WriteLock_nvIndex (TPM_RC_H + TPM_RC_2) TPM_RC TPM2_NV_WriteLock( NV_WriteLock_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/NV_Write_fp.h000066400000000000000000000074711421143571500172150ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: NV_Write_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef NV_WRITE_FP_H #define NV_WRITE_FP_H typedef struct { TPMI_RH_NV_AUTH authHandle; TPMI_RH_NV_INDEX nvIndex; TPM2B_MAX_NV_BUFFER data; UINT16 offset; } NV_Write_In; #define RC_NV_Write_authHandle (TPM_RC_H + TPM_RC_1) #define RC_NV_Write_nvIndex (TPM_RC_H + TPM_RC_2) #define RC_NV_Write_data (TPM_RC_P + TPM_RC_1) #define RC_NV_Write_offset (TPM_RC_P + TPM_RC_2) TPM_RC TPM2_NV_Write( NV_Write_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/NV_spt.c000066400000000000000000000171621421143571500162350ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: NV_spt.c 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016, 2017 */ /* */ /********************************************************************************/ /* 7.5 NV Command Support (NV_spt.c) */ /* 7.5.1 Includes */ #include "Tpm.h" #include "NV_spt_fp.h" /* 7.5.2 Functions */ /* 7.5.2.1 NvReadAccessChecks() */ /* Common routine for validating a read Used by TPM2_NV_Read(), TPM2_NV_ReadLock() and TPM2_PolicyNV() */ /* Error Returns Meaning */ /* TPM_RC_NV_AUTHORIZATION autHandle is not allowed to authorize read of the index */ /* TPM_RC_NV_LOCKED Read locked */ /* TPM_RC_NV_UNINITIALIZED Try to read an uninitialized index */ TPM_RC NvReadAccessChecks( TPM_HANDLE authHandle, // IN: the handle that provided the // authorization TPM_HANDLE nvHandle, // IN: the handle of the NV index to be read TPMA_NV attributes // IN: the attributes of 'nvHandle' ) { // If data is read locked, returns an error if(IS_ATTRIBUTE(attributes, TPMA_NV, READLOCKED)) return TPM_RC_NV_LOCKED; // If the authorization was provided by the owner or platform, then check // that the attributes allow the read. If the authorization handle // is the same as the index, then the checks were made when the authorization // was checked.. if(authHandle == TPM_RH_OWNER) { // If Owner provided authorization then ONWERWRITE must be SET if(!IS_ATTRIBUTE(attributes, TPMA_NV, OWNERREAD)) return TPM_RC_NV_AUTHORIZATION; } else if(authHandle == TPM_RH_PLATFORM) { // If Platform provided authorization then PPWRITE must be SET if(!IS_ATTRIBUTE(attributes, TPMA_NV, PPREAD)) return TPM_RC_NV_AUTHORIZATION; } // If neither Owner nor Platform provided authorization, make sure that it was // provided by this index. else if(authHandle != nvHandle) return TPM_RC_NV_AUTHORIZATION; // If the index has not been written, then the value cannot be read // NOTE: This has to come after other access checks to make sure that // the proper authorization is given to TPM2_NV_ReadLock() if(!IS_ATTRIBUTE(attributes, TPMA_NV, WRITTEN)) return TPM_RC_NV_UNINITIALIZED; return TPM_RC_SUCCESS; } /* 7.5.2.2 NvWriteAccessChecks() */ /* Common routine for validating a write Used by TPM2_NV_Write(), TPM2_NV_Increment(), TPM2_SetBits(), and TPM2_NV_WriteLock() */ /* Error Returns Meaning */ /* TPM_RC_NV_AUTHORIZATION Authorization fails */ /* TPM_RC_NV_LOCKED Write locked */ TPM_RC NvWriteAccessChecks( TPM_HANDLE authHandle, // IN: the handle that provided the // authorization TPM_HANDLE nvHandle, // IN: the handle of the NV index to be written TPMA_NV attributes // IN: the attributes of 'nvHandle' ) { // If data is write locked, returns an error if(IS_ATTRIBUTE(attributes, TPMA_NV, WRITELOCKED)) return TPM_RC_NV_LOCKED; // If the authorization was provided by the owner or platform, then check // that the attributes allow the write. If the authorization handle // is the same as the index, then the checks were made when the authorization // was checked.. if(authHandle == TPM_RH_OWNER) { // If Owner provided authorization then ONWERWRITE must be SET if(!IS_ATTRIBUTE(attributes, TPMA_NV, OWNERWRITE)) return TPM_RC_NV_AUTHORIZATION; } else if(authHandle == TPM_RH_PLATFORM) { // If Platform provided authorization then PPWRITE must be SET if(!IS_ATTRIBUTE(attributes, TPMA_NV, PPWRITE)) return TPM_RC_NV_AUTHORIZATION; } // If neither Owner nor Platform provided authorization, make sure that it was // provided by this index. else if(authHandle != nvHandle) return TPM_RC_NV_AUTHORIZATION; return TPM_RC_SUCCESS; } /* 7.5.2.3 NvClearOrderly() */ /* This function is used to cause gp.orderlyState to be cleared to the non-orderly state. */ TPM_RC NvClearOrderly( void ) { if(gp.orderlyState < SU_DA_USED_VALUE) RETURN_IF_NV_IS_NOT_AVAILABLE; g_clearOrderly = TRUE; return TPM_RC_SUCCESS; } /* 7.5.2.4 NvIsPinPassIndex() */ /* Function to check to see if an NV index is a PIN Pass Index */ /* Return Value Meaning */ /* TRUE is pin pass */ /* FALSE is not pin pass */ BOOL NvIsPinPassIndex( TPM_HANDLE index // IN: Handle to check ) { if(HandleGetType(index) == TPM_HT_NV_INDEX) { NV_INDEX *nvIndex = NvGetIndexInfo(index, NULL); return IsNvPinPassIndex(nvIndex->publicArea.attributes); } return FALSE; } libtpms-0.9.3/src/tpm2/NV_spt_fp.h000066400000000000000000000100641421143571500167210ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: NV_spt_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 */ /* */ /********************************************************************************/ #ifndef NV_SPT_FP_H #define NV_SPT_FP_H TPM_RC NvReadAccessChecks( TPM_HANDLE authHandle, // IN: the handle that provided the // authorization TPM_HANDLE nvHandle, // IN: the handle of the NV index to be read TPMA_NV attributes // IN: the attributes of 'nvHandle' ); TPM_RC NvWriteAccessChecks( TPM_HANDLE authHandle, // IN: the handle that provided the // authorization TPM_HANDLE nvHandle, // IN: the handle of the NV index to be written TPMA_NV attributes // IN: the attributes of 'nvHandle' ); TPM_RC NvClearOrderly( void ); BOOL NvIsPinPassIndex( TPM_HANDLE index // IN: Handle to check ); #endif libtpms-0.9.3/src/tpm2/OIDs.h000066400000000000000000000253401421143571500156240ustar00rootroot00000000000000/********************************************************************************/ /* */ /* OID values */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: OIDs.h 1628 2020-05-27 19:35:29Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2019 - 2020 */ /* */ /********************************************************************************/ // 10.1.16 OIDs.h #include "Tpm.h" #ifndef _OIDS_H_ #define _OIDS_H_ // All the OIDs in this file are defined as DER-encoded values with a leading tag 0x06 // (ASN1_OBJECT_IDENTIFIER), followed by a single length byte. This allows the OID size to be // determined by looking at octet[1] of the OID (total size is OID[1] + 2). // These macros allow OIDs to be defined (or not) depending on whether the associated hash // algorithm is implemented. // NOTE: When one of these macros is used, the NAME needs '_" on each side. The exception is when // the macro is used for the hash OID when only a single _ is used. #ifndef ALG_SHA1 # define ALG_SHA1 NO #endif #if ALG_SHA1 #define SHA1_OID(NAME) MAKE_OID(NAME##SHA1) #else #define SHA1_OID(NAME) #endif #ifndef ALG_SHA256 # define ALG_SHA256 NO #endif #if ALG_SHA256 #define SHA256_OID(NAME) MAKE_OID(NAME##SHA256) #else #define SHA256_OID(NAME) #endif #ifndef ALG_SHA384 # define ALG_SHA384 NO #endif #if ALG_SHA384 #define SHA384_OID(NAME) MAKE_OID(NAME##SHA384) #else #define SHA384_OID(NAME) #endif #ifndef ALG_SHA512 # define ALG_SHA512 NO #endif #if ALG_SHA512 #define SHA512_OID(NAME) MAKE_OID(NAME##SHA512) #else #define SHA512_OID(NAME) #endif #ifndef ALG_SM3_256 # define ALG_SM3_256 NO #endif #if ALG_SM3_256 #define SM3_256_OID(NAME) MAKE_OID(NAME##SM3_256) #else #define SM3_256_OID(NAME) #endif #ifndef ALG_SHA3_256 # define ALG_SHA3_256 NO #endif #if ALG_SHA3_256 #define SHA3_256_OID(NAME) MAKE_OID(NAME##SHA3_256) #else #define SHA3_256_OID(NAME) #endif #ifndef ALG_SHA3_384 # define ALG_SHA3_384 NO #endif #if ALG_SHA3_384 #define SHA3_384_OID(NAME) MAKE_OID(NAME##SHA3_384) #else #define SHA3_384_OID(NAME) #endif #ifndef ALG_SHA3_512 # define ALG_SHA3_512 NO #endif #if ALG_SHA3_512 #define SHA3_512_OID(NAME) MAKE_OID(NAME##SHA3_512) #else #define SHA3_512_OID(NAME) #endif // These are encoded to take one additional byte of algorithm selector #define NIST_HASH 0x06, 0x09, 0x60, 0x86, 0x48, 1, 101, 3, 4, 2 #define NIST_SIG 0x06, 0x09, 0x60, 0x86, 0x48, 1, 101, 3, 4, 3 // These hash OIDs used in a lot of places. #define OID_SHA1_VALUE 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A SHA1_OID(_); // Expands to: // MAKE_OID(_SHA1) // which expands to: // EXTERN const BYTE OID_SHA1[] INITIALIZER({OID_SHA1_VALUE}) // which, depending on the setting of EXTERN and // INITIALIZER, expands to either: // extern const BYTE OID_SHA1[] // or // const BYTE OID_SHA1[] = {OID_SHA1_VALUE} // which is: // const BYTE OID_SHA1[] = {0x06, 0x05, 0x2B, 0x0E, // 0x03, 0x02, 0x1A} #define OID_SHA256_VALUE NIST_HASH, 1 SHA256_OID(_); #define OID_SHA384_VALUE NIST_HASH, 2 SHA384_OID(_); #define OID_SHA512_VALUE NIST_HASH, 3 SHA512_OID(_); #define OID_SM3_256_VALUE 0x06, 0x08, 0x2A, 0x81, 0x1C, 0xCF, 0x55, 0x01, \ 0x83, 0x11 SM3_256_OID(_); // (1.2.156.10197.1.401) #define OID_SHA3_256_VALUE NIST_HASH, 8 SHA3_256_OID(_); #define OID_SHA3_384_VALUE NIST_HASH, 9 SHA3_384_OID(_); #define OID_SHA3_512_VALUE NIST_HASH, 10 SHA3_512_OID(_); // These are used for RSA-PSS #if ALG_RSA #define OID_MGF1_VALUE 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, \ 0x01, 0x01, 0x08 MAKE_OID(_MGF1); #define OID_RSAPSS_VALUE 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, \ 0x01, 0x01, 0x0A MAKE_OID(_RSAPSS); // This is the OID to designate the public part of an RSA key. #define OID_PKCS1_PUB_VALUE 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, \ 0x01, 0x01, 0x01 MAKE_OID(_PKCS1_PUB); // These are used for RSA PKCS1 signature Algorithms #define OID_PKCS1_SHA1_VALUE 0x06,0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, \ 0x0D, 0x01, 0x01, 0x05 SHA1_OID(_PKCS1_); // (1.2.840.113549.1.1.5) #define OID_PKCS1_SHA256_VALUE 0x06,0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, \ 0x0D, 0x01, 0x01, 0x0B SHA256_OID(_PKCS1_); // (1.2.840.113549.1.1.11) #define OID_PKCS1_SHA384_VALUE 0x06,0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, \ 0x0D, 0x01, 0x01, 0x0C SHA384_OID(_PKCS1_); // (1.2.840.113549.1.1.12) #define OID_PKCS1_SHA512_VALUE 0x06,0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, \ 0x0D, 0x01, 0x01, 0x0D SHA512_OID(_PKCS1_); //(1.2.840.113549.1.1.13) #define OID_PKCS1_SM3_256_VALUE 0x06, 0x08, 0x2A, 0x81, 0x1C, 0xCF, 0x55, \ 0x01, 0x83, 0x78 SM3_256_OID(_PKCS1_); // 1.2.156.10197.1.504 #define OID_PKCS1_SHA3_256_VALUE NIST_SIG, 14 SHA3_256_OID(_PKCS1_); #define OID_PKCS1_SHA3_384_VALUE NIST_SIG, 15 SHA3_384_OID(_PKCS1_); #define OID_PKCS1_SHA3_512_VALUE NIST_SIG, 16 SHA3_512_OID(_PKCS1_); #endif // ALG_RSA #if ALG_ECDSA #define OID_ECDSA_SHA1_VALUE 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, \ 0x01 SHA1_OID(_ECDSA_); // (1.2.840.10045.4.1) SHA1 digest signed by an ECDSA key. #define OID_ECDSA_SHA256_VALUE 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, \ 0x03, 0x02 SHA256_OID(_ECDSA_); // (1.2.840.10045.4.3.2) SHA256 digest signed by an ECDSA key. #define OID_ECDSA_SHA384_VALUE 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, \ 0x03, 0x03 SHA384_OID(_ECDSA_); // (1.2.840.10045.4.3.3) SHA384 digest signed by an ECDSA key. #define OID_ECDSA_SHA512_VALUE 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, \ 0x03, 0x04 SHA512_OID(_ECDSA_); // (1.2.840.10045.4.3.4) SHA512 digest signed by an ECDSA key. #define OID_ECDSA_SM3_256_VALUE 0x06, 0x08, 0x2A, 0x81, 0x1C, 0xCF, 0x55, 0x01, \ 0x83, 0x75 SM3_256_OID(_ECDSA_); // 1.2.156.10197.1.501 #define OID_ECDSA_SHA3_256_VALUE NIST_SIG, 10 SHA3_256_OID(_ECDSA_); #define OID_ECDSA_SHA3_384_VALUE NIST_SIG, 11 SHA3_384_OID(_ECDSA_); #define OID_ECDSA_SHA3_512_VALUE NIST_SIG, 12 SHA3_512_OID(_ECDSA_); #endif // ALG_ECDSA #if ALG_ECC #define OID_ECC_PUBLIC_VALUE 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, \ 0x01 MAKE_OID(_ECC_PUBLIC); #define OID_ECC_NIST_P192_VALUE 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, \ 0x01, 0x01 #if ECC_NIST_P192 MAKE_OID(_ECC_NIST_P192); // (1.2.840.10045.3.1.1) 'nistP192' #endif // ECC_NIST_P192 #define OID_ECC_NIST_P224_VALUE 0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x21 #if ECC_NIST_P224 MAKE_OID(_ECC_NIST_P224); // (1.3.132.0.33) 'nistP224' #endif // ECC_NIST_P224 #define OID_ECC_NIST_P256_VALUE 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, \ 0x01, 0x07 #if ECC_NIST_P256 MAKE_OID(_ECC_NIST_P256); // (1.2.840.10045.3.1.7) 'nistP256' #endif // ECC_NIST_P256 #define OID_ECC_NIST_P384_VALUE 0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22 #if ECC_NIST_P384 MAKE_OID(_ECC_NIST_P384); // (1.3.132.0.34) 'nistP384' #endif // ECC_NIST_P384 #define OID_ECC_NIST_P521_VALUE 0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x23 #if ECC_NIST_P521 MAKE_OID(_ECC_NIST_P521); // (1.3.132.0.35) 'nistP521' #endif // ECC_NIST_P521 // No OIDs defined for these anonymous curves #define OID_ECC_BN_P256_VALUE 0x00 #if ECC_BN_P256 MAKE_OID(_ECC_BN_P256); #endif // ECC_BN_P256 #define OID_ECC_BN_P638_VALUE 0x00 #if ECC_BN_P638 MAKE_OID(_ECC_BN_P638); #endif // ECC_BN_P638 #define OID_ECC_SM2_P256_VALUE 0x06, 0x08, 0x2A, 0x81, 0x1C, 0xCF, 0x55, 0x01, \ 0x82, 0x2D #if ECC_SM2_P256 MAKE_OID(_ECC_SM2_P256); // Don't know where I found this OID. It needs checking #endif // ECC_SM2_P256 #if ECC_BN_P256 #define OID_ECC_BN_P256 NULL #endif // ECC_BN_P256 #endif // ALG_ECC // #undef MAKE_OID #define OID_SIZE(OID) (OID[1] + 2) #endif // !_OIDS_H_ libtpms-0.9.3/src/tpm2/Object.c000066400000000000000000001053021421143571500162240ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Manage the object store of the TPM. */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Object.c 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2021 */ /* */ /********************************************************************************/ /* 8.6 Object.c */ /* 8.6.1 Introduction */ /* This file contains the functions that manage the object store of the TPM. */ /* 8.6.2 Includes and Data Definitions */ #define OBJECT_C #include "Tpm.h" #include "NVMarshal.h" // libtpms added #include "BackwardsCompatibilityObject.h" // libtpms added /* 8.6.3 Functions */ /* 8.6.3.1 ObjectFlush() */ /* This function marks an object slot as available. Since there is no checking of the input parameters, it should be used judiciously. */ /* NOTE: This could be converted to a macro. */ void ObjectFlush( OBJECT *object ) { object->attributes.occupied = CLEAR; } /* 8.6.3.2 ObjectSetInUse() */ /* This access function sets the occupied attribute of an object slot. */ void ObjectSetInUse( OBJECT *object ) { object->attributes.occupied = SET; } /* 8.6.3.3 ObjectStartup() */ /* This function is called at TPM2_Startup() to initialize the object subsystem. */ BOOL ObjectStartup( void ) { UINT32 i; // object slots initialization for(i = 0; i < MAX_LOADED_OBJECTS; i++) { //Set the slot to not occupied ObjectFlush(&s_objects[i]); } return TRUE; } /* 8.6.3.4 ObjectCleanupEvict() */ /* In this implementation, a persistent object is moved from NV into an object slot for processing. It is flushed after command execution. This function is called from ExecuteCommand(). */ void ObjectCleanupEvict( void ) { UINT32 i; // This has to be iterated because a command may have two handles // and they may both be persistent. // This could be made to be more efficient so that a search is not needed. for(i = 0; i < MAX_LOADED_OBJECTS; i++) { // If an object is a temporary evict object, flush it from slot OBJECT *object = &s_objects[i]; if(object->attributes.evict == SET) ObjectFlush(object); } return; } /* 8.6.3.5 IsObjectPresent() */ /* This function checks to see if a transient handle references a loaded object. This routine should not be called if the handle is not a transient handle. The function validates that the handle is in the implementation-dependent allowed in range for loaded transient objects. */ /* Return Values Meaning */ /* TRUE if the handle references a loaded object */ /* FALSE if the handle is not an object handle, or it does not reference to a loaded object */ BOOL IsObjectPresent( TPMI_DH_OBJECT handle // IN: handle to be checked ) { UINT32 slotIndex = handle - TRANSIENT_FIRST; // Since the handle is just an index into the array that is zero based, any // handle value outsize of the range of: // TRANSIENT_FIRST -- (TRANSIENT_FIRST + MAX_LOADED_OBJECT - 1) // will now be greater than or equal to MAX_LOADED_OBJECTS if(slotIndex >= MAX_LOADED_OBJECTS) return FALSE; // Indicate if the slot is occupied return (s_objects[slotIndex].attributes.occupied == TRUE); } /* 8.6.3.6 ObjectIsSequence() */ /* This function is used to check if the object is a sequence object. This function should not be called if the handle does not reference a loaded object. */ /* Return Values Meaning */ /* TRUE object is an HMAC, hash, or event sequence object */ /* FALSE object is not an HMAC, hash, or event sequence object */ BOOL ObjectIsSequence( OBJECT *object // IN: handle to be checked ) { pAssert(object != NULL); return (object->attributes.hmacSeq == SET || object->attributes.hashSeq == SET || object->attributes.eventSeq == SET); } /* 8.6.3.7 HandleToObject() */ /* This function is used to find the object structure associated with a handle. */ /* This function requires that handle references a loaded object or a permanent handle. */ OBJECT* HandleToObject( TPMI_DH_OBJECT handle // IN: handle of the object ) { UINT32 index; // Return NULL if the handle references a permanent handle because there is no // associated OBJECT. if(HandleGetType(handle) == TPM_HT_PERMANENT) return NULL; // In this implementation, the handle is determined by the slot occupied by the // object. index = handle - TRANSIENT_FIRST; pAssert(index < MAX_LOADED_OBJECTS); pAssert(s_objects[index].attributes.occupied); return &s_objects[index]; } /* 8.6.3.9 GetQualifiedName() */ /* This function returns the Qualified Name of the object. In this implementation, the Qualified Name is computed when the object is loaded and is saved in the internal representation of the object. The alternative would be to retain the Name of the parent and compute the QN when needed. This would take the same amount of space so it is not recommended that the alternate be used. */ /* This function requires that handle references a loaded object. */ void GetQualifiedName( TPMI_DH_OBJECT handle, // IN: handle of the object TPM2B_NAME *qualifiedName // OUT: qualified name of the object ) { OBJECT *object; switch(HandleGetType(handle)) { case TPM_HT_PERMANENT: qualifiedName->t.size = sizeof(TPM_HANDLE); UINT32_TO_BYTE_ARRAY(handle, qualifiedName->t.name); break; case TPM_HT_TRANSIENT: object = HandleToObject(handle); if(object == NULL || object->publicArea.nameAlg == TPM_ALG_NULL) qualifiedName->t.size = 0; else // Copy the name *qualifiedName = object->qualifiedName; break; default: FAIL(FATAL_ERROR_INTERNAL); } return; } /* 8.6.3.10 ObjectGetHierarchy() */ /* This function returns the handle for the hierarchy of an object. */ TPMI_RH_HIERARCHY ObjectGetHierarchy( OBJECT *object // IN :object ) { if(object->attributes.spsHierarchy) { return TPM_RH_OWNER; } else if(object->attributes.epsHierarchy) { return TPM_RH_ENDORSEMENT; } else if(object->attributes.ppsHierarchy) { return TPM_RH_PLATFORM; } else { return TPM_RH_NULL; } } /* 8.6.3.11 GetHierarchy() */ /* This function returns the handle of the hierarchy to which a handle belongs. This function is similar to ObjectGetHierarchy() but this routine takes a handle while ObjectGetHierarchy() takes a pointer to an object. */ /* This function requires that handle references a loaded object. */ TPMI_RH_HIERARCHY GetHieriarchy( TPMI_DH_OBJECT handle // IN :object handle ) { OBJECT *object = HandleToObject(handle); return ObjectGetHierarchy(object); } /* 8.6.3.12 FindEmptyObjectSlot() */ /* This function finds an open object slot, if any. It will clear the attributes but will not set the occupied attribute. This is so that a slot may be used and discarded if everything does not go as planned. */ /* Return Values Meaning */ /* null no open slot found */ /* !=null pointer to available slot */ OBJECT * FindEmptyObjectSlot( TPMI_DH_OBJECT *handle // OUT: (optional) ) { UINT32 i; OBJECT *object; for(i = 0; i < MAX_LOADED_OBJECTS; i++) { object = &s_objects[i]; if(object->attributes.occupied == CLEAR) { if(handle) *handle = i + TRANSIENT_FIRST; // Initialize the object attributes // MemorySet(&object->attributes, 0, sizeof(OBJECT_ATTRIBUTES)); MemorySet(object, 0, sizeof(*object)); // libtpms added: Initialize the whole object return object; } } return NULL; } /* 8.6.3.13 ObjectAllocateSlot() */ /* This function is used to allocate a slot in internal object array. */ /* Return Values Meaning */ OBJECT * ObjectAllocateSlot( TPMI_DH_OBJECT *handle // OUT: handle of allocated object ) { OBJECT *object = FindEmptyObjectSlot(handle); if(object != NULL) { // if found, mark as occupied ObjectSetInUse(object); } return object; } /* 8.6.3.14 ObjectSetLoadedAttributes() */ /* This function sets the internal attributes for a loaded object. It is called to finalize the OBJECT attributes (not the TPMA_OBJECT attributes) for a loaded object. */ void ObjectSetLoadedAttributes( OBJECT *object, // IN: object attributes to finalize TPM_HANDLE parentHandle, // IN: the parent handle SEED_COMPAT_LEVEL seedCompatLevel // IN: seed compat level to use for children ) { OBJECT *parent = HandleToObject(parentHandle); TPMA_OBJECT objectAttributes = object->publicArea.objectAttributes; object->seedCompatLevel = seedCompatLevel; // libtpms added // // Copy the stClear attribute from the public area. This could be overwritten // if the parent has stClear SET object->attributes.stClear = IS_ATTRIBUTE(objectAttributes, TPMA_OBJECT, stClear); // If parent handle is a permanent handle, it is a primary (unless it is NULL if(parent == NULL) { object->attributes.primary = SET; switch(parentHandle) { case TPM_RH_ENDORSEMENT: object->attributes.epsHierarchy = SET; break; case TPM_RH_OWNER: object->attributes.spsHierarchy = SET; break; case TPM_RH_PLATFORM: object->attributes.ppsHierarchy = SET; break; default: // Treat the temporary attribute as a hierarchy object->attributes.temporary = SET; object->attributes.primary = CLEAR; break; } } else { // is this a stClear object object->attributes.stClear = (IS_ATTRIBUTE(objectAttributes, TPMA_OBJECT, stClear) || (parent->attributes.stClear == SET)); object->attributes.epsHierarchy = parent->attributes.epsHierarchy; object->attributes.spsHierarchy = parent->attributes.spsHierarchy; object->attributes.ppsHierarchy = parent->attributes.ppsHierarchy; // An object is temporary if its parent is temporary or if the object // is external object->attributes.temporary = parent->attributes.temporary || object->attributes.external; } // If this is an external object, set the QN == name but don't SET other // key properties ('parent' or 'derived') if(object->attributes.external) object->qualifiedName = object->name; else { // check attributes for different types of parents if(IS_ATTRIBUTE(objectAttributes, TPMA_OBJECT, restricted) && !object->attributes.publicOnly && IS_ATTRIBUTE(objectAttributes, TPMA_OBJECT, decrypt) && object->publicArea.nameAlg != TPM_ALG_NULL) { // This is a parent. If it is not a KEYEDHASH, it is an ordinary parent. // Otherwise, it is a derivation parent. if(object->publicArea.type == TPM_ALG_KEYEDHASH) object->attributes.derivation = SET; else object->attributes.isParent = SET; } ComputeQualifiedName(parentHandle, object->publicArea.nameAlg, &object->name, &object->qualifiedName); } // Set slot occupied ObjectSetInUse(object); return; } /* 8.6.3.15 ObjectLoad() */ /* Common function to load an object. A loaded object has its public area validated (unless its nameAlg is TPM_ALG_NULL). If a sensitive part is loaded, it is verified to be correct and if both public and sensitive parts are loaded, then the cryptographic binding between the objects is validated. This function does not cause the allocated slot to be marked as in use. */ TPM_RC ObjectLoad( OBJECT *object, // IN: pointer to object slot // object OBJECT *parent, // IN: (optional) the parent object TPMT_PUBLIC *publicArea, // IN: public area to be installed in the object TPMT_SENSITIVE *sensitive, // IN: (optional) sensitive area to be // installed in the object TPM_RC blamePublic, // IN: parameter number to associate with the // publicArea errors TPM_RC blameSensitive,// IN: parameter number to associate with the // sensitive area errors TPM2B_NAME *name // IN: (optional) ) { TPM_RC result = TPM_RC_SUCCESS; BOOL doCheck; // // Do validations of public area object descriptions // Is this public only or a no-name object? if(sensitive == NULL || publicArea->nameAlg == TPM_ALG_NULL) { // Need to have schemes checked so that we do the right thing with the // public key. result = SchemeChecks(NULL, publicArea); } else { // For any sensitive area, make sure that the seedSize is no larger than the // digest size of nameAlg if(sensitive->seedValue.t.size > CryptHashGetDigestSize(publicArea->nameAlg)) return TPM_RCS_KEY_SIZE + blameSensitive; // Check attributes and schemes for consistency result = PublicAttributesValidation(parent, publicArea); } if(result != TPM_RC_SUCCESS) return RcSafeAddToResult(result, blamePublic); // If object == NULL, then this is am import. For import, load is not called // unless the parent is fixedTPM. if(object == NULL) doCheck = TRUE;// // // If the parent is not NULL, then this is an ordinary load and we only check // if the parent is not fixedTPM else if(parent != NULL) doCheck = !IS_ATTRIBUTE(parent->publicArea.objectAttributes, TPMA_OBJECT, fixedTPM); else // This is a loadExternal. Check everything. // Note: the check functions will filter things based on the name algorithm // and whether or not both parts are loaded. doCheck = TRUE; // Note: the parent will be NULL if this is a load external. CryptValidateKeys() // will only check the parts that need to be checked based on the settings // of publicOnly and nameAlg. // Note: For an RSA key, the keys sizes are checked but the binding is not // checked. if(doCheck) { // Do the cryptographic key validation result = CryptValidateKeys(publicArea, sensitive, blamePublic, blameSensitive); } // If this is an import, we are done if(object == NULL || result != TPM_RC_SUCCESS) return result; // Set the name, if one was provided if(name != NULL) object->name = *name; else object->name.t.size = 0; // Initialize public object->publicArea = *publicArea; // If there is a sensitive area, load it if(sensitive == NULL) object->attributes.publicOnly = SET; else { object->sensitive = *sensitive; #if ALG_RSA // If this is an RSA key that is not a parent, complete the load by // computing the private exponent. if(publicArea->type == ALG_RSA_VALUE) result = CryptRsaLoadPrivateExponent(object); #endif } return result; } /* 8.6.3.16 AllocateSequenceSlot() */ /* This function allocates a sequence slot and initializes the parts that are used by the normal objects so that a sequence object is not inadvertently used for an operation that is not appropriate for a sequence. */ static HASH_OBJECT * AllocateSequenceSlot( TPM_HANDLE *newHandle, // OUT: receives the allocated handle TPM2B_AUTH *auth // IN: the authValue for the slot ) { HASH_OBJECT *object = (HASH_OBJECT *)ObjectAllocateSlot(newHandle); // // Validate that the proper location of the hash state data relative to the // object state data. It would be good if this could have been done at compile // time but it can't so do it in something that can be removed after debug. cAssert(offsetof(HASH_OBJECT, auth) == offsetof(OBJECT, publicArea.authPolicy)); if(object != NULL) { // Set the common values that a sequence object shares with an ordinary object // First, clear all attributes MemorySet(&object->objectAttributes, 0, sizeof(TPMA_OBJECT)); // The type is TPM_ALG_NULL object->type = TPM_ALG_NULL; // This has no name algorithm and the name is the Empty Buffer object->nameAlg = TPM_ALG_NULL; // A sequence object is considered to be in the NULL hierarchy so it should // be marked as temporary so that it can't be persisted object->attributes.temporary = SET; // A sequence object is DA exempt. SET_ATTRIBUTE(object->objectAttributes, TPMA_OBJECT, noDA); // Copy the authorization value if(auth != NULL) object->auth = *auth; else object->auth.t.size = 0; } return object; } /* 8.6.3.17 ObjectCreateHMACSequence() */ /* This function creates an internal HMAC sequence object. */ /* Error Returns Meaning */ /* TPM_RC_OBJECT_MEMORY if there is no free slot for an object */ #if CC_HMAC_Start || CC_MAC_Start TPM_RC ObjectCreateHMACSequence( TPMI_ALG_HASH hashAlg, // IN: hash algorithm OBJECT *keyObject, // IN: the object containing the HMAC key TPM2B_AUTH *auth, // IN: authValue TPMI_DH_OBJECT *newHandle // OUT: HMAC sequence object handle ) { HASH_OBJECT *hmacObject; // // Try to allocate a slot for new object hmacObject = AllocateSequenceSlot(newHandle, auth); if(hmacObject == NULL) return TPM_RC_OBJECT_MEMORY; // Set HMAC sequence bit hmacObject->attributes.hmacSeq = SET; #if !SMAC_IMPLEMENTED if(CryptHmacStart(&hmacObject->state.hmacState, hashAlg, keyObject->sensitive.sensitive.bits.b.size, keyObject->sensitive.sensitive.bits.b.buffer) == 0) #else if(CryptMacStart(&hmacObject->state.hmacState, &keyObject->publicArea.parameters, hashAlg, &keyObject->sensitive.sensitive.any.b) == 0) #endif // SMAC_IMPLEMENTED return TPM_RC_FAILURE; return TPM_RC_SUCCESS; } #endif /* 8.6.3.18 ObjectCreateHashSequence() */ /* This function creates a hash sequence object. */ /* Error Returns Meaning */ /* TPM_RC_OBJECT_MEMORY if there is no free slot for an object */ TPM_RC ObjectCreateHashSequence( TPMI_ALG_HASH hashAlg, // IN: hash algorithm TPM2B_AUTH *auth, // IN: authValue TPMI_DH_OBJECT *newHandle // OUT: sequence object handle ) { HASH_OBJECT *hashObject = AllocateSequenceSlot(newHandle, auth); // See if slot allocated if(hashObject == NULL) return TPM_RC_OBJECT_MEMORY; // Set hash sequence bit hashObject->attributes.hashSeq = SET; // Start hash for hash sequence CryptHashStart(&hashObject->state.hashState[0], hashAlg); return TPM_RC_SUCCESS; } /* 8.6.3.19 ObjectCreateEventSequence() */ /* This function creates an event sequence object. */ /* Error Returns Meaning */ /* TPM_RC_OBJECT_MEMORY if there is no free slot for an object */ TPM_RC ObjectCreateEventSequence( TPM2B_AUTH *auth, // IN: authValue TPMI_DH_OBJECT *newHandle // OUT: sequence object handle ) { HASH_OBJECT *hashObject = AllocateSequenceSlot(newHandle, auth); UINT32 count; TPM_ALG_ID hash; // See if slot allocated if(hashObject == NULL) return TPM_RC_OBJECT_MEMORY; // Set the event sequence attribute hashObject->attributes.eventSeq = SET; // Initialize hash states for each implemented PCR algorithms for(count = 0; (hash = CryptHashGetAlgByIndex(count)) != TPM_ALG_NULL; count++) CryptHashStart(&hashObject->state.hashState[count], hash); return TPM_RC_SUCCESS; } /* 8.6.3.20 ObjectTerminateEvent() */ /* This function is called to close out the event sequence and clean up the hash context states. */ void ObjectTerminateEvent( void ) { HASH_OBJECT *hashObject; int count; BYTE buffer[MAX_DIGEST_SIZE]; hashObject = (HASH_OBJECT *)HandleToObject(g_DRTMHandle); // Don't assume that this is a proper sequence object if(hashObject->attributes.eventSeq) { // If it is, close any open hash contexts. This is done in case // the cryptographic implementation has some context values that need to be // cleaned up (hygiene). // for(count = 0; CryptHashGetAlgByIndex(count) != TPM_ALG_NULL; count++) { CryptHashEnd(&hashObject->state.hashState[count], 0, buffer); } // Flush sequence object FlushObject(g_DRTMHandle); } g_DRTMHandle = TPM_RH_UNASSIGNED; } /* 8.6.3.21 ObjectContextLoad() */ /* This function loads an object from a saved object context. */ /* Return Values Meaning */ /* NULL if there is no free slot for an object */ /* NON_NULL points to the loaded object */ #if 0 // libtpms added OBJECT * ObjectContextLoad( ANY_OBJECT_BUFFER *object, // IN: pointer to object structure in saved // context TPMI_DH_OBJECT *handle // OUT: object handle ) { OBJECT *newObject = ObjectAllocateSlot(handle); // Try to allocate a slot for new object if(newObject != NULL) { // Copy the first part of the object MemoryCopy(newObject, object, offsetof(HASH_OBJECT, state)); // See if this is a sequence object if(ObjectIsSequence(newObject)) { // If this is a sequence object, import the data SequenceDataImport((HASH_OBJECT *)newObject, (HASH_OBJECT_BUFFER *)object); } else { // Copy input object data to internal structure MemoryCopy(newObject, object, sizeof(OBJECT)); } } return newObject; } #endif // libtpms added begin OBJECT * ObjectContextLoadLibtpms(BYTE *buffer, INT32 size, TPMI_DH_OBJECT *handle ) { OBJECT *newObject = ObjectAllocateSlot(handle); TPM_RC rc; BYTE *mybuf = buffer; INT32 mysize = size; pAssert(handle); // Try to allocate a slot for new object if(newObject != NULL) { rc = ANY_OBJECT_Unmarshal(newObject, &mybuf, &mysize, false); if (rc) { /* Attempt to load an old OBJECT that was copied out directly from * an older version of OBJECT. */ rc = OLD_OBJECTToOBJECT(newObject, buffer, size); if (rc) { FlushObject(*handle); newObject = NULL; } } } return newObject; } // libtpms added end /* 8.6.3.22 FlushObject() */ /* This function frees an object slot. */ /* This function requires that the object is loaded. */ void FlushObject( TPMI_DH_OBJECT handle // IN: handle to be freed ) { UINT32 index = handle - TRANSIENT_FIRST; pAssert(index < MAX_LOADED_OBJECTS); // Clear all the object attributes MemorySet((BYTE*)&(s_objects[index].attributes), 0, sizeof(OBJECT_ATTRIBUTES)); return; } /* 8.6.3.23 ObjectFlushHierarchy() */ /* This function is called to flush all the loaded transient objects associated with a hierarchy when the hierarchy is disabled. */ void ObjectFlushHierarchy( TPMI_RH_HIERARCHY hierarchy // IN: hierarchy to be flush ) { UINT16 i; // iterate object slots for(i = 0; i < MAX_LOADED_OBJECTS; i++) { if(s_objects[i].attributes.occupied) // If found an occupied slot { switch(hierarchy) { case TPM_RH_PLATFORM: if(s_objects[i].attributes.ppsHierarchy == SET) s_objects[i].attributes.occupied = FALSE; break; case TPM_RH_OWNER: if(s_objects[i].attributes.spsHierarchy == SET) s_objects[i].attributes.occupied = FALSE; break; case TPM_RH_ENDORSEMENT: if(s_objects[i].attributes.epsHierarchy == SET) s_objects[i].attributes.occupied = FALSE; break; default: FAIL(FATAL_ERROR_INTERNAL); break; } } } return; } /* 8.6.3.24 ObjectLoadEvict() */ /* This function loads a persistent object into a transient object slot. */ /* This function requires that handle is associated with a persistent object. */ /* Error Returns Meaning */ /* TPM_RC_HANDLE the persistent object does not exist or the associated hierarchy is disabled. */ /* TPM_RC_OBJECT_MEMORY no object slot */ TPM_RC ObjectLoadEvict( TPM_HANDLE *handle, // IN:OUT: evict object handle. If success, it // will be replace by the loaded object handle COMMAND_INDEX commandIndex // IN: the command being processed ) { TPM_RC result; TPM_HANDLE evictHandle = *handle; // Save the evict handle OBJECT *object; // If this is an index that references a persistent object created by // the platform, then return TPM_RH_HANDLE if the phEnable is FALSE if(*handle >= PLATFORM_PERSISTENT) { // belongs to platform if(g_phEnable == CLEAR) return TPM_RC_HANDLE; } // belongs to owner else if(gc.shEnable == CLEAR) return TPM_RC_HANDLE; // Try to allocate a slot for an object object = ObjectAllocateSlot(handle); if(object == NULL) return TPM_RC_OBJECT_MEMORY; // Copy persistent object to transient object slot. A TPM_RC_HANDLE // may be returned at this point. This will mark the slot as containing // a transient object so that it will be flushed at the end of the // command result = NvGetEvictObject(evictHandle, object); // Bail out if this failed if(result != TPM_RC_SUCCESS) return result; // check the object to see if it is in the endorsement hierarchy // if it is and this is not a TPM2_EvictControl() command, indicate // that the hierarchy is disabled. // If the associated hierarchy is disabled, make it look like the // handle is not defined if(ObjectGetHierarchy(object) == TPM_RH_ENDORSEMENT && gc.ehEnable == CLEAR && GetCommandCode(commandIndex) != TPM_CC_EvictControl) return TPM_RC_HANDLE; return result; } /* 8.6.3.25 ObjectComputeName() */ /* This does the name computation from a public area (can be marshaled or not). */ TPM2B_NAME * ObjectComputeName( UINT32 size, // IN: the size of the area to digest BYTE *publicArea, // IN: the public area to digest TPM_ALG_ID nameAlg, // IN: the hash algorithm to use TPM2B_NAME *name // OUT: Computed name ) { // Hash the publicArea into the name buffer leaving room for the nameAlg name->t.size = CryptHashBlock(nameAlg, size, publicArea, sizeof(name->t.name) - 2, &name->t.name[2]); // set the nameAlg UINT16_TO_BYTE_ARRAY(nameAlg, name->t.name); name->t.size += 2; return name; } /* 8.6.3.26 PublicMarshalAndComputeName() */ /* This function computes the Name of an object from its public area. */ TPM2B_NAME * PublicMarshalAndComputeName( TPMT_PUBLIC *publicArea, // IN: public area of an object TPM2B_NAME *name // OUT: name of the object ) { // Will marshal a public area into a template. This is because the internal // format for a TPM2B_PUBLIC is a structure and not a simple BYTE buffer. TPM2B_TEMPLATE marshaled; // this is big enough to hold a // marshaled TPMT_PUBLIC BYTE *buffer = (BYTE *)&marshaled.t.buffer; // if the nameAlg is NULL then there is no name. if(publicArea->nameAlg == TPM_ALG_NULL) name->t.size = 0; else { // Marshal the public area into its canonical form marshaled.t.size = TPMT_PUBLIC_Marshal(publicArea, &buffer, NULL); // and compute the name ObjectComputeName(marshaled.t.size, marshaled.t.buffer, publicArea->nameAlg, name); } return name; } /* 8.6.3.28 ComputeQualifiedName() */ /* This function computes the qualified name of an object. */ void ComputeQualifiedName( TPM_HANDLE parentHandle, // IN: parent's handle TPM_ALG_ID nameAlg, // IN: name hash TPM2B_NAME *name, // IN: name of the object TPM2B_NAME *qualifiedName // OUT: qualified name of the object ) { HASH_STATE hashState; // hash state TPM2B_NAME parentName; if(parentHandle == TPM_RH_UNASSIGNED) { MemoryCopy2B(&qualifiedName->b, &name->b, sizeof(qualifiedName->t.name)); *qualifiedName = *name; } else { GetQualifiedName(parentHandle, &parentName); // QN_A = hash_A (QN of parent || NAME_A) // Start hash qualifiedName->t.size = CryptHashStart(&hashState, nameAlg); // Add parent's qualified name CryptDigestUpdate2B(&hashState, &parentName.b); // Add self name CryptDigestUpdate2B(&hashState, &name->b); // Complete hash leaving room for the name algorithm CryptHashEnd(&hashState, qualifiedName->t.size, &qualifiedName->t.name[2]); UINT16_TO_BYTE_ARRAY(nameAlg, qualifiedName->t.name); qualifiedName->t.size += 2; } return; } /* 8.6.3.29 ObjectIsStorage() */ /* This function determines if an object has the attributes associated with a parent. A parent is an asymmetric or symmetric block cipher key that has its restricted and decrypt attributes SET, and sign CLEAR. */ /* Return Values Meaning */ /* TRUE if the object is a storage key */ /* FALSE if the object is not a storage key */ BOOL ObjectIsStorage( TPMI_DH_OBJECT handle // IN: object handle ) { OBJECT *object = HandleToObject(handle); TPMT_PUBLIC *publicArea = ((object != NULL) ? &object->publicArea : NULL); // return (publicArea != NULL && IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted) && IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, decrypt) && !IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign) && (object->publicArea.type == ALG_RSA_VALUE || object->publicArea.type == ALG_ECC_VALUE)); } /* 8.6.3.30 ObjectCapGetLoaded() */ /* This function returns a a list of handles of loaded object, starting from handle. Handle must be in the range of valid transient object handles, but does not have to be the handle of a loaded transient object. */ /* Return Values Meaning */ /* YES if there are more handles available */ /* NO all the available handles has been returned */ TPMI_YES_NO ObjectCapGetLoaded( TPMI_DH_OBJECT handle, // IN: start handle UINT32 count, // IN: count of returned handles TPML_HANDLE *handleList // OUT: list of handle ) { TPMI_YES_NO more = NO; UINT32 i; pAssert(HandleGetType(handle) == TPM_HT_TRANSIENT); // Initialize output handle list handleList->count = 0; // The maximum count of handles we may return is MAX_CAP_HANDLES if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES; // Iterate object slots to get loaded object handles for(i = handle - TRANSIENT_FIRST; i < MAX_LOADED_OBJECTS; i++) { if(s_objects[i].attributes.occupied == TRUE) { // A valid transient object can not be the copy of a persistent object pAssert(s_objects[i].attributes.evict == CLEAR); if(handleList->count < count) { // If we have not filled up the return list, add this object // handle to it handleList->handle[handleList->count] = i + TRANSIENT_FIRST; handleList->count++; } else { // If the return list is full but we still have loaded object // available, report this and stop iterating more = YES; break; } } } return more; } /* 8.6.3.31 ObjectCapGetTransientAvail() */ /* This function returns an estimate of the number of additional transient objects that could be loaded into the TPM. */ UINT32 ObjectCapGetTransientAvail( void ) { UINT32 i; UINT32 num = 0; // Iterate object slot to get the number of unoccupied slots for(i = 0; i < MAX_LOADED_OBJECTS; i++) { if(s_objects[i].attributes.occupied == FALSE) num++; } return num; } /* 8.6.3.32 ObjectGetPublicAttributes() */ /* Returns the attributes associated with an object handles. */ TPMA_OBJECT ObjectGetPublicAttributes( TPM_HANDLE handle ) { return HandleToObject(handle)->publicArea.objectAttributes; } #if 0 /* libtpms added */ OBJECT_ATTRIBUTES ObjectGetProperties( TPM_HANDLE handle ) { return HandleToObject(handle)->attributes; } #endif /* libtpms added */ libtpms-0.9.3/src/tpm2/ObjectChangeAuth_fp.h000066400000000000000000000077401421143571500206550ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: ObjectChangeAuth_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef OBJECTCHANGEAUTH_FP_H #define OBJECTCHANGEAUTH_FP_H typedef struct { TPMI_DH_OBJECT objectHandle; TPMI_DH_OBJECT parentHandle; TPM2B_AUTH newAuth; } ObjectChangeAuth_In; #define RC_ObjectChangeAuth_objectHandle (TPM_RC_H + TPM_RC_1) #define RC_ObjectChangeAuth_parentHandle (TPM_RC_H + TPM_RC_2) #define RC_ObjectChangeAuth_newAuth (TPM_RC_P + TPM_RC_1) typedef struct { TPM2B_PRIVATE outPrivate; } ObjectChangeAuth_Out; TPM_RC TPM2_ObjectChangeAuth( ObjectChangeAuth_In *in, // IN: input parameter list ObjectChangeAuth_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/ObjectCommands.c000066400000000000000000000565741421143571500177260ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Object Commands */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: ObjectCommands.c 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2021 */ /* */ /********************************************************************************/ #include "Tpm.h" #include "Object_spt_fp.h" #include "Create_fp.h" #if CC_Create // Conditional expansion of this file TPM_RC TPM2_Create( Create_In *in, // IN: input parameter list Create_Out *out // OUT: output parameter list ) { TPM_RC result = TPM_RC_SUCCESS; OBJECT *parentObject; OBJECT *newObject; TPMT_PUBLIC *publicArea; // Input Validation parentObject = HandleToObject(in->parentHandle); pAssert(parentObject != NULL); // Does parent have the proper attributes? if(!ObjectIsParent(parentObject)) return TPM_RCS_TYPE + RC_Create_parentHandle; // Get a slot for the creation newObject = FindEmptyObjectSlot(NULL); if(newObject == NULL) return TPM_RC_OBJECT_MEMORY; // If the TPM2B_PUBLIC was passed as a structure, marshal it into is canonical // form for processing // to save typing. publicArea = &newObject->publicArea; // Copy the input structure to the allocated structure *publicArea = in->inPublic.publicArea; // Check attributes in input public area. CreateChecks() checks the things that // are unique to creation and then validates the attributes and values that are // common to create and load. result = CreateChecks(parentObject, publicArea, in->inSensitive.sensitive.data.t.size); if(result != TPM_RC_SUCCESS) return RcSafeAddToResult(result, RC_Create_inPublic); // Clean up the authValue if necessary if(!AdjustAuthSize(&in->inSensitive.sensitive.userAuth, publicArea->nameAlg)) return TPM_RCS_SIZE + RC_Create_inSensitive; // Command Output // Create the object using the default TPM random-number generator result = CryptCreateObject(newObject, &in->inSensitive.sensitive, NULL); if(result != TPM_RC_SUCCESS) return result; // Fill in creation data FillInCreationData(in->parentHandle, publicArea->nameAlg, &in->creationPCR, &in->outsideInfo, &out->creationData, &out->creationHash); // Compute creation ticket TicketComputeCreation(EntityGetHierarchy(in->parentHandle), &newObject->name, &out->creationHash, &out->creationTicket); // Prepare output private data from sensitive SensitiveToPrivate(&newObject->sensitive, &newObject->name, parentObject, publicArea->nameAlg, &out->outPrivate); // Finish by copying the remaining return values out->outPublic.publicArea = newObject->publicArea; return TPM_RC_SUCCESS; } #endif // CC_Create #include "Tpm.h" #include "Load_fp.h" #if CC_Load // Conditional expansion of this file #include "Object_spt_fp.h" TPM_RC TPM2_Load( Load_In *in, // IN: input parameter list Load_Out *out // OUT: output parameter list ) { TPM_RC result = TPM_RC_SUCCESS; TPMT_SENSITIVE sensitive = {0}; // libtpms changed (valgrind) OBJECT *parentObject; OBJECT *newObject; // Input Validation // Don't get invested in loading if there is no place to put it. newObject = FindEmptyObjectSlot(&out->objectHandle); if(newObject == NULL) return TPM_RC_OBJECT_MEMORY; if(in->inPrivate.t.size == 0) return TPM_RCS_SIZE + RC_Load_inPrivate; parentObject = HandleToObject(in->parentHandle); pAssert(parentObject != NULL); // Is the object that is being used as the parent actually a parent. if(!ObjectIsParent(parentObject)) return TPM_RCS_TYPE + RC_Load_parentHandle; // Compute the name of object. If there isn't one, it is because the nameAlg is // not valid. PublicMarshalAndComputeName(&in->inPublic.publicArea, &out->name); if(out->name.t.size == 0) return TPM_RCS_HASH + RC_Load_inPublic; // Retrieve sensitive data. result = PrivateToSensitive(&in->inPrivate.b, &out->name.b, parentObject, in->inPublic.publicArea.nameAlg, &sensitive); if(result != TPM_RC_SUCCESS) return RcSafeAddToResult(result, RC_Load_inPrivate); // Internal Data Update // Load and validate object result = ObjectLoad(newObject, parentObject, &in->inPublic.publicArea, &sensitive, RC_Load_inPublic, RC_Load_inPrivate, &out->name); if(result == TPM_RC_SUCCESS) { // Set the common OBJECT attributes for a loaded object. ObjectSetLoadedAttributes(newObject, in->parentHandle, parentObject->seedCompatLevel); // libtpms added } return result; } #endif // CC_Load #include "Tpm.h" #include "LoadExternal_fp.h" #if CC_LoadExternal // Conditional expansion of this file #include "Object_spt_fp.h" TPM_RC TPM2_LoadExternal( LoadExternal_In *in, // IN: input parameter list LoadExternal_Out *out // OUT: output parameter list ) { TPM_RC result; OBJECT *object; TPMT_SENSITIVE *sensitive = NULL; // Input Validation // Don't get invested in loading if there is no place to put it. object = FindEmptyObjectSlot(&out->objectHandle); if(object == NULL) return TPM_RC_OBJECT_MEMORY; // If the hierarchy to be associated with this object is turned off, the object // cannot be loaded. if(!HierarchyIsEnabled(in->hierarchy)) return TPM_RCS_HIERARCHY + RC_LoadExternal_hierarchy; // For loading an object with both public and sensitive if(in->inPrivate.size != 0) { // An external object with a sensitive area can only be loaded in the // NULL hierarchy if(in->hierarchy != TPM_RH_NULL) return TPM_RCS_HIERARCHY + RC_LoadExternal_hierarchy; // An external object with a sensitive area must have fixedTPM == CLEAR // fixedParent == CLEAR so that it does not appear to be a key created by // this TPM. if(IS_ATTRIBUTE(in->inPublic.publicArea.objectAttributes, TPMA_OBJECT, fixedTPM) || IS_ATTRIBUTE(in->inPublic.publicArea.objectAttributes, TPMA_OBJECT, fixedParent) || IS_ATTRIBUTE(in->inPublic.publicArea.objectAttributes, TPMA_OBJECT, restricted)) return TPM_RCS_ATTRIBUTES + RC_LoadExternal_inPublic; // Have sensitive point to something other than NULL so that object // initialization will load the sensitive part too sensitive = &in->inPrivate.sensitiveArea; } // Need the name to initialize the object structure PublicMarshalAndComputeName(&in->inPublic.publicArea, &out->name); // Load and validate key result = ObjectLoad(object, NULL, &in->inPublic.publicArea, sensitive, RC_LoadExternal_inPublic, RC_LoadExternal_inPrivate, &out->name); if(result == TPM_RC_SUCCESS) { object->attributes.external = SET; // Set the common OBJECT attributes for a loaded object. ObjectSetLoadedAttributes(object, in->hierarchy, // if anything can be derived from an external object, // we make sure it always uses the old algorithm SEED_COMPAT_LEVEL_ORIGINAL); // libtpms added } return result; } #endif // CC_LoadExternal #include "Tpm.h" #include "ReadPublic_fp.h" #if CC_ReadPublic // Conditional expansion of this file TPM_RC TPM2_ReadPublic( ReadPublic_In *in, // IN: input parameter list ReadPublic_Out *out // OUT: output parameter list ) { OBJECT *object = HandleToObject(in->objectHandle); // Input Validation // Can not read public area of a sequence object if(ObjectIsSequence(object)) return TPM_RC_SEQUENCE; // Command Output out->outPublic.publicArea = object->publicArea; out->name = object->name; out->qualifiedName = object->qualifiedName; return TPM_RC_SUCCESS; } #endif // CC_ReadPublic #include "Tpm.h" #include "ActivateCredential_fp.h" #if CC_ActivateCredential // Conditional expansion of this file #include "Object_spt_fp.h" TPM_RC TPM2_ActivateCredential( ActivateCredential_In *in, // IN: input parameter list ActivateCredential_Out *out // OUT: output parameter list ) { TPM_RC result = TPM_RC_SUCCESS; OBJECT *object; // decrypt key OBJECT *activateObject; // key associated with credential TPM2B_DATA data; // credential data // Input Validation // Get decrypt key pointer object = HandleToObject(in->keyHandle); // Get certificated object pointer activateObject = HandleToObject(in->activateHandle); // input decrypt key must be an asymmetric, restricted decryption key if(!CryptIsAsymAlgorithm(object->publicArea.type) || !IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, decrypt) || !IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, restricted)) return TPM_RCS_TYPE + RC_ActivateCredential_keyHandle; // Command output // Decrypt input credential data via asymmetric decryption. A // TPM_RC_VALUE, TPM_RC_KEY or unmarshal errors may be returned at this // point result = CryptSecretDecrypt(object, NULL, IDENTITY_STRING, &in->secret, &data); if(result != TPM_RC_SUCCESS) { if(result == TPM_RC_KEY) return TPM_RC_FAILURE; return RcSafeAddToResult(result, RC_ActivateCredential_secret); } // Retrieve secret data. A TPM_RC_INTEGRITY error or unmarshal // errors may be returned at this point result = CredentialToSecret(&in->credentialBlob.b, &activateObject->name.b, &data.b, object, &out->certInfo); if(result != TPM_RC_SUCCESS) return RcSafeAddToResult(result, RC_ActivateCredential_credentialBlob); return TPM_RC_SUCCESS; } #endif // CC_ActivateCredential #include "Tpm.h" #include "MakeCredential_fp.h" #if CC_MakeCredential // Conditional expansion of this file #include "Object_spt_fp.h" TPM_RC TPM2_MakeCredential( MakeCredential_In *in, // IN: input parameter list MakeCredential_Out *out // OUT: output parameter list ) { TPM_RC result = TPM_RC_SUCCESS; OBJECT *object; TPM2B_DATA data; // Input Validation // Get object pointer object = HandleToObject(in->handle); // input key must be an asymmetric, restricted decryption key // NOTE: Needs to be restricted to have a symmetric value. if(!CryptIsAsymAlgorithm(object->publicArea.type) || !IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, decrypt) || !IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, restricted)) return TPM_RCS_TYPE + RC_MakeCredential_handle; // The credential information may not be larger than the digest size used for // the Name of the key associated with handle. if(in->credential.t.size > CryptHashGetDigestSize(object->publicArea.nameAlg)) return TPM_RCS_SIZE + RC_MakeCredential_credential; // Command Output // Make encrypt key and its associated secret structure. out->secret.t.size = sizeof(out->secret.t.secret); result = CryptSecretEncrypt(object, IDENTITY_STRING, &data, &out->secret); if(result != TPM_RC_SUCCESS) return result; // Prepare output credential data from secret SecretToCredential(&in->credential, &in->objectName.b, &data.b, object, &out->credentialBlob); return TPM_RC_SUCCESS; } #endif // CC_MakeCredential #include "Tpm.h" #include "Unseal_fp.h" #if CC_Unseal // Conditional expansion of this file TPM_RC TPM2_Unseal( Unseal_In *in, Unseal_Out *out ) { OBJECT *object; // Input Validation // Get pointer to loaded object object = HandleToObject(in->itemHandle); // Input handle must be a data object if(object->publicArea.type != TPM_ALG_KEYEDHASH) return TPM_RCS_TYPE + RC_Unseal_itemHandle; if(IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, decrypt) || IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, sign) || IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, restricted)) return TPM_RCS_ATTRIBUTES + RC_Unseal_itemHandle; // Command Output // Copy data out->outData = object->sensitive.sensitive.bits; return TPM_RC_SUCCESS; } #endif // CC_Unseal #include "Tpm.h" #include "ObjectChangeAuth_fp.h" #if CC_ObjectChangeAuth // Conditional expansion of this file #include "Object_spt_fp.h" TPM_RC TPM2_ObjectChangeAuth( ObjectChangeAuth_In *in, // IN: input parameter list ObjectChangeAuth_Out *out // OUT: output parameter list ) { TPMT_SENSITIVE sensitive; OBJECT *object = HandleToObject(in->objectHandle); TPM2B_NAME QNCompare; // Input Validation // Can not change authorization on sequence object if(ObjectIsSequence(object)) return TPM_RCS_TYPE + RC_ObjectChangeAuth_objectHandle; // Make sure that the authorization value is consistent with the nameAlg if(!AdjustAuthSize(&in->newAuth, object->publicArea.nameAlg)) return TPM_RCS_SIZE + RC_ObjectChangeAuth_newAuth; // Parent handle should be the parent of object handle. In this // implementation we verify this by checking the QN of object. Other // implementation may choose different method to verify this attribute. ComputeQualifiedName(in->parentHandle, object->publicArea.nameAlg, &object->name, &QNCompare); if(!MemoryEqual2B(&object->qualifiedName.b, &QNCompare.b)) return TPM_RCS_TYPE + RC_ObjectChangeAuth_parentHandle; // Command Output // Prepare the sensitive area with the new authorization value sensitive = object->sensitive; sensitive.authValue = in->newAuth; // Protect the sensitive area SensitiveToPrivate(&sensitive, &object->name, HandleToObject(in->parentHandle), object->publicArea.nameAlg, &out->outPrivate); return TPM_RC_SUCCESS; } #endif // CC_ObjectChangeAuth #include "Tpm.h" #include "CreateLoaded_fp.h" #if CC_CreateLoaded // Conditional expansion of this file TPM_RC TPM2_CreateLoaded( CreateLoaded_In *in, // IN: input parameter list CreateLoaded_Out *out // OUT: output parameter list ) { TPM_RC result = TPM_RC_SUCCESS; OBJECT *parent = HandleToObject(in->parentHandle); OBJECT *newObject; BOOL derivation; TPMT_PUBLIC *publicArea; RAND_STATE randState; RAND_STATE *rand = &randState; TPMS_DERIVE labelContext; SEED_COMPAT_LEVEL seedCompatLevel = SEED_COMPAT_LEVEL_LAST; // libtpms added // Input Validation // How the public area is unmarshaled is determined by the parent, so // see if parent is a derivation parent derivation = (parent != NULL && parent->attributes.derivation); // If the parent is an object, then make sure that it is either a parent or // derivation parent if(parent != NULL && !parent->attributes.isParent && !derivation) return TPM_RCS_TYPE + RC_CreateLoaded_parentHandle; // Get a spot in which to create the newObject newObject = FindEmptyObjectSlot(&out->objectHandle); if(newObject == NULL) return TPM_RC_OBJECT_MEMORY; // Do this to save typing publicArea = &newObject->publicArea; // Unmarshal the template into the object space. TPM2_Create() and // TPM2_CreatePrimary() have the publicArea unmarshaled by CommandDispatcher. // This command is different because of an unfortunate property of the // unique field of an ECC key. It is a structure rather than a single TPM2B. If // if had been a TPM2B, then the label and context could be within a TPM2B and // unmarshaled like other public areas. Since it is not, this command needs its // on template that is a TPM2B that is unmarshaled as a BYTE array with a // its own unmarshal function. result = UnmarshalToPublic(publicArea, &in->inPublic, derivation, &labelContext); if(result != TPM_RC_SUCCESS) return result + RC_CreateLoaded_inPublic; // Validate that the authorization size is appropriate if(!AdjustAuthSize(&in->inSensitive.sensitive.userAuth, publicArea->nameAlg)) return TPM_RCS_SIZE + RC_CreateLoaded_inSensitive; // Command output if(derivation) { TPMT_KEYEDHASH_SCHEME *scheme; scheme = &parent->publicArea.parameters.keyedHashDetail.scheme; // SP800-108 is the only KDF supported by this implementation and there is // no default hash algorithm. pAssert(scheme->details.xorr.hashAlg != TPM_ALG_NULL && scheme->details.xorr.kdf == TPM_ALG_KDF1_SP800_108); // Don't derive RSA keys if(publicArea->type == TPM_ALG_RSA) return TPM_RCS_TYPE + RC_CreateLoaded_inPublic; // sensitiveDataOrigin has to be CLEAR in a derived object. Since this // is specific to a derived object, it is checked here. if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sensitiveDataOrigin)) return TPM_RCS_ATTRIBUTES; // Check the reset of the attributes result = PublicAttributesValidation(parent, publicArea); if(result != TPM_RC_SUCCESS) return RcSafeAddToResult(result, RC_CreateLoaded_inPublic); // Process the template and sensitive areas to get the actual 'label' and // 'context' values to be used for this derivation. result = SetLabelAndContext(&labelContext, &in->inSensitive.sensitive.data); if(result != TPM_RC_SUCCESS) return result; // Set up the KDF for object generation DRBG_InstantiateSeededKdf((KDF_STATE *)rand, scheme->details.xorr.hashAlg, scheme->details.xorr.kdf, &parent->sensitive.sensitive.bits.b, &labelContext.label.b, &labelContext.context.b, TPM_MAX_DERIVATION_BITS); // Clear the sensitive size so that the creation functions will not try // to use this value. in->inSensitive.sensitive.data.t.size = 0; seedCompatLevel = parent->seedCompatLevel; // libtpms added } else { // Check attributes in input public area. CreateChecks() checks the things // that are unique to creation and then validates the attributes and values // that are common to create and load. result = CreateChecks(parent, publicArea, in->inSensitive.sensitive.data.t.size); if(result != TPM_RC_SUCCESS) return RcSafeAddToResult(result, RC_CreateLoaded_inPublic); // Creating a primary object if(parent == NULL) { TPM2B_NAME name; newObject->attributes.primary = SET; if(in->parentHandle == TPM_RH_ENDORSEMENT) newObject->attributes.epsHierarchy = SET; seedCompatLevel = HierarchyGetPrimarySeedCompatLevel(in->parentHandle); // libtpms added // If so, use the primary seed and the digest of the template // to seed the DRBG result = DRBG_InstantiateSeeded((DRBG_STATE *)rand, &HierarchyGetPrimarySeed(in->parentHandle)->b, PRIMARY_OBJECT_CREATION, (TPM2B *)PublicMarshalAndComputeName(publicArea,&name), &in->inSensitive.sensitive.data.b, seedCompatLevel); // libtpms added if (result != TPM_RC_SUCCESS) return result; } else // This is an ordinary object so use the normal random number generator rand = NULL; } // Internal data update // Create the object result = CryptCreateObject(newObject, &in->inSensitive.sensitive, rand); if(result != TPM_RC_SUCCESS) return result; // if this is not a Primary key and not a derived key, then return the sensitive // area if(parent != NULL && !derivation) // Prepare output private data from sensitive SensitiveToPrivate(&newObject->sensitive, &newObject->name, parent, newObject->publicArea.nameAlg, &out->outPrivate); else out->outPrivate.t.size = 0; // Set the remaining return values out->outPublic.publicArea = newObject->publicArea; out->name = newObject->name; // Set the remaining attributes for a loaded object ObjectSetLoadedAttributes(newObject, in->parentHandle, seedCompatLevel); // libtpms added return result; } #endif // CC_CreateLoaded libtpms-0.9.3/src/tpm2/Object_fp.h000066400000000000000000000207521421143571500167230ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Functions That Manage the Object Store of the TPM */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Object_fp.h 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2021 */ /* */ /********************************************************************************/ #ifndef OBJECT_FP_H #define OBJECT_FP_H void ObjectFlush( OBJECT *object ); void ObjectSetInUse( OBJECT *object ); BOOL ObjectStartup( void ); void ObjectCleanupEvict( void ); BOOL IsObjectPresent( TPMI_DH_OBJECT handle // IN: handle to be checked ); BOOL ObjectIsSequence( OBJECT *object // IN: handle to be checked ); OBJECT* HandleToObject( TPMI_DH_OBJECT handle // IN: handle of the object ); UINT16 GetName( TPMI_DH_OBJECT handle, // IN: handle of the object NAME *name // OUT: name of the object ); void GetQualifiedName( TPMI_DH_OBJECT handle, // IN: handle of the object TPM2B_NAME *qualifiedName // OUT: qualified name of the object ); TPMI_RH_HIERARCHY ObjectGetHierarchy( OBJECT *object // IN :object ); TPMI_RH_HIERARCHY GetHieriarchy( TPMI_DH_OBJECT handle // IN :object handle ); OBJECT * FindEmptyObjectSlot( TPMI_DH_OBJECT *handle // OUT: (optional) ); OBJECT * ObjectAllocateSlot( TPMI_DH_OBJECT *handle // OUT: handle of allocated object ); void ObjectSetLoadedAttributes( OBJECT *object, // IN: object attributes to finalize TPM_HANDLE parentHandle, // IN: the parent handle SEED_COMPAT_LEVEL seedCompatLevel // IN: seedCompatLevel to use for children ); TPM_RC ObjectLoad( OBJECT *object, // IN: pointer to object slot // object OBJECT *parent, // IN: (optional) the parent object TPMT_PUBLIC *publicArea, // IN: public area to be installed in the object TPMT_SENSITIVE *sensitive, // IN: (optional) sensitive area to be // installed in the object TPM_RC blamePublic, // IN: parameter number to associate with the // publicArea errors TPM_RC blameSensitive,// IN: parameter number to associate with the // sensitive area errors TPM2B_NAME *name // IN: (optional) ); TPM_RC ObjectCreateHMACSequence( TPMI_ALG_HASH hashAlg, // IN: hash algorithm OBJECT *keyObject, // IN: the object containing the HMAC key TPM2B_AUTH *auth, // IN: authValue TPMI_DH_OBJECT *newHandle // OUT: HMAC sequence object handle ); TPM_RC ObjectCreateHashSequence( TPMI_ALG_HASH hashAlg, // IN: hash algorithm TPM2B_AUTH *auth, // IN: authValue TPMI_DH_OBJECT *newHandle // OUT: sequence object handle ); TPM_RC ObjectCreateEventSequence( TPM2B_AUTH *auth, // IN: authValue TPMI_DH_OBJECT *newHandle // OUT: sequence object handle ); void ObjectTerminateEvent( void ); #if 0 // libtpms added OBJECT * ObjectContextLoad( ANY_OBJECT_BUFFER *object, // IN: pointer to object structure in saved // context TPMI_DH_OBJECT *handle // OUT: object handle ); #endif // libtpms added begin OBJECT * ObjectContextLoadLibtpms(BYTE *buffer, // IN: buffer holding the marshaled object INT32 size, // IN: size of buffer TPMI_DH_OBJECT *handle // OUT: object handle ); // libtpms added end void FlushObject( TPMI_DH_OBJECT handle // IN: handle to be freed ); void ObjectFlushHierarchy( TPMI_RH_HIERARCHY hierarchy // IN: hierarchy to be flush ); TPM_RC ObjectLoadEvict( TPM_HANDLE *handle, // IN:OUT: evict object handle. If success, it // will be replace by the loaded object handle COMMAND_INDEX commandIndex // IN: the command being processed ); TPM2B_NAME * ObjectComputeName( UINT32 size, // IN: the size of the area to digest BYTE *publicArea, // IN: the public area to digest area TPM_ALG_ID nameAlg, // IN: the hash algorithm to use TPM2B_NAME *name // OUT: Computed name ); TPM2B_NAME * PublicMarshalAndComputeName( TPMT_PUBLIC *publicArea, // IN: public area of an object TPM2B_NAME *name // OUT: name of the object ); TPMI_ALG_HASH AlgOfName( TPM2B_NAME *name ); void ComputeQualifiedName( TPM_HANDLE parentHandle, // IN: parent's name TPM_ALG_ID nameAlg, // IN: name hash TPM2B_NAME *name, // IN: name of the object TPM2B_NAME *qualifiedName // OUT: qualified name of the object ); BOOL ObjectIsStorage( TPMI_DH_OBJECT handle // IN: object handle ); TPMI_YES_NO ObjectCapGetLoaded( TPMI_DH_OBJECT handle, // IN: start handle UINT32 count, // IN: count of returned handles TPML_HANDLE *handleList // OUT: list of handle ); UINT32 ObjectCapGetTransientAvail( void ); TPMA_OBJECT ObjectGetPublicAttributes( TPM_HANDLE handle ); OBJECT_ATTRIBUTES ObjectGetProperties( TPM_HANDLE handle ); #endif libtpms-0.9.3/src/tpm2/Object_spt.c000066400000000000000000001661131421143571500171210ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Object Command Support */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Object_spt.c 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2021 */ /* */ /********************************************************************************/ /* 7.6 Object Command Support (Object_spt.c) */ /* 7.6.1 Includes */ #include "Tpm.h" #include "Object_spt_fp.h" /* 7.6.2 Local Functions */ /* 7.6.2.1 GetIV2BSize() */ /* Get the size of TPM2B_IV in canonical form that will be append to the start of the sensitive data. It includes both size of size field and size of iv data */ /* Return Values Meaning */ static UINT16 GetIV2BSize( OBJECT *protector // IN: the protector handle ) { TPM_ALG_ID symAlg; UINT16 keyBits; // Determine the symmetric algorithm and size of key if(protector == NULL) { // Use the context encryption algorithm and key size symAlg = CONTEXT_ENCRYPT_ALG; keyBits = CONTEXT_ENCRYPT_KEY_BITS; } else { symAlg = protector->publicArea.parameters.asymDetail.symmetric.algorithm; keyBits = protector->publicArea.parameters.asymDetail.symmetric.keyBits.sym; } // The IV size is a UINT16 size field plus the block size of the symmetric // algorithm return sizeof(UINT16) + CryptGetSymmetricBlockSize(symAlg, keyBits); } /* 7.6.2.2 ComputeProtectionKeyParms() */ /* This function retrieves the symmetric protection key parameters for the sensitive data The parameters retrieved from this function include encryption algorithm, key size in bit, and a TPM2B_SYM_KEY containing the key material as well as the key size in bytes This function is used for any action that requires encrypting or decrypting of the sensitive area of an object or a credential blob */ static void ComputeProtectionKeyParms( OBJECT *protector, // IN: the protector object TPM_ALG_ID hashAlg, // IN: hash algorithm for KDFa TPM2B *name, // IN: name of the object TPM2B *seedIn, /* IN: optional seed for duplication blob. */ // For non duplication blob, this parameter should be NULL TPM_ALG_ID *symAlg, // OUT: the symmetric algorithm UINT16 *keyBits, // OUT: the symmetric key size in bits TPM2B_SYM_KEY *symKey // OUT: the symmetric key ) { const TPM2B *seed = seedIn; // Determine the algorithms for the KDF and the encryption/decryption // For TPM_RH_NULL, using context settings if(protector == NULL) { // Use the context encryption algorithm and key size *symAlg = CONTEXT_ENCRYPT_ALG; symKey->t.size = CONTEXT_ENCRYPT_KEY_BYTES; *keyBits = CONTEXT_ENCRYPT_KEY_BITS; } else { TPMT_SYM_DEF_OBJECT *symDef; symDef = &protector->publicArea.parameters.asymDetail.symmetric; *symAlg = symDef->algorithm; *keyBits = symDef->keyBits.sym; symKey->t.size = (*keyBits + 7) / 8; } // Get seed for KDF if(seed == NULL) seed = GetSeedForKDF(protector); // KDFa to generate symmetric key and IV value CryptKDFa(hashAlg, seed, STORAGE_KEY, name, NULL, symKey->t.size * 8, symKey->t.buffer, NULL, FALSE); return; } /* 7.6.2.3 ComputeOuterIntegrity() */ /* The sensitive area parameter is a buffer that holds a space for the integrity value and the marshaled sensitive area. The caller should skip over the area set aside for the integrity value and compute the hash of the remainder of the object. The size field of sensitive is in unmarshaled form and the sensitive area contents is an array of bytes. */ static void ComputeOuterIntegrity( TPM2B *name, // IN: the name of the object OBJECT *protector, // IN: the object that // provides protection. For an object, // it is a parent. For a credential, it // is the encrypt object. For // a Temporary Object, it is NULL TPMI_ALG_HASH hashAlg, // IN: algorithm to use for integrity TPM2B *seedIn, // IN: an external seed may be provided for // duplication blob. For non duplication // blob, this parameter should be NULL UINT32 sensitiveSize, // IN: size of the marshaled sensitive data BYTE *sensitiveData, // IN: sensitive area TPM2B_DIGEST *integrity // OUT: integrity ) { HMAC_STATE hmacState; TPM2B_DIGEST hmacKey; const TPM2B *seed = seedIn; // // Get seed for KDF if(seed == NULL) seed = GetSeedForKDF(protector); // Determine the HMAC key bits hmacKey.t.size = CryptHashGetDigestSize(hashAlg); // KDFa to generate HMAC key CryptKDFa(hashAlg, seed, INTEGRITY_KEY, NULL, NULL, hmacKey.t.size * 8, hmacKey.t.buffer, NULL, FALSE); // Start HMAC and get the size of the digest which will become the integrity integrity->t.size = CryptHmacStart2B(&hmacState, hashAlg, &hmacKey.b); // Adding the marshaled sensitive area to the integrity value CryptDigestUpdate(&hmacState.hashState, sensitiveSize, sensitiveData); // Adding name CryptDigestUpdate2B(&hmacState.hashState, name); // Compute HMAC CryptHmacEnd2B(&hmacState, &integrity->b); return; } /* 7.6.2.4 ComputeInnerIntegrity() */ /* This function computes the integrity of an inner wrap */ static void ComputeInnerIntegrity( TPM_ALG_ID hashAlg, // IN: hash algorithm for inner wrap TPM2B *name, // IN: the name of the object UINT16 dataSize, // IN: the size of sensitive data BYTE *sensitiveData, // IN: sensitive data TPM2B_DIGEST *integrity // OUT: inner integrity ) { HASH_STATE hashState; // // Start hash and get the size of the digest which will become the integrity integrity->t.size = CryptHashStart(&hashState, hashAlg); // Adding the marshaled sensitive area to the integrity value CryptDigestUpdate(&hashState, dataSize, sensitiveData); // Adding name CryptDigestUpdate2B(&hashState, name); // Compute hash CryptHashEnd2B(&hashState, &integrity->b); return; } /* 7.6.2.5 ProduceInnerIntegrity() */ /* This function produces an inner integrity for regular private, credential or duplication blob It requires the sensitive data being marshaled to the innerBuffer, with the leading bytes reserved for integrity hash. It assume the sensitive data starts at address (innerBuffer + integrity size). This function integrity at the beginning of the inner buffer It returns the total size of buffer with the inner wrap */ static UINT16 ProduceInnerIntegrity( TPM2B *name, // IN: the name of the object TPM_ALG_ID hashAlg, // IN: hash algorithm for inner wrap UINT16 dataSize, /* IN: the size of sensitive data, excluding the leading integrity buffer size */ BYTE *innerBuffer // IN/OUT: inner buffer with sensitive data in // it. At input, the leading bytes of this // buffer is reserved for integrity ) { BYTE *sensitiveData; // pointer to the sensitive data TPM2B_DIGEST integrity; UINT16 integritySize; BYTE *buffer; // Auxiliary buffer pointer // sensitiveData points to the beginning of sensitive data in innerBuffer integritySize = sizeof(UINT16) + CryptHashGetDigestSize(hashAlg); sensitiveData = innerBuffer + integritySize; ComputeInnerIntegrity(hashAlg, name, dataSize, sensitiveData, &integrity); // Add integrity at the beginning of inner buffer buffer = innerBuffer; TPM2B_DIGEST_Marshal(&integrity, &buffer, NULL); return dataSize + integritySize; } /* 7.6.2.6 CheckInnerIntegrity() */ /* This function check integrity of inner blob */ /* Error Returns Meaning */ /* TPM_RC_INTEGRITY if the outer blob integrity is bad */ /* unmarshal errors unmarshal errors while unmarshaling integrity */ static TPM_RC CheckInnerIntegrity( TPM2B *name, // IN: the name of the object TPM_ALG_ID hashAlg, // IN: hash algorithm for inner wrap UINT16 dataSize, // IN: the size of sensitive data, including the // leading integrity buffer size BYTE *innerBuffer // IN/OUT: inner buffer with sensitive data in // it ) { TPM_RC result; TPM2B_DIGEST integrity; TPM2B_DIGEST integrityToCompare; BYTE *buffer; // Auxiliary buffer pointer INT32 size; // Unmarshal integrity buffer = innerBuffer; size = (INT32)dataSize; result = TPM2B_DIGEST_Unmarshal(&integrity, &buffer, &size); if(result == TPM_RC_SUCCESS) { // Compute integrity to compare ComputeInnerIntegrity(hashAlg, name, (UINT16)size, buffer, &integrityToCompare); // Compare outer blob integrity if(!MemoryEqual2B(&integrity.b, &integrityToCompare.b)) result = TPM_RC_INTEGRITY; } return result; } /* 7.6.3 Public Functions */ /* 7.6.3.1 AdjustAuthSize() */ /* This function will validate that the input authValue is no larger than the digestSize for the nameAlg. It will then pad with zeros to the size of the digest. */ BOOL AdjustAuthSize( TPM2B_AUTH *auth, // IN/OUT: value to adjust TPMI_ALG_HASH nameAlg // IN: ) { UINT16 digestSize; // If there is no nameAlg, then this is a LoadExternal and the authVale can // be any size up to the maximum allowed by the implementation digestSize = (nameAlg == TPM_ALG_NULL) ? sizeof(TPMU_HA) : CryptHashGetDigestSize(nameAlg); if(digestSize < MemoryRemoveTrailingZeros(auth)) return FALSE; else if(digestSize > auth->t.size) MemoryPad2B(&auth->b, digestSize); auth->t.size = digestSize; return TRUE; } /* 7.6.3.2 AreAttributesForParent() */ /* This function is called by create, load, and import functions. */ /* NOTE: The isParent attribute is SET when an object is loaded and it has attributes that are suitable for a parent object. */ /* Return Values Meaning */ /* TRUE properties are those of a parent */ /* FALSE properties are not those of a parent */ BOOL ObjectIsParent( OBJECT *parentObject // IN: parent handle ) { return parentObject->attributes.isParent; } /* 7.6.3.3 CreateChecks() */ /* Attribute checks that are unique to creation. */ /* Error Returns Meaning */ /* TPM_RC_ATTRIBUTES sensitiveDataOrigin is not consistent with the object type */ /* other returns from PublicAttributesValidation() */ TPM_RC CreateChecks( OBJECT *parentObject, TPMT_PUBLIC *publicArea, UINT16 sensitiveDataSize ) { TPMA_OBJECT attributes = publicArea->objectAttributes; TPM_RC result = TPM_RC_SUCCESS; // // If the caller indicates that they have provided the data, then make sure that // they have provided some data. if((!IS_ATTRIBUTE(attributes, TPMA_OBJECT, sensitiveDataOrigin)) && (sensitiveDataSize == 0)) return TPM_RCS_ATTRIBUTES; // For an ordinary object, data can only be provided when sensitiveDataOrigin // is CLEAR if((parentObject != NULL) && (IS_ATTRIBUTE(attributes, TPMA_OBJECT, sensitiveDataOrigin)) && (sensitiveDataSize != 0)) return TPM_RCS_ATTRIBUTES; switch(publicArea->type) { case TPM_ALG_KEYEDHASH: // if this is a data object (sign == decrypt == CLEAR) then the // TPM cannot be the data source. if(!IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign) && !IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt) && IS_ATTRIBUTE(attributes, TPMA_OBJECT, sensitiveDataOrigin)) result = TPM_RC_ATTRIBUTES; // comment out the next line in order to prevent a fixedTPM derivation // parent // break; case TPM_ALG_SYMCIPHER: // A restricted key symmetric key (SYMCIPHER and KEYEDHASH) // must have sensitiveDataOrigin SET unless it has fixedParent and // fixedTPM CLEAR. if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted)) if(!IS_ATTRIBUTE(attributes, TPMA_OBJECT, sensitiveDataOrigin)) if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedParent) || IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM)) result = TPM_RCS_ATTRIBUTES; break; default: // Asymmetric keys cannot have the sensitive portion provided if(!IS_ATTRIBUTE(attributes, TPMA_OBJECT, sensitiveDataOrigin)) result = TPM_RCS_ATTRIBUTES; break; } if(TPM_RC_SUCCESS == result) { result = PublicAttributesValidation(parentObject, publicArea); } return result; } /* 7.6.3.4 SchemeChecks */ /* This function is called by TPM2_LoadExternal() and PublicAttributesValidation(). This function validates the schemes in the public area of an object. */ /* Error Returns Meaning */ /* TPM_RC_HASH non-duplicable storage key and its parent have different name algorithm */ /* TPM_RC_KDF incorrect KDF specified for decrypting keyed hash object */ /* TPM_RC_KEY invalid key size values in an asymmetric key public area */ /* TPM_RCS_SCHEME inconsistent attributes decrypt, sign, restricted and key's scheme ID; or hash algorithm is inconsistent with the scheme ID for keyed hash object */ /* TPM_RC_SYMMETRIC a storage key with no symmetric algorithm specified; or non-storage key with symmetric algorithm different from TPM_ALG_NULL */ TPM_RC SchemeChecks( OBJECT *parentObject, // IN: parent (null if primary seed) TPMT_PUBLIC *publicArea // IN: public area of the object ) { TPMT_SYM_DEF_OBJECT *symAlgs = NULL; TPM_ALG_ID scheme = TPM_ALG_NULL; TPMA_OBJECT attributes = publicArea->objectAttributes; TPMU_PUBLIC_PARMS *parms = &publicArea->parameters; // switch(publicArea->type) { case TPM_ALG_SYMCIPHER: symAlgs = &parms->symDetail.sym; // If this is a decrypt key, then only the block cipher modes (not // SMAC) are valid. TPM_ALG_NULL is OK too. If this is a 'sign' key, // then any mode that got through the unmarshaling is OK. if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt) && !CryptSymModeIsValid(symAlgs->mode.sym, TRUE)) return TPM_RCS_SCHEME; break; case TPM_ALG_KEYEDHASH: scheme = parms->keyedHashDetail.scheme.scheme; // if both sign and decrypt if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign) == IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt)) { // if both sign and decrypt are set or clear, then need // TPM_ALG_NULL as scheme if(scheme != TPM_ALG_NULL) return TPM_RCS_SCHEME; } else if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign) && scheme != TPM_ALG_HMAC) return TPM_RCS_SCHEME; else if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt)) { if(scheme != TPM_ALG_XOR) return TPM_RCS_SCHEME; // If this is a derivation parent, then the KDF needs to be // SP800-108 for this implementation. This is the only derivation // supported by this implementation. Other implementations could // support additional schemes. There is no default. if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted)) { if(parms->keyedHashDetail.scheme.details.xorr.kdf != TPM_ALG_KDF1_SP800_108) return TPM_RCS_SCHEME; // Must select a digest. if(CryptHashGetDigestSize (parms->keyedHashDetail.scheme.details.xorr.hashAlg) == 0) return TPM_RCS_HASH; } } break; default: // handling for asymmetric scheme = parms->asymDetail.scheme.scheme; symAlgs = &parms->asymDetail.symmetric; // if the key is both sign and decrypt, then the scheme must be // TPM_ALG_NULL because there is no way to specify both a sign and a // decrypt scheme in the key. if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign) == IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt)) { // scheme must be TPM_ALG_NULL if(scheme != TPM_ALG_NULL) return TPM_RCS_SCHEME; } else if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign)) { // If this is a signing key, see if it has a signing scheme if(CryptIsAsymSignScheme(publicArea->type, scheme)) { // if proper signing scheme then it needs a proper hash if(parms->asymDetail.scheme.details.anySig.hashAlg == TPM_ALG_NULL) return TPM_RCS_SCHEME; } else { // signing key that does not have a proper signing scheme. // This is OK if the key is not restricted and its scheme // is TPM_ALG_NULL if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted) || scheme != TPM_ALG_NULL) return TPM_RCS_SCHEME; } } else if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt)) { if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted)) { // for a restricted decryption key (a parent), scheme // is required to be TPM_ALG_NULL if(scheme != TPM_ALG_NULL) return TPM_RCS_SCHEME; } else { // For an unrestricted decryption key, the scheme has to // be a valid scheme or TPM_ALG_NULL if(scheme != TPM_ALG_NULL && !CryptIsAsymDecryptScheme(publicArea->type, scheme)) return TPM_RCS_SCHEME; } } if(!IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted) || !IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt)) { // For an asymmetric key that is not a parent, the symmetric // algorithms must be TPM_ALG_NULL if(symAlgs->algorithm != TPM_ALG_NULL) return TPM_RCS_SYMMETRIC; } // Special checks for an ECC key #if ALG_ECC if(publicArea->type == TPM_ALG_ECC) { TPM_ECC_CURVE curveID; const TPMT_ECC_SCHEME *curveScheme; curveID = publicArea->parameters.eccDetail.curveID; curveScheme = CryptGetCurveSignScheme(curveID); // The curveId must be valid or the unmarshaling is busted. pAssert(curveScheme != NULL); // If the curveID requires a specific scheme, then the key must // select the same scheme if(curveScheme->scheme != TPM_ALG_NULL) { TPMS_ECC_PARMS *ecc = &publicArea->parameters.eccDetail; if(scheme != curveScheme->scheme) return TPM_RCS_SCHEME; // The scheme can allow any hash, or not... if(curveScheme->details.anySig.hashAlg != TPM_ALG_NULL && (ecc->scheme.details.anySig.hashAlg != curveScheme->details.anySig.hashAlg)) return TPM_RCS_SCHEME; } // For now, the KDF must be TPM_ALG_NULL if(publicArea->parameters.eccDetail.kdf.scheme != TPM_ALG_NULL) return TPM_RCS_KDF; } #endif break; } // If this is a restricted decryption key with symmetric algorithms, then it // is an ordinary parent (not a derivation parent). It needs to specific // symmetric algorithms other than TPM_ALG_NULL if(symAlgs != NULL && IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted) && IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt)) { if(symAlgs->algorithm == TPM_ALG_NULL) return TPM_RCS_SYMMETRIC; #if 0 //?? // This next check is under investigation. Need to see if it will break Windows // before it is enabled. If it does not, then it should be default because a // the mode used with a parent is always CFB and Part 2 indicates as much. if(symAlgs->mode.sym != TPM_ALG_CFB) return TPM_RCS_MODE; #endif // If this parent is not duplicable, then the symmetric algorithms // (encryption and hash) must match those of its parent if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedParent) && (parentObject != NULL)) { if(publicArea->nameAlg != parentObject->publicArea.nameAlg) return TPM_RCS_HASH; if(!MemoryEqual(symAlgs, &parentObject->publicArea.parameters, sizeof(TPMT_SYM_DEF_OBJECT))) return TPM_RCS_SYMMETRIC; } } return TPM_RC_SUCCESS; } /* 7.6.3.5 PublicAttributesValidation() */ /* This function validates the values in the public area of an object. This function is used in the processing of TPM2_Create(), TPM2_CreatePrimary(), TPM2_CreateLoaded(), TPM2_Load(), TPM2_Import(), and TPM2_LoadExternal(). For TPM2_Import() this is only used if the new parent has fixedTPM SET. For TPM2_LoadExternal(), this is not used for a public-only key */ /* Error Returns Meaning */ /* TPM_RC_ATTRIBUTES fixedTPM, fixedParent, or encryptedDuplication attributes are inconsistent between themselves or with those of the parent object; inconsistent restricted, decrypt and sign attributes; attempt to inject sensitive data for an asymmetric key; attempt to create a symmetric cipher key that is not a decryption key */ /* TPM_RC_HASH nameAlg is TPM_ALG_NULL */ /* TPM_RC_SIZE authPolicy size does not match digest size of the name algorithm in publicArea */ /* other returns from SchemeChecks() */ TPM_RC PublicAttributesValidation( OBJECT *parentObject, // IN: input parent object TPMT_PUBLIC *publicArea // IN: public area of the object ) { TPMA_OBJECT attributes = publicArea->objectAttributes; TPMA_OBJECT parentAttributes = TPMA_ZERO_INITIALIZER(); // if(parentObject != NULL) parentAttributes = parentObject->publicArea.objectAttributes; if(publicArea->nameAlg == TPM_ALG_NULL) return TPM_RCS_HASH; // If there is an authPolicy, it needs to be the size of the digest produced // by the nameAlg of the object if((publicArea->authPolicy.t.size != 0 && (publicArea->authPolicy.t.size != CryptHashGetDigestSize(publicArea->nameAlg)))) return TPM_RCS_SIZE; // If the parent is fixedTPM (including a Primary Object) the object must have // the same value for fixedTPM and fixedParent if(parentObject == NULL || IS_ATTRIBUTE(parentAttributes, TPMA_OBJECT, fixedTPM)) { if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedParent) != IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM)) return TPM_RCS_ATTRIBUTES; } else { // The parent is not fixedTPM so the object can't be fixedTPM if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM)) return TPM_RCS_ATTRIBUTES; } // See if sign and decrypt are the same if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign) == IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt)) { // a restricted key cannot have both SET or both CLEAR if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted)) return TPM_RC_ATTRIBUTES; // only a data object may have both sign and decrypt CLEAR // BTW, since we know that decrypt==sign, no need to check both if(publicArea->type != TPM_ALG_KEYEDHASH && !IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign)) return TPM_RC_ATTRIBUTES; } // If the object can't be duplicated (directly or indirectly) then there // is no justification for having encryptedDuplication SET if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM) && IS_ATTRIBUTE(attributes, TPMA_OBJECT, encryptedDuplication)) return TPM_RCS_ATTRIBUTES; // If a parent object has fixedTPM CLEAR, the child must have the // same encryptedDuplication value as its parent. // Primary objects are considered to have a fixedTPM parent (the seeds). if(parentObject != NULL && !IS_ATTRIBUTE(parentAttributes, TPMA_OBJECT, fixedTPM)) { if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, encryptedDuplication) != IS_ATTRIBUTE(parentAttributes, TPMA_OBJECT, encryptedDuplication)) return TPM_RCS_ATTRIBUTES; } // Special checks for derived objects if((parentObject != NULL) && (parentObject->attributes.derivation == SET)) { // A derived object has the same settings for fixedTPM as its parent if(IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM) != IS_ATTRIBUTE(parentAttributes, TPMA_OBJECT, fixedTPM)) return TPM_RCS_ATTRIBUTES; // A derived object is required to be fixedParent if(!IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedParent)) return TPM_RCS_ATTRIBUTES; } return SchemeChecks(parentObject, publicArea); } /* 7.6.3.6 FillInCreationData() */ /* Fill in creation data for an object. */ void FillInCreationData( TPMI_DH_OBJECT parentHandle, // IN: handle of parent TPMI_ALG_HASH nameHashAlg, // IN: name hash algorithm TPML_PCR_SELECTION *creationPCR, // IN: PCR selection TPM2B_DATA *outsideData, // IN: outside data TPM2B_CREATION_DATA *outCreation, // OUT: creation data for output TPM2B_DIGEST *creationDigest // OUT: creation digest ) { BYTE creationBuffer[sizeof(TPMS_CREATION_DATA)]; BYTE *buffer; HASH_STATE hashState; // Fill in TPMS_CREATION_DATA in outCreation // Compute PCR digest PCRComputeCurrentDigest(nameHashAlg, creationPCR, &outCreation->creationData.pcrDigest); // Put back PCR selection list outCreation->creationData.pcrSelect = *creationPCR; // Get locality outCreation->creationData.locality = LocalityGetAttributes(_plat__LocalityGet()); outCreation->creationData.parentNameAlg = TPM_ALG_NULL; // If the parent is either a primary seed or TPM_ALG_NULL, then the Name // and QN of the parent are the parent's handle. if(HandleGetType(parentHandle) == TPM_HT_PERMANENT) { buffer = &outCreation->creationData.parentName.t.name[0]; outCreation->creationData.parentName.t.size = TPM_HANDLE_Marshal(&parentHandle, &buffer, NULL); // For a primary or temporary object, the parent name (a handle) and the // parent's QN are the same outCreation->creationData.parentQualifiedName = outCreation->creationData.parentName; } else // Regular object { OBJECT *parentObject = HandleToObject(parentHandle); // Set name algorithm outCreation->creationData.parentNameAlg = parentObject->publicArea.nameAlg; // Copy parent name outCreation->creationData.parentName = parentObject->name; // Copy parent qualified name outCreation->creationData.parentQualifiedName = parentObject->qualifiedName; } // Copy outside information outCreation->creationData.outsideInfo = *outsideData; // Marshal creation data to canonical form buffer = creationBuffer; outCreation->size = TPMS_CREATION_DATA_Marshal(&outCreation->creationData, &buffer, NULL); // Compute hash for creation field in public template creationDigest->t.size = CryptHashStart(&hashState, nameHashAlg); CryptDigestUpdate(&hashState, outCreation->size, creationBuffer); CryptHashEnd2B(&hashState, &creationDigest->b); return; } /* 7.6.3.7 GetSeedForKDF() */ /* Get a seed for KDF. The KDF for encryption and HMAC key use the same seed. */ /* Return Values Meaning */ const TPM2B * GetSeedForKDF( OBJECT *protector // IN: the protector handle ) { // Get seed for encryption key. Use input seed if provided. // Otherwise, using protector object's seedValue. TPM_RH_NULL is the only // exception that we may not have a loaded object as protector. In such a // case, use nullProof as seed. if(protector == NULL) return &gr.nullProof.b; else return &protector->sensitive.seedValue.b; } /* 7.6.3.8 ProduceOuterWrap() */ /* This function produce outer wrap for a buffer containing the sensitive data. It requires the sensitive data being marshaled to the outerBuffer, with the leading bytes reserved for integrity hash. If iv is used, iv space should be reserved at the beginning of the buffer. It assumes the sensitive data starts at address (outerBuffer + integrity size {+ iv size}). This function: */ /* a) adds IV before sensitive area if required */ /* b) encrypts sensitive data with IV or a NULL IV as required */ /* c) adds HMAC integrity at the beginning of the buffer */ /* d) returns the total size of blob with outer wrap */ UINT16 ProduceOuterWrap( OBJECT *protector, // IN: The handle of the object that provides // protection. For object, it is parent // handle. For credential, it is the handle // of encrypt object. TPM2B *name, // IN: the name of the object TPM_ALG_ID hashAlg, // IN: hash algorithm for outer wrap TPM2B *seed, // IN: an external seed may be provided for // duplication blob. For non duplication // blob, this parameter should be NULL BOOL useIV, // IN: indicate if an IV is used UINT16 dataSize, // IN: the size of sensitive data, excluding the // leading integrity buffer size or the // optional iv size BYTE *outerBuffer // IN/OUT: outer buffer with sensitive data in // it ) { TPM_ALG_ID symAlg; UINT16 keyBits; TPM2B_SYM_KEY symKey; TPM2B_IV ivRNG; // IV from RNG TPM2B_IV *iv = NULL; UINT16 ivSize = 0; // size of iv area, including the size field BYTE *sensitiveData; // pointer to the sensitive data TPM2B_DIGEST integrity; UINT16 integritySize; BYTE *buffer; // Auxiliary buffer pointer // Compute the beginning of sensitive data. The outer integrity should // always exist if this function is called to make an outer wrap integritySize = sizeof(UINT16) + CryptHashGetDigestSize(hashAlg); sensitiveData = outerBuffer + integritySize; // If iv is used, adjust the pointer of sensitive data and add iv before it if(useIV) { ivSize = GetIV2BSize(protector); // Generate IV from RNG. The iv data size should be the total IV area // size minus the size of size field ivRNG.t.size = ivSize - sizeof(UINT16); CryptRandomGenerate(ivRNG.t.size, ivRNG.t.buffer); // Marshal IV to buffer buffer = sensitiveData; TPM2B_IV_Marshal(&ivRNG, &buffer, NULL); // adjust sensitive data starting after IV area sensitiveData += ivSize; // Use iv for encryption iv = &ivRNG; } // Compute symmetric key parameters for outer buffer encryption ComputeProtectionKeyParms(protector, hashAlg, name, seed, &symAlg, &keyBits, &symKey); // Encrypt inner buffer in place CryptSymmetricEncrypt(sensitiveData, symAlg, keyBits, symKey.t.buffer, iv, TPM_ALG_CFB, dataSize, sensitiveData); // Compute outer integrity. Integrity computation includes the optional IV // area ComputeOuterIntegrity(name, protector, hashAlg, seed, dataSize + ivSize, outerBuffer + integritySize, &integrity); // Add integrity at the beginning of outer buffer buffer = outerBuffer; TPM2B_DIGEST_Marshal(&integrity, &buffer, NULL); // return the total size in outer wrap return dataSize + integritySize + ivSize; } /* 7.6.3.9 UnwrapOuter() */ /* This function remove the outer wrap of a blob containing sensitive data This function performs: */ /* a) check integrity of outer blob */ /* b) decrypt outer blob */ /* Error Returns Meaning */ /* TPM_RCS_INSUFFICIENT error during sensitive data unmarshaling */ /* TPM_RCS_INTEGRITY sensitive data integrity is broken */ /* TPM_RCS_SIZE error during sensitive data unmarshaling */ /* TPM_RCS_VALUE IV size for CFB does not match the encryption algorithm block size */ TPM_RC UnwrapOuter( OBJECT *protector, // IN: The object that provides // protection. For object, it is parent // handle. For credential, it is the // encrypt object. TPM2B *name, // IN: the name of the object TPM_ALG_ID hashAlg, // IN: hash algorithm for outer wrap TPM2B *seed, // IN: an external seed may be provided for // duplication blob. For non duplication // blob, this parameter should be NULL. BOOL useIV, // IN: indicates if an IV is used UINT16 dataSize, // IN: size of sensitive data in outerBuffer, // including the leading integrity buffer // size, and an optional iv area BYTE *outerBuffer // IN/OUT: sensitive data ) { TPM_RC result; TPM_ALG_ID symAlg = TPM_ALG_NULL; TPM2B_SYM_KEY symKey; UINT16 keyBits = 0; TPM2B_IV ivIn; // input IV retrieved from input buffer TPM2B_IV *iv = NULL; BYTE *sensitiveData; // pointer to the sensitive data TPM2B_DIGEST integrityToCompare; TPM2B_DIGEST integrity; INT32 size; // Unmarshal integrity sensitiveData = outerBuffer; size = (INT32)dataSize; result = TPM2B_DIGEST_Unmarshal(&integrity, &sensitiveData, &size); if(result == TPM_RC_SUCCESS) { // Compute integrity to compare ComputeOuterIntegrity(name, protector, hashAlg, seed, (UINT16)size, sensitiveData, &integrityToCompare); // Compare outer blob integrity if(!MemoryEqual2B(&integrity.b, &integrityToCompare.b)) return TPM_RCS_INTEGRITY; // Get the symmetric algorithm parameters used for encryption ComputeProtectionKeyParms(protector, hashAlg, name, seed, &symAlg, &keyBits, &symKey); // Retrieve IV if it is used if(useIV) { result = TPM2B_IV_Unmarshal(&ivIn, &sensitiveData, &size); if(result == TPM_RC_SUCCESS) { // The input iv size for CFB must match the encryption algorithm // block size if(ivIn.t.size != CryptGetSymmetricBlockSize(symAlg, keyBits)) result = TPM_RC_VALUE; else iv = &ivIn; } } } // If no errors, decrypt private in place. Since this function uses CFB, // CryptSymmetricDecrypt() will not return any errors. It may fail but it will // not return an error. if(result == TPM_RC_SUCCESS) CryptSymmetricDecrypt(sensitiveData, symAlg, keyBits, symKey.t.buffer, iv, TPM_ALG_CFB, (UINT16)size, sensitiveData); return result; } /* 7.6.3.10 MarshalSensitive() */ /* This function is used to marshal a sensitive area. Among other things, it adjusts the size of the authValue to be no smaller than the digest of nameAlg. Returns the size of the marshaled area. */ static UINT16 MarshalSensitive( BYTE *buffer, // OUT: receiving buffer TPMT_SENSITIVE *sensitive, // IN: the sensitive area to marshal TPMI_ALG_HASH nameAlg // IN: ) { BYTE *sizeField = buffer; // saved so that size can be // marshaled after it is known UINT16 retVal; // Pad the authValue if needed MemoryPad2B(&sensitive->authValue.b, CryptHashGetDigestSize(nameAlg)); buffer += 2; // Marshal the structure retVal = TPMT_SENSITIVE_Marshal(sensitive, &buffer, NULL); // Marshal the size retVal = (UINT16)(retVal + UINT16_Marshal(&retVal, &sizeField, NULL)); return retVal; } /* 7.6.3.11 SensitiveToPrivate() */ /* This function prepare the private blob for off the chip storage The operations in this function: */ /* a) marshal TPM2B_SENSITIVE structure into the buffer of TPM2B_PRIVATE */ /* b) apply encryption to the sensitive area. */ /* c) apply outer integrity computation. */ void SensitiveToPrivate( TPMT_SENSITIVE *sensitive, // IN: sensitive structure TPM2B_NAME *name, // IN: the name of the object OBJECT *parent, // IN: The parent object TPM_ALG_ID nameAlg, // IN: hash algorithm in public area. This // parameter is used when parentHandle is // NULL, in which case the object is // temporary. TPM2B_PRIVATE *outPrivate // OUT: output private structure ) { BYTE *sensitiveData; // pointer to the sensitive data UINT16 dataSize; // data blob size TPMI_ALG_HASH hashAlg; // hash algorithm for integrity UINT16 integritySize; UINT16 ivSize; // pAssert(name != NULL && name->t.size != 0); // Find the hash algorithm for integrity computation if(parent == NULL) { // For Temporary Object, using self name algorithm hashAlg = nameAlg; } else { // Otherwise, using parent's name algorithm hashAlg = parent->publicArea.nameAlg; } // Starting of sensitive data without wrappers sensitiveData = outPrivate->t.buffer; // Compute the integrity size integritySize = sizeof(UINT16) + CryptHashGetDigestSize(hashAlg); // Reserve space for integrity sensitiveData += integritySize; // Get iv size ivSize = GetIV2BSize(parent); // Reserve space for iv sensitiveData += ivSize; // Marshal the sensitive area including authValue size adjustments. dataSize = MarshalSensitive(sensitiveData, sensitive, nameAlg); //Produce outer wrap, including encryption and HMAC outPrivate->t.size = ProduceOuterWrap(parent, &name->b, hashAlg, NULL, TRUE, dataSize, outPrivate->t.buffer); return; } /* 7.6.3.12 PrivateToSensitive() */ /* Unwrap an input private area. Check the integrity, decrypt and retrieve data to a sensitive structure. The operations in this function: */ /* a) check the integrity HMAC of the input private area */ /* b) decrypt the private buffer */ /* c) unmarshal TPMT_SENSITIVE structure into the buffer of TPMT_SENSITIVE */ /* Error Returns Meaning */ /* TPM_RCS_INTEGRITY if the private area integrity is bad */ /* TPM_RC_SENSITIVE unmarshal errors while unmarshaling TPMS_ENCRYPT from input private */ /* TPM_RCS_SIZE error during sensitive data unmarshaling */ /* TPM_RCS_VALUE outer wrapper does not have an iV of the correct size */ TPM_RC PrivateToSensitive( TPM2B *inPrivate, // IN: input private structure TPM2B *name, // IN: the name of the object OBJECT *parent, // IN: parent object TPM_ALG_ID nameAlg, // IN: hash algorithm in public area. It is // passed separately because we only pass // name, rather than the whole public area // of the object. This parameter is used in // the following two cases: 1. primary // objects. 2. duplication blob with inner // wrap. In other cases, this parameter // will be ignored TPMT_SENSITIVE *sensitive // OUT: sensitive structure ) { TPM_RC result; BYTE *buffer; INT32 size; BYTE *sensitiveData; // pointer to the sensitive data UINT16 dataSize; UINT16 dataSizeInput; TPMI_ALG_HASH hashAlg; // hash algorithm for integrity UINT16 integritySize; UINT16 ivSize; // // Make sure that name is provided pAssert(name != NULL && name->size != 0); // Find the hash algorithm for integrity computation if(parent == NULL) { // For Temporary Object, using self name algorithm hashAlg = nameAlg; } else { // Otherwise, using parent's name algorithm hashAlg = parent->publicArea.nameAlg; } // unwrap outer result = UnwrapOuter(parent, name, hashAlg, NULL, TRUE, inPrivate->size, inPrivate->buffer); if(result != TPM_RC_SUCCESS) return result; // Compute the inner integrity size. integritySize = sizeof(UINT16) + CryptHashGetDigestSize(hashAlg); // Get iv size ivSize = GetIV2BSize(parent); // The starting of sensitive data and data size without outer wrapper sensitiveData = inPrivate->buffer + integritySize + ivSize; dataSize = inPrivate->size - integritySize - ivSize; // Unmarshal input data size buffer = sensitiveData; size = (INT32)dataSize; result = UINT16_Unmarshal(&dataSizeInput, &buffer, &size); if(result == TPM_RC_SUCCESS) { if((dataSizeInput + sizeof(UINT16)) != dataSize) result = TPM_RC_SENSITIVE; else { // Unmarshal sensitive buffer to sensitive structure result = TPMT_SENSITIVE_Unmarshal(sensitive, &buffer, &size); if(result != TPM_RC_SUCCESS || size != 0) { result = TPM_RC_SENSITIVE; } } } return result; } /* 7.6.3.13 SensitiveToDuplicate() */ /* This function prepare the duplication blob from the sensitive area. The operations in this function: */ /* a) marshal TPMT_SENSITIVE structure into the buffer of TPM2B_PRIVATE */ /* b) apply inner wrap to the sensitive area if required */ /* c) apply outer wrap if required */ void SensitiveToDuplicate( TPMT_SENSITIVE *sensitive, // IN: sensitive structure TPM2B *name, // IN: the name of the object OBJECT *parent, // IN: The new parent object TPM_ALG_ID nameAlg, // IN: hash algorithm in public area. It // is passed separately because we // only pass name, rather than the // whole public area of the object. TPM2B *seed, // IN: the external seed. If external // seed is provided with size of 0, // no outer wrap should be applied // to duplication blob. TPMT_SYM_DEF_OBJECT *symDef, // IN: Symmetric key definition. If the // symmetric key algorithm is NULL, // no inner wrap should be applied. TPM2B_DATA *innerSymKey, // IN/OUT: a symmetric key may be // provided to encrypt the inner // wrap of a duplication blob. May // be generated here if needed. TPM2B_PRIVATE *outPrivate // OUT: output private structure ) { BYTE *sensitiveData; // pointer to the sensitive data TPMI_ALG_HASH outerHash = TPM_ALG_NULL;// The hash algorithm for outer wrap TPMI_ALG_HASH innerHash = TPM_ALG_NULL;// The hash algorithm for inner wrap UINT16 dataSize; // data blob size BOOL doInnerWrap = FALSE; BOOL doOuterWrap = FALSE; // // Make sure that name is provided pAssert(name != NULL && name->size != 0); // Make sure symDef and innerSymKey are not NULL pAssert(symDef != NULL && innerSymKey != NULL); // Starting of sensitive data without wrappers sensitiveData = outPrivate->t.buffer; // Find out if inner wrap is required if(symDef->algorithm != TPM_ALG_NULL) { doInnerWrap = TRUE; // Use self nameAlg as inner hash algorithm innerHash = nameAlg; // Adjust sensitive data pointer sensitiveData += sizeof(UINT16) + CryptHashGetDigestSize(innerHash); } // Find out if outer wrap is required if(seed->size != 0) { doOuterWrap = TRUE; // Use parent nameAlg as outer hash algorithm outerHash = parent->publicArea.nameAlg; // Adjust sensitive data pointer sensitiveData += sizeof(UINT16) + CryptHashGetDigestSize(outerHash); } // Marshal sensitive area dataSize = MarshalSensitive(sensitiveData, sensitive, nameAlg); // Apply inner wrap for duplication blob. It includes both integrity and // encryption if(doInnerWrap) { BYTE *innerBuffer = NULL; BOOL symKeyInput = TRUE; innerBuffer = outPrivate->t.buffer; // Skip outer integrity space if(doOuterWrap) innerBuffer += sizeof(UINT16) + CryptHashGetDigestSize(outerHash); dataSize = ProduceInnerIntegrity(name, innerHash, dataSize, innerBuffer); // Generate inner encryption key if needed if(innerSymKey->t.size == 0) { innerSymKey->t.size = (symDef->keyBits.sym + 7) / 8; CryptRandomGenerate(innerSymKey->t.size, innerSymKey->t.buffer); // TPM generates symmetric encryption. Set the flag to FALSE symKeyInput = FALSE; } else { // assume the input key size should matches the symmetric definition pAssert(innerSymKey->t.size == (symDef->keyBits.sym + 7) / 8); } // Encrypt inner buffer in place CryptSymmetricEncrypt(innerBuffer, symDef->algorithm, symDef->keyBits.sym, innerSymKey->t.buffer, NULL, TPM_ALG_CFB, dataSize, innerBuffer); // If the symmetric encryption key is imported, clear the buffer for // output if(symKeyInput) innerSymKey->t.size = 0; } // Apply outer wrap for duplication blob. It includes both integrity and // encryption if(doOuterWrap) { dataSize = ProduceOuterWrap(parent, name, outerHash, seed, FALSE, dataSize, outPrivate->t.buffer); } // Data size for output outPrivate->t.size = dataSize; return; } /* 7.6.3.14 DuplicateToSensitive() */ /* Unwrap a duplication blob. Check the integrity, decrypt and retrieve data to a sensitive structure. The operations in this function: */ /* a) check the integrity HMAC of the input private area */ /* b) decrypt the private buffer */ /* c) unmarshal TPMT_SENSITIVE structure into the buffer of TPMT_SENSITIVE */ /* Error Returns Meaning */ /* TPM_RC_INSUFFICIENT unmarshaling sensitive data from inPrivate failed */ /* TPM_RC_INTEGRITY inPrivate data integrity is broken */ /* TPM_RC_SIZE unmarshaling sensitive data from inPrivate failed */ TPM_RC DuplicateToSensitive( TPM2B *inPrivate, // IN: input private structure TPM2B *name, // IN: the name of the object OBJECT *parent, // IN: the parent TPM_ALG_ID nameAlg, // IN: hash algorithm in public area. TPM2B *seed, // IN: an external seed may be provided. // If external seed is provided with // size of 0, no outer wrap is // applied TPMT_SYM_DEF_OBJECT *symDef, // IN: Symmetric key definition. If the // symmetric key algorithm is NULL, // no inner wrap is applied TPM2B *innerSymKey, // IN: a symmetric key may be provided // to decrypt the inner wrap of a // duplication blob. TPMT_SENSITIVE *sensitive // OUT: sensitive structure ) { TPM_RC result; BYTE *buffer; INT32 size; BYTE *sensitiveData; // pointer to the sensitive data UINT16 dataSize; UINT16 dataSizeInput; // Make sure that name is provided pAssert(name != NULL && name->size != 0); // Make sure symDef and innerSymKey are not NULL pAssert(symDef != NULL && innerSymKey != NULL); // Starting of sensitive data sensitiveData = inPrivate->buffer; dataSize = inPrivate->size; // Find out if outer wrap is applied if(seed->size != 0) { // Use parent nameAlg as outer hash algorithm TPMI_ALG_HASH outerHash = parent->publicArea.nameAlg; result = UnwrapOuter(parent, name, outerHash, seed, FALSE, dataSize, sensitiveData); if(result != TPM_RC_SUCCESS) return result; // Adjust sensitive data pointer and size sensitiveData += sizeof(UINT16) + CryptHashGetDigestSize(outerHash); dataSize -= sizeof(UINT16) + CryptHashGetDigestSize(outerHash); } // Find out if inner wrap is applied if(symDef->algorithm != TPM_ALG_NULL) { // assume the input key size matches the symmetric definition pAssert(innerSymKey->size == (symDef->keyBits.sym + 7) / 8); // Decrypt inner buffer in place CryptSymmetricDecrypt(sensitiveData, symDef->algorithm, symDef->keyBits.sym, innerSymKey->buffer, NULL, TPM_ALG_CFB, dataSize, sensitiveData); // Check inner integrity result = CheckInnerIntegrity(name, nameAlg, dataSize, sensitiveData); if(result != TPM_RC_SUCCESS) return result; // Adjust sensitive data pointer and size sensitiveData += sizeof(UINT16) + CryptHashGetDigestSize(nameAlg); dataSize -= sizeof(UINT16) + CryptHashGetDigestSize(nameAlg); } // Unmarshal input data size buffer = sensitiveData; size = (INT32)dataSize; result = UINT16_Unmarshal(&dataSizeInput, &buffer, &size); if(result == TPM_RC_SUCCESS) { if((dataSizeInput + sizeof(UINT16)) != dataSize) result = TPM_RC_SIZE; else { // Unmarshal sensitive buffer to sensitive structure result = TPMT_SENSITIVE_Unmarshal(sensitive, &buffer, &size); // if the results is OK make sure that all the data was unmarshaled if(result == TPM_RC_SUCCESS && size != 0) result = TPM_RC_SIZE; } } return result; } /* 7.6.3.15 SecretToCredential() */ /* This function prepare the credential blob from a secret (a TPM2B_DIGEST) The operations in this function: */ /* a) marshal TPM2B_DIGEST structure into the buffer of TPM2B_ID_OBJECT */ /* b) encrypt the private buffer, excluding the leading integrity HMAC area */ /* c) compute integrity HMAC and append to the beginning of the buffer. */ /* d) Set the total size of TPM2B_ID_OBJECT buffer */ void SecretToCredential( TPM2B_DIGEST *secret, // IN: secret information TPM2B *name, // IN: the name of the object TPM2B *seed, // IN: an external seed. OBJECT *protector, // IN: the protector TPM2B_ID_OBJECT *outIDObject // OUT: output credential ) { BYTE *buffer; // Auxiliary buffer pointer BYTE *sensitiveData; // pointer to the sensitive data TPMI_ALG_HASH outerHash; // The hash algorithm for outer wrap UINT16 dataSize; // data blob size pAssert(secret != NULL && outIDObject != NULL); // use protector's name algorithm as outer hash outerHash = protector->publicArea.nameAlg; // Marshal secret area to credential buffer, leave space for integrity sensitiveData = outIDObject->t.credential + sizeof(UINT16) + CryptHashGetDigestSize(outerHash); // Marshal secret area buffer = sensitiveData; dataSize = TPM2B_DIGEST_Marshal(secret, &buffer, NULL); // Apply outer wrap outIDObject->t.size = ProduceOuterWrap(protector, name, outerHash, seed, FALSE, dataSize, outIDObject->t.credential); return; } /* 7.6.3.16 CredentialToSecret() */ /* Unwrap a credential. Check the integrity, decrypt and retrieve data to a TPM2B_DIGEST structure. The operations in this function: */ /* a) check the integrity HMAC of the input credential area */ /* b) decrypt the credential buffer */ /* c) unmarshal TPM2B_DIGEST structure into the buffer of TPM2B_DIGEST */ /* Error Returns Meaning */ /* TPM_RC_INSUFFICIENT error during credential unmarshaling */ /* TPM_RC_INTEGRITY credential integrity is broken */ /* TPM_RC_SIZE error during credential unmarshaling */ /* TPM_RC_VALUE IV size does not match the encryption algorithm block size */ TPM_RC CredentialToSecret( TPM2B *inIDObject, // IN: input credential blob TPM2B *name, // IN: the name of the object TPM2B *seed, // IN: an external seed. OBJECT *protector, // IN: the protector TPM2B_DIGEST *secret // OUT: secret information ) { TPM_RC result; BYTE *buffer; INT32 size; TPMI_ALG_HASH outerHash; // The hash algorithm for outer wrap BYTE *sensitiveData; // pointer to the sensitive data UINT16 dataSize; // use protector's name algorithm as outer hash outerHash = protector->publicArea.nameAlg; // Unwrap outer, a TPM_RC_INTEGRITY error may be returned at this point result = UnwrapOuter(protector, name, outerHash, seed, FALSE, inIDObject->size, inIDObject->buffer); if(result == TPM_RC_SUCCESS) { // Compute the beginning of sensitive data sensitiveData = inIDObject->buffer + sizeof(UINT16) + CryptHashGetDigestSize(outerHash); dataSize = inIDObject->size - (sizeof(UINT16) + CryptHashGetDigestSize(outerHash)); // Unmarshal secret buffer to TPM2B_DIGEST structure buffer = sensitiveData; size = (INT32)dataSize; result = TPM2B_DIGEST_Unmarshal(secret, &buffer, &size); // If there were no other unmarshaling errors, make sure that the // expected amount of data was recovered if(result == TPM_RC_SUCCESS && size != 0) return TPM_RC_SIZE; } return result; } /* 7.6.3.17 MemoryRemoveTrailingZeros() */ /* This function is used to adjust the length of an authorization value. It adjusts the size of the TPM2B so that it does not include octets at the end of the buffer that contain zero. The function returns the number of non-zero octets in the buffer. */ UINT16 MemoryRemoveTrailingZeros( TPM2B_AUTH *auth // IN/OUT: value to adjust ) { while((auth->t.size > 0) && (auth->t.buffer[auth->t.size - 1] == 0)) auth->t.size--; return auth->t.size; } /* 7.6.3.18 SetLabelAndContext() */ /* This function sets the label and context for a derived key. It is possible that label or context can end up being an Empty Buffer. */ TPM_RC SetLabelAndContext( TPMS_DERIVE *labelContext, // IN/OUT: the recovered label and context TPM2B_SENSITIVE_DATA *sensitive // IN: the sensitive data ) { TPMS_DERIVE sensitiveValue; TPM_RC result; INT32 size; BYTE *buff; // // Unmarshal a TPMS_DERIVE from the TPM2B_SENSITIVE_DATA buffer // If there is something to unmarshal... if(sensitive->t.size != 0) { size = sensitive->t.size; buff = sensitive->t.buffer; result = TPMS_DERIVE_Unmarshal(&sensitiveValue, &buff, &size); if(result != TPM_RC_SUCCESS) return result; // If there was a label in the public area leave it there, otherwise, copy // the new value if(labelContext->label.t.size == 0) MemoryCopy2B(&labelContext->label.b, &sensitiveValue.label.b, sizeof(labelContext->label.t.buffer)); // if there was a context string in publicArea, it overrides if(labelContext->context.t.size == 0) MemoryCopy2B(&labelContext->context.b, &sensitiveValue.context.b, sizeof(labelContext->label.t.buffer)); } return TPM_RC_SUCCESS; } /* 7.6.3.19 UnmarshalToPublic() */ /* Support function to unmarshal the template. This is used because the Input may be a TPMT_TEMPLATE and that structure does not have the same size as a TPMT_PUBLIC() because of the difference between the unique and seed fields. If derive is not NULL, then the seed field is assumed to contain a label and context that are unmarshaled into derive. */ TPM_RC UnmarshalToPublic( TPMT_PUBLIC *tOut, // OUT: output TPM2B_TEMPLATE *tIn, // IN: BOOL derivation, // IN: indicates if this is for a derivation TPMS_DERIVE *labelContext // OUT: label and context if derivation ) { BYTE *buffer = tIn->t.buffer; INT32 size = tIn->t.size; TPM_RC result; // // make sure that tOut is zeroed so that there are no remnants from previous // uses MemorySet(tOut, 0, sizeof(TPMT_PUBLIC)); // Unmarshal the components of the TPMT_PUBLIC up to the unique field result = TPMI_ALG_PUBLIC_Unmarshal(&tOut->type, &buffer, &size); if(result != TPM_RC_SUCCESS) return result; result = TPMI_ALG_HASH_Unmarshal(&tOut->nameAlg, &buffer, &size, FALSE); if(result != TPM_RC_SUCCESS) return result; result = TPMA_OBJECT_Unmarshal(&tOut->objectAttributes, &buffer, &size); if(result != TPM_RC_SUCCESS) return result; result = TPM2B_DIGEST_Unmarshal(&tOut->authPolicy, &buffer, &size); if(result != TPM_RC_SUCCESS) return result; result = TPMU_PUBLIC_PARMS_Unmarshal(&tOut->parameters, &buffer, &size, tOut->type); if(result != TPM_RC_SUCCESS) return result; // Now unmarshal a TPMS_DERIVE if this is for derivation if(derivation) result = TPMS_DERIVE_Unmarshal(labelContext, &buffer, &size); else // otherwise, unmarshal a TPMU_PUBLIC_ID result = TPMU_PUBLIC_ID_Unmarshal(&tOut->unique, &buffer, &size, tOut->type); // Make sure the template was used up if((result == TPM_RC_SUCCESS) && (size != 0)) result = TPM_RC_SIZE; return result; } #if 0 /* libtpms added */ /* 7.6.3.20 ObjectSetExternal() */ /* Set the external attributes for an object. */ void ObjectSetExternal( OBJECT *object ) { object->attributes.external = SET; } #endif /* libtpms added */ libtpms-0.9.3/src/tpm2/Object_spt_fp.h000066400000000000000000000261401421143571500176060ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Object Command Support */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Object_spt_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ #ifndef OBJECT_SPT_FP_H #define OBJECT_SPT_FP_H BOOL AdjustAuthSize( TPM2B_AUTH *auth, // IN/OUT: value to adjust TPMI_ALG_HASH nameAlg // IN: ); BOOL ObjectIsParent( OBJECT *parentObject // IN: parent handle ); TPM_RC CreateChecks( OBJECT *parentObject, TPMT_PUBLIC *publicArea, UINT16 sensitiveDataSize ); TPM_RC SchemeChecks( OBJECT *parentObject, // IN: parent (null if primary seed) TPMT_PUBLIC *publicArea // IN: public area of the object ); TPM_RC PublicAttributesValidation( OBJECT *parentObject, // IN: input parent object TPMT_PUBLIC *publicArea // IN: public area of the object ); void FillInCreationData( TPMI_DH_OBJECT parentHandle, // IN: handle of parent TPMI_ALG_HASH nameHashAlg, // IN: name hash algorithm TPML_PCR_SELECTION *creationPCR, // IN: PCR selection TPM2B_DATA *outsideData, // IN: outside data TPM2B_CREATION_DATA *outCreation, // OUT: creation data for output TPM2B_DIGEST *creationDigest // OUT: creation digest ); const TPM2B * GetSeedForKDF( OBJECT *protector // IN: the protector handle ); UINT16 ProduceOuterWrap( OBJECT *protector, // IN: The handle of the object that provides // protection. For object, it is parent // handle. For credential, it is the handle // of encrypt object. TPM2B *name, // IN: the name of the object TPM_ALG_ID hashAlg, // IN: hash algorithm for outer wrap TPM2B *seed, // IN: an external seed may be provided for // duplication blob. For non duplication // blob, this parameter should be NULL BOOL useIV, // IN: indicate if an IV is used UINT16 dataSize, // IN: the size of sensitive data, excluding the // leading integrity buffer size or the // optional iv size BYTE *outerBuffer // IN/OUT: outer buffer with sensitive data in // it ); TPM_RC UnwrapOuter( OBJECT *protector, // IN: The object that provides // protection. For object, it is parent // handle. For credential, it is the // encrypt object. TPM2B *name, // IN: the name of the object TPM_ALG_ID hashAlg, // IN: hash algorithm for outer wrap TPM2B *seed, // IN: an external seed may be provided for // duplication blob. For non duplication // blob, this parameter should be NULL. BOOL useIV, // IN: indicates if an IV is used UINT16 dataSize, // IN: size of sensitive data in outerBuffer, // including the leading integrity buffer // size, and an optional iv area BYTE *outerBuffer // IN/OUT: sensitive data ); void SensitiveToPrivate( TPMT_SENSITIVE *sensitive, // IN: sensitive structure TPM2B_NAME *name, // IN: the name of the object OBJECT *parent, // IN: The parent object TPM_ALG_ID nameAlg, // IN: hash algorithm in public area. This // parameter is used when parentHandle is // NULL, in which case the object is // temporary. TPM2B_PRIVATE *outPrivate // OUT: output private structure ); TPM_RC PrivateToSensitive( TPM2B *inPrivate, // IN: input private structure TPM2B *name, // IN: the name of the object OBJECT *parent, // IN: parent object TPM_ALG_ID nameAlg, // IN: hash algorithm in public area. It is // passed separately because we only pass // name, rather than the whole public area // of the object. This parameter is used in // the following two cases: 1. primary // objects. 2. duplication blob with inner // wrap. In other cases, this parameter // will be ignored TPMT_SENSITIVE *sensitive // OUT: sensitive structure ); void SensitiveToDuplicate( TPMT_SENSITIVE *sensitive, // IN: sensitive structure TPM2B *name, // IN: the name of the object OBJECT *parent, // IN: The new parent object TPM_ALG_ID nameAlg, // IN: hash algorithm in public area. It // is passed separately because we // only pass name, rather than the // whole public area of the object. TPM2B *seed, // IN: the external seed. If external // seed is provided with size of 0, // no outer wrap should be applied // to duplication blob. TPMT_SYM_DEF_OBJECT *symDef, // IN: Symmetric key definition. If the // symmetric key algorithm is NULL, // no inner wrap should be applied. TPM2B_DATA *innerSymKey, // IN/OUT: a symmetric key may be // provided to encrypt the inner // wrap of a duplication blob. May // be generated here if needed. TPM2B_PRIVATE *outPrivate // OUT: output private structure ); TPM_RC DuplicateToSensitive( TPM2B *inPrivate, // IN: input private structure TPM2B *name, // IN: the name of the object OBJECT *parent, // IN: the parent TPM_ALG_ID nameAlg, // IN: hash algorithm in public area. TPM2B *seed, // IN: an external seed may be provided. // If external seed is provided with // size of 0, no outer wrap is // applied TPMT_SYM_DEF_OBJECT *symDef, // IN: Symmetric key definition. If the // symmetric key algorithm is NULL, // no inner wrap is applied TPM2B *innerSymKey, // IN: a symmetric key may be provided // to decrypt the inner wrap of a // duplication blob. TPMT_SENSITIVE *sensitive // OUT: sensitive structure ); void SecretToCredential( TPM2B_DIGEST *secret, // IN: secret information TPM2B *name, // IN: the name of the object TPM2B *seed, // IN: an external seed. OBJECT *protector, // IN: the protector TPM2B_ID_OBJECT *outIDObject // OUT: output credential ); TPM_RC CredentialToSecret( TPM2B *inIDObject, // IN: input credential blob TPM2B *name, // IN: the name of the object TPM2B *seed, // IN: an external seed. OBJECT *protector, // IN: the protector TPM2B_DIGEST *secret // OUT: secret information ); UINT16 MemoryRemoveTrailingZeros( TPM2B_AUTH *auth // IN/OUT: value to adjust ); TPM_RC SetLabelAndContext( TPMS_DERIVE *labelContext, // OUT: the recovered label and context TPM2B_SENSITIVE_DATA *sensitive // IN: the sensitive data ); TPM_RC UnmarshalToPublic( TPMT_PUBLIC *tOut, // OUT: output TPM2B_TEMPLATE *tIn, // IN: BOOL derivation, // IN: indicates if this is for a derivation TPMS_DERIVE *labelContext // OUT: label and context if derivation ); void ObjectSetHierarchy( OBJECT *object, TPM_HANDLE parentHandle, OBJECT *parent ); #if 0 /* libtpms added */ void ObjectSetExternal( OBJECT *object ); #endif /* libtpms added */ #endif libtpms-0.9.3/src/tpm2/PCR.c000066400000000000000000001177741421143571500154620ustar00rootroot00000000000000/********************************************************************************/ /* */ /* PCR access and manipulation */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PCR.c 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2021 */ /* */ /********************************************************************************/ /* 8.7 PCR.c */ /* 8.7.1 Introduction */ /* This function contains the functions needed for PCR access and manipulation. */ /* This implementation uses a static allocation for the PCR. The amount of memory is allocated based on the number of PCR in the implementation and the number of implemented hash algorithms. This is not the expected implementation. PCR SPACE DEFINITIONS. */ /* In the definitions below, the g_hashPcrMap is a bit array that indicates which of the PCR are implemented. The g_hashPcr array is an array of digests. In this implementation, the space is allocated whether the PCR is implemented or not. */ /* 8.7.2 Includes, Defines, and Data Definitions */ #define PCR_C #include "Tpm.h" /* The initial value of PCR attributes. The value of these fields should be consistent with PC Client specification In this implementation, we assume the total number of implemented PCR is 24. */ static const PCR_Attributes s_initAttributes[] = { // PCR 0 - 15, static RTM {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, {1, 0, 0x1F}, {0, 0x0F, 0x1F}, // PCR 16, Debug {0, 0x10, 0x1C}, // PCR 17, Locality 4 {0, 0x10, 0x1C}, // PCR 18, Locality 3 {0, 0x10, 0x0C}, // PCR 19, Locality 2 {0, 0x14, 0x0E}, // PCR 20, Locality 1 {0, 0x14, 0x04}, // PCR 21, Dynamic OS {0, 0x14, 0x04}, // PCR 22, Dynamic OS {0, 0x0F, 0x1F}, // PCR 23, Application specific {0, 0x0F, 0x1F} // PCR 24, testing policy }; /* 8.7.2 Functions */ /* 8.7.2.1 PCRBelongsAuthGroup() */ /* This function indicates if a PCR belongs to a group that requires an authValue in order to modify the PCR. If it does, groupIndex is set to value of the group index. This feature of PCR is decided by the platform specification. */ /* Return Type: BOOL */ /* TRUE: PCR belongs an authorization group */ /* FALSE: PCR does not belong an authorization group */ BOOL PCRBelongsAuthGroup( TPMI_DH_PCR handle, // IN: handle of PCR UINT32 *groupIndex // OUT: group index if PCR belongs a // group that allows authValue. If PCR // does not belong to an authorization // group, the value in this parameter is // invalid ) { #if defined NUM_AUTHVALUE_PCR_GROUP && NUM_AUTHVALUE_PCR_GROUP > 0 // Platform specification determines to which authorization group a PCR belongs // (if any). In this implementation, we assume there is only // one authorization group which contains PCR[20-22]. If the platform // specification requires differently, the implementation should be changed // accordingly if(handle >= 20 && handle <= 22) { *groupIndex = 0; return TRUE; } #endif return FALSE; } /* 8.7.2.2 PCRBelongsPolicyGroup() */ /* This function indicates if a PCR belongs to a group that requires a policy authorization in order to modify the PCR. If it does, groupIndex is set to value of the group index. This feature of PCR is decided by the platform specification. */ /* Return Values Meaning */ /* TRUE: PCR belongs to a policy group */ /* FALSE: PCR does not belong to a policy group */ BOOL PCRBelongsPolicyGroup( TPMI_DH_PCR handle, // IN: handle of PCR UINT32 *groupIndex // OUT: group index if PCR belongs a group that // allows policy. If PCR does not belong to // a policy group, the value in this // parameter is invalid ) { #if defined NUM_POLICY_PCR_GROUP && NUM_POLICY_PCR_GROUP > 0 // Platform specification decides if a PCR belongs to a policy group and // belongs to which group. In this implementation, we assume there is only // one policy group which contains PCR20-22. If the platform specification // requires differently, the implementation should be changed accordingly if(handle >= 20 && handle <= 22) { *groupIndex = 0; return TRUE; } #endif return FALSE; } /* 8.7.2.3 PCRBelongsTCBGroup() */ /* This function indicates if a PCR belongs to the TCB group. */ /* Return Values Meaning */ /* TRUE: PCR belongs to a TCB group */ /* FALSE: PCR does not belong to a TCB group */ static BOOL PCRBelongsTCBGroup( TPMI_DH_PCR handle // IN: handle of PCR ) { #if ENABLE_PCR_NO_INCREMENT == YES #if 0 // Platform specification decides if a PCR belongs to a TCB group. In this // implementation, we assume PCR[20-22] belong to TCB group. If the platform // specification requires differently, the implementation should be // changed accordingly if(handle >= 20 && handle <= 22) return TRUE; #endif /* kgold - changed for PC Client, 16, 21-23 no increment */ if ((handle == 16) || ((handle >= 21) && (handle <= 23))) { return TRUE; } #endif return FALSE; } /* 8.7.2.4 PCRPolicyIsAvailable() */ /* This function indicates if a policy is available for a PCR. */ /* Return Values Meaning */ /* TRUE the PCR may be authorized by policy */ /* FALSE the PCR does not allow policy */ BOOL PCRPolicyIsAvailable( TPMI_DH_PCR handle // IN: PCR handle ) { UINT32 groupIndex; return PCRBelongsPolicyGroup(handle, &groupIndex); } /* 8.7.2.5 PCRGetAuthValue() */ /* This function is used to access the authValue of a PCR. If PCR does not belong to an authValue group, an EmptyAuth() will be returned. */ TPM2B_AUTH * PCRGetAuthValue( TPMI_DH_PCR handle // IN: PCR handle ) { UINT32 groupIndex; if(PCRBelongsAuthGroup(handle, &groupIndex)) { return &gc.pcrAuthValues.auth[groupIndex]; } else { return NULL; } } /* 8.7.2.6 PCRGetAuthPolicy() */ /* This function is used to access the authorization policy of a PCR. It sets policy to the authorization policy and returns the hash algorithm for policy If the PCR does not allow a policy, TPM_ALG_NULL is returned. */ TPMI_ALG_HASH PCRGetAuthPolicy( TPMI_DH_PCR handle, // IN: PCR handle TPM2B_DIGEST *policy // OUT: policy of PCR ) { UINT32 groupIndex; if(PCRBelongsPolicyGroup(handle, &groupIndex)) { *policy = gp.pcrPolicies.policy[groupIndex]; return gp.pcrPolicies.hashAlg[groupIndex]; } else { policy->t.size = 0; return TPM_ALG_NULL; } } /* 8.7.2.7 PCRSimStart() */ /* This function is used to initialize the policies when a TPM is manufactured. This function would only be called in a manufacturing environment or in a TPM simulator. */ void PCRSimStart( void ) { UINT32 i; #if defined NUM_POLICY_PCR_GROUP && NUM_POLICY_PCR_GROUP > 0 for(i = 0; i < NUM_POLICY_PCR_GROUP; i++) { gp.pcrPolicies.hashAlg[i] = TPM_ALG_NULL; gp.pcrPolicies.policy[i].t.size = 0; } #endif #if defined NUM_AUTHVALUE_PCR_GROUP && NUM_AUTHVALUE_PCR_GROUP > 0 for(i = 0; i < NUM_AUTHVALUE_PCR_GROUP; i++) { gc.pcrAuthValues.auth[i].t.size = 0; } #endif // We need to give an initial configuration on allocated PCR before // receiving any TPM2_PCR_Allocate command to change this configuration // When the simulation environment starts, we allocate all the PCRs for(gp.pcrAllocated.count = 0; gp.pcrAllocated.count < HASH_COUNT; gp.pcrAllocated.count++) { gp.pcrAllocated.pcrSelections[gp.pcrAllocated.count].hash = CryptHashGetAlgByIndex(gp.pcrAllocated.count); gp.pcrAllocated.pcrSelections[gp.pcrAllocated.count].sizeofSelect = PCR_SELECT_MAX; for(i = 0; i < PCR_SELECT_MAX; i++) gp.pcrAllocated.pcrSelections[gp.pcrAllocated.count].pcrSelect[i] = 0xFF; } // Store the initial configuration to NV NV_SYNC_PERSISTENT(pcrPolicies); NV_SYNC_PERSISTENT(pcrAllocated); return; } /* 8.7.3.8 GetSavedPcrPointer() */ /* This function returns the address of an array of state saved PCR based on the hash algorithm. */ /* Return Values Meaning */ /* NULL no such algorithm */ /* not NULL pointer to the 0th byte of the 0th PCR */ static BYTE * GetSavedPcrPointer( TPM_ALG_ID alg, // IN: algorithm for bank UINT32 pcrIndex // IN: PCR index in PCR_SAVE ) { BYTE *retVal; switch(alg) { #define HASH_CASE(HASH, Hash) \ case TPM_ALG_##HASH: \ retVal = gc.pcrSave.Hash[pcrIndex]; \ break; FOR_EACH_HASH(HASH_CASE) #undef HASH_CASE default: FAIL(FATAL_ERROR_INTERNAL); } return retVal; } /* 8.7.2.9 PcrIsAllocated() */ /* This function indicates if a PCR number for the particular hash algorithm is allocated. */ /* Return Values Meaning */ /* FALSE PCR is not allocated */ /* TRUE PCR is allocated */ BOOL PcrIsAllocated( UINT32 pcr, // IN: The number of the PCR TPMI_ALG_HASH hashAlg // IN: The PCR algorithm ) { UINT32 i; BOOL allocated = FALSE; if(pcr < IMPLEMENTATION_PCR) { for(i = 0; i < gp.pcrAllocated.count; i++) { if(gp.pcrAllocated.pcrSelections[i].hash == hashAlg) { if(((gp.pcrAllocated.pcrSelections[i].pcrSelect[pcr / 8]) & (1 << (pcr % 8))) != 0) allocated = TRUE; else allocated = FALSE; break; } } } return allocated; } /* 8.7.3.10 GetPcrPointer() */ /* This function returns the address of an array of PCR based on the hash algorithm. */ /* Return Values Meaning */ /* NULL no such algorithm */ /* not NULL pointer to the 0th byte of the 0th PCR */ static BYTE * GetPcrPointer( TPM_ALG_ID alg, // IN: algorithm for bank UINT32 pcrNumber // IN: PCR number ) { static BYTE *pcr = NULL; if(!PcrIsAllocated(pcrNumber, alg)) return NULL; switch(alg) { #define HASH_CASE(HASH, Hash) \ case TPM_ALG_##HASH: \ pcr = s_pcrs[pcrNumber].Hash##Pcr; \ break; FOR_EACH_HASH(HASH_CASE) #undef HASH_CASE default: FAIL(FATAL_ERROR_INTERNAL); break; } return pcr; } /* 8.7.2.11 IsPcrSelected() */ /* This function indicates if an indicated PCR number is selected by the bit map in selection. */ /* Return Values Meaning */ /* FALSE PCR is not selected */ /* TRUE PCR is selected */ static BOOL IsPcrSelected( UINT32 pcr, // IN: The number of the PCR TPMS_PCR_SELECTION *selection // IN: The selection structure ) { BOOL selected; selected = (pcr < IMPLEMENTATION_PCR && ((selection->pcrSelect[pcr / 8]) & (1 << (pcr % 8))) != 0); return selected; } /* 8.7.2.12 FilterPcr() */ /* This function modifies a PCR selection array based on the implemented PCR. */ static void FilterPcr( TPMS_PCR_SELECTION *selection // IN: input PCR selection ) { UINT32 i; TPMS_PCR_SELECTION *allocated = NULL; // If size of select is less than PCR_SELECT_MAX, zero the unspecified PCR for(i = selection->sizeofSelect; i < PCR_SELECT_MAX; i++) selection->pcrSelect[i] = 0; // Find the internal configuration for the bank for(i = 0; i < gp.pcrAllocated.count; i++) { if(gp.pcrAllocated.pcrSelections[i].hash == selection->hash) { allocated = &gp.pcrAllocated.pcrSelections[i]; break; } } for(i = 0; i < selection->sizeofSelect; i++) { if(allocated == NULL) { // If the required bank does not exist, clear input selection selection->pcrSelect[i] = 0; } else selection->pcrSelect[i] &= allocated->pcrSelect[i]; } return; } /* 8.7.2.13 PcrDrtm() */ /* This function does the DRTM and H-CRTM processing it is called from _TPM_Hash_End(). */ void PcrDrtm( const TPMI_DH_PCR pcrHandle, // IN: the index of the PCR to be // modified const TPMI_ALG_HASH hash, // IN: the bank identifier const TPM2B_DIGEST *digest // IN: the digest to modify the PCR ) { BYTE *pcrData = GetPcrPointer(hash, pcrHandle); if(pcrData != NULL) { // Rest the PCR to zeros MemorySet(pcrData, 0, digest->t.size); // if the TPM has not started, then set the PCR to 0...04 and then extend if(!TPMIsStarted()) { pcrData[digest->t.size - 1] = 4; } // Now, extend the value PCRExtend(pcrHandle, hash, digest->t.size, (BYTE *)digest->t.buffer); } } /* 8.7.2.14 PCR_ClearAuth() */ /* This function is used to reset the PCR authorization values. It is called on TPM2_Startup(CLEAR) and TPM2_Clear(). */ void PCR_ClearAuth( void ) { #if defined NUM_AUTHVALUE_PCR_GROUP && NUM_AUTHVALUE_PCR_GROUP > 0 int j; for(j = 0; j < NUM_AUTHVALUE_PCR_GROUP; j++) { gc.pcrAuthValues.auth[j].t.size = 0; } #endif } /* 8.7.2.15 PCRStartup() */ /* This function initializes the PCR subsystem at TPM2_Startup(). */ BOOL PCRStartup( STARTUP_TYPE type, // IN: startup type BYTE locality // IN: startup locality ) { UINT32 pcr, j; UINT32 saveIndex = 0; g_pcrReConfig = FALSE; // Don't test for SU_RESET because that should be the default when nothing // else is selected if(type != SU_RESUME && type != SU_RESTART) { // PCR generation counter is cleared at TPM_RESET gr.pcrCounter = 0; } // Initialize/Restore PCR values for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++) { // On resume, need to know if this PCR had its state saved or not UINT32 stateSaved; if(type == SU_RESUME && s_initAttributes[pcr].stateSave == SET) { stateSaved = 1; } else { stateSaved = 0; PCRChanged(pcr); } // If this is the H-CRTM PCR and we are not doing a resume and we // had an H-CRTM event, then we don't change this PCR if(pcr == HCRTM_PCR && type != SU_RESUME && g_DrtmPreStartup == TRUE) continue; // Iterate each hash algorithm bank for(j = 0; j < gp.pcrAllocated.count; j++) { TPMI_ALG_HASH hash = gp.pcrAllocated.pcrSelections[j].hash; BYTE *pcrData = GetPcrPointer(hash, pcr); UINT16 pcrSize = CryptHashGetDigestSize(hash); if(pcrData != NULL) { // if state was saved if(stateSaved == 1) { // Restore saved PCR value BYTE *pcrSavedData; pcrSavedData = GetSavedPcrPointer( gp.pcrAllocated.pcrSelections[j].hash, saveIndex); if(pcrSavedData == NULL) return FALSE; MemoryCopy(pcrData, pcrSavedData, pcrSize); } else // PCR was not restored by state save { // If the reset locality of the PCR is 4, then // the reset value is all one's, otherwise it is // all zero. if((s_initAttributes[pcr].resetLocality & 0x10) != 0) MemorySet(pcrData, 0xFF, pcrSize); else { MemorySet(pcrData, 0, pcrSize); if(pcr == HCRTM_PCR) pcrData[pcrSize - 1] = locality; } } } } saveIndex += stateSaved; } // Reset authValues on TPM2_Startup(CLEAR) if(type != SU_RESUME) PCR_ClearAuth(); return TRUE; } /* 8.7.2.16 PCRStateSave() */ /* This function is used to save the PCR values that will be restored on TPM Resume. */ void PCRStateSave( TPM_SU type // IN: startup type ) { UINT32 pcr, j; UINT32 saveIndex = 0; // if state save CLEAR, nothing to be done. Return here if(type == TPM_SU_CLEAR) return; // Copy PCR values to the structure that should be saved to NV for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++) { UINT32 stateSaved = (s_initAttributes[pcr].stateSave == SET) ? 1 : 0; // Iterate each hash algorithm bank for(j = 0; j < gp.pcrAllocated.count; j++) { BYTE *pcrData; UINT32 pcrSize; pcrData = GetPcrPointer(gp.pcrAllocated.pcrSelections[j].hash, pcr); if(pcrData != NULL) { pcrSize = CryptHashGetDigestSize(gp.pcrAllocated.pcrSelections[j].hash); if(stateSaved == 1) { // Restore saved PCR value BYTE *pcrSavedData; pcrSavedData = GetSavedPcrPointer(gp.pcrAllocated.pcrSelections[j].hash, saveIndex); MemoryCopy(pcrSavedData, pcrData, pcrSize); } } } saveIndex += stateSaved; } return; } /* 8.7.2.17 PCRIsStateSaved() */ /* This function indicates if the selected PCR is a PCR that is state saved on TPM2_Shutdown(STATE). The return value is based on PCR attributes. */ /* Return Values Meaning */ /* TRUE PCR is state saved */ /* FALSE PCR is not state saved */ BOOL PCRIsStateSaved( TPMI_DH_PCR handle // IN: PCR handle to be extended ) { UINT32 pcr = handle - PCR_FIRST; if(s_initAttributes[pcr].stateSave == SET) return TRUE; else return FALSE; } /* 8.7.2.18 PCRIsResetAllowed() */ /* This function indicates if a PCR may be reset by the current command locality. The return value is based on PCR attributes, and not the PCR allocation. */ /* Return Values Meaning */ /* TRUE TPM2_PCR_Reset() is allowed */ /* FALSE TPM2_PCR_Reset() is not allowed */ BOOL PCRIsResetAllowed( TPMI_DH_PCR handle // IN: PCR handle to be extended ) { UINT8 commandLocality; UINT8 localityBits = 1; UINT32 pcr = handle - PCR_FIRST; // Check for the locality commandLocality = _plat__LocalityGet(); #ifdef DRTM_PCR // For a TPM that does DRTM, Reset is not allowed at locality 4 if(commandLocality == 4) return FALSE; #endif localityBits = localityBits << commandLocality; if((localityBits & s_initAttributes[pcr].resetLocality) == 0) return FALSE; else return TRUE; } /* 8.7.2.19 PCRChanged() */ /* This function checks a PCR handle to see if the attributes for the PCR are set so that any change to the PCR causes an increment of the pcrCounter. If it does, then the function increments the counter. Will also bump the counter if the handle is zero which means that PCR 0 can not be in the TCB group. Bump on zero is used by TPM2_Clear(). */ void PCRChanged( TPM_HANDLE pcrHandle // IN: the handle of the PCR that changed. ) { // For the reference implementation, the only change that does not cause // increment is a change to a PCR in the TCB group. if((pcrHandle == 0) || !PCRBelongsTCBGroup(pcrHandle)) { gr.pcrCounter++; if(gr.pcrCounter == 0) FAIL(FATAL_ERROR_COUNTER_OVERFLOW); } } /* 8.7.2.20 PCRIsExtendAllowed() */ /* This function indicates a PCR may be extended at the current command locality. The return value is based on PCR attributes, and not the PCR allocation. */ /* Return Values Meaning */ /* TRUE extend is allowed */ /* FALSE extend is not allowed */ BOOL PCRIsExtendAllowed( TPMI_DH_PCR handle // IN: PCR handle to be extended ) { UINT8 commandLocality; UINT8 localityBits = 1; UINT32 pcr = handle - PCR_FIRST; // Check for the locality commandLocality = _plat__LocalityGet(); localityBits = localityBits << commandLocality; if((localityBits & s_initAttributes[pcr].extendLocality) == 0) return FALSE; else return TRUE; } /* 8.7.2.21 PCRExtend() */ /* This function is used to extend a PCR in a specific bank. */ void PCRExtend( TPMI_DH_PCR handle, // IN: PCR handle to be extended TPMI_ALG_HASH hash, // IN: hash algorithm of PCR UINT32 size, // IN: size of data to be extended BYTE *data // IN: data to be extended ) { BYTE *pcrData; HASH_STATE hashState; UINT16 pcrSize; pcrData = GetPcrPointer(hash, handle - PCR_FIRST); // Extend PCR if it is allocated if(pcrData != NULL) { pcrSize = CryptHashGetDigestSize(hash); CryptHashStart(&hashState, hash); CryptDigestUpdate(&hashState, pcrSize, pcrData); CryptDigestUpdate(&hashState, size, data); CryptHashEnd(&hashState, pcrSize, pcrData); // PCR has changed so update the pcrCounter if necessary PCRChanged(handle); } return; } /* 8.7.2.22 PCRComputeCurrentDigest() */ /* This function computes the digest of the selected PCR. */ /* As a side-effect, selection is modified so that only the implemented PCR will have their bits still set. */ void PCRComputeCurrentDigest( TPMI_ALG_HASH hashAlg, // IN: hash algorithm to compute digest TPML_PCR_SELECTION *selection, // IN/OUT: PCR selection (filtered on // output) TPM2B_DIGEST *digest // OUT: digest ) { HASH_STATE hashState; TPMS_PCR_SELECTION *select; BYTE *pcrData; // will point to a digest UINT32 pcrSize; UINT32 pcr; UINT32 i; // Initialize the hash digest->t.size = CryptHashStart(&hashState, hashAlg); pAssert(digest->t.size > 0 && digest->t.size < UINT16_MAX); // Iterate through the list of PCR selection structures for(i = 0; i < selection->count; i++) { // Point to the current selection select = &selection->pcrSelections[i]; // Point to the current selection FilterPcr(select); // Clear out the bits for unimplemented PCR // Need the size of each digest pcrSize = CryptHashGetDigestSize(selection->pcrSelections[i].hash); // Iterate through the selection for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++) { if(IsPcrSelected(pcr, select)) // Is this PCR selected { // Get pointer to the digest data for the bank pcrData = GetPcrPointer(selection->pcrSelections[i].hash, pcr); pAssert(pcrData != NULL); CryptDigestUpdate(&hashState, pcrSize, pcrData); // add to digest } } } // Complete hash stack CryptHashEnd2B(&hashState, &digest->b); return; } /* 8.7.2.23 PCRRead() */ /* This function is used to read a list of selected PCR. If the requested PCR number exceeds the maximum number that can be output, the selection is adjusted to reflect the actual output PCR. */ void PCRRead( TPML_PCR_SELECTION *selection, // IN/OUT: PCR selection (filtered on // output) TPML_DIGEST *digest, // OUT: digest UINT32 *pcrCounter // OUT: the current value of PCR generation // number ) { TPMS_PCR_SELECTION *select; BYTE *pcrData; // will point to a digest UINT32 pcr; UINT32 i; digest->count = 0; // Iterate through the list of PCR selection structures for(i = 0; i < selection->count; i++) { // Point to the current selection select = &selection->pcrSelections[i]; // Point to the current selection FilterPcr(select); // Clear out the bits for unimplemented PCR // Iterate through the selection for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++) { if(IsPcrSelected(pcr, select)) // Is this PCR selected { // Check if number of digest exceed upper bound if(digest->count > 7) { // Clear rest of the current select bitmap while(pcr < IMPLEMENTATION_PCR // do not round up! && (pcr / 8) < select->sizeofSelect) { // do not round up! select->pcrSelect[pcr / 8] &= (BYTE)~(1 << (pcr % 8)); pcr++; } // Exit inner loop break; } // Need the size of each digest digest->digests[digest->count].t.size = CryptHashGetDigestSize(selection->pcrSelections[i].hash); // Get pointer to the digest data for the bank pcrData = GetPcrPointer(selection->pcrSelections[i].hash, pcr); pAssert(pcrData != NULL); // Add to the data to digest MemoryCopy(digest->digests[digest->count].t.buffer, pcrData, digest->digests[digest->count].t.size); digest->count++; } } // If we exit inner loop because we have exceed the output upper bound if(digest->count > 7 && pcr < IMPLEMENTATION_PCR) { // Clear rest of the selection while(i < selection->count) { MemorySet(selection->pcrSelections[i].pcrSelect, 0, selection->pcrSelections[i].sizeofSelect); i++; } // exit outer loop break; } } *pcrCounter = gr.pcrCounter; return; } /* 8.7.2.25 PCRAllocate() */ /* This function is used to change the PCR allocation. */ /* Error Returns Meaning */ /* TPM_RC_NO_RESULT allocate failed */ /* TPM_RC_PCR improper allocation */ TPM_RC PCRAllocate( TPML_PCR_SELECTION *allocate, // IN: required allocation UINT32 *maxPCR, // OUT: Maximum number of PCR UINT32 *sizeNeeded, // OUT: required space UINT32 *sizeAvailable // OUT: available space ) { UINT32 i, j, k; TPML_PCR_SELECTION newAllocate; // Initialize the flags to indicate if HCRTM PCR and DRTM PCR are allocated. BOOL pcrHcrtm = FALSE; BOOL pcrDrtm = FALSE; // Create the expected new PCR allocation based on the existing allocation // and the new input: // 1. if a PCR bank does not appear in the new allocation, the existing // allocation of this PCR bank will be preserved. // 2. if a PCR bank appears multiple times in the new allocation, only the // last one will be in effect. newAllocate = gp.pcrAllocated; for(i = 0; i < allocate->count; i++) { for(j = 0; j < newAllocate.count; j++) { // If hash matches, the new allocation covers the old allocation // for this particular bank. // The assumption is the initial PCR allocation (from manufacture) // has all the supported hash algorithms with an assigned bank // (possibly empty). So there must be a match for any new bank // allocation from the input. if(newAllocate.pcrSelections[j].hash == allocate->pcrSelections[i].hash) { newAllocate.pcrSelections[j] = allocate->pcrSelections[i]; break; } } // The j loop must exit with a match. pAssert(j < newAllocate.count); } // Max PCR in a bank is MIN(implemented PCR, PCR with attributes defined) *maxPCR = sizeof(s_initAttributes) / sizeof(PCR_Attributes); if(*maxPCR > IMPLEMENTATION_PCR) *maxPCR = IMPLEMENTATION_PCR; // Compute required size for allocation *sizeNeeded = 0; for(i = 0; i < newAllocate.count; i++) { UINT32 digestSize = CryptHashGetDigestSize(newAllocate.pcrSelections[i].hash); #if defined(DRTM_PCR) // Make sure that we end up with at least one DRTM PCR pcrDrtm = pcrDrtm || TestBit(DRTM_PCR, newAllocate.pcrSelections[i].pcrSelect, newAllocate.pcrSelections[i].sizeofSelect); #else // if DRTM PCR is not required, indicate that the allocation is OK pcrDrtm = TRUE; #endif #if defined(HCRTM_PCR) // and one HCRTM PCR (since this is usually PCR 0...) pcrHcrtm = pcrHcrtm || TestBit(HCRTM_PCR, newAllocate.pcrSelections[i].pcrSelect, newAllocate.pcrSelections[i].sizeofSelect); #else pcrHcrtm = TRUE; #endif for(j = 0; j < newAllocate.pcrSelections[i].sizeofSelect; j++) { BYTE mask = 1; for(k = 0; k < 8; k++) { if((newAllocate.pcrSelections[i].pcrSelect[j] & mask) != 0) *sizeNeeded += digestSize; mask = mask << 1; } } } if(!pcrDrtm || !pcrHcrtm) return TPM_RC_PCR; // In this particular implementation, we always have enough space to // allocate PCR. Different implementation may return a sizeAvailable less // than the sizeNeed. *sizeAvailable = sizeof(s_pcrs); // Save the required allocation to NV. Note that after NV is written, the // PCR allocation in NV is no longer consistent with the RAM data // gp.pcrAllocated. The NV version reflect the allocate after next // TPM_RESET, while the RAM version reflects the current allocation NV_WRITE_PERSISTENT(pcrAllocated, newAllocate); return TPM_RC_SUCCESS; } /* 8.7.2.26 PCRSetValue() */ /* This function is used to set the designated PCR in all banks to an initial value. The initial value is signed and will be sign extended into the entire PCR. */ void PCRSetValue( TPM_HANDLE handle, // IN: the handle of the PCR to set INT8 initialValue // IN: the value to set ) { int i; UINT32 pcr = handle - PCR_FIRST; TPMI_ALG_HASH hash; UINT16 digestSize; BYTE *pcrData; // Iterate supported PCR bank algorithms to reset for(i = 0; i < HASH_COUNT; i++) { hash = CryptHashGetAlgByIndex(i); // Prevent runaway if(hash == TPM_ALG_NULL) break; // Get a pointer to the data pcrData = GetPcrPointer(gp.pcrAllocated.pcrSelections[i].hash, pcr); // If the PCR is allocated if(pcrData != NULL) { // And the size of the digest digestSize = CryptHashGetDigestSize(hash); // Set the LSO to the input value pcrData[digestSize - 1] = initialValue; // Sign extend if(initialValue >= 0) MemorySet(pcrData, 0, digestSize - 1); else MemorySet(pcrData, -1, digestSize - 1); } } } /* 8.7.2.27 PCRResetDynamics */ /* This function is used to reset a dynamic PCR to 0. This function is used in DRTM sequence. */ void PCRResetDynamics( void ) { UINT32 pcr, i; // Initialize PCR values for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++) { // Iterate each hash algorithm bank for(i = 0; i < gp.pcrAllocated.count; i++) { BYTE *pcrData; UINT32 pcrSize; pcrData = GetPcrPointer(gp.pcrAllocated.pcrSelections[i].hash, pcr); if(pcrData != NULL) { pcrSize = CryptHashGetDigestSize(gp.pcrAllocated.pcrSelections[i].hash); // Reset PCR // Any PCR can be reset by locality 4 should be reset to 0 if((s_initAttributes[pcr].resetLocality & 0x10) != 0) MemorySet(pcrData, 0, pcrSize); } } } return; } /* 8.7.2.28 PCRCapGetAllocation() */ /* This function is used to get the current allocation of PCR banks. */ /* Return Values Meaning */ /* YES: if the return count is 0 */ /* NO: if the return count is not 0 */ TPMI_YES_NO PCRCapGetAllocation( UINT32 count, // IN: count of return TPML_PCR_SELECTION *pcrSelection // OUT: PCR allocation list ) { if(count == 0) { pcrSelection->count = 0; return YES; } else { *pcrSelection = gp.pcrAllocated; return NO; } } /* 8.7.2.29 PCRSetSelectBit() */ /* This function sets a bit in a bitmap array. */ static void PCRSetSelectBit( UINT32 pcr, // IN: PCR number BYTE *bitmap // OUT: bit map to be set ) { bitmap[pcr / 8] |= (1 << (pcr % 8)); return; } /* 8.7.2.30 PCRGetProperty() */ /* This function returns the selected PCR property. */ /* Return Values Meaning */ /* TRUE the property type is implemented */ /* FALSE the property type is not implemented */ static BOOL PCRGetProperty( TPM_PT_PCR property, TPMS_TAGGED_PCR_SELECT *select ) { UINT32 pcr; UINT32 groupIndex; select->tag = property; // Always set the bitmap to be the size of all PCR select->sizeofSelect = (IMPLEMENTATION_PCR + 7) / 8; // Initialize bitmap MemorySet(select->pcrSelect, 0, select->sizeofSelect); // Collecting properties for(pcr = 0; pcr < IMPLEMENTATION_PCR; pcr++) { switch(property) { case TPM_PT_PCR_SAVE: if(s_initAttributes[pcr].stateSave == SET) PCRSetSelectBit(pcr, select->pcrSelect); break; case TPM_PT_PCR_EXTEND_L0: if((s_initAttributes[pcr].extendLocality & 0x01) != 0) PCRSetSelectBit(pcr, select->pcrSelect); break; case TPM_PT_PCR_RESET_L0: if((s_initAttributes[pcr].resetLocality & 0x01) != 0) PCRSetSelectBit(pcr, select->pcrSelect); break; case TPM_PT_PCR_EXTEND_L1: if((s_initAttributes[pcr].extendLocality & 0x02) != 0) PCRSetSelectBit(pcr, select->pcrSelect); break; case TPM_PT_PCR_RESET_L1: if((s_initAttributes[pcr].resetLocality & 0x02) != 0) PCRSetSelectBit(pcr, select->pcrSelect); break; case TPM_PT_PCR_EXTEND_L2: if((s_initAttributes[pcr].extendLocality & 0x04) != 0) PCRSetSelectBit(pcr, select->pcrSelect); break; case TPM_PT_PCR_RESET_L2: if((s_initAttributes[pcr].resetLocality & 0x04) != 0) PCRSetSelectBit(pcr, select->pcrSelect); break; case TPM_PT_PCR_EXTEND_L3: if((s_initAttributes[pcr].extendLocality & 0x08) != 0) PCRSetSelectBit(pcr, select->pcrSelect); break; case TPM_PT_PCR_RESET_L3: if((s_initAttributes[pcr].resetLocality & 0x08) != 0) PCRSetSelectBit(pcr, select->pcrSelect); break; case TPM_PT_PCR_EXTEND_L4: if((s_initAttributes[pcr].extendLocality & 0x10) != 0) PCRSetSelectBit(pcr, select->pcrSelect); break; case TPM_PT_PCR_RESET_L4: if((s_initAttributes[pcr].resetLocality & 0x10) != 0) PCRSetSelectBit(pcr, select->pcrSelect); break; case TPM_PT_PCR_DRTM_RESET: // DRTM reset PCRs are the PCR reset by locality 4 if((s_initAttributes[pcr].resetLocality & 0x10) != 0) PCRSetSelectBit(pcr, select->pcrSelect); break; #if defined NUM_POLICY_PCR_GROUP && NUM_POLICY_PCR_GROUP > 0 case TPM_PT_PCR_POLICY: if(PCRBelongsPolicyGroup(pcr + PCR_FIRST, &groupIndex)) PCRSetSelectBit(pcr, select->pcrSelect); break; #endif #if defined NUM_AUTHVALUE_PCR_GROUP && NUM_AUTHVALUE_PCR_GROUP > 0 case TPM_PT_PCR_AUTH: if(PCRBelongsAuthGroup(pcr + PCR_FIRST, &groupIndex)) PCRSetSelectBit(pcr, select->pcrSelect); break; #endif #if ENABLE_PCR_NO_INCREMENT == YES case TPM_PT_PCR_NO_INCREMENT: if(PCRBelongsTCBGroup(pcr + PCR_FIRST)) PCRSetSelectBit(pcr, select->pcrSelect); break; #endif default: // If property is not supported, stop scanning PCR attributes // and return. return FALSE; break; } } return TRUE; } /* 8.7.2.31 PCRCapGetProperties() */ /* This function returns a list of PCR properties starting at property. */ /* Return Values Meaning */ /* YES: if no more property is available */ /* NO: if there are more properties not reported */ TPMI_YES_NO PCRCapGetProperties( TPM_PT_PCR property, // IN: the starting PCR property UINT32 count, // IN: count of returned properties TPML_TAGGED_PCR_PROPERTY *select // OUT: PCR select ) { TPMI_YES_NO more = NO; UINT32 i; // Initialize output property list select->count = 0; // The maximum count of properties we may return is MAX_PCR_PROPERTIES if(count > MAX_PCR_PROPERTIES) count = MAX_PCR_PROPERTIES; // TPM_PT_PCR_FIRST is defined as 0 in spec. It ensures that property // value would never be less than TPM_PT_PCR_FIRST cAssert(TPM_PT_PCR_FIRST == 0); // Iterate PCR properties. TPM_PT_PCR_LAST is the index of the last property // implemented on the TPM. for(i = property; i <= TPM_PT_PCR_LAST; i++) { if(select->count < count) { // If we have not filled up the return list, add more properties to it if(PCRGetProperty(i, &select->pcrProperty[select->count])) // only increment if the property is implemented select->count++; } else { // If the return list is full but we still have properties // available, report this and stop iterating. more = YES; break; } } return more; } /* 8.7.2.32 PCRCapGetHandles() */ /* This function is used to get a list of handles of PCR, started from handle. If handle exceeds the maximum PCR handle range, an empty list will be returned and the return value will be NO. */ /* Return Values Meaning */ /* YES if there are more handles available */ /* NO all the available handles has been returned */ TPMI_YES_NO PCRCapGetHandles( TPMI_DH_PCR handle, // IN: start handle UINT32 count, // IN: count of returned handles TPML_HANDLE *handleList // OUT: list of handle ) { TPMI_YES_NO more = NO; UINT32 i; pAssert(HandleGetType(handle) == TPM_HT_PCR); // Initialize output handle list handleList->count = 0; // The maximum count of handles we may return is MAX_CAP_HANDLES if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES; // Iterate PCR handle range for(i = handle & HR_HANDLE_MASK; i <= PCR_LAST; i++) { if(handleList->count < count) { // If we have not filled up the return list, add this PCR // handle to it handleList->handle[handleList->count] = i + PCR_FIRST; handleList->count++; } else { // If the return list is full but we still have PCR handle // available, report this and stop iterating more = YES; break; } } return more; } libtpms-0.9.3/src/tpm2/PCR_Allocate_fp.h000066400000000000000000000076421421143571500177500ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PCR_Allocate_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef PCR_ALLOCATE_FP_H #define PCR_ALLOCATE_FP_H typedef struct { TPMI_RH_PLATFORM authHandle; TPML_PCR_SELECTION pcrAllocation; } PCR_Allocate_In; #define RC_PCR_Allocate_authHandle (TPM_RC_H + TPM_RC_1) #define RC_PCR_Allocate_pcrAllocation (TPM_RC_P + TPM_RC_1) typedef struct { TPMI_YES_NO allocationSuccess; UINT32 maxPCR; UINT32 sizeNeeded; UINT32 sizeAvailable; } PCR_Allocate_Out; TPM_RC TPM2_PCR_Allocate( PCR_Allocate_In *in, // IN: input parameter list PCR_Allocate_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/PCR_Event_fp.h000066400000000000000000000074621421143571500173050ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PCR_Event_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef PCR_EVENT_FP_H #define PCR_EVENT_FP_H typedef struct { TPMI_DH_PCR pcrHandle; TPM2B_EVENT eventData; } PCR_Event_In; #define RC_PCR_Event_pcrHandle (TPM_RC_H + TPM_RC_1) #define RC_PCR_Event_eventData (TPM_RC_P + TPM_RC_1) typedef struct { TPML_DIGEST_VALUES digests; } PCR_Event_Out; TPM_RC TPM2_PCR_Event( PCR_Event_In *in, // IN: input parameter list PCR_Event_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/PCR_Extend_fp.h000066400000000000000000000072471421143571500174540ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PCR_Extend_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef PCR_EXTEND_FP_H #define PCR_EXTEND_FP_H typedef struct { TPMI_DH_PCR pcrHandle; TPML_DIGEST_VALUES digests; } PCR_Extend_In; #define RC_PCR_Extend_pcrHandle (TPM_RC_H + TPM_RC_1) #define RC_PCR_Extend_digests (TPM_RC_P + TPM_RC_1) TPM_RC TPM2_PCR_Extend( PCR_Extend_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/PCR_Read_fp.h000066400000000000000000000074511421143571500170750ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PCR_Read_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef PCR_READ_FP_H #define PCR_READ_FP_H typedef struct { TPML_PCR_SELECTION pcrSelectionIn; } PCR_Read_In; #define RC_PCR_Read_pcrSelectionIn (TPM_RC_P + TPM_RC_1) typedef struct { UINT32 pcrUpdateCounter; TPML_PCR_SELECTION pcrSelectionOut; TPML_DIGEST pcrValues; } PCR_Read_Out; TPM_RC TPM2_PCR_Read( PCR_Read_In *in, // IN: input parameter list PCR_Read_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/PCR_Reset_fp.h000066400000000000000000000071301421143571500172760ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PCR_Reset_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef PCR_RESET_FP_H #define PCR_RESET_FP_H typedef struct { TPMI_DH_PCR pcrHandle; } PCR_Reset_In; #define RC_PCR_Reset__pcrHandle (TPM_RC_H + TPM_RC_1) TPM_RC TPM2_PCR_Reset( PCR_Reset_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/PCR_SetAuthPolicy_fp.h000066400000000000000000000076351421143571500207630ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PCR_SetAuthPolicy_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef PCR_SETAUTHPOLICY_FP_H #define PCR_SETAUTHPOLICY_FP_H typedef struct { TPMI_RH_PLATFORM authHandle; TPM2B_DIGEST authPolicy; TPMI_ALG_HASH hashAlg; TPMI_DH_PCR pcrNum; } PCR_SetAuthPolicy_In; #define RC_PCR_SetAuthPolicy_authHandle (TPM_RC_H + TPM_RC_1) #define RC_PCR_SetAuthPolicy_authPolicy (TPM_RC_P + TPM_RC_1) #define RC_PCR_SetAuthPolicy_hashAlg (TPM_RC_P + TPM_RC_2) #define RC_PCR_SetAuthPolicy_pcrNum (TPM_RC_P + TPM_RC_3) TPM_RC TPM2_PCR_SetAuthPolicy( PCR_SetAuthPolicy_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/PCR_SetAuthValue_fp.h000066400000000000000000000073301421143571500205700ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PCR_SetAuthValue_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef PCR_SETAUTHVALUE_FP_H #define PCR_SETAUTHVALUE_FP_H typedef struct { TPMI_DH_PCR pcrHandle; TPM2B_DIGEST auth; } PCR_SetAuthValue_In; #define RC_PCR_SetAuthValue_pcrHandle (TPM_RC_H + TPM_RC_1) #define RC_PCR_SetAuthValue_auth (TPM_RC_P + TPM_RC_1) TPM_RC TPM2_PCR_SetAuthValue( PCR_SetAuthValue_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/PCR_fp.h000066400000000000000000000166201421143571500161400ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Functions Needed for PCR Access and Manipulation */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PCR_fp.h 1519 2019-11-15 20:43:51Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ #ifndef PCR_FP_H #define PCR_FP_H BOOL PCRBelongsAuthGroup( TPMI_DH_PCR handle, // IN: handle of PCR UINT32 *groupIndex // OUT: group index if PCR belongs a // group that allows authValue. If PCR // does not belong to an authorization // group, the value in this parameter is // invalid ); BOOL PCRBelongsPolicyGroup( TPMI_DH_PCR handle, // IN: handle of PCR UINT32 *groupIndex // OUT: group index if PCR belongs a group that // allows policy. If PCR does not belong to // a policy group, the value in this // parameter is invalid ); BOOL PCRPolicyIsAvailable( TPMI_DH_PCR handle // IN: PCR handle ); TPM2B_AUTH * PCRGetAuthValue( TPMI_DH_PCR handle // IN: PCR handle ); TPMI_ALG_HASH PCRGetAuthPolicy( TPMI_DH_PCR handle, // IN: PCR handle TPM2B_DIGEST *policy // OUT: policy of PCR ); void PCRSimStart( void ); BOOL PcrIsAllocated( UINT32 pcr, // IN: The number of the PCR TPMI_ALG_HASH hashAlg // IN: The PCR algorithm ); void PcrDrtm( const TPMI_DH_PCR pcrHandle, // IN: the index of the PCR to be // modified const TPMI_ALG_HASH hash, // IN: the bank identifier const TPM2B_DIGEST *digest // IN: the digest to modify the PCR ); void PCR_ClearAuth( void ); BOOL PCRStartup( STARTUP_TYPE type, // IN: startup type BYTE locality // IN: startup locality ); void PCRStateSave( TPM_SU type // IN: startup type ); BOOL PCRIsStateSaved( TPMI_DH_PCR handle // IN: PCR handle to be extended ); BOOL PCRIsResetAllowed( TPMI_DH_PCR handle // IN: PCR handle to be extended ); void PCRChanged( TPM_HANDLE pcrHandle // IN: the handle of the PCR that changed. ); BOOL PCRIsExtendAllowed( TPMI_DH_PCR handle // IN: PCR handle to be extended ); void PCRExtend( TPMI_DH_PCR handle, // IN: PCR handle to be extended TPMI_ALG_HASH hash, // IN: hash algorithm of PCR UINT32 size, // IN: size of data to be extended BYTE *data // IN: data to be extended ); void PCRComputeCurrentDigest( TPMI_ALG_HASH hashAlg, // IN: hash algorithm to compute digest TPML_PCR_SELECTION *selection, // IN/OUT: PCR selection (filtered on // output) TPM2B_DIGEST *digest // OUT: digest ); void PCRRead( TPML_PCR_SELECTION *selection, // IN/OUT: PCR selection (filtered on // output) TPML_DIGEST *digest, // OUT: digest UINT32 *pcrCounter // OUT: the current value of PCR generation // number ); TPM_RC PCRAllocate( TPML_PCR_SELECTION *allocate, // IN: required allocation UINT32 *maxPCR, // OUT: Maximum number of PCR UINT32 *sizeNeeded, // OUT: required space UINT32 *sizeAvailable // OUT: available space ); void PCRSetValue( TPM_HANDLE handle, // IN: the handle of the PCR to set INT8 initialValue // IN: the value to set ); void PCRResetDynamics( void ); TPMI_YES_NO PCRCapGetAllocation( UINT32 count, // IN: count of return TPML_PCR_SELECTION *pcrSelection // OUT: PCR allocation list ); TPMI_YES_NO PCRCapGetProperties( TPM_PT_PCR property, // IN: the starting PCR property UINT32 count, // IN: count of returned properties TPML_TAGGED_PCR_PROPERTY *select // OUT: PCR select ); TPMI_YES_NO PCRCapGetHandles( TPMI_DH_PCR handle, // IN: start handle UINT32 count, // IN: count of returned handles TPML_HANDLE *handleList // OUT: list of handle ); #endif libtpms-0.9.3/src/tpm2/PP.c000066400000000000000000000171231421143571500153400ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PP.c 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 */ /* */ /********************************************************************************/ /* 8.8 PP.c */ /* 8.8.1 Introduction */ /* This file contains the functions that support the physical presence operations of the TPM. */ /* 8.8.2 Includes */ #include "Tpm.h" /* 8.8.3 Functions */ /* 8.8.3.1 PhysicalPresencePreInstall_Init() */ /* This function is used to initialize the array of commands that always require confirmation with physical presence. The array is an array of bits that has a correspondence with the command code. */ /* This command should only ever be executable in a manufacturing setting or in a simulation. */ /* When set, these cannot be cleared. */ void PhysicalPresencePreInstall_Init( void ) { COMMAND_INDEX commandIndex; // Clear all the PP commands MemorySet(&gp.ppList, 0, sizeof(gp.ppList)); // Any command that is PP_REQUIRED should be SET for(commandIndex = 0; commandIndex < COMMAND_COUNT; commandIndex++) { if(s_commandAttributes[commandIndex] & IS_IMPLEMENTED && s_commandAttributes[commandIndex] & PP_REQUIRED) SET_BIT(commandIndex, gp.ppList); } // Write PP list to NV NV_SYNC_PERSISTENT(ppList); return; } /* 8.8.3.2 PhysicalPresenceCommandSet() */ /* This function is used to set the indicator that a command requires PP confirmation. */ void PhysicalPresenceCommandSet( TPM_CC commandCode // IN: command code ) { COMMAND_INDEX commandIndex = CommandCodeToCommandIndex(commandCode); // if the command isn't implemented, the do nothing if(commandIndex == UNIMPLEMENTED_COMMAND_INDEX) return; // only set the bit if this is a command for which PP is allowed if(s_commandAttributes[commandIndex] & PP_COMMAND) SET_BIT(commandIndex, gp.ppList); return; } /* 8.8.3.3 PhysicalPresenceCommandClear() */ /* This function is used to clear the indicator that a command requires PP confirmation. */ void PhysicalPresenceCommandClear( TPM_CC commandCode // IN: command code ) { COMMAND_INDEX commandIndex = CommandCodeToCommandIndex(commandCode); // If the command isn't implemented, then don't do anything if(commandIndex == UNIMPLEMENTED_COMMAND_INDEX) return; // Only clear the bit if the command does not require PP if((s_commandAttributes[commandIndex] & PP_REQUIRED) == 0) CLEAR_BIT(commandIndex, gp.ppList); return; } /* 8.8.3.4 PhysicalPresenceIsRequired() */ /* This function indicates if PP confirmation is required for a command. */ /* Return Values Meaning */ /* TRUE if physical presence is required */ /* FALSE if physical presence is not required */ BOOL PhysicalPresenceIsRequired( COMMAND_INDEX commandIndex // IN: command index ) { // Check the bit map. If the bit is SET, PP authorization is required return (TEST_BIT(commandIndex, gp.ppList)); } /* 8.8.3.5 PhysicalPresenceCapGetCCList() */ /* This function returns a list of commands that require PP confirmation. The list starts from the first implemented command that has a command code that the same or greater than commandCode. */ /* Return Values Meaning */ /* YES if there are more command codes available */ /* NO all the available command codes have been returned */ TPMI_YES_NO PhysicalPresenceCapGetCCList( TPM_CC commandCode, // IN: start command code UINT32 count, // IN: count of returned TPM_CC TPML_CC *commandList // OUT: list of TPM_CC ) { TPMI_YES_NO more = NO; COMMAND_INDEX commandIndex; // Initialize output handle list commandList->count = 0; // The maximum count of command we may return is MAX_CAP_CC if(count > MAX_CAP_CC) count = MAX_CAP_CC; // Collect PP commands for(commandIndex = GetClosestCommandIndex(commandCode); commandIndex != UNIMPLEMENTED_COMMAND_INDEX; commandIndex = GetNextCommandIndex(commandIndex)) { if(PhysicalPresenceIsRequired(commandIndex)) { if(commandList->count < count) { // If we have not filled up the return list, add this command // code to it commandList->commandCodes[commandList->count] = GetCommandCode(commandIndex); commandList->count++; } else { // If the return list is full but we still have PP command // available, report this and stop iterating more = YES; break; } } } return more; } libtpms-0.9.3/src/tpm2/PPPlat.c000066400000000000000000000112071421143571500161560ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Simulates the Physical Present Interface */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PPPlat.c 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ /* C.10 PPPlat.c */ /* C.10.1. Description */ /* This module simulates the physical presence interface pins on the TPM. */ /* C.10.2. Includes */ #include "Platform.h" #include "LibtpmsCallbacks.h" /* libtpms added */ /* C.10.3. Functions */ /* C.10.3.1. _plat__PhysicalPresenceAsserted() */ /* Check if physical presence is signaled */ /* Return Values Meaning */ /* TRUE(1) if physical presence is signaled */ /* FALSE(0) if physical presence is not signaled */ LIB_EXPORT int _plat__PhysicalPresenceAsserted( void ) { #ifdef TPM_LIBTPMS_CALLBACKS BOOL pp; int ret = libtpms_plat__PhysicalPresenceAsserted(&pp); if (ret != LIBTPMS_CALLBACK_FALLTHROUGH) return pp; #endif /* TPM_LIBTPMS_CALLBACKS */ // Do not know how to check physical presence without real hardware. // so always return TRUE; return s_physicalPresence; } #if 0 /* libtpms added */ /* C.10.3.2. _plat__Signal_PhysicalPresenceOn() */ /* Signal physical presence on */ LIB_EXPORT void _plat__Signal_PhysicalPresenceOn( void ) { s_physicalPresence = TRUE; return; } /* C.10.3.3. _plat__Signal_PhysicalPresenceOff() */ /* Signal physical presence off */ LIB_EXPORT void _plat__Signal_PhysicalPresenceOff( void ) { s_physicalPresence = FALSE; return; } #endif /* libtpms added */ libtpms-0.9.3/src/tpm2/PP_Commands_fp.h000066400000000000000000000073361421143571500176600ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PP_Commands_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 */ /* */ /********************************************************************************/ #ifndef PP_COMMANDS_FP_H #define PP_COMMANDS_FP_H typedef struct { TPMI_RH_PLATFORM auth; TPML_CC setList; TPML_CC clearList; } PP_Commands_In; #define RC_PP_Commands_auth (TPM_RC_H + TPM_RC_1) #define RC_PP_Commands_setList (TPM_RC_P + TPM_RC_1) #define RC_PP_Commands_clearList (TPM_RC_P + TPM_RC_2) TPM_RC TPM2_PP_Commands( PP_Commands_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/PP_fp.h000066400000000000000000000077001421143571500160320ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PP_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 */ /* */ /********************************************************************************/ #ifndef PP_FP_H #define PP_FP_H void PhysicalPresencePreInstall_Init( void ); void PhysicalPresenceCommandSet( TPM_CC commandCode // IN: command code ); void PhysicalPresenceCommandClear( TPM_CC commandCode // IN: command code ); BOOL PhysicalPresenceIsRequired( COMMAND_INDEX commandIndex // IN: command index ); TPMI_YES_NO PhysicalPresenceCapGetCCList( TPM_CC commandCode, // IN: start command code UINT32 count, // IN: count of returned TPM_CC TPML_CC *commandList // OUT: list of TPM_CC ); #endif libtpms-0.9.3/src/tpm2/PRNG_TestVectors.h000066400000000000000000000130001421143571500201270ustar00rootroot00000000000000/********************************************************************************/ /* */ /* PRNG Test Vectors */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PRNG_TestVectors.h 1529 2019-11-21 23:29:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ /* 10.1.17 PRNG_TestVectors.h */ #ifndef _MSBN_DRBG_TEST_VECTORS_H #define _MSBN_DRBG_TEST_VECTORS_H //#if DRBG_ALGORITHM == TPM_ALG_AES && DRBG_KEY_BITS == 256 #if DRBG_KEY_SIZE_BITS == 256 /* Entropy is the size of the state. The state is the size of the key plus the IV. The IV is a block. If Key = 256 and Block = 128 then State = 384 */ #define DRBG_TEST_INITIATE_ENTROPY \ 0x0d, 0x15, 0xaa, 0x80, 0xb1, 0x6c, 0x3a, 0x10, \ 0x90, 0x6c, 0xfe, 0xdb, 0x79, 0x5d, 0xae, 0x0b, \ 0x5b, 0x81, 0x04, 0x1c, 0x5c, 0x5b, 0xfa, 0xcb, \ 0x37, 0x3d, 0x44, 0x40, 0xd9, 0x12, 0x0f, 0x7e, \ 0x3d, 0x6c, 0xf9, 0x09, 0x86, 0xcf, 0x52, 0xd8, \ 0x5d, 0x3e, 0x94, 0x7d, 0x8c, 0x06, 0x1f, 0x91 #define DRBG_TEST_RESEED_ENTROPY \ 0x6e, 0xe7, 0x93, 0xa3, 0x39, 0x55, 0xd7, 0x2a, \ 0xd1, 0x2f, 0xd8, 0x0a, 0x8a, 0x3f, 0xcf, 0x95, \ 0xed, 0x3b, 0x4d, 0xac, 0x57, 0x95, 0xfe, 0x25, \ 0xcf, 0x86, 0x9f, 0x7c, 0x27, 0x57, 0x3b, 0xbc, \ 0x56, 0xf1, 0xac, 0xae, 0x13, 0xa6, 0x50, 0x42, \ 0xb3, 0x40, 0x09, 0x3c, 0x46, 0x4a, 0x7a, 0x22 #define DRBG_TEST_GENERATED_INTERM \ 0x28, 0xe0, 0xeb, 0xb8, 0x21, 0x01, 0x66, 0x50, \ 0x8c, 0x8f, 0x65, 0xf2, 0x20, 0x7b, 0xd0, 0xa3 #define DRBG_TEST_GENERATED \ 0x94, 0x6f, 0x51, 0x82, 0xd5, 0x45, 0x10, 0xb9, \ 0x46, 0x12, 0x48, 0xf5, 0x71, 0xca, 0x06, 0xc9 #elif DRBG_KEY_SIZE_BITS == 128 #define DRBG_TEST_INITIATE_ENTROPY \ 0x8f, 0xc1, 0x1b, 0xdb, 0x5a, 0xab, 0xb7, 0xe0, \ 0x93, 0xb6, 0x14, 0x28, 0xe0, 0x90, 0x73, 0x03, \ 0xcb, 0x45, 0x9f, 0x3b, 0x60, 0x0d, 0xad, 0x87, \ 0x09, 0x55, 0xf2, 0x2d, 0xa8, 0x0a, 0x44, 0xf8 #define DRBG_TEST_RESEED_ENTROPY \ 0x0c, 0xd5, 0x3c, 0xd5, 0xec, 0xcd, 0x5a, 0x10, \ 0xd7, 0xea, 0x26, 0x61, 0x11, 0x25, 0x9b, 0x05, \ 0x57, 0x4f, 0xc6, 0xdd, 0xd8, 0xbe, 0xd8, 0xbd, \ 0x72, 0x37, 0x8c, 0xf8, 0x2f, 0x1d, 0xba, 0x2a #define DRBG_TEST_GENERATED_INTERM \ 0xdc, 0x3c, 0xf6, 0xbf, 0x5b, 0xd3, 0x41, 0x13, \ 0x5f, 0x2c, 0x68, 0x11, 0xa1, 0x07, 0x1c, 0x87 #define DRBG_TEST_GENERATED \ 0xb6, 0x18, 0x50, 0xde, 0xcf, 0xd7, 0x10, 0x6d, \ 0x44, 0x76, 0x9a, 0x8e, 0x6e, 0x8c, 0x1a, 0xd4 #endif #endif // _MSBN_DRBG_TEST_VECTORS_H libtpms-0.9.3/src/tpm2/Platform.h000066400000000000000000000071471421143571500166170ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Platform.h 1521 2019-11-15 21:00:47Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2019. */ /* */ /********************************************************************************/ /* C.14 Platform.h */ #ifndef _PLATFORM_H_ #define _PLATFORM_H_ #include "TpmBuildSwitches.h" #include "BaseTypes.h" #include "TPMB.h" #include "MinMax.h" #include "TpmProfile.h" #include "PlatformACT.h" #include "PlatformClock.h" #include "PlatformData.h" #include "Platform_fp.h" #endif // _PLATFORM_H_ libtpms-0.9.3/src/tpm2/PlatformACT.c000066400000000000000000000264671421143571500171500ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Platform Authenticated Countdown Timer */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PlatformACT.c 1594 2020-03-26 22:15:48Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2019 - 2020 */ /* */ /********************************************************************************/ /* C.16 PlatformACT.c */ /* C.16.1. Includes */ #include "Platform.h" #include "PlatformACT_fp.h" /* C.16.2. Functions */ /* C.16.2.1. ActSignal() */ /* Function called when there is an ACT event to signal or unsignal */ #ifndef __ACT_DISABLED // libtpms added static void ActSignal( P_ACT_DATA actData, int on ) { if(actData == NULL) return; // If this is to turn a signal on, don't do anything if it is already on. If this // is to turn the signal off, do it anyway because this might be for // initialization. if(on && (actData->signaled == TRUE)) return; actData->signaled = (uint8_t)on; // If there is an action, then replace the "Do something" with the correct action. // It should test 'on' to see if it is turning the signal on or off. switch(actData->number) { #if RH_ACT_0 case 0: // Do something return; #endif #if RH_ACT_1 case 1: // Do something return; #endif #if RH_ACT_2 case 2: // Do something return; #endif #if RH_ACT_3 case 3: // Do something return; #endif #if RH_ACT_4 case 4: // Do something return; #endif #if RH_ACT_5 case 5: // Do something return; #endif #if RH_ACT_6 case 6: // Do something return; #endif #if RH_ACT_7 case 7: // Do something return; #endif #if RH_ACT_8 case 8: // Do something return; #endif #if RH_ACT_9 case 9: // Do something return; #endif #if RH_ACT_A case 0xA: // Do something return; #endif #if RH_ACT_B case 0xB: // Do something return; #endif #if RH_ACT_C case 0xC: // Do something return; #endif #if RH_ACT_D case 0xD: // Do something return; #endif #if RH_ACT_E case 0xE: // Do something return; #endif #if RH_ACT_F case 0xF: // Do something return; #endif default: return; } } #endif // libtpms added /* C.16.2.2. ActGetDataPointer() */ static P_ACT_DATA ActGetDataPointer( uint32_t act ) { #define RETURN_ACT_POINTER(N) if(0x##N == act) return &ACT_##N; FOR_EACH_ACT(RETURN_ACT_POINTER) return (P_ACT_DATA)NULL; } /* C.16.2.3. _plat__ACT_GetImplemented() */ /* This function tests to see if an ACT is implemented. It is a belt and suspenders function because the TPM should not be calling to manipulate an ACT that is not implemented. However, this could help the simulator code which doesn't necessarily know if an ACT is implemented or not. */ LIB_EXPORT int _plat__ACT_GetImplemented( uint32_t act ) { return (ActGetDataPointer(act) != NULL); } /* C.16.2.4. _plat__ACT_GetRemaining() */ /* This function returns the remaining time. If an update is pending, newValue is returned. Otherwise, the current counter value is returned. Note that since the timers keep running, the returned value can get stale immediately. The actual count value will be no greater than the returned value. */ LIB_EXPORT uint32_t _plat__ACT_GetRemaining( uint32_t act //IN: the ACT selector ) { P_ACT_DATA actData = ActGetDataPointer(act); uint32_t remain; // if(actData == NULL) return 0; remain = actData->remaining; if(actData->pending) remain = actData->newValue; return remain; } /* C.16.2.5. _plat__ACT_GetSignaled() */ LIB_EXPORT int _plat__ACT_GetSignaled( uint32_t act //IN: number of ACT to check ) { P_ACT_DATA actData = ActGetDataPointer(act); // if(actData == NULL) return 0; return (int)actData->signaled; } /* C.16.2.6. _plat__ACT_SetSignaled() */ #ifndef __ACT_DISABLED // libtpms added LIB_EXPORT void _plat__ACT_SetSignaled( uint32_t act, int on ) { ActSignal(ActGetDataPointer(act), on); } /* C.16.2.7. _plat__ACT_GetPending() */ LIB_EXPORT int _plat__ACT_GetPending( uint32_t act //IN: number of ACT to check ) { P_ACT_DATA actData = ActGetDataPointer(act); // if(actData == NULL) return 0; return (int)actData->pending; } /* C.16.2.8. _plat__ACT_UpdateCounter() */ /* This function is used to write the newValue for the counter. If an update is pending, then no update occurs and the function returns FALSE. If setSignaled is TRUE, then the ACT signaled state is SET and if newValue is 0, nothing is posted. */ LIB_EXPORT int _plat__ACT_UpdateCounter( uint32_t act, // IN: ACT to update uint32_t newValue // IN: the value to post ) { P_ACT_DATA actData = ActGetDataPointer(act); // if(actData == NULL) // actData doesn't exist but pretend update is pending rather than indicate // that a retry is necessary. return TRUE; // if an update is pending then return FALSE so that there will be a retry if(actData->pending != 0) return FALSE; actData->newValue = newValue; actData->pending = TRUE; return TRUE; } #endif // libtpms added /* C.16.2.9. _plat__ACT_EnableTicks() */ /* This enables and disables the processing of the once-per-second ticks. This should be turned off (enable = FALSE) by _TPM_Init() and turned on (enable = TRUE) by TPM2_Startup() after all the initializations have completed. */ LIB_EXPORT void _plat__ACT_EnableTicks( int enable ) { actTicksAllowed = enable; } /* C.16.2.10. ActDecrement() */ /* If newValue is non-zero it is copied to remaining and then newValue is set to zero. Then remaining is decremented by one if it is not already zero. If the value is decremented to zero, then the associated event is signaled. If setting remaining causes it to be greater than 1, then the signal associated with the ACT is turned off. */ #ifndef __ACT_DISABLED // libtpms added static void ActDecrement( P_ACT_DATA actData ) { // Check to see if there is an update pending if(actData->pending) { // If this update will cause the count to go from non-zero to zero, set // the newValue to 1 so that it will timeout when decremented below. if((actData->newValue == 0) && (actData->remaining != 0)) actData->newValue = 1; actData->remaining = actData->newValue; // Update processed actData->pending = 0; } // no update so countdown if the count is non-zero but not max if((actData->remaining != 0) && (actData->remaining != UINT32_MAX)) { // If this countdown causes the count to go to zero, then turn the signal for // the ACT on. if((actData->remaining -= 1) == 0) ActSignal(actData, TRUE); } // If the current value of the counter is non-zero, then the signal should be // off. if(actData->signaled && (actData->remaining > 0)) ActSignal(actData, FALSE); } /* C.16.2.11. _plat__ACT_Tick() */ /* This processes the once-per-second clock tick from the hardware. This is set up for the simulator to use the control interface to send ticks to the TPM. These ticks do not have to be on a per second basis. They can be as slow or as fast as desired so that the simulation can be tested. */ LIB_EXPORT void _plat__ACT_Tick( void ) { // Ticks processing is turned off at certain times just to make sure that nothing // strange is happening before pointers and things are if(actTicksAllowed) { // Handle the update for each counter. #define DECREMENT_COUNT(N) ActDecrement(&ACT_##N); FOR_EACH_ACT(DECREMENT_COUNT) } } /* C.16.2.12. ActZero() */ /* This function initializes a single ACT */ static void ActZero( uint32_t act, P_ACT_DATA actData ) { actData->remaining = 0; actData->newValue = 0; actData->pending = 0; actData->number = (uint8_t)act; ActSignal(actData, FALSE); } #endif // libtpms added /* C.16.2.13. _plat__ACT_Initialize() */ /* This function initializes the ACT hardware and data structures */ LIB_EXPORT int _plat__ACT_Initialize( void ) { actTicksAllowed = 0; #define ZERO_ACT(N) ActZero(0x##N, &ACT_##N); FOR_EACH_ACT(ZERO_ACT) return TRUE; } libtpms-0.9.3/src/tpm2/PlatformACT.h000066400000000000000000000162331421143571500171430ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Platform Authenticated Countdown Timer */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PlatformACT.h 1531 2019-11-21 23:54:38Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2019. */ /* */ /********************************************************************************/ /* C.15 PlatformACT.h */ // This file contains the definitions for the ACT macros and data types used in the ACT // implementation. #ifndef PLATFORMACT_H #define PLATFORMACT_H typedef struct ACT_DATA { uint32_t remaining; uint32_t newValue; uint8_t signaled; uint8_t pending; uint8_t number; } ACT_DATA, *P_ACT_DATA; #if !(defined RH_ACT_0) || (RH_ACT_0 != YES) # undef RH_ACT_0 # define RH_ACT_0 NO # define IF_ACT_0_IMPLEMENTED(op) #else # define IF_ACT_0_IMPLEMENTED(op) op(0) #endif #if !(defined RH_ACT_1) || (RH_ACT_1 != YES) # undef RH_ACT_1 # define RH_ACT_1 NO # define IF_ACT_1_IMPLEMENTED(op) #else # define IF_ACT_1_IMPLEMENTED(op) op(1) #endif #if !(defined RH_ACT_2) || (RH_ACT_2 != YES) # undef RH_ACT_2 # define RH_ACT_2 NO # define IF_ACT_2_IMPLEMENTED(op) #else # define IF_ACT_2_IMPLEMENTED(op) op(2) #endif #if !(defined RH_ACT_3) || (RH_ACT_3 != YES) # undef RH_ACT_3 # define RH_ACT_3 NO # define IF_ACT_3_IMPLEMENTED(op) #else # define IF_ACT_3_IMPLEMENTED(op) op(3) #endif #if !(defined RH_ACT_4) || (RH_ACT_4 != YES) # undef RH_ACT_4 # define RH_ACT_4 NO # define IF_ACT_4_IMPLEMENTED(op) #else # define IF_ACT_4_IMPLEMENTED(op) op(4) #endif #if !(defined RH_ACT_5) || (RH_ACT_5 != YES) # undef RH_ACT_5 # define RH_ACT_5 NO # define IF_ACT_5_IMPLEMENTED(op) #else # define IF_ACT_5_IMPLEMENTED(op) op(5) #endif #if !(defined RH_ACT_6) || (RH_ACT_6 != YES) # undef RH_ACT_6 # define RH_ACT_6 NO # define IF_ACT_6_IMPLEMENTED(op) #else # define IF_ACT_6_IMPLEMENTED(op) op(6) #endif #if !(defined RH_ACT_7) || (RH_ACT_7 != YES) # undef RH_ACT_7 # define RH_ACT_7 NO # define IF_ACT_7_IMPLEMENTED(op) #else # define IF_ACT_7_IMPLEMENTED(op) op(7) #endif #if !(defined RH_ACT_8) || (RH_ACT_8 != YES) # undef RH_ACT_8 # define RH_ACT_8 NO # define IF_ACT_8_IMPLEMENTED(op) #else # define IF_ACT_8_IMPLEMENTED(op) op(8) #endif #if !(defined RH_ACT_9) || (RH_ACT_9 != YES) # undef RH_ACT_9 # define RH_ACT_9 NO # define IF_ACT_9_IMPLEMENTED(op) #else # define IF_ACT_9_IMPLEMENTED(op) op(9) #endif #if !(defined RH_ACT_A) || (RH_ACT_A != YES) # undef RH_ACT_A # define RH_ACT_A NO # define IF_ACT_A_IMPLEMENTED(op) #else # define IF_ACT_A_IMPLEMENTED(op) op(A) #endif #if !(defined RH_ACT_B) || (RH_ACT_B != YES) # undef RH_ACT_B # define RH_ACT_B NO # define IF_ACT_B_IMPLEMENTED(op) #else # define IF_ACT_B_IMPLEMENTED(op) op(B) #endif #if !(defined RH_ACT_C) || (RH_ACT_C != YES) # undef RH_ACT_C # define RH_ACT_C NO # define IF_ACT_C_IMPLEMENTED(op) #else # define IF_ACT_C_IMPLEMENTED(op) op(C) #endif #if !(defined RH_ACT_D) || (RH_ACT_D != YES) # undef RH_ACT_D # define RH_ACT_D NO # define IF_ACT_D_IMPLEMENTED(op) #else # define IF_ACT_D_IMPLEMENTED(op) op(D) #endif #if !(defined RH_ACT_E) || (RH_ACT_E != YES) # undef RH_ACT_E # define RH_ACT_E NO # define IF_ACT_E_IMPLEMENTED(op) #else # define IF_ACT_E_IMPLEMENTED(op) op(E) #endif #if !(defined RH_ACT_F) || (RH_ACT_F != YES) # undef RH_ACT_F # define RH_ACT_F NO # define IF_ACT_F_IMPLEMENTED(op) #else # define IF_ACT_F_IMPLEMENTED(op) op(F) #endif #define FOR_EACH_ACT(op) \ IF_ACT_0_IMPLEMENTED(op) \ IF_ACT_1_IMPLEMENTED(op) \ IF_ACT_2_IMPLEMENTED(op) \ IF_ACT_3_IMPLEMENTED(op) \ IF_ACT_4_IMPLEMENTED(op) \ IF_ACT_5_IMPLEMENTED(op) \ IF_ACT_6_IMPLEMENTED(op) \ IF_ACT_7_IMPLEMENTED(op) \ IF_ACT_8_IMPLEMENTED(op) \ IF_ACT_9_IMPLEMENTED(op) \ IF_ACT_A_IMPLEMENTED(op) \ IF_ACT_B_IMPLEMENTED(op) \ IF_ACT_C_IMPLEMENTED(op) \ IF_ACT_D_IMPLEMENTED(op) \ IF_ACT_E_IMPLEMENTED(op) \ IF_ACT_F_IMPLEMENTED(op) #endif // _PLATFORM_ACT_H_ libtpms-0.9.3/src/tpm2/PlatformACT_fp.h000066400000000000000000000104161421143571500176250ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Platform Authenticated Countdown Timer */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PlatformACT_fp.h 1531 2019-11-21 23:54:38Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2019 */ /* */ /********************************************************************************/ #ifndef PLATFORMACT_FP_H #define PLATFORMACT_FP_H LIB_EXPORT int _plat__ACT_GetImplemented( uint32_t act ); LIB_EXPORT uint32_t _plat__ACT_GetRemaining( uint32_t act //IN: the ACT selector ); LIB_EXPORT int _plat__ACT_GetSignaled( uint32_t act //IN: number of ACT to check ); LIB_EXPORT void _plat__ACT_SetSignaled( uint32_t act, int on ); LIB_EXPORT int _plat__ACT_GetPending( uint32_t act //IN: number of ACT to check ); LIB_EXPORT int _plat__ACT_UpdateCounter( uint32_t act, // IN: ACT to update uint32_t newValue // IN: the value to post ); LIB_EXPORT void _plat__ACT_EnableTicks( int enable ); LIB_EXPORT void _plat__ACT_Tick( void ); LIB_EXPORT int _plat__ACT_Initialize( void ); #endif libtpms-0.9.3/src/tpm2/PlatformClock.h000066400000000000000000000112701421143571500175630ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Platform Clock . */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PlatformClock.h 1594 2020-03-26 22:15:48Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2019 - 2020 */ /* */ /********************************************************************************/ // C.16 PlatformClock.h This file contains the instance data for the Platform module. It is // collected in this file so that the state of the module is easier to manage. #ifndef _PLATFORM_CLOCK_H_ #define _PLATFORM_CLOCK_H_ #ifdef _MSC_VER #include #include #else #include #include #endif // CLOCK_NOMINAL is the number of hardware ticks per mS. A value of 300000 means that the nominal // clock rate used to drive the hardware clock is 30 MHz. The adjustment rates are used to determine // the conversion of the hardware ticks to internal hardware clock value. In practice, we would // expect that there would be a hardware register will accumulated mS. It would be incremented by // the output of a pre-scaler. The pre-scaler would divide the ticks from the clock by some value // that would compensate for the difference between clock time and real time. The code in Clock does // the emulation of this function. #define CLOCK_NOMINAL 30000 // A 1% change in rate is 300 counts #define CLOCK_ADJUST_COARSE 300 // A 0.1% change in rate is 30 counts #define CLOCK_ADJUST_MEDIUM 30 // A minimum change in rate is 1 count #define CLOCK_ADJUST_FINE 1 // The clock tolerance is +/-15% (4500 counts) Allow some guard band (16.7%) #define CLOCK_ADJUST_LIMIT 5000 #endif // _PLATFORM_CLOCK_H_ libtpms-0.9.3/src/tpm2/PlatformData.c000066400000000000000000000071631421143571500174020ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM variables that are not stack allocated */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PlatformData.c 1519 2019-11-15 20:43:51Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ /* C.9 PlatformData.c */ /* C.9.1. Description */ /* This file will instance the TPM variables that are not stack allocated. The descriptions for these variables are in Global.h for this project. */ /* C.9.2. Includes */ #define _PLATFORM_DATA_C_ #include "Platform.h" libtpms-0.9.3/src/tpm2/PlatformData.h000066400000000000000000000150011421143571500173750ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Instance data for the Platform module. */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PlatformData.h 1519 2019-11-15 20:43:51Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019. */ /* */ /********************************************************************************/ /* c.8 PlatformData.h */ /* This file contains the instance data for the Platform module. It is collected in this file so that the state of the module is easier to manage. */ #ifndef _PLATFORM_DATA_H_ #define _PLATFORM_DATA_H_ #ifdef _PLATFORM_DATA_C_ #define EXTERN #else #define EXTERN extern #endif /* From Cancel.c Cancel flag. It is initialized as FALSE, which indicate the command is not being canceled */ EXTERN int s_isCanceled; #ifndef HARDWARE_CLOCK typedef uint64_t clock64_t; // This is the value returned the last time that the system clock was read. This is only relevant // for a simulator or virtual TPM. EXTERN clock64_t s_realTimePrevious; // These values are used to try to synthesize a long lived version of clock(). EXTERN clock64_t s_lastSystemTime; EXTERN clock64_t s_lastReportedTime; // This is the rate adjusted value that is the equivalent of what would be read from a hardware // register that produced rate adjusted time. EXTERN clock64_t s_tpmTime; /* libtpms added begin */ EXTERN int64_t s_hostMonotonicAdjustTime; EXTERN uint64_t s_suspendedElapsedTime; /* libtpms added end */ #endif // HARDWARE_CLOCK /* This value indicates that the timer was reset */ EXTERN BOOL s_timerReset; /* This value indicates that the timer was stopped. It causes a clock discontinuity. */ EXTERN BOOL s_timerStopped; /* This variable records the time when _plat__TimerReset() is called. This mechanism allow us to subtract the time when TPM is power off from the total time reported by clock() function */ EXTERN uint64_t s_initClock; /* This variable records the timer adjustment factor. */ EXTERN unsigned int s_adjustRate; /* From LocalityPlat.c Locality of current command */ EXTERN unsigned char s_locality; /* From NVMem.c Choose if the NV memory should be backed by RAM or by file. If this macro is defined, then a file is used as NV. If it is not defined, then RAM is used to back NV memory. Comment out to use RAM. */ #if (!defined VTPM) || ((VTPM != NO) && (VTPM != YES)) # undef VTPM # define VTPM NO // Default: Either YES or NO libtpms: NO #endif // For a simulation, use a file to back up the NV #if (!defined FILE_BACKED_NV) || ((FILE_BACKED_NV != NO) && (FILE_BACKED_NV != YES)) # undef FILE_BACKED_NV # define FILE_BACKED_NV (VTPM && YES) // Default: Either YES or NO #endif #if !SIMULATION # undef FILE_BACKED_NV # define FILE_BACKED_NV YES // libtpms: write NvChip file if no callbacks are set #else #error Do not define SIMULATION for libtpms! #endif // SIMULATION EXTERN unsigned char s_NV[NV_MEMORY_SIZE]; EXTERN BOOL s_NvIsAvailable; EXTERN BOOL s_NV_unrecoverable; EXTERN BOOL s_NV_recoverable; /* From PPPlat.c Physical presence. It is initialized to FALSE */ EXTERN BOOL s_physicalPresence; /* From Power */ EXTERN BOOL s_powerLost; /* From Entropy.c */ EXTERN uint32_t lastEntropy; #define DEFINE_ACT(N) EXTERN ACT_DATA ACT_##N; FOR_EACH_ACT(DEFINE_ACT) EXTERN int actTicksAllowed; #endif // _PLATFORM_DATA_H_ libtpms-0.9.3/src/tpm2/Platform_fp.h000066400000000000000000000402161421143571500172760ustar00rootroot00000000000000/********************************************************************************/ /* */ /* NV read and write access methods */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Platform_fp.h 1594 2020-03-26 22:15:48Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2020 */ /* */ /********************************************************************************/ /* C.8 Platform_fp.h */ #ifndef _PLATFORM_FP_H_ #define _PLATFORM_FP_H_ #include "BaseTypes.h" /* C.8.1. From Cancel.c */ /* C.8.1.1. _plat__IsCanceled() */ /* Check if the cancel flag is set */ /* Return Values Meaning */ /* TRUE(1) if cancel flag is set */ /* FALSE(0) if cancel flag is not set */ LIB_EXPORT int _plat__IsCanceled( void ); /* Set cancel flag. */ LIB_EXPORT void _plat__SetCancel( void ); /* C.8.1.2. _plat__ClearCancel() */ /* Clear cancel flag */ LIB_EXPORT void _plat__ClearCancel( void ); /* C.8.2. From Clock.c */ /* C.8.2.1. _plat__TimerReset() */ /* This function sets current system clock time as t0 for counting TPM time. This function is called at a power on event to reset the clock. When the clock is reset, the indication that the clock was stopped is also set. */ LIB_EXPORT void _plat__TimerReset( void ); /* C.8.2.2. _plat__TimerRestart() */ /* This function should be called in order to simulate the restart of the timer should it be stopped while power is still applied. */ LIB_EXPORT void _plat__TimerRestart( void ); // C.8.2.3. _plat__Time() This is another, probably futile, attempt to define a portable function // that will return a 64-bit clock value that has mSec resolution. LIB_EXPORT uint64_t _plat__RealTime( void ); /* C.8.2.4. _plat__TimerRead() */ /* This function provides access to the tick timer of the platform. The TPM code uses this value to drive the TPM Clock. */ /* The tick timer is supposed to run when power is applied to the device. This timer should not be reset by time events including _TPM_Init(). It should only be reset when TPM power is re-applied. */ /* If the TPM is run in a protected environment, that environment may provide the tick time to the TPM as long as the time provided by the environment is not allowed to go backwards. If the time provided by the system can go backwards during a power discontinuity, then the _plat__Signal_PowerOn() should call _plat__TimerReset(). */ LIB_EXPORT uint64_t _plat__TimerRead( void ); /* C.8.2.5. _plat__TimerWasReset() */ /* This function is used to interrogate the flag indicating if the tick timer has been reset. */ /* If the resetFlag parameter is SET, then the flag will be CLEAR before the function returns. */ LIB_EXPORT int _plat__TimerWasReset( void ); /* C.8.2.6. _plat__TimerWasStopped() */ /* This function is used to interrogate the flag indicating if the tick timer has been stopped. If so, this is typically a reason to roll the nonce. */ /* This function will CLEAR the s_timerStopped flag before returning. This provides functionality that is similar to status register that is cleared when read. This is the model used here because it is the one that has the most impact on the TPM code as the flag can only be accessed by one entity in the TPM. Any other implementation of the hardware can be made to look like a read-once register. */ LIB_EXPORT int _plat__TimerWasStopped( void ); /* C.8.2.7. _plat__ClockAdjustRate() */ /* Adjust the clock rate */ LIB_EXPORT void _plat__ClockAdjustRate( int adjust // IN: the adjust number. It could be positive // or negative ); /* C.8.3. From Entropy.c */ // C.8.4. _plat__GetEntropy() // This function is used to get available hardware entropy. In a hardware implementation of this // function, there would be no call to the system to get entropy. /* Return Values Meaning */ /* < 0 hardware failure of the entropy generator, this is sticky */ /* >= 0 the returned amount of entropy (bytes) */ LIB_EXPORT int32_t _plat__GetEntropy( unsigned char *entropy, // output buffer uint32_t amount // amount requested ); /* C.8.4. From LocalityPlat.c */ /* C.8.4.1. _plat__LocalityGet() */ /* Get the most recent command locality in locality value form. This is an integer value for locality and not a locality structure The locality can be 0-4 or 32-255. 5-31 is not allowed. */ LIB_EXPORT unsigned char _plat__LocalityGet( void ); /* C.8.4.2. _plat__LocalitySet() */ /* Set the most recent command locality in locality value form */ LIB_EXPORT void _plat__LocalitySet( unsigned char locality ); /* C.8.5. From NVMem.c */ #if 0 /* libtpms added */ /* C.8.5.1. _plat__NvErrors() */ /* This function is used by the simulator to set the error flags in the NV subsystem to simulate an error in the NV loading process */ LIB_EXPORT void _plat__NvErrors( int recoverable, int unrecoverable ); #endif /* libtpms added */ /* C.8.5.2. _plat__NVEnable() */ /* Enable NV memory. */ /* This version just pulls in data from a file. In a real TPM, with NV on chip, this function would verify the integrity of the saved context. If the NV memory was not on chip but was in something like RPMB, the NV state would be read in, decrypted and integrity checked. */ /* The recovery from an integrity failure depends on where the error occurred. It it was in the state that is discarded by TPM Reset, then the error is recoverable if the TPM is reset. Otherwise, the TPM must go into failure mode. */ /* Return Values Meaning */ /* 0 if success */ /* > 0 if receive recoverable error */ /* <0 if unrecoverable error */ LIB_EXPORT int _plat__NVEnable( void *platParameter // IN: platform specific parameters ); /* libtpms added begin */ LIB_EXPORT int _plat__NVEnable_NVChipFile( void *platParameter // IN: platform specific parameters ); /* libtpms added end */ /* C.8.5.3. _plat__NVDisable() */ /* Disable NV memory */ LIB_EXPORT void _plat__NVDisable( int delete // IN: If TRUE, delete the NV contents. ); /* C.8.6.4. _plat__IsNvAvailable() */ /* Check if NV is available */ /* Return Values Meaning */ /* 0 NV is available */ /* 1 NV is not available due to write failure */ /* 2 NV is not available due to rate limit */ LIB_EXPORT int _plat__IsNvAvailable( void ); /* C.8.5.5. _plat__NvMemoryRead() */ /* Function: Read a chunk of NV memory */ LIB_EXPORT void _plat__NvMemoryRead( unsigned int startOffset, // IN: read start unsigned int size, // IN: size of bytes to read void *data // OUT: data buffer ); /* C.8.5.6. _plat__NvIsDifferent() */ /* This function checks to see if the NV is different from the test value. This is so that NV will not be written if it has not changed. */ /* Return Values Meaning */ /* TRUE(1) the NV location is different from the test value */ /* FALSE(0) the NV location is the same as the test value */ LIB_EXPORT int _plat__NvIsDifferent( unsigned int startOffset, // IN: read start unsigned int size, // IN: size of bytes to read void *data // IN: data buffer ); /* C.8.5.7. _plat__NvMemoryWrite() */ /* This function is used to update NV memory. The write is to a memory copy of NV. At the end of the current command, any changes are written to the actual NV memory. */ /* NOTE: A useful optimization would be for this code to compare the current contents of NV with the local copy and note the blocks that have changed. Then only write those blocks when _plat__NvCommit() is called. */ LIB_EXPORT int _plat__NvMemoryWrite( unsigned int startOffset, // IN: write start unsigned int size, // IN: size of bytes to write void *data // OUT: data buffer ); /* C.8.6.8. _plat__NvMemoryClear() */ /* Function is used to set a range of NV memory bytes to an implementation-dependent value. The value represents the erase state of the memory. */ LIB_EXPORT void _plat__NvMemoryClear( unsigned int start, // IN: clear start unsigned int size // IN: number of bytes to clear ); /* C.8.5.9. _plat__NvMemoryMove() */ /* Function: Move a chunk of NV memory from source to destination This function should ensure that if there overlap, the original data is copied before it is written */ LIB_EXPORT void _plat__NvMemoryMove( unsigned int sourceOffset, // IN: source offset unsigned int destOffset, // IN: destination offset unsigned int size // IN: size of data being moved ); /* C.8.5.10. _plat__NvCommit() */ // This function writes the local copy of NV to NV for permanent store. It will write NV_MEMORY_SIZE // bytes to NV. If a file is use, the entire file is written. /* Return Values Meaning */ /* 0 NV write success */ /* non-0 NV write fail */ LIB_EXPORT int _plat__NvCommit( void ); /* C.8.5.11. _plat__SetNvAvail() */ /* Set the current NV state to available. This function is for testing purpose only. It is not part of the platform NV logic */ LIB_EXPORT void _plat__SetNvAvail( void ); /* C.8.5.12. _plat__ClearNvAvail() */ /* Set the current NV state to unavailable. This function is for testing purpose only. It is not part of the platform NV logic */ LIB_EXPORT void _plat__ClearNvAvail( void ); /* C.6.2.15. _plat__NVNeedsManufacture() */ /* This function is used by the simulator to determine when the TPM's NV state needs to be manufactured. */ LIB_EXPORT int _plat__NVNeedsManufacture( void ); /* C.8.6. From PowerPlat.c */ /* C.8.6.1. _plat__Signal_PowerOn() */ /* Signal platform power on */ LIB_EXPORT int _plat__Signal_PowerOn( void ); /* C.8.6.2. _plat__WasPowerLost() */ /* Test whether power was lost before a _TPM_Init(). */ /* This function will clear the hardware indication of power loss before return. This means that there can only be one spot in the TPM code where this value gets read. This method is used here as it is the most difficult to manage in the TPM code and, if the hardware actually works this way, it is hard to make it look like anything else. So, the burden is placed on the TPM code rather than the platform code */ /* Return Values Meaning */ /* TRUE(1) power was lost */ /* FALSE(0) power was not lost */ LIB_EXPORT int _plat__WasPowerLost( void ); /* C.8.6.3. _plat_Signal_Reset() */ /* This a TPM reset without a power loss. */ LIB_EXPORT int _plat__Signal_Reset( void ); /* C.8.6.4. _plat__Signal_PowerOff() */ /* Signal platform power off */ LIB_EXPORT void _plat__Signal_PowerOff( void ); /* C.8.7. From PPPlat.c */ /* C.8.7.1. _plat__PhysicalPresenceAsserted() */ /* Check if physical presence is signaled */ /* Return Values Meaning */ /* TRUE(1) if physical presence is signaled */ /* FALSE(0) if physical presence is not signaled */ LIB_EXPORT int _plat__PhysicalPresenceAsserted( void ); #if 0 /* libtpms added */ /* C.8.7.2. _plat__Signal_PhysicalPresenceOn() */ /* Signal physical presence on */ LIB_EXPORT void _plat__Signal_PhysicalPresenceOn( void ); /* C.8.7.3. _plat__Signal_PhysicalPresenceOff() */ /* Signal physical presence off */ LIB_EXPORT void _plat__Signal_PhysicalPresenceOff( void ); #endif /* libtpms added */ /* C.8.8. From RunCommand.c */ /* C.8.8.1. _plat__RunCommand() */ /* This version of RunCommand() will set up a jum_buf and call ExecuteCommand(). If the command executes without failing, it will return and RunCommand() will return. If there is a failure in the command, then _plat__Fail() is called and it will longjump back to RunCommand() which will call ExecuteCommand() again. However, this time, the TPM will be in failure mode so ExecuteCommand() will simply build a failure response and return. */ LIB_EXPORT void _plat__RunCommand( uint32_t requestSize, // IN: command buffer size unsigned char *request, // IN: command buffer uint32_t *responseSize, // IN/OUT: response buffer size unsigned char **response // IN/OUT: response buffer ); /* C.8.8.2. _plat__Fail() */ /* This is the platform depended failure exit for the TPM. */ LIB_EXPORT NORETURN void _plat__Fail( void ); /* C.8.9. From Unique.c */ /* C.8.9.1 _plat__GetUnique() */ /* This function is used to access the platform-specific unique value. This function places the unique value in the provided buffer (b) and returns the number of bytes transferred. The function will not copy more data than bSize. */ /* NOTE: If a platform unique value has unequal distribution of uniqueness and bSize is smaller than the size of the unique value, the bSize portion with the most uniqueness should be returned. */ LIB_EXPORT uint32_t _plat__GetUnique( uint32_t which, // authorities (0) or details uint32_t bSize, // size of the buffer unsigned char *b // output buffer ); /* libtpms added begin */ #include void ClockAdjustPostResume(UINT64 backthen, BOOL timesAreRealtime); uint64_t ClockGetTime(clockid_t clk_id); /* libtpms added end */ #endif // _PLATFORM_FP_H_ libtpms-0.9.3/src/tpm2/PolicyAuthValue_fp.h000066400000000000000000000072101421143571500205650ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PolicyAuthValue_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef POLICYAUTHVALUE_FP_H #define POLICYAUTHVALUE_FP_H typedef struct { TPMI_SH_POLICY policySession; } PolicyAuthValue_In; #define RC_PolicyAuthValue_policySession (TPM_RC_H + TPM_RC_1) TPM_RC TPM2_PolicyAuthValue( PolicyAuthValue_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/PolicyAuthorizeNV_fp.h000066400000000000000000000075341421143571500211160ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PolicyAuthorizeNV_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015, 2016 */ /* */ /********************************************************************************/ /* rev 136 */ #ifndef POLICYAUTHORIZENV_FP_H #define POLICYAUTHORIZENV_FP_H typedef struct { TPMI_RH_NV_AUTH authHandle; TPMI_RH_NV_INDEX nvIndex; TPMI_SH_POLICY policySession; } PolicyAuthorizeNV_In; #define RC_PolicyAuthorizeNV_authHandle (TPM_RC_H + TPM_RC_1) #define RC_PolicyAuthorizeNV_nvIndex (TPM_RC_H + TPM_RC_2) #define RC_PolicyAuthorizeNV_policySession (TPM_RC_H + TPM_RC_3) TPM_RC TPM2_PolicyAuthorizeNV( PolicyAuthorizeNV_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/PolicyAuthorize_fp.h000066400000000000000000000077661421143571500206610ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PolicyAuthorize_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef POLICYAUTHORIZE_FP_H #define POLICYAUTHORIZE_FP_H typedef struct { TPMI_SH_POLICY policySession; TPM2B_DIGEST approvedPolicy; TPM2B_NONCE policyRef; TPM2B_NAME keySign; TPMT_TK_VERIFIED checkTicket; } PolicyAuthorize_In; #define RC_PolicyAuthorize_policySession (TPM_RC_H + TPM_RC_1) #define RC_PolicyAuthorize_approvedPolicy (TPM_RC_P + TPM_RC_1) #define RC_PolicyAuthorize_policyRef (TPM_RC_P + TPM_RC_2) #define RC_PolicyAuthorize_keySign (TPM_RC_P + TPM_RC_3) #define RC_PolicyAuthorize_checkTicket (TPM_RC_P + TPM_RC_4) TPM_RC TPM2_PolicyAuthorize( PolicyAuthorize_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/PolicyCommandCode_fp.h000066400000000000000000000073471421143571500210530ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PolicyCommandCode_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef POLICYCOMMANDCODE_FP_H #define POLICYCOMMANDCODE_FP_H typedef struct { TPMI_SH_POLICY policySession; TPM_CC code; } PolicyCommandCode_In; #define RC_PolicyCommandCode_policySession (TPM_RC_H + TPM_RC_1) #define RC_PolicyCommandCode_code (TPM_RC_P + TPM_RC_1) TPM_RC TPM2_PolicyCommandCode( PolicyCommandCode_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/PolicyCounterTimer_fp.h000066400000000000000000000076261421143571500213220ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PolicyCounterTimer_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef POLICYCOUNTERTIMER_FP_H #define POLICYCOUNTERTIMER_FP_H typedef struct { TPMI_SH_POLICY policySession; TPM2B_OPERAND operandB; UINT16 offset; TPM_EO operation; } PolicyCounterTimer_In; #define RC_PolicyCounterTimer_policySession (TPM_RC_H + TPM_RC_1) #define RC_PolicyCounterTimer_operandB (TPM_RC_P + TPM_RC_1) #define RC_PolicyCounterTimer_offset (TPM_RC_P + TPM_RC_2) #define RC_PolicyCounterTimer_operation (TPM_RC_P + TPM_RC_3) TPM_RC TPM2_PolicyCounterTimer( PolicyCounterTimer_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/PolicyCpHash_fp.h000066400000000000000000000073021421143571500200370ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PolicyCpHash_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef POLICYCPHASH_FP_H #define POLICYCPHASH_FP_H typedef struct { TPMI_SH_POLICY policySession; TPM2B_DIGEST cpHashA; } PolicyCpHash_In; #define RC_PolicyCpHash_policySession (TPM_RC_H + TPM_RC_1) #define RC_PolicyCpHash_cpHashA (TPM_RC_P + TPM_RC_1) TPM_RC TPM2_PolicyCpHash( PolicyCpHash_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/PolicyDuplicationSelect_fp.h000066400000000000000000000077451421143571500223170ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PolicyDuplicationSelect_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef POLICYDUPLICATIONSELECT_FP_H #define POLICYDUPLICATIONSELECT_FP_H typedef struct { TPMI_SH_POLICY policySession; TPM2B_NAME objectName; TPM2B_NAME newParentName; TPMI_YES_NO includeObject; } PolicyDuplicationSelect_In; #define RC_PolicyDuplicationSelect_policySession (TPM_RC_H + TPM_RC_1) #define RC_PolicyDuplicationSelect_objectName (TPM_RC_P + TPM_RC_1) #define RC_PolicyDuplicationSelect_newParentName (TPM_RC_P + TPM_RC_2) #define RC_PolicyDuplicationSelect_includeObject (TPM_RC_P + TPM_RC_3) TPM_RC TPM2_PolicyDuplicationSelect( PolicyDuplicationSelect_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/PolicyGetDigest_fp.h000066400000000000000000000074411421143571500205540ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PolicyGetDigest_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef POLICYGETDIGEST_FP_H #define POLICYGETDIGEST_FP_H typedef struct { TPMI_SH_POLICY policySession; } PolicyGetDigest_In; #define RC_PolicyGetDigest_policySession (TPM_RC_P + TPM_RC_1) typedef struct { TPM2B_DIGEST policyDigest; } PolicyGetDigest_Out; TPM_RC TPM2_PolicyGetDigest( PolicyGetDigest_In *in, // IN: input parameter list PolicyGetDigest_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/PolicyLocality_fp.h000066400000000000000000000073261421143571500204570ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PolicyLocality_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef POLICYLOCALITY_FP_H #define POLICYLOCALITY_FP_H typedef struct { TPMI_SH_POLICY policySession; TPMA_LOCALITY locality; } PolicyLocality_In; #define RC_PolicyLocality_policySession (TPM_RC_H + TPM_RC_1) #define RC_PolicyLocality_locality (TPM_RC_P + TPM_RC_1) TPM_RC TPM2_PolicyLocality( PolicyLocality_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/PolicyNV_fp.h000066400000000000000000000077451421143571500172270ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PolicyNV_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef POLICYNV_FP_H #define POLICYNV_FP_H typedef struct { TPMI_RH_NV_AUTH authHandle; TPMI_RH_NV_INDEX nvIndex; TPMI_SH_POLICY policySession; TPM2B_OPERAND operandB; UINT16 offset; TPM_EO operation; } PolicyNV_In; #define RC_PolicyNV_authHandle (TPM_RC_H + TPM_RC_1) #define RC_PolicyNV_nvIndex (TPM_RC_H + TPM_RC_2) #define RC_PolicyNV_policySession (TPM_RC_H + TPM_RC_3) #define RC_PolicyNV_operandB (TPM_RC_P + TPM_RC_1) #define RC_PolicyNV_offset (TPM_RC_P + TPM_RC_2) #define RC_PolicyNV_operation (TPM_RC_P + TPM_RC_3) TPM_RC TPM2_PolicyNV( PolicyNV_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/PolicyNameHash_fp.h000066400000000000000000000073251421143571500203620ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PolicyNameHash_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef POLICYNAMEHASH_FP_H #define POLICYNAMEHASH_FP_H typedef struct { TPMI_SH_POLICY policySession; TPM2B_DIGEST nameHash; } PolicyNameHash_In; #define RC_PolicyNameHash_policySession (TPM_RC_H + TPM_RC_1) #define RC_PolicyNameHash_nameHash (TPM_RC_P + TPM_RC_1) TPM_RC TPM2_PolicyNameHash( PolicyNameHash_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/PolicyNvWritten_fp.h000066400000000000000000000073431421143571500206360ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PolicyNvWritten_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef POLICYNVWRITTEN_FP_H #define POLICYNVWRITTEN_FP_H typedef struct { TPMI_SH_POLICY policySession; TPMI_YES_NO writtenSet; } PolicyNvWritten_In; #define RC_PolicyNvWritten_policySession (TPM_RC_H + TPM_RC_1) #define RC_PolicyNvWritten_writtenSet (TPM_RC_P + TPM_RC_1) TPM_RC TPM2_PolicyNvWritten( PolicyNvWritten_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/PolicyOR_fp.h000066400000000000000000000072551421143571500172200ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PolicyOR_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef POLICYOR_FP_H #define POLICYOR_FP_H typedef struct { TPMI_SH_POLICY policySession; TPML_DIGEST pHashList; } PolicyOR_In; #define RC_PolicyOR_policySession (TPM_RC_H + TPM_RC_1) #define RC_PolicyOR_pHashList (TPM_RC_P + TPM_RC_1) TPM_RC TPM2_PolicyOR( PolicyOR_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/PolicyPCR_fp.h000066400000000000000000000074031421143571500173170ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PolicyPCR_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef POLICYPCR_FP_H #define POLICYPCR_FP_H typedef struct { TPMI_SH_POLICY policySession; TPM2B_DIGEST pcrDigest; TPML_PCR_SELECTION pcrs; } PolicyPCR_In; #define RC_PolicyPCR_policySession (TPM_RC_H + TPM_RC_1) #define RC_PolicyPCR_pcrDigest (TPM_RC_P + TPM_RC_1) #define RC_PolicyPCR_pcrs (TPM_RC_P + TPM_RC_2) TPM_RC TPM2_PolicyPCR( PolicyPCR_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/PolicyPassword_fp.h000066400000000000000000000072001421143571500204700ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PolicyPassword_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef POLICYPASSWORD_FP_H #define POLICYPASSWORD_FP_H typedef struct { TPMI_SH_POLICY policySession; } PolicyPassword_In; #define RC_PolicyPassword_policySession (TPM_RC_H + TPM_RC_1) TPM_RC TPM2_PolicyPassword( PolicyPassword_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/PolicyPhysicalPresence_fp.h000066400000000000000000000072561421143571500221420ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PolicyPhysicalPresence_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef POLICYPHYSICALPRESENCE_FP_H #define POLICYPHYSICALPRESENCE_FP_H typedef struct { TPMI_SH_POLICY policySession; } PolicyPhysicalPresence_In; #define RC_PolicyPhysicalPresence_policySession (TPM_RC_H + TPM_RC_1) TPM_RC TPM2_PolicyPhysicalPresence( PolicyPhysicalPresence_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/PolicyRestart_fp.h000066400000000000000000000071701421143571500203200ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PolicyRestart_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef POLICYRESTART_FP_H #define POLICYRESTART_FP_H typedef struct { TPMI_SH_POLICY sessionHandle; } PolicyRestart_In; #define RC_PolicyRestart_sessionHandle (TPM_RC_H + TPM_RC_1) TPM_RC TPM2_PolicyRestart( PolicyRestart_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/PolicySecret_fp.h000066400000000000000000000102661421143571500201210ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PolicySecret_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 124 */ #ifndef POLICYSECRET_FP_H #define POLICYSECRET_FP_H typedef struct { TPMI_DH_ENTITY authHandle; TPMI_SH_POLICY policySession; TPM2B_NONCE nonceTPM; TPM2B_DIGEST cpHashA; TPM2B_NONCE policyRef; INT32 expiration; } PolicySecret_In; #define RC_PolicySecret_authHandle (TPM_RC_H + TPM_RC_1) #define RC_PolicySecret_policySession (TPM_RC_H + TPM_RC_2) #define RC_PolicySecret_nonceTPM (TPM_RC_P + TPM_RC_1) #define RC_PolicySecret_cpHashA (TPM_RC_P + TPM_RC_2) #define RC_PolicySecret_policyRef (TPM_RC_P + TPM_RC_3) #define RC_PolicySecret_expiration (TPM_RC_P + TPM_RC_4) typedef struct { TPM2B_TIMEOUT timeout; TPMT_TK_AUTH policyTicket; } PolicySecret_Out; TPM_RC TPM2_PolicySecret( PolicySecret_In *in, // IN: input parameter list PolicySecret_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/PolicySigned_fp.h000066400000000000000000000104031421143571500200760ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PolicySigned_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef POLICYSIGNED_FP_H #define POLICYSIGNED_FP_H typedef struct { TPMI_DH_OBJECT authObject; TPMI_SH_POLICY policySession; TPM2B_NONCE nonceTPM; TPM2B_DIGEST cpHashA; TPM2B_NONCE policyRef; INT32 expiration; TPMT_SIGNATURE auth; } PolicySigned_In; #define RC_PolicySigned_authObject (TPM_RC_H + TPM_RC_1) #define RC_PolicySigned_policySession (TPM_RC_H + TPM_RC_2) #define RC_PolicySigned_nonceTPM (TPM_RC_P + TPM_RC_1) #define RC_PolicySigned_cpHashA (TPM_RC_P + TPM_RC_2) #define RC_PolicySigned_policyRef (TPM_RC_P + TPM_RC_3) #define RC_PolicySigned_expiration (TPM_RC_P + TPM_RC_4) #define RC_PolicySigned_auth (TPM_RC_P + TPM_RC_5) typedef struct { TPM2B_TIMEOUT timeout; TPMT_TK_AUTH policyTicket; } PolicySigned_Out; TPM_RC TPM2_PolicySigned( PolicySigned_In *in, // IN: input parameter list PolicySigned_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/PolicyTemplate_fp.h000066400000000000000000000073451421143571500204530ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PolicyTemplate_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015, 2016 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef POLICYTEMPLATE_FP_H #define POLICYTEMPLATE_FP_H typedef struct { TPMI_SH_POLICY policySession; TPM2B_DIGEST templateHash; } PolicyTemplate_In; #define RC_PolicyTemplate_policySession (TPM_RC_H + TPM_RC_1) #define RC_PolicyTemplate_templateHash (TPM_RC_P + TPM_RC_1) TPM_RC TPM2_PolicyTemplate( PolicyTemplate_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/PolicyTicket_fp.h000066400000000000000000000100121421143571500201040ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PolicyTicket_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef POLICYTICKET_FP_H #define POLICYTICKET_FP_H typedef struct { TPMI_SH_POLICY policySession; TPM2B_TIMEOUT timeout; TPM2B_DIGEST cpHashA; TPM2B_NONCE policyRef; TPM2B_NAME authName; TPMT_TK_AUTH ticket; } PolicyTicket_In; #define RC_PolicyTicket_policySession (TPM_RC_H + TPM_RC_1) #define RC_PolicyTicket_timeout (TPM_RC_P + TPM_RC_1) #define RC_PolicyTicket_cpHashA (TPM_RC_P + TPM_RC_2) #define RC_PolicyTicket_policyRef (TPM_RC_P + TPM_RC_3) #define RC_PolicyTicket_authName (TPM_RC_P + TPM_RC_4) #define RC_PolicyTicket_ticket (TPM_RC_P + TPM_RC_5) TPM_RC TPM2_PolicyTicket( PolicyTicket_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/Policy_spt.c000066400000000000000000000264701421143571500171530ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Policy Command Support */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Policy_spt.c 1594 2020-03-26 22:15:48Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2020 */ /* */ /********************************************************************************/ /* 7.4 Policy Command Support (Policy_spt.c) */ #include "Tpm.h" #include "Policy_spt_fp.h" #include "PolicySigned_fp.h" #include "PolicySecret_fp.h" #include "PolicyTicket_fp.h" /* 7.4.1 PolicyParameterChecks() */ /* This function validates the common parameters of TPM2_PolicySiged() and TPM2_PolicySecret(). The common parameters are nonceTPM, expiration, and cpHashA. */ TPM_RC PolicyParameterChecks( SESSION *session, UINT64 authTimeout, TPM2B_DIGEST *cpHashA, TPM2B_NONCE *nonce, TPM_RC blameNonce, TPM_RC blameCpHash, TPM_RC blameExpiration ) { // Validate that input nonceTPM is correct if present if(nonce != NULL && nonce->t.size != 0) { if(!MemoryEqual2B(&nonce->b, &session->nonceTPM.b)) return TPM_RCS_NONCE + blameNonce; } // If authTimeout is set (expiration != 0... if(authTimeout != 0) { // Validate input expiration. // Cannot compare time if clock stop advancing. A TPM_RC_NV_UNAVAILABLE // or TPM_RC_NV_RATE error may be returned here. RETURN_IF_NV_IS_NOT_AVAILABLE; // if the time has already passed or the time epoch has changed then the // time value is no longer good. if((authTimeout < g_time) || (session->epoch != g_timeEpoch)) return TPM_RCS_EXPIRED + blameExpiration; } // If the cpHash is present, then check it if(cpHashA != NULL && cpHashA->t.size != 0) { // The cpHash input has to have the correct size if(cpHashA->t.size != session->u2.policyDigest.t.size) return TPM_RCS_SIZE + blameCpHash; // If the cpHash has already been set, then this input value // must match the current value. if(session->u1.cpHash.b.size != 0 && !MemoryEqual2B(&cpHashA->b, &session->u1.cpHash.b)) return TPM_RC_CPHASH; } return TPM_RC_SUCCESS; } /* 7.4.2 PolicyContextUpdate() */ /* Update policy hash Update the policyDigest in policy session by extending policyRef and objectName to it. This will also update the cpHash if it is present. */ void PolicyContextUpdate( TPM_CC commandCode, // IN: command code TPM2B_NAME *name, // IN: name of entity TPM2B_NONCE *ref, // IN: the reference data TPM2B_DIGEST *cpHash, // IN: the cpHash (optional) UINT64 policyTimeout, // IN: the timeout value for the policy SESSION *session // IN/OUT: policy session to be updated ) { HASH_STATE hashState; // Start hash CryptHashStart(&hashState, session->authHashAlg); // policyDigest size should always be the digest size of session hash algorithm. pAssert(session->u2.policyDigest.t.size == CryptHashGetDigestSize(session->authHashAlg)); // add old digest CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); // add commandCode CryptDigestUpdateInt(&hashState, sizeof(commandCode), commandCode); // add name if applicable if(name != NULL) CryptDigestUpdate2B(&hashState, &name->b); // Complete the digest and get the results CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); // If the policy reference is not null, do a second update to the digest. if(ref != NULL) { // Start second hash computation CryptHashStart(&hashState, session->authHashAlg); // add policyDigest CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b); // add policyRef CryptDigestUpdate2B(&hashState, &ref->b); // Complete second digest CryptHashEnd2B(&hashState, &session->u2.policyDigest.b); } // Deal with the cpHash. If the cpHash value is present // then it would have already been checked to make sure that // it is compatible with the current value so all we need // to do here is copy it and set the isCpHashDefined attribute if(cpHash != NULL && cpHash->t.size != 0) { session->u1.cpHash = *cpHash; session->attributes.isCpHashDefined = SET; } // update the timeout if it is specified if(policyTimeout != 0) { // If the timeout has not been set, then set it to the new value // than the current timeout then set it to the new value if(session->timeout == 0 || session->timeout > policyTimeout) session->timeout = policyTimeout; } return; } /* 7.4.2.1 ComputeAuthTimeout() */ /* This function is used to determine what the authorization timeout value for the session should be. */ UINT64 ComputeAuthTimeout( SESSION *session, // IN: the session containing the time // values INT32 expiration, // IN: either the number of seconds from // the start of the session or the // time in g_timer; TPM2B_NONCE *nonce // IN: indicator of the time base ) { UINT64 policyTime; // If no expiration, policy time is 0 if(expiration == 0) policyTime = 0; else { if(expiration < 0) { if (expiration == (INT32)0x80000000) /* libtpms changed begin; ubsan */ expiration++; /* libtpms changed end */ expiration = -expiration; } if(nonce->t.size == 0) // The input time is absolute Time (not Clock), but it is expressed // in seconds. To make sure that we don't time out too early, take the // current value of milliseconds in g_time and add that to the input // seconds value. policyTime = (((UINT64)expiration) * 1000) + g_time % 1000; else // The policy timeout is the absolute value of the expiration in seconds // added to the start time of the policy. policyTime = session->startTime + (((UINT64)expiration) * 1000); } return policyTime; } /* 7.4.2.2 PolicyDigestClear() */ /* Function to reset the policyDigest of a session */ void PolicyDigestClear( SESSION *session ) { session->u2.policyDigest.t.size = CryptHashGetDigestSize(session->authHashAlg); MemorySet(session->u2.policyDigest.t.buffer, 0, session->u2.policyDigest.t.size); } /* 7.4.2.5 PolicySptCheckCondition() */ /* Checks to see if the condition in the policy is satisfied. */ BOOL PolicySptCheckCondition( TPM_EO operation, BYTE *opA, BYTE *opB, UINT16 size ) { // Arithmetic Comparison switch(operation) { case TPM_EO_EQ: // compare A = B return (UnsignedCompareB(size, opA, size, opB) == 0); break; case TPM_EO_NEQ: // compare A != B return (UnsignedCompareB(size, opA, size, opB) != 0); break; case TPM_EO_SIGNED_GT: // compare A > B signed return (SignedCompareB(size, opA, size, opB) > 0); break; case TPM_EO_UNSIGNED_GT: // compare A > B unsigned return (UnsignedCompareB(size, opA, size, opB) > 0); break; case TPM_EO_SIGNED_LT: // compare A < B signed return (SignedCompareB(size, opA, size, opB) < 0); break; case TPM_EO_UNSIGNED_LT: // compare A < B unsigned return (UnsignedCompareB(size, opA, size, opB) < 0); break; case TPM_EO_SIGNED_GE: // compare A >= B signed return (SignedCompareB(size, opA, size, opB) >= 0); break; case TPM_EO_UNSIGNED_GE: // compare A >= B unsigned return (UnsignedCompareB(size, opA, size, opB) >= 0); break; case TPM_EO_SIGNED_LE: // compare A <= B signed return (SignedCompareB(size, opA, size, opB) <= 0); break; case TPM_EO_UNSIGNED_LE: // compare A <= B unsigned return (UnsignedCompareB(size, opA, size, opB) <= 0); break; case TPM_EO_BITSET: // All bits SET in B are SET in A. ((A&B)=B) { UINT32 i; for(i = 0; i < size; i++) if((opA[i] & opB[i]) != opB[i]) return FALSE; } break; case TPM_EO_BITCLEAR: // All bits SET in B are CLEAR in A. ((A&B)=0) { UINT32 i; for(i = 0; i < size; i++) if((opA[i] & opB[i]) != 0) return FALSE; } break; default: FAIL(FATAL_ERROR_INTERNAL); break; } return TRUE; } libtpms-0.9.3/src/tpm2/Policy_spt_fp.h000066400000000000000000000112251421143571500176350ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Policy_spt_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 */ /* */ /********************************************************************************/ #ifndef POLICY_SPT_FP_H #define POLICY_SPT_FP_H TPM_RC PolicyParameterChecks( SESSION *session, UINT64 authTimeout, TPM2B_DIGEST *cpHashA, TPM2B_NONCE *nonce, TPM_RC blameNonce, TPM_RC blameCpHash, TPM_RC blameExpiration ); void PolicyContextUpdate( TPM_CC commandCode, // IN: command code TPM2B_NAME *name, // IN: name of entity TPM2B_NONCE *ref, // IN: the reference data TPM2B_DIGEST *cpHash, // IN: the cpHash (optional) UINT64 policyTimeout, // IN: the timeout value for the policy SESSION *session // IN/OUT: policy session to be updated ); UINT64 ComputeAuthTimeout( SESSION *session, // IN: the session containing the time // values INT32 expiration, // IN: either the number of seconds from // the start of the session or the // time in g_timer; TPM2B_NONCE *nonce // IN: indicator of the time base ); void PolicyDigestClear( SESSION *session ); BOOL PolicySptCheckCondition( TPM_EO operation, BYTE *opA, BYTE *opB, UINT16 size ); #endif libtpms-0.9.3/src/tpm2/Power.c000066400000000000000000000105471421143571500161200ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Simulated Power State Transitions of the TPM */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Power.c 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ /* 9.13 Power.c */ /* 9.13.1 Description */ /* This file contains functions that receive the simulated power state transitions of the TPM. */ /* 9.13.2 Includes and Data Definitions */ #define POWER_C #include "Tpm.h" /* 9.13.3 Functions */ /* 9.13.3.1 TPMInit() */ /* This function is used to process a power on event. */ void TPMInit( void ) { // Set state as not initialized. This means that Startup is required g_initialized = FALSE; return; } /* 9.13.3.2 TPMRegisterStartup() */ /* This function registers the fact that the TPM has been initialized (a TPM2_Startup() has completed successfully). */ BOOL TPMRegisterStartup( void ) { g_initialized = TRUE; return TRUE; } /* 9.13.3.3 TPMIsStarted() */ /* Indicates if the TPM has been initialized (a TPM2_Startup() has completed successfully after a _TPM_Init()). */ /* Return Values Meaning */ /* TRUE TPM has been initialized */ /* FALSE TPM has not been initialized */ BOOL TPMIsStarted( void ) { return g_initialized; } libtpms-0.9.3/src/tpm2/PowerPlat.c000066400000000000000000000122351421143571500167350ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Platform Power Support */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PowerPlat.c 1529 2019-11-21 23:29:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ /* C.7 PowerPlat.c */ /* C.7.1. Includes and Function Prototypes */ #include "Platform.h" #include "PlatformACT_fp.h" /* added kgold */ #include "_TPM_Init_fp.h" /* C.7.2. Functions */ /* C.7.2.1. _plat__Signal_PowerOn() */ /* Signal platform power on */ LIB_EXPORT int _plat__Signal_PowerOn( void ) { // Reset the timer _plat__TimerReset(); // Need to indicate that we lost power s_powerLost = TRUE; return 0; } /* C.7.2.2. _plat__WasPowerLost() */ /* Test whether power was lost before a _TPM_Init(). */ /* This function will clear the hardware indication of power loss before return. This means that there can only be one spot in the TPM code where this value gets read. This method is used here as it is the most difficult to manage in the TPM code and, if the hardware actually works this way, it is hard to make it look like anything else. So, the burden is placed on the TPM code rather than the platform code */ /* Return Values Meaning */ /* TRUE(1) power was lost */ /* FALSE(0) power was not lost */ LIB_EXPORT int _plat__WasPowerLost( void ) { int retVal = s_powerLost; s_powerLost = FALSE; return retVal; } /* C.7.2.3. _plat_Signal_Reset() */ /* This a TPM reset without a power loss. */ LIB_EXPORT int _plat__Signal_Reset( void ) { // Initialize locality s_locality = 0; // Command cancel s_isCanceled = FALSE; _TPM_Init(); // if we are doing reset but did not have a power failure, then we should // not need to reload NV ... return 0; } /* C.7.2.4. _plat__Signal_PowerOff() */ /* Signal platform power off */ LIB_EXPORT void _plat__Signal_PowerOff( void ) { // Prepare NV memory for power off _plat__NVDisable(0); // Disable tick ACT tick processing _plat__ACT_EnableTicks(FALSE); return; } libtpms-0.9.3/src/tpm2/Power_fp.h000066400000000000000000000070161421143571500166070ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Functions That Receive the Simulated Power State Transitions of the TPM */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Power_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ #ifndef POWER_FP_H #define POWER_FP_H void TPMInit( void ); BOOL TPMRegisterStartup( void ); BOOL TPMIsStarted( void ); #endif libtpms-0.9.3/src/tpm2/PrimeData.c000066400000000000000000000746631421143571500167030ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Product of all of the Primes up to 1000 */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PrimeData.c 1311 2018-08-23 21:39:29Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2018 */ /* */ /********************************************************************************/ #include "Tpm.h" /* This table is the product of all of the primes up to 1000. Checking to see if there is a GCD between a prime candidate and this number will eliminate many prime candidates from consideration before running Miller-Rabin on the result. */ const BN_STRUCT(43 * RADIX_BITS) s_CompositeOfSmallPrimes_ = {44, 44, { 0x2ED42696, 0x2BBFA177, 0x4820594F, 0xF73F4841, 0xBFAC313A, 0xCAC3EB81, 0xF6F26BF8, 0x7FAB5061, 0x59746FB7, 0xF71377F6, 0x3B19855B, 0xCBD03132, 0xBB92EF1B, 0x3AC3152C, 0xE87C8273, 0xC0AE0E69, 0x74A9E295, 0x448CCE86, 0x63CA1907, 0x8A0BF944, 0xF8CC3BE0, 0xC26F0AF5, 0xC501C02F, 0x6579441A, 0xD1099CDA, 0x6BC76A00, 0xC81A3228, 0xBFB1AB25, 0x70FA3841, 0x51B3D076, 0xCC2359ED, 0xD9EE0769, 0x75E47AF0, 0xD45FF31E, 0x52CCE4F6, 0x04DBC891, 0x96658ED2, 0x1753EFE5, 0x3AE4A5A6, 0x8FD4A97F, 0x8B15E7EB, 0x0243C3E1, 0xE0F0C31D, 0x0000000B } }; bigConst s_CompositeOfSmallPrimes = (const bigNum)&s_CompositeOfSmallPrimes_; /* This table contains a bit for each of the odd values between 1 and 2^16 + 1. This table allows fast checking of the primes in that range. Don't change the size of this table unless you are prepared to do redo IsPrimeInt(). */ const uint32_t s_LastPrimeInTable = 65537; const uint32_t s_PrimeTableSize = 4097; const uint32_t s_PrimesInTable = 6542; const unsigned char s_PrimeTable[] = { 0x6e, 0xcb, 0xb4, 0x64, 0x9a, 0x12, 0x6d, 0x81, 0x32, 0x4c, 0x4a, 0x86, 0x0d, 0x82, 0x96, 0x21, 0xc9, 0x34, 0x04, 0x5a, 0x20, 0x61, 0x89, 0xa4, 0x44, 0x11, 0x86, 0x29, 0xd1, 0x82, 0x28, 0x4a, 0x30, 0x40, 0x42, 0x32, 0x21, 0x99, 0x34, 0x08, 0x4b, 0x06, 0x25, 0x42, 0x84, 0x48, 0x8a, 0x14, 0x05, 0x42, 0x30, 0x6c, 0x08, 0xb4, 0x40, 0x0b, 0xa0, 0x08, 0x51, 0x12, 0x28, 0x89, 0x04, 0x65, 0x98, 0x30, 0x4c, 0x80, 0x96, 0x44, 0x12, 0x80, 0x21, 0x42, 0x12, 0x41, 0xc9, 0x04, 0x21, 0xc0, 0x32, 0x2d, 0x98, 0x00, 0x00, 0x49, 0x04, 0x08, 0x81, 0x96, 0x68, 0x82, 0xb0, 0x25, 0x08, 0x22, 0x48, 0x89, 0xa2, 0x40, 0x59, 0x26, 0x04, 0x90, 0x06, 0x40, 0x43, 0x30, 0x44, 0x92, 0x00, 0x69, 0x10, 0x82, 0x08, 0x08, 0xa4, 0x0d, 0x41, 0x12, 0x60, 0xc0, 0x00, 0x24, 0xd2, 0x22, 0x61, 0x08, 0x84, 0x04, 0x1b, 0x82, 0x01, 0xd3, 0x10, 0x01, 0x02, 0xa0, 0x44, 0xc0, 0x22, 0x60, 0x91, 0x14, 0x0c, 0x40, 0xa6, 0x04, 0xd2, 0x94, 0x20, 0x09, 0x94, 0x20, 0x52, 0x00, 0x08, 0x10, 0xa2, 0x4c, 0x00, 0x82, 0x01, 0x51, 0x10, 0x08, 0x8b, 0xa4, 0x25, 0x9a, 0x30, 0x44, 0x81, 0x10, 0x4c, 0x03, 0x02, 0x25, 0x52, 0x80, 0x08, 0x49, 0x84, 0x20, 0x50, 0x32, 0x00, 0x18, 0xa2, 0x40, 0x11, 0x24, 0x28, 0x01, 0x84, 0x01, 0x01, 0xa0, 0x41, 0x0a, 0x12, 0x45, 0x00, 0x36, 0x08, 0x00, 0x26, 0x29, 0x83, 0x82, 0x61, 0xc0, 0x80, 0x04, 0x10, 0x10, 0x6d, 0x00, 0x22, 0x48, 0x58, 0x26, 0x0c, 0xc2, 0x10, 0x48, 0x89, 0x24, 0x20, 0x58, 0x20, 0x45, 0x88, 0x24, 0x00, 0x19, 0x02, 0x25, 0xc0, 0x10, 0x68, 0x08, 0x14, 0x01, 0xca, 0x32, 0x28, 0x80, 0x00, 0x04, 0x4b, 0x26, 0x00, 0x13, 0x90, 0x60, 0x82, 0x80, 0x25, 0xd0, 0x00, 0x01, 0x10, 0x32, 0x0c, 0x43, 0x86, 0x21, 0x11, 0x00, 0x08, 0x43, 0x24, 0x04, 0x48, 0x10, 0x0c, 0x90, 0x92, 0x00, 0x43, 0x20, 0x2d, 0x00, 0x06, 0x09, 0x88, 0x24, 0x40, 0xc0, 0x32, 0x09, 0x09, 0x82, 0x00, 0x53, 0x80, 0x08, 0x80, 0x96, 0x41, 0x81, 0x00, 0x40, 0x48, 0x10, 0x48, 0x08, 0x96, 0x48, 0x58, 0x20, 0x29, 0xc3, 0x80, 0x20, 0x02, 0x94, 0x60, 0x92, 0x00, 0x20, 0x81, 0x22, 0x44, 0x10, 0xa0, 0x05, 0x40, 0x90, 0x01, 0x49, 0x20, 0x04, 0x0a, 0x00, 0x24, 0x89, 0x34, 0x48, 0x13, 0x80, 0x2c, 0xc0, 0x82, 0x29, 0x00, 0x24, 0x45, 0x08, 0x00, 0x08, 0x98, 0x36, 0x04, 0x52, 0x84, 0x04, 0xd0, 0x04, 0x00, 0x8a, 0x90, 0x44, 0x82, 0x32, 0x65, 0x18, 0x90, 0x00, 0x0a, 0x02, 0x01, 0x40, 0x02, 0x28, 0x40, 0xa4, 0x04, 0x92, 0x30, 0x04, 0x11, 0x86, 0x08, 0x42, 0x00, 0x2c, 0x52, 0x04, 0x08, 0xc9, 0x84, 0x60, 0x48, 0x12, 0x09, 0x99, 0x24, 0x44, 0x00, 0x24, 0x00, 0x03, 0x14, 0x21, 0x00, 0x10, 0x01, 0x1a, 0x32, 0x05, 0x88, 0x20, 0x40, 0x40, 0x06, 0x09, 0xc3, 0x84, 0x40, 0x01, 0x30, 0x60, 0x18, 0x02, 0x68, 0x11, 0x90, 0x0c, 0x02, 0xa2, 0x04, 0x00, 0x86, 0x29, 0x89, 0x14, 0x24, 0x82, 0x02, 0x41, 0x08, 0x80, 0x04, 0x19, 0x80, 0x08, 0x10, 0x12, 0x68, 0x42, 0xa4, 0x04, 0x00, 0x02, 0x61, 0x10, 0x06, 0x0c, 0x10, 0x00, 0x01, 0x12, 0x10, 0x20, 0x03, 0x94, 0x21, 0x42, 0x12, 0x65, 0x18, 0x94, 0x0c, 0x0a, 0x04, 0x28, 0x01, 0x14, 0x29, 0x0a, 0xa4, 0x40, 0xd0, 0x00, 0x40, 0x01, 0x90, 0x04, 0x41, 0x20, 0x2d, 0x40, 0x82, 0x48, 0xc1, 0x20, 0x00, 0x10, 0x30, 0x01, 0x08, 0x24, 0x04, 0x59, 0x84, 0x24, 0x00, 0x02, 0x29, 0x82, 0x00, 0x61, 0x58, 0x02, 0x48, 0x81, 0x16, 0x48, 0x10, 0x00, 0x21, 0x11, 0x06, 0x00, 0xca, 0xa0, 0x40, 0x02, 0x00, 0x04, 0x91, 0xb0, 0x00, 0x42, 0x04, 0x0c, 0x81, 0x06, 0x09, 0x48, 0x14, 0x25, 0x92, 0x20, 0x25, 0x11, 0xa0, 0x00, 0x0a, 0x86, 0x0c, 0xc1, 0x02, 0x48, 0x00, 0x20, 0x45, 0x08, 0x32, 0x00, 0x98, 0x06, 0x04, 0x13, 0x22, 0x00, 0x82, 0x04, 0x48, 0x81, 0x14, 0x44, 0x82, 0x12, 0x24, 0x18, 0x10, 0x40, 0x43, 0x80, 0x28, 0xd0, 0x04, 0x20, 0x81, 0x24, 0x64, 0xd8, 0x00, 0x2c, 0x09, 0x12, 0x08, 0x41, 0xa2, 0x00, 0x00, 0x02, 0x41, 0xca, 0x20, 0x41, 0xc0, 0x10, 0x01, 0x18, 0xa4, 0x04, 0x18, 0xa4, 0x20, 0x12, 0x94, 0x20, 0x83, 0xa0, 0x40, 0x02, 0x32, 0x44, 0x80, 0x04, 0x00, 0x18, 0x00, 0x0c, 0x40, 0x86, 0x60, 0x8a, 0x00, 0x64, 0x88, 0x12, 0x05, 0x01, 0x82, 0x00, 0x4a, 0xa2, 0x01, 0xc1, 0x10, 0x61, 0x09, 0x04, 0x01, 0x88, 0x00, 0x60, 0x01, 0xb4, 0x40, 0x08, 0x06, 0x01, 0x03, 0x80, 0x08, 0x40, 0x94, 0x04, 0x8a, 0x20, 0x29, 0x80, 0x02, 0x0c, 0x52, 0x02, 0x01, 0x42, 0x84, 0x00, 0x80, 0x84, 0x64, 0x02, 0x32, 0x48, 0x00, 0x30, 0x44, 0x40, 0x22, 0x21, 0x00, 0x02, 0x08, 0xc3, 0xa0, 0x04, 0xd0, 0x20, 0x40, 0x18, 0x16, 0x40, 0x40, 0x00, 0x28, 0x52, 0x90, 0x08, 0x82, 0x14, 0x01, 0x18, 0x10, 0x08, 0x09, 0x82, 0x40, 0x0a, 0xa0, 0x20, 0x93, 0x80, 0x08, 0xc0, 0x00, 0x20, 0x52, 0x00, 0x05, 0x01, 0x10, 0x40, 0x11, 0x06, 0x0c, 0x82, 0x00, 0x00, 0x4b, 0x90, 0x44, 0x9a, 0x00, 0x28, 0x80, 0x90, 0x04, 0x4a, 0x06, 0x09, 0x43, 0x02, 0x28, 0x00, 0x34, 0x01, 0x18, 0x00, 0x65, 0x09, 0x80, 0x44, 0x03, 0x00, 0x24, 0x02, 0x82, 0x61, 0x48, 0x14, 0x41, 0x00, 0x12, 0x28, 0x00, 0x34, 0x08, 0x51, 0x04, 0x05, 0x12, 0x90, 0x28, 0x89, 0x84, 0x60, 0x12, 0x10, 0x49, 0x10, 0x26, 0x40, 0x49, 0x82, 0x00, 0x91, 0x10, 0x01, 0x0a, 0x24, 0x40, 0x88, 0x10, 0x4c, 0x10, 0x04, 0x00, 0x50, 0xa2, 0x2c, 0x40, 0x90, 0x48, 0x0a, 0xb0, 0x01, 0x50, 0x12, 0x08, 0x00, 0xa4, 0x04, 0x09, 0xa0, 0x28, 0x92, 0x02, 0x00, 0x43, 0x10, 0x21, 0x02, 0x20, 0x41, 0x81, 0x32, 0x00, 0x08, 0x04, 0x0c, 0x52, 0x00, 0x21, 0x49, 0x84, 0x20, 0x10, 0x02, 0x01, 0x81, 0x10, 0x48, 0x40, 0x22, 0x01, 0x01, 0x84, 0x69, 0xc1, 0x30, 0x01, 0xc8, 0x02, 0x44, 0x88, 0x00, 0x0c, 0x01, 0x02, 0x2d, 0xc0, 0x12, 0x61, 0x00, 0xa0, 0x00, 0xc0, 0x30, 0x40, 0x01, 0x12, 0x08, 0x0b, 0x20, 0x00, 0x80, 0x94, 0x40, 0x01, 0x84, 0x40, 0x00, 0x32, 0x00, 0x10, 0x84, 0x00, 0x0b, 0x24, 0x00, 0x01, 0x06, 0x29, 0x8a, 0x84, 0x41, 0x80, 0x10, 0x08, 0x08, 0x94, 0x4c, 0x03, 0x80, 0x01, 0x40, 0x96, 0x40, 0x41, 0x20, 0x20, 0x50, 0x22, 0x25, 0x89, 0xa2, 0x40, 0x40, 0xa4, 0x20, 0x02, 0x86, 0x28, 0x01, 0x20, 0x21, 0x4a, 0x10, 0x08, 0x00, 0x14, 0x08, 0x40, 0x04, 0x25, 0x42, 0x02, 0x21, 0x43, 0x10, 0x04, 0x92, 0x00, 0x21, 0x11, 0xa0, 0x4c, 0x18, 0x22, 0x09, 0x03, 0x84, 0x41, 0x89, 0x10, 0x04, 0x82, 0x22, 0x24, 0x01, 0x14, 0x08, 0x08, 0x84, 0x08, 0xc1, 0x00, 0x09, 0x42, 0xb0, 0x41, 0x8a, 0x02, 0x00, 0x80, 0x36, 0x04, 0x49, 0xa0, 0x24, 0x91, 0x00, 0x00, 0x02, 0x94, 0x41, 0x92, 0x02, 0x01, 0x08, 0x06, 0x08, 0x09, 0x00, 0x01, 0xd0, 0x16, 0x28, 0x89, 0x80, 0x60, 0x00, 0x00, 0x68, 0x01, 0x90, 0x0c, 0x50, 0x20, 0x01, 0x40, 0x80, 0x40, 0x42, 0x30, 0x41, 0x00, 0x20, 0x25, 0x81, 0x06, 0x40, 0x49, 0x00, 0x08, 0x01, 0x12, 0x49, 0x00, 0xa0, 0x20, 0x18, 0x30, 0x05, 0x01, 0xa6, 0x00, 0x10, 0x24, 0x28, 0x00, 0x02, 0x20, 0xc8, 0x20, 0x00, 0x88, 0x12, 0x0c, 0x90, 0x92, 0x00, 0x02, 0x26, 0x01, 0x42, 0x16, 0x49, 0x00, 0x04, 0x24, 0x42, 0x02, 0x01, 0x88, 0x80, 0x0c, 0x1a, 0x80, 0x08, 0x10, 0x00, 0x60, 0x02, 0x94, 0x44, 0x88, 0x00, 0x69, 0x11, 0x30, 0x08, 0x12, 0xa0, 0x24, 0x13, 0x84, 0x00, 0x82, 0x00, 0x65, 0xc0, 0x10, 0x28, 0x00, 0x30, 0x04, 0x03, 0x20, 0x01, 0x11, 0x06, 0x01, 0xc8, 0x80, 0x00, 0xc2, 0x20, 0x08, 0x10, 0x82, 0x0c, 0x13, 0x02, 0x0c, 0x52, 0x06, 0x40, 0x00, 0xb0, 0x61, 0x40, 0x10, 0x01, 0x98, 0x86, 0x04, 0x10, 0x84, 0x08, 0x92, 0x14, 0x60, 0x41, 0x80, 0x41, 0x1a, 0x10, 0x04, 0x81, 0x22, 0x40, 0x41, 0x20, 0x29, 0x52, 0x00, 0x41, 0x08, 0x34, 0x60, 0x10, 0x00, 0x28, 0x01, 0x10, 0x40, 0x00, 0x84, 0x08, 0x42, 0x90, 0x20, 0x48, 0x04, 0x04, 0x52, 0x02, 0x00, 0x08, 0x20, 0x04, 0x00, 0x82, 0x0d, 0x00, 0x82, 0x40, 0x02, 0x10, 0x05, 0x48, 0x20, 0x40, 0x99, 0x00, 0x00, 0x01, 0x06, 0x24, 0xc0, 0x00, 0x68, 0x82, 0x04, 0x21, 0x12, 0x10, 0x44, 0x08, 0x04, 0x00, 0x40, 0xa6, 0x20, 0xd0, 0x16, 0x09, 0xc9, 0x24, 0x41, 0x02, 0x20, 0x0c, 0x09, 0x92, 0x40, 0x12, 0x00, 0x00, 0x40, 0x00, 0x09, 0x43, 0x84, 0x20, 0x98, 0x02, 0x01, 0x11, 0x24, 0x00, 0x43, 0x24, 0x00, 0x03, 0x90, 0x08, 0x41, 0x30, 0x24, 0x58, 0x20, 0x4c, 0x80, 0x82, 0x08, 0x10, 0x24, 0x25, 0x81, 0x06, 0x41, 0x09, 0x10, 0x20, 0x18, 0x10, 0x44, 0x80, 0x10, 0x00, 0x4a, 0x24, 0x0d, 0x01, 0x94, 0x28, 0x80, 0x30, 0x00, 0xc0, 0x02, 0x60, 0x10, 0x84, 0x0c, 0x02, 0x00, 0x09, 0x02, 0x82, 0x01, 0x08, 0x10, 0x04, 0xc2, 0x20, 0x68, 0x09, 0x06, 0x04, 0x18, 0x00, 0x00, 0x11, 0x90, 0x08, 0x0b, 0x10, 0x21, 0x82, 0x02, 0x0c, 0x10, 0xb6, 0x08, 0x00, 0x26, 0x00, 0x41, 0x02, 0x01, 0x4a, 0x24, 0x21, 0x1a, 0x20, 0x24, 0x80, 0x00, 0x44, 0x02, 0x00, 0x2d, 0x40, 0x02, 0x00, 0x8b, 0x94, 0x20, 0x10, 0x00, 0x20, 0x90, 0xa6, 0x40, 0x13, 0x00, 0x2c, 0x11, 0x86, 0x61, 0x01, 0x80, 0x41, 0x10, 0x02, 0x04, 0x81, 0x30, 0x48, 0x48, 0x20, 0x28, 0x50, 0x80, 0x21, 0x8a, 0x10, 0x04, 0x08, 0x10, 0x09, 0x10, 0x10, 0x48, 0x42, 0xa0, 0x0c, 0x82, 0x92, 0x60, 0xc0, 0x20, 0x05, 0xd2, 0x20, 0x40, 0x01, 0x00, 0x04, 0x08, 0x82, 0x2d, 0x82, 0x02, 0x00, 0x48, 0x80, 0x41, 0x48, 0x10, 0x00, 0x91, 0x04, 0x04, 0x03, 0x84, 0x00, 0xc2, 0x04, 0x68, 0x00, 0x00, 0x64, 0xc0, 0x22, 0x40, 0x08, 0x32, 0x44, 0x09, 0x86, 0x00, 0x91, 0x02, 0x28, 0x01, 0x00, 0x64, 0x48, 0x00, 0x24, 0x10, 0x90, 0x00, 0x43, 0x00, 0x21, 0x52, 0x86, 0x41, 0x8b, 0x90, 0x20, 0x40, 0x20, 0x08, 0x88, 0x04, 0x44, 0x13, 0x20, 0x00, 0x02, 0x84, 0x60, 0x81, 0x90, 0x24, 0x40, 0x30, 0x00, 0x08, 0x10, 0x08, 0x08, 0x02, 0x01, 0x10, 0x04, 0x20, 0x43, 0xb4, 0x40, 0x90, 0x12, 0x68, 0x01, 0x80, 0x4c, 0x18, 0x00, 0x08, 0xc0, 0x12, 0x49, 0x40, 0x10, 0x24, 0x1a, 0x00, 0x41, 0x89, 0x24, 0x4c, 0x10, 0x00, 0x04, 0x52, 0x10, 0x09, 0x4a, 0x20, 0x41, 0x48, 0x22, 0x69, 0x11, 0x14, 0x08, 0x10, 0x06, 0x24, 0x80, 0x84, 0x28, 0x00, 0x10, 0x00, 0x40, 0x10, 0x01, 0x08, 0x26, 0x08, 0x48, 0x06, 0x28, 0x00, 0x14, 0x01, 0x42, 0x84, 0x04, 0x0a, 0x20, 0x00, 0x01, 0x82, 0x08, 0x00, 0x82, 0x24, 0x12, 0x04, 0x40, 0x40, 0xa0, 0x40, 0x90, 0x10, 0x04, 0x90, 0x22, 0x40, 0x10, 0x20, 0x2c, 0x80, 0x10, 0x28, 0x43, 0x00, 0x04, 0x58, 0x00, 0x01, 0x81, 0x10, 0x48, 0x09, 0x20, 0x21, 0x83, 0x04, 0x00, 0x42, 0xa4, 0x44, 0x00, 0x00, 0x6c, 0x10, 0xa0, 0x44, 0x48, 0x80, 0x00, 0x83, 0x80, 0x48, 0xc9, 0x00, 0x00, 0x00, 0x02, 0x05, 0x10, 0xb0, 0x04, 0x13, 0x04, 0x29, 0x10, 0x92, 0x40, 0x08, 0x04, 0x44, 0x82, 0x22, 0x00, 0x19, 0x20, 0x00, 0x19, 0x20, 0x01, 0x81, 0x90, 0x60, 0x8a, 0x00, 0x41, 0xc0, 0x02, 0x45, 0x10, 0x04, 0x00, 0x02, 0xa2, 0x09, 0x40, 0x10, 0x21, 0x49, 0x20, 0x01, 0x42, 0x30, 0x2c, 0x00, 0x14, 0x44, 0x01, 0x22, 0x04, 0x02, 0x92, 0x08, 0x89, 0x04, 0x21, 0x80, 0x10, 0x05, 0x01, 0x20, 0x40, 0x41, 0x80, 0x04, 0x00, 0x12, 0x09, 0x40, 0xb0, 0x64, 0x58, 0x32, 0x01, 0x08, 0x90, 0x00, 0x41, 0x04, 0x09, 0xc1, 0x80, 0x61, 0x08, 0x90, 0x00, 0x9a, 0x00, 0x24, 0x01, 0x12, 0x08, 0x02, 0x26, 0x05, 0x82, 0x06, 0x08, 0x08, 0x00, 0x20, 0x48, 0x20, 0x00, 0x18, 0x24, 0x48, 0x03, 0x02, 0x00, 0x11, 0x00, 0x09, 0x00, 0x84, 0x01, 0x4a, 0x10, 0x01, 0x98, 0x00, 0x04, 0x18, 0x86, 0x00, 0xc0, 0x00, 0x20, 0x81, 0x80, 0x04, 0x10, 0x30, 0x05, 0x00, 0xb4, 0x0c, 0x4a, 0x82, 0x29, 0x91, 0x02, 0x28, 0x00, 0x20, 0x44, 0xc0, 0x00, 0x2c, 0x91, 0x80, 0x40, 0x01, 0xa2, 0x00, 0x12, 0x04, 0x09, 0xc3, 0x20, 0x00, 0x08, 0x02, 0x0c, 0x10, 0x22, 0x04, 0x00, 0x00, 0x2c, 0x11, 0x86, 0x00, 0xc0, 0x00, 0x00, 0x12, 0x32, 0x40, 0x89, 0x80, 0x40, 0x40, 0x02, 0x05, 0x50, 0x86, 0x60, 0x82, 0xa4, 0x60, 0x0a, 0x12, 0x4d, 0x80, 0x90, 0x08, 0x12, 0x80, 0x09, 0x02, 0x14, 0x48, 0x01, 0x24, 0x20, 0x8a, 0x00, 0x44, 0x90, 0x04, 0x04, 0x01, 0x02, 0x00, 0xd1, 0x12, 0x00, 0x0a, 0x04, 0x40, 0x00, 0x32, 0x21, 0x81, 0x24, 0x08, 0x19, 0x84, 0x20, 0x02, 0x04, 0x08, 0x89, 0x80, 0x24, 0x02, 0x02, 0x68, 0x18, 0x82, 0x44, 0x42, 0x00, 0x21, 0x40, 0x00, 0x28, 0x01, 0x80, 0x45, 0x82, 0x20, 0x40, 0x11, 0x80, 0x0c, 0x02, 0x00, 0x24, 0x40, 0x90, 0x01, 0x40, 0x20, 0x20, 0x50, 0x20, 0x28, 0x19, 0x00, 0x40, 0x09, 0x20, 0x08, 0x80, 0x04, 0x60, 0x40, 0x80, 0x20, 0x08, 0x30, 0x49, 0x09, 0x34, 0x00, 0x11, 0x24, 0x24, 0x82, 0x00, 0x41, 0xc2, 0x00, 0x04, 0x92, 0x02, 0x24, 0x80, 0x00, 0x0c, 0x02, 0xa0, 0x00, 0x01, 0x06, 0x60, 0x41, 0x04, 0x21, 0xd0, 0x00, 0x01, 0x01, 0x00, 0x48, 0x12, 0x84, 0x04, 0x91, 0x12, 0x08, 0x00, 0x24, 0x44, 0x00, 0x12, 0x41, 0x18, 0x26, 0x0c, 0x41, 0x80, 0x00, 0x52, 0x04, 0x20, 0x09, 0x00, 0x24, 0x90, 0x20, 0x48, 0x18, 0x02, 0x00, 0x03, 0xa2, 0x09, 0xd0, 0x14, 0x00, 0x8a, 0x84, 0x25, 0x4a, 0x00, 0x20, 0x98, 0x14, 0x40, 0x00, 0xa2, 0x05, 0x00, 0x00, 0x00, 0x40, 0x14, 0x01, 0x58, 0x20, 0x2c, 0x80, 0x84, 0x00, 0x09, 0x20, 0x20, 0x91, 0x02, 0x08, 0x02, 0xb0, 0x41, 0x08, 0x30, 0x00, 0x09, 0x10, 0x00, 0x18, 0x02, 0x21, 0x02, 0x02, 0x00, 0x00, 0x24, 0x44, 0x08, 0x12, 0x60, 0x00, 0xb2, 0x44, 0x12, 0x02, 0x0c, 0xc0, 0x80, 0x40, 0xc8, 0x20, 0x04, 0x50, 0x20, 0x05, 0x00, 0xb0, 0x04, 0x0b, 0x04, 0x29, 0x53, 0x00, 0x61, 0x48, 0x30, 0x00, 0x82, 0x20, 0x29, 0x00, 0x16, 0x00, 0x53, 0x22, 0x20, 0x43, 0x10, 0x48, 0x00, 0x80, 0x04, 0xd2, 0x00, 0x40, 0x00, 0xa2, 0x44, 0x03, 0x80, 0x29, 0x00, 0x04, 0x08, 0xc0, 0x04, 0x64, 0x40, 0x30, 0x28, 0x09, 0x84, 0x44, 0x50, 0x80, 0x21, 0x02, 0x92, 0x00, 0xc0, 0x10, 0x60, 0x88, 0x22, 0x08, 0x80, 0x00, 0x00, 0x18, 0x84, 0x04, 0x83, 0x96, 0x00, 0x81, 0x20, 0x05, 0x02, 0x00, 0x45, 0x88, 0x84, 0x00, 0x51, 0x20, 0x20, 0x51, 0x86, 0x41, 0x4b, 0x94, 0x00, 0x80, 0x00, 0x08, 0x11, 0x20, 0x4c, 0x58, 0x80, 0x04, 0x03, 0x06, 0x20, 0x89, 0x00, 0x05, 0x08, 0x22, 0x05, 0x90, 0x00, 0x40, 0x00, 0x82, 0x09, 0x50, 0x00, 0x00, 0x00, 0xa0, 0x41, 0xc2, 0x20, 0x08, 0x00, 0x16, 0x08, 0x40, 0x26, 0x21, 0xd0, 0x90, 0x08, 0x81, 0x90, 0x41, 0x00, 0x02, 0x44, 0x08, 0x10, 0x0c, 0x0a, 0x86, 0x09, 0x90, 0x04, 0x00, 0xc8, 0xa0, 0x04, 0x08, 0x30, 0x20, 0x89, 0x84, 0x00, 0x11, 0x22, 0x2c, 0x40, 0x00, 0x08, 0x02, 0xb0, 0x01, 0x48, 0x02, 0x01, 0x09, 0x20, 0x04, 0x03, 0x04, 0x00, 0x80, 0x02, 0x60, 0x42, 0x30, 0x21, 0x4a, 0x10, 0x44, 0x09, 0x02, 0x00, 0x01, 0x24, 0x00, 0x12, 0x82, 0x21, 0x80, 0xa4, 0x20, 0x10, 0x02, 0x04, 0x91, 0xa0, 0x40, 0x18, 0x04, 0x00, 0x02, 0x06, 0x69, 0x09, 0x00, 0x05, 0x58, 0x02, 0x01, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x03, 0x92, 0x20, 0x00, 0x34, 0x01, 0xc8, 0x20, 0x48, 0x08, 0x30, 0x08, 0x42, 0x80, 0x20, 0x91, 0x90, 0x68, 0x01, 0x04, 0x40, 0x12, 0x02, 0x61, 0x00, 0x12, 0x08, 0x01, 0xa0, 0x00, 0x11, 0x04, 0x21, 0x48, 0x04, 0x24, 0x92, 0x00, 0x0c, 0x01, 0x84, 0x04, 0x00, 0x00, 0x01, 0x12, 0x96, 0x40, 0x01, 0xa0, 0x41, 0x88, 0x22, 0x28, 0x88, 0x00, 0x44, 0x42, 0x80, 0x24, 0x12, 0x14, 0x01, 0x42, 0x90, 0x60, 0x1a, 0x10, 0x04, 0x81, 0x10, 0x48, 0x08, 0x06, 0x29, 0x83, 0x02, 0x40, 0x02, 0x24, 0x64, 0x80, 0x10, 0x05, 0x80, 0x10, 0x40, 0x02, 0x02, 0x08, 0x42, 0x84, 0x01, 0x09, 0x20, 0x04, 0x50, 0x00, 0x60, 0x11, 0x30, 0x40, 0x13, 0x02, 0x04, 0x81, 0x00, 0x09, 0x08, 0x20, 0x45, 0x4a, 0x10, 0x61, 0x90, 0x26, 0x0c, 0x08, 0x02, 0x21, 0x91, 0x00, 0x60, 0x02, 0x04, 0x00, 0x02, 0x00, 0x0c, 0x08, 0x06, 0x08, 0x48, 0x84, 0x08, 0x11, 0x02, 0x00, 0x80, 0xa4, 0x00, 0x5a, 0x20, 0x00, 0x88, 0x04, 0x04, 0x02, 0x00, 0x09, 0x00, 0x14, 0x08, 0x49, 0x14, 0x20, 0xc8, 0x00, 0x04, 0x91, 0xa0, 0x40, 0x59, 0x80, 0x00, 0x12, 0x10, 0x00, 0x80, 0x80, 0x65, 0x00, 0x00, 0x04, 0x00, 0x80, 0x40, 0x19, 0x00, 0x21, 0x03, 0x84, 0x60, 0xc0, 0x04, 0x24, 0x1a, 0x12, 0x61, 0x80, 0x80, 0x08, 0x02, 0x04, 0x09, 0x42, 0x12, 0x20, 0x08, 0x34, 0x04, 0x90, 0x20, 0x01, 0x01, 0xa0, 0x00, 0x0b, 0x00, 0x08, 0x91, 0x92, 0x40, 0x02, 0x34, 0x40, 0x88, 0x10, 0x61, 0x19, 0x02, 0x00, 0x40, 0x04, 0x25, 0xc0, 0x80, 0x68, 0x08, 0x04, 0x21, 0x80, 0x22, 0x04, 0x00, 0xa0, 0x0c, 0x01, 0x84, 0x20, 0x41, 0x00, 0x08, 0x8a, 0x00, 0x20, 0x8a, 0x00, 0x48, 0x88, 0x04, 0x04, 0x11, 0x82, 0x08, 0x40, 0x86, 0x09, 0x49, 0xa4, 0x40, 0x00, 0x10, 0x01, 0x01, 0xa2, 0x04, 0x50, 0x80, 0x0c, 0x80, 0x00, 0x48, 0x82, 0xa0, 0x01, 0x18, 0x12, 0x41, 0x01, 0x04, 0x48, 0x41, 0x00, 0x24, 0x01, 0x00, 0x00, 0x88, 0x14, 0x00, 0x02, 0x00, 0x68, 0x01, 0x20, 0x08, 0x4a, 0x22, 0x08, 0x83, 0x80, 0x00, 0x89, 0x04, 0x01, 0xc2, 0x00, 0x00, 0x00, 0x34, 0x04, 0x00, 0x82, 0x28, 0x02, 0x02, 0x41, 0x4a, 0x90, 0x05, 0x82, 0x02, 0x09, 0x80, 0x24, 0x04, 0x41, 0x00, 0x01, 0x92, 0x80, 0x28, 0x01, 0x14, 0x00, 0x50, 0x20, 0x4c, 0x10, 0xb0, 0x04, 0x43, 0xa4, 0x21, 0x90, 0x04, 0x01, 0x02, 0x00, 0x44, 0x48, 0x00, 0x64, 0x08, 0x06, 0x00, 0x42, 0x20, 0x08, 0x02, 0x92, 0x01, 0x4a, 0x00, 0x20, 0x50, 0x32, 0x25, 0x90, 0x22, 0x04, 0x09, 0x00, 0x08, 0x11, 0x80, 0x21, 0x01, 0x10, 0x05, 0x00, 0x32, 0x08, 0x88, 0x94, 0x08, 0x08, 0x24, 0x0d, 0xc1, 0x80, 0x40, 0x0b, 0x20, 0x40, 0x18, 0x12, 0x04, 0x00, 0x22, 0x40, 0x10, 0x26, 0x05, 0xc1, 0x82, 0x00, 0x01, 0x30, 0x24, 0x02, 0x22, 0x41, 0x08, 0x24, 0x48, 0x1a, 0x00, 0x25, 0xd2, 0x12, 0x28, 0x42, 0x00, 0x04, 0x40, 0x30, 0x41, 0x00, 0x02, 0x00, 0x13, 0x20, 0x24, 0xd1, 0x84, 0x08, 0x89, 0x80, 0x04, 0x52, 0x00, 0x44, 0x18, 0xa4, 0x00, 0x00, 0x06, 0x20, 0x91, 0x10, 0x09, 0x42, 0x20, 0x24, 0x40, 0x30, 0x28, 0x00, 0x84, 0x40, 0x40, 0x80, 0x08, 0x10, 0x04, 0x09, 0x08, 0x04, 0x40, 0x08, 0x22, 0x00, 0x19, 0x02, 0x00, 0x00, 0x80, 0x2c, 0x02, 0x02, 0x21, 0x01, 0x90, 0x20, 0x40, 0x00, 0x0c, 0x00, 0x34, 0x48, 0x58, 0x20, 0x01, 0x43, 0x04, 0x20, 0x80, 0x14, 0x00, 0x90, 0x00, 0x6d, 0x11, 0x00, 0x00, 0x40, 0x20, 0x00, 0x03, 0x10, 0x40, 0x88, 0x30, 0x05, 0x4a, 0x00, 0x65, 0x10, 0x24, 0x08, 0x18, 0x84, 0x28, 0x03, 0x80, 0x20, 0x42, 0xb0, 0x40, 0x00, 0x10, 0x69, 0x19, 0x04, 0x00, 0x00, 0x80, 0x04, 0xc2, 0x04, 0x00, 0x01, 0x00, 0x05, 0x00, 0x22, 0x25, 0x08, 0x96, 0x04, 0x02, 0x22, 0x00, 0xd0, 0x10, 0x29, 0x01, 0xa0, 0x60, 0x08, 0x10, 0x04, 0x01, 0x16, 0x44, 0x10, 0x02, 0x28, 0x02, 0x82, 0x48, 0x40, 0x84, 0x20, 0x90, 0x22, 0x28, 0x80, 0x04, 0x00, 0x40, 0x04, 0x24, 0x00, 0x80, 0x29, 0x03, 0x10, 0x60, 0x48, 0x00, 0x00, 0x81, 0xa0, 0x00, 0x51, 0x20, 0x0c, 0xd1, 0x00, 0x01, 0x41, 0x20, 0x04, 0x92, 0x00, 0x00, 0x10, 0x92, 0x00, 0x42, 0x04, 0x05, 0x01, 0x86, 0x40, 0x80, 0x10, 0x20, 0x52, 0x20, 0x21, 0x00, 0x10, 0x48, 0x0a, 0x02, 0x00, 0xd0, 0x12, 0x41, 0x48, 0x80, 0x04, 0x00, 0x00, 0x48, 0x09, 0x22, 0x04, 0x00, 0x24, 0x00, 0x43, 0x10, 0x60, 0x0a, 0x00, 0x44, 0x12, 0x20, 0x2c, 0x08, 0x20, 0x44, 0x00, 0x84, 0x09, 0x40, 0x06, 0x08, 0xc1, 0x00, 0x40, 0x80, 0x20, 0x00, 0x98, 0x12, 0x48, 0x10, 0xa2, 0x20, 0x00, 0x84, 0x48, 0xc0, 0x10, 0x20, 0x90, 0x12, 0x08, 0x98, 0x82, 0x00, 0x0a, 0xa0, 0x04, 0x03, 0x00, 0x28, 0xc3, 0x00, 0x44, 0x42, 0x10, 0x04, 0x08, 0x04, 0x40, 0x00, 0x00, 0x05, 0x10, 0x00, 0x21, 0x03, 0x80, 0x04, 0x88, 0x12, 0x69, 0x10, 0x00, 0x04, 0x08, 0x04, 0x04, 0x02, 0x84, 0x48, 0x49, 0x04, 0x20, 0x18, 0x02, 0x64, 0x80, 0x30, 0x08, 0x01, 0x02, 0x00, 0x52, 0x12, 0x49, 0x08, 0x20, 0x41, 0x88, 0x10, 0x48, 0x08, 0x34, 0x00, 0x01, 0x86, 0x05, 0xd0, 0x00, 0x00, 0x83, 0x84, 0x21, 0x40, 0x02, 0x41, 0x10, 0x80, 0x48, 0x40, 0xa2, 0x20, 0x51, 0x00, 0x00, 0x49, 0x00, 0x01, 0x90, 0x20, 0x40, 0x18, 0x02, 0x40, 0x02, 0x22, 0x05, 0x40, 0x80, 0x08, 0x82, 0x10, 0x20, 0x18, 0x00, 0x05, 0x01, 0x82, 0x40, 0x58, 0x00, 0x04, 0x81, 0x90, 0x29, 0x01, 0xa0, 0x64, 0x00, 0x22, 0x40, 0x01, 0xa2, 0x00, 0x18, 0x04, 0x0d, 0x00, 0x00, 0x60, 0x80, 0x94, 0x60, 0x82, 0x10, 0x0d, 0x80, 0x30, 0x0c, 0x12, 0x20, 0x00, 0x00, 0x12, 0x40, 0xc0, 0x20, 0x21, 0x58, 0x02, 0x41, 0x10, 0x80, 0x44, 0x03, 0x02, 0x04, 0x13, 0x90, 0x29, 0x08, 0x00, 0x44, 0xc0, 0x00, 0x21, 0x00, 0x26, 0x00, 0x1a, 0x80, 0x01, 0x13, 0x14, 0x20, 0x0a, 0x14, 0x20, 0x00, 0x32, 0x61, 0x08, 0x00, 0x40, 0x42, 0x20, 0x09, 0x80, 0x06, 0x01, 0x81, 0x80, 0x60, 0x42, 0x00, 0x68, 0x90, 0x82, 0x08, 0x42, 0x80, 0x04, 0x02, 0x80, 0x09, 0x0b, 0x04, 0x00, 0x98, 0x00, 0x0c, 0x81, 0x06, 0x44, 0x48, 0x84, 0x28, 0x03, 0x92, 0x00, 0x01, 0x80, 0x40, 0x0a, 0x00, 0x0c, 0x81, 0x02, 0x08, 0x51, 0x04, 0x28, 0x90, 0x02, 0x20, 0x09, 0x10, 0x60, 0x00, 0x00, 0x09, 0x81, 0xa0, 0x0c, 0x00, 0xa4, 0x09, 0x00, 0x02, 0x28, 0x80, 0x20, 0x00, 0x02, 0x02, 0x04, 0x81, 0x14, 0x04, 0x00, 0x04, 0x09, 0x11, 0x12, 0x60, 0x40, 0x20, 0x01, 0x48, 0x30, 0x40, 0x11, 0x00, 0x08, 0x0a, 0x86, 0x00, 0x00, 0x04, 0x60, 0x81, 0x04, 0x01, 0xd0, 0x02, 0x41, 0x18, 0x90, 0x00, 0x0a, 0x20, 0x00, 0xc1, 0x06, 0x01, 0x08, 0x80, 0x64, 0xca, 0x10, 0x04, 0x99, 0x80, 0x48, 0x01, 0x82, 0x20, 0x50, 0x90, 0x48, 0x80, 0x84, 0x20, 0x90, 0x22, 0x00, 0x19, 0x00, 0x04, 0x18, 0x20, 0x24, 0x10, 0x86, 0x40, 0xc2, 0x00, 0x24, 0x12, 0x10, 0x44, 0x00, 0x16, 0x08, 0x10, 0x24, 0x00, 0x12, 0x06, 0x01, 0x08, 0x90, 0x00, 0x12, 0x02, 0x4d, 0x10, 0x80, 0x40, 0x50, 0x22, 0x00, 0x43, 0x10, 0x01, 0x00, 0x30, 0x21, 0x0a, 0x00, 0x00, 0x01, 0x14, 0x00, 0x10, 0x84, 0x04, 0xc1, 0x10, 0x29, 0x0a, 0x00, 0x01, 0x8a, 0x00, 0x20, 0x01, 0x12, 0x0c, 0x49, 0x20, 0x04, 0x81, 0x00, 0x48, 0x01, 0x04, 0x60, 0x80, 0x12, 0x0c, 0x08, 0x10, 0x48, 0x4a, 0x04, 0x28, 0x10, 0x00, 0x28, 0x40, 0x84, 0x45, 0x50, 0x10, 0x60, 0x10, 0x06, 0x44, 0x01, 0x80, 0x09, 0x00, 0x86, 0x01, 0x42, 0xa0, 0x00, 0x90, 0x00, 0x05, 0x90, 0x22, 0x40, 0x41, 0x00, 0x08, 0x80, 0x02, 0x08, 0xc0, 0x00, 0x01, 0x58, 0x30, 0x49, 0x09, 0x14, 0x00, 0x41, 0x02, 0x0c, 0x02, 0x80, 0x40, 0x89, 0x00, 0x24, 0x08, 0x10, 0x05, 0x90, 0x32, 0x40, 0x0a, 0x82, 0x08, 0x00, 0x12, 0x61, 0x00, 0x04, 0x21, 0x00, 0x22, 0x04, 0x10, 0x24, 0x08, 0x0a, 0x04, 0x01, 0x10, 0x00, 0x20, 0x40, 0x84, 0x04, 0x88, 0x22, 0x20, 0x90, 0x12, 0x00, 0x53, 0x06, 0x24, 0x01, 0x04, 0x40, 0x0b, 0x14, 0x60, 0x82, 0x02, 0x0d, 0x10, 0x90, 0x0c, 0x08, 0x20, 0x09, 0x00, 0x14, 0x09, 0x80, 0x80, 0x24, 0x82, 0x00, 0x40, 0x01, 0x02, 0x44, 0x01, 0x20, 0x0c, 0x40, 0x84, 0x40, 0x0a, 0x10, 0x41, 0x00, 0x30, 0x05, 0x09, 0x80, 0x44, 0x08, 0x20, 0x20, 0x02, 0x00, 0x49, 0x43, 0x20, 0x21, 0x00, 0x20, 0x00, 0x01, 0xb6, 0x08, 0x40, 0x04, 0x08, 0x02, 0x80, 0x01, 0x41, 0x80, 0x40, 0x08, 0x10, 0x24, 0x00, 0x20, 0x04, 0x12, 0x86, 0x09, 0xc0, 0x12, 0x21, 0x81, 0x14, 0x04, 0x00, 0x02, 0x20, 0x89, 0xb4, 0x44, 0x12, 0x80, 0x00, 0xd1, 0x00, 0x69, 0x40, 0x80, 0x00, 0x42, 0x12, 0x00, 0x18, 0x04, 0x00, 0x49, 0x06, 0x21, 0x02, 0x04, 0x28, 0x02, 0x84, 0x01, 0xc0, 0x10, 0x68, 0x00, 0x20, 0x08, 0x40, 0x00, 0x08, 0x91, 0x10, 0x01, 0x81, 0x24, 0x04, 0xd2, 0x10, 0x4c, 0x88, 0x86, 0x00, 0x10, 0x80, 0x0c, 0x02, 0x14, 0x00, 0x8a, 0x90, 0x40, 0x18, 0x20, 0x21, 0x80, 0xa4, 0x00, 0x58, 0x24, 0x20, 0x10, 0x10, 0x60, 0xc1, 0x30, 0x41, 0x48, 0x02, 0x48, 0x09, 0x00, 0x40, 0x09, 0x02, 0x05, 0x11, 0x82, 0x20, 0x4a, 0x20, 0x24, 0x18, 0x02, 0x0c, 0x10, 0x22, 0x0c, 0x0a, 0x04, 0x00, 0x03, 0x06, 0x48, 0x48, 0x04, 0x04, 0x02, 0x00, 0x21, 0x80, 0x84, 0x00, 0x18, 0x00, 0x0c, 0x02, 0x12, 0x01, 0x00, 0x14, 0x05, 0x82, 0x10, 0x41, 0x89, 0x12, 0x08, 0x40, 0xa4, 0x21, 0x01, 0x84, 0x48, 0x02, 0x10, 0x60, 0x40, 0x02, 0x28, 0x00, 0x14, 0x08, 0x40, 0xa0, 0x20, 0x51, 0x12, 0x00, 0xc2, 0x00, 0x01, 0x1a, 0x30, 0x40, 0x89, 0x12, 0x4c, 0x02, 0x80, 0x00, 0x00, 0x14, 0x01, 0x01, 0xa0, 0x21, 0x18, 0x22, 0x21, 0x18, 0x06, 0x40, 0x01, 0x80, 0x00, 0x90, 0x04, 0x48, 0x02, 0x30, 0x04, 0x08, 0x00, 0x05, 0x88, 0x24, 0x08, 0x48, 0x04, 0x24, 0x02, 0x06, 0x00, 0x80, 0x00, 0x00, 0x00, 0x10, 0x65, 0x11, 0x90, 0x00, 0x0a, 0x82, 0x04, 0xc3, 0x04, 0x60, 0x48, 0x24, 0x04, 0x92, 0x02, 0x44, 0x88, 0x80, 0x40, 0x18, 0x06, 0x29, 0x80, 0x10, 0x01, 0x00, 0x00, 0x44, 0xc8, 0x10, 0x21, 0x89, 0x30, 0x00, 0x4b, 0xa0, 0x01, 0x10, 0x14, 0x00, 0x02, 0x94, 0x40, 0x00, 0x20, 0x65, 0x00, 0xa2, 0x0c, 0x40, 0x22, 0x20, 0x81, 0x12, 0x20, 0x82, 0x04, 0x01, 0x10, 0x00, 0x08, 0x88, 0x00, 0x00, 0x11, 0x80, 0x04, 0x42, 0x80, 0x40, 0x41, 0x14, 0x00, 0x40, 0x32, 0x2c, 0x80, 0x24, 0x04, 0x19, 0x00, 0x00, 0x91, 0x00, 0x20, 0x83, 0x00, 0x05, 0x40, 0x20, 0x09, 0x01, 0x84, 0x40, 0x40, 0x20, 0x20, 0x11, 0x00, 0x40, 0x41, 0x90, 0x20, 0x00, 0x00, 0x40, 0x90, 0x92, 0x48, 0x18, 0x06, 0x08, 0x81, 0x80, 0x48, 0x01, 0x34, 0x24, 0x10, 0x20, 0x04, 0x00, 0x20, 0x04, 0x18, 0x06, 0x2d, 0x90, 0x10, 0x01, 0x00, 0x90, 0x00, 0x0a, 0x22, 0x01, 0x00, 0x22, 0x00, 0x11, 0x84, 0x01, 0x01, 0x00, 0x20, 0x88, 0x00, 0x44, 0x00, 0x22, 0x01, 0x00, 0xa6, 0x40, 0x02, 0x06, 0x20, 0x11, 0x00, 0x01, 0xc8, 0xa0, 0x04, 0x8a, 0x00, 0x28, 0x19, 0x80, 0x00, 0x52, 0xa0, 0x24, 0x12, 0x12, 0x09, 0x08, 0x24, 0x01, 0x48, 0x00, 0x04, 0x00, 0x24, 0x40, 0x02, 0x84, 0x08, 0x00, 0x04, 0x48, 0x40, 0x90, 0x60, 0x0a, 0x22, 0x01, 0x88, 0x14, 0x08, 0x01, 0x02, 0x08, 0xd3, 0x00, 0x20, 0xc0, 0x90, 0x24, 0x10, 0x00, 0x00, 0x01, 0xb0, 0x08, 0x0a, 0xa0, 0x00, 0x80, 0x00, 0x01, 0x09, 0x00, 0x20, 0x52, 0x02, 0x25, 0x00, 0x24, 0x04, 0x02, 0x84, 0x24, 0x10, 0x92, 0x40, 0x02, 0xa0, 0x40, 0x00, 0x22, 0x08, 0x11, 0x04, 0x08, 0x01, 0x22, 0x00, 0x42, 0x14, 0x00, 0x09, 0x90, 0x21, 0x00, 0x30, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x22, 0x09, 0x90, 0x10, 0x28, 0x40, 0x00, 0x20, 0xc0, 0x20, 0x00, 0x90, 0x00, 0x40, 0x01, 0x82, 0x05, 0x12, 0x12, 0x09, 0xc1, 0x04, 0x61, 0x80, 0x02, 0x28, 0x81, 0x24, 0x00, 0x49, 0x04, 0x08, 0x10, 0x86, 0x29, 0x41, 0x80, 0x21, 0x0a, 0x30, 0x49, 0x88, 0x90, 0x00, 0x41, 0x04, 0x29, 0x81, 0x80, 0x41, 0x09, 0x00, 0x40, 0x12, 0x10, 0x40, 0x00, 0x10, 0x40, 0x48, 0x02, 0x05, 0x80, 0x02, 0x21, 0x40, 0x20, 0x00, 0x58, 0x20, 0x60, 0x00, 0x90, 0x48, 0x00, 0x80, 0x28, 0xc0, 0x80, 0x48, 0x00, 0x00, 0x44, 0x80, 0x02, 0x00, 0x09, 0x06, 0x00, 0x12, 0x02, 0x01, 0x00, 0x10, 0x08, 0x83, 0x10, 0x45, 0x12, 0x00, 0x2c, 0x08, 0x04, 0x44, 0x00, 0x20, 0x20, 0xc0, 0x10, 0x20, 0x01, 0x00, 0x05, 0xc8, 0x20, 0x04, 0x98, 0x10, 0x08, 0x10, 0x00, 0x24, 0x02, 0x16, 0x40, 0x88, 0x00, 0x61, 0x88, 0x12, 0x24, 0x80, 0xa6, 0x00, 0x42, 0x00, 0x08, 0x10, 0x06, 0x48, 0x40, 0xa0, 0x00, 0x50, 0x20, 0x04, 0x81, 0xa4, 0x40, 0x18, 0x00, 0x08, 0x10, 0x80, 0x01, 0x01}; #if RSA_KEY_SIEVE && SIMULATION && RSA_INSTRUMENT UINT32 PrimeIndex = 0; UINT32 failedAtIteration[10] = {0}; UINT32 PrimeCounts[3] = {0}; UINT32 MillerRabinTrials[3] = {0}; UINT32 totalFieldsSieved[3] = {0}; UINT32 bitsInFieldAfterSieve[3] = {0}; UINT32 emptyFieldsSieved[3] = {0}; UINT32 noPrimeFields[3] = {0}; UINT32 primesChecked[3] = {0}; UINT16 lastSievePrime = 0; #endif libtpms-0.9.3/src/tpm2/PropertyCap.c000066400000000000000000000540731421143571500172760ustar00rootroot00000000000000/********************************************************************************/ /* */ /* For accessing the TPM_CAP_TPM_PROPERTY values */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PropertyCap.c 1519 2019-11-15 20:43:51Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ /* 9.14 PropertyCap.c */ /* 9.14.1 Description */ /* This file contains the functions that are used for accessing the TPM_CAP_TPM_PROPERTY values. */ /* 9.14.2 Includes */ #include "Tpm.h" #define TPM_HAVE_TPM2_DECLARATIONS #include "tpm_library_intern.h" // libtpms added /* 9.14.3 Functions */ /* 9.14.3.1 TPMPropertyIsDefined() */ /* This function accepts a property selection and, if so, sets value to the value of the property. */ /* All the fixed values are vendor dependent or determined by a platform-specific specification. The values in the table below are examples and should be changed by the vendor. */ /* Return Values Meaning */ /* TRUE referenced property exists and value set */ /* FALSE referenced property does not exist */ static BOOL TPMPropertyIsDefined( TPM_PT property, // IN: property UINT32 *value // OUT: property value ) { switch(property) { case TPM_PT_FAMILY_INDICATOR: // from the title page of the specification // For this specification, the value is "2.0". *value = TPM_SPEC_FAMILY; break; case TPM_PT_LEVEL: // from the title page of the specification *value = TPM_SPEC_LEVEL; break; case TPM_PT_REVISION: // from the title page of the specification *value = TPM_SPEC_VERSION; break; case TPM_PT_DAY_OF_YEAR: // computed from the date value on the title page of the specification *value = TPM_SPEC_DAY_OF_YEAR; break; case TPM_PT_YEAR: // from the title page of the specification *value = TPM_SPEC_YEAR; break; case TPM_PT_MANUFACTURER: // vendor ID unique to each TPM manufacturer *value = BYTE_ARRAY_TO_UINT32(MANUFACTURER); break; case TPM_PT_VENDOR_STRING_1: // first four characters of the vendor ID string *value = BYTE_ARRAY_TO_UINT32(VENDOR_STRING_1); break; case TPM_PT_VENDOR_STRING_2: // second four characters of the vendor ID string #ifdef VENDOR_STRING_2 *value = BYTE_ARRAY_TO_UINT32(VENDOR_STRING_2); #else *value = 0; #endif break; case TPM_PT_VENDOR_STRING_3: // third four characters of the vendor ID string #ifdef VENDOR_STRING_3 *value = BYTE_ARRAY_TO_UINT32(VENDOR_STRING_3); #else *value = 0; #endif break; case TPM_PT_VENDOR_STRING_4: // fourth four characters of the vendor ID string #ifdef VENDOR_STRING_4 *value = BYTE_ARRAY_TO_UINT32(VENDOR_STRING_4); #else *value = 0; #endif break; case TPM_PT_VENDOR_TPM_TYPE: // vendor-defined value indicating the TPM model *value = 1; break; case TPM_PT_FIRMWARE_VERSION_1: // more significant 32-bits of a vendor-specific value *value = gp.firmwareV1; break; case TPM_PT_FIRMWARE_VERSION_2: // less significant 32-bits of a vendor-specific value *value = gp.firmwareV2; break; case TPM_PT_INPUT_BUFFER: // maximum size of TPM2B_MAX_BUFFER *value = MAX_DIGEST_BUFFER; break; case TPM_PT_HR_TRANSIENT_MIN: // minimum number of transient objects that can be held in TPM // RAM *value = MAX_LOADED_OBJECTS; break; case TPM_PT_HR_PERSISTENT_MIN: // minimum number of persistent objects that can be held in // TPM NV memory // In this implementation, there is no minimum number of // persistent objects. *value = MIN_EVICT_OBJECTS; break; case TPM_PT_HR_LOADED_MIN: // minimum number of authorization sessions that can be held in // TPM RAM *value = MAX_LOADED_SESSIONS; break; case TPM_PT_ACTIVE_SESSIONS_MAX: // number of authorization sessions that may be active at a time *value = MAX_ACTIVE_SESSIONS; break; case TPM_PT_PCR_COUNT: // number of PCR implemented *value = IMPLEMENTATION_PCR; break; case TPM_PT_PCR_SELECT_MIN: // minimum number of bytes in a TPMS_PCR_SELECT.sizeOfSelect *value = PCR_SELECT_MIN; break; case TPM_PT_CONTEXT_GAP_MAX: // maximum allowed difference (unsigned) between the contextID // values of two saved session contexts #if 0 *value = ((UINT32)1 << (sizeof(CONTEXT_SLOT) * 8)) - 1; #endif *value = s_ContextSlotMask; // libtpms added; the mask is either 0xff (old state) or 0xffff break; case TPM_PT_NV_COUNTERS_MAX: // maximum number of NV indexes that are allowed to have the // TPMA_NV_COUNTER attribute SET // In this implementation, there is no limitation on the number // of counters, except for the size of the NV Index memory. *value = 0; break; case TPM_PT_NV_INDEX_MAX: // maximum size of an NV index data area *value = MAX_NV_INDEX_SIZE; break; case TPM_PT_MEMORY: // a TPMA_MEMORY indicating the memory management method for the TPM { union { TPMA_MEMORY att; UINT32 u32; } attributes = { TPMA_ZERO_INITIALIZER() }; SET_ATTRIBUTE(attributes.att, TPMA_MEMORY, sharedNV); SET_ATTRIBUTE(attributes.att, TPMA_MEMORY, objectCopiedToRam); // Note: For a LSb0 machine, the bits in a bit field are in the correct // order even if the machine is MSB0. For a MSb0 machine, a TPMA will // be an integer manipulated by masking (USE_BIT_FIELD_STRUCTURES will // NO) so the bits are manipulated correctly. *value = attributes.u32; break; } case TPM_PT_CLOCK_UPDATE: // interval, in seconds, between updates to the copy of // TPMS_TIME_INFO .clock in NV *value = (1 << NV_CLOCK_UPDATE_INTERVAL); break; case TPM_PT_CONTEXT_HASH: // algorithm used for the integrity hash on saved contexts and // for digesting the fuData of TPM2_FirmwareRead() *value = CONTEXT_INTEGRITY_HASH_ALG; break; case TPM_PT_CONTEXT_SYM: // algorithm used for encryption of saved contexts *value = CONTEXT_ENCRYPT_ALG; break; case TPM_PT_CONTEXT_SYM_SIZE: // size of the key used for encryption of saved contexts *value = CONTEXT_ENCRYPT_KEY_BITS; break; case TPM_PT_ORDERLY_COUNT: // maximum difference between the volatile and non-volatile // versions of TPMA_NV_COUNTER that have TPMA_NV_ORDERLY SET *value = MAX_ORDERLY_COUNT; break; case TPM_PT_MAX_COMMAND_SIZE: // maximum value for 'commandSize' *value = MAX_COMMAND_SIZE; break; case TPM_PT_MAX_RESPONSE_SIZE: // maximum value for 'responseSize' *value = MAX_RESPONSE_SIZE; break; case TPM_PT_MAX_DIGEST: // maximum size of a digest that can be produced by the TPM *value = sizeof(TPMU_HA); break; case TPM_PT_MAX_OBJECT_CONTEXT: // Header has 'sequence', 'handle' and 'hierarchy' #define SIZE_OF_CONTEXT_HEADER \ sizeof(UINT64) + sizeof(TPMI_DH_CONTEXT) + sizeof(TPMI_RH_HIERARCHY) #define SIZE_OF_CONTEXT_INTEGRITY (sizeof(UINT16) + CONTEXT_INTEGRITY_HASH_SIZE) #define SIZE_OF_FINGERPRINT sizeof(UINT64) #define SIZE_OF_CONTEXT_BLOB_OVERHEAD \ (sizeof(UINT16) + SIZE_OF_CONTEXT_INTEGRITY + SIZE_OF_FINGERPRINT) #define SIZE_OF_CONTEXT_OVERHEAD \ (SIZE_OF_CONTEXT_HEADER + SIZE_OF_CONTEXT_BLOB_OVERHEAD) #if 0 // maximum size of a TPMS_CONTEXT that will be returned by // TPM2_ContextSave for object context *value = 0; // adding sequence, saved handle and hierarchy *value += sizeof(UINT64) + sizeof(TPMI_DH_CONTEXT) + sizeof(TPMI_RH_HIERARCHY); // add size field in TPM2B_CONTEXT *value += sizeof(UINT16); // add integrity hash size *value += sizeof(UINT16) + CryptHashGetDigestSize(CONTEXT_INTEGRITY_HASH_ALG); // Add fingerprint size, which is the same as sequence size *value += sizeof(UINT64); // Add OBJECT structure size *value += sizeof(OBJECT); #else // the maximum size of a TPMS_CONTEXT that will be returned by // TPM2_ContextSave for object context *value = SIZE_OF_CONTEXT_OVERHEAD + sizeof(OBJECT); #endif break; case TPM_PT_MAX_SESSION_CONTEXT: #if 0 // the maximum size of a TPMS_CONTEXT that will be returned by // TPM2_ContextSave for object context *value = 0; // adding sequence, saved handle and hierarchy *value += sizeof(UINT64) + sizeof(TPMI_DH_CONTEXT) + sizeof(TPMI_RH_HIERARCHY); // Add size field in TPM2B_CONTEXT *value += sizeof(UINT16); // Add integrity hash size *value += sizeof(UINT16) + CryptHashGetDigestSize(CONTEXT_INTEGRITY_HASH_ALG); // Add fingerprint size, which is the same as sequence size *value += sizeof(UINT64); // Add SESSION structure size *value += sizeof(SESSION); #else // the maximum size of a TPMS_CONTEXT that will be returned by // TPM2_ContextSave for object context *value = SIZE_OF_CONTEXT_OVERHEAD + sizeof(SESSION); #endif break; case TPM_PT_PS_FAMILY_INDICATOR: // platform specific values for the TPM_PT_PS parameters from // the relevant platform-specific specification // In this reference implementation, all of these values are 0. *value = PLATFORM_FAMILY; break; case TPM_PT_PS_LEVEL: // level of the platform-specific specification *value = PLATFORM_LEVEL; break; case TPM_PT_PS_REVISION: // specification Revision times 100 for the platform-specific // specification *value = PLATFORM_VERSION; break; case TPM_PT_PS_DAY_OF_YEAR: // platform-specific specification day of year using TCG calendar *value = PLATFORM_DAY_OF_YEAR; break; case TPM_PT_PS_YEAR: // platform-specific specification year using the CE *value = PLATFORM_YEAR; break; case TPM_PT_SPLIT_MAX: // number of split signing operations supported by the TPM *value = 0; #if ALG_ECC *value = sizeof(gr.commitArray) * 8; #endif break; case TPM_PT_TOTAL_COMMANDS: // total number of commands implemented in the TPM // Since the reference implementation does not have any // vendor-defined commands, this will be the same as the // number of library commands. { #if COMPRESSED_LISTS (*value) = COMMAND_COUNT; #else COMMAND_INDEX commandIndex; *value = 0; // scan all implemented commands for(commandIndex = GetClosestCommandIndex(0); commandIndex != UNIMPLEMENTED_COMMAND_INDEX; commandIndex = GetNextCommandIndex(commandIndex)) { (*value)++; // count of all implemented } #endif break; } case TPM_PT_LIBRARY_COMMANDS: // number of commands from the TPM library that are implemented { #if COMPRESSED_LISTS *value = LIBRARY_COMMAND_ARRAY_SIZE; #else COMMAND_INDEX commandIndex; *value = 0; // scan all implemented commands for(commandIndex = GetClosestCommandIndex(0); commandIndex < LIBRARY_COMMAND_ARRAY_SIZE; commandIndex = GetNextCommandIndex(commandIndex)) { (*value)++; } #endif break; } case TPM_PT_VENDOR_COMMANDS: // number of vendor commands that are implemented *value = VENDOR_COMMAND_ARRAY_SIZE; break; case TPM_PT_NV_BUFFER_MAX: // Maximum data size in an NV write command *value = MAX_NV_BUFFER_SIZE; break; case TPM_PT_MODES: #if FIPS_COMPLIANT *value = 1; #else *value = 0; #endif break; case TPM_PT_MAX_CAP_BUFFER: *value = MAX_CAP_BUFFER; break; // Start of variable commands case TPM_PT_PERMANENT: // TPMA_PERMANENT { union { TPMA_PERMANENT attr; UINT32 u32; } flags = { TPMA_ZERO_INITIALIZER() }; if(gp.ownerAuth.t.size != 0) SET_ATTRIBUTE(flags.attr, TPMA_PERMANENT, ownerAuthSet); if(gp.endorsementAuth.t.size != 0) SET_ATTRIBUTE(flags.attr, TPMA_PERMANENT, endorsementAuthSet); if(gp.lockoutAuth.t.size != 0) SET_ATTRIBUTE(flags.attr, TPMA_PERMANENT, lockoutAuthSet); if(gp.disableClear) SET_ATTRIBUTE(flags.attr, TPMA_PERMANENT, disableClear); if(gp.failedTries >= gp.maxTries) SET_ATTRIBUTE(flags.attr, TPMA_PERMANENT, inLockout); // In this implementation, EPS is always generated by TPM SET_ATTRIBUTE(flags.attr, TPMA_PERMANENT, tpmGeneratedEPS); // Note: For a LSb0 machine, the bits in a bit field are in the correct // order even if the machine is MSB0. For a MSb0 machine, a TPMA will // be an integer manipulated by masking (USE_BIT_FIELD_STRUCTURES will // be NO ) so the bits are manipulate correctly. *value = flags.u32; break; } case TPM_PT_STARTUP_CLEAR: // TPMA_STARTUP_CLEAR { union { TPMA_STARTUP_CLEAR attr; UINT32 u32; } flags = { TPMA_ZERO_INITIALIZER() }; // if(g_phEnable) SET_ATTRIBUTE(flags.attr, TPMA_STARTUP_CLEAR, phEnable); if(gc.shEnable) SET_ATTRIBUTE(flags.attr, TPMA_STARTUP_CLEAR, shEnable); if(gc.ehEnable) SET_ATTRIBUTE(flags.attr, TPMA_STARTUP_CLEAR, ehEnable); if(gc.phEnableNV) SET_ATTRIBUTE(flags.attr, TPMA_STARTUP_CLEAR, phEnableNV); if(g_prevOrderlyState != SU_NONE_VALUE) SET_ATTRIBUTE(flags.attr, TPMA_STARTUP_CLEAR, orderly); // Note: For a LSb0 machine, the bits in a bit field are in the correct // order even if the machine is MSB0. For a MSb0 machine, a TPMA will // be an integer manipulated by masking (USE_BIT_FIELD_STRUCTURES will // be NO) so the bits are manipulate correctly. *value = flags.u32; break; } case TPM_PT_HR_NV_INDEX: // number of NV indexes currently defined *value = NvCapGetIndexNumber(); break; case TPM_PT_HR_LOADED: // number of authorization sessions currently loaded into TPM // RAM *value = SessionCapGetLoadedNumber(); break; case TPM_PT_HR_LOADED_AVAIL: // number of additional authorization sessions, of any type, // that could be loaded into TPM RAM *value = SessionCapGetLoadedAvail(); break; case TPM_PT_HR_ACTIVE: // number of active authorization sessions currently being // tracked by the TPM *value = SessionCapGetActiveNumber(); break; case TPM_PT_HR_ACTIVE_AVAIL: // number of additional authorization sessions, of any type, // that could be created *value = SessionCapGetActiveAvail(); break; case TPM_PT_HR_TRANSIENT_AVAIL: // estimate of the number of additional transient objects that // could be loaded into TPM RAM *value = ObjectCapGetTransientAvail(); break; case TPM_PT_HR_PERSISTENT: // number of persistent objects currently loaded into TPM // NV memory *value = NvCapGetPersistentNumber(); break; case TPM_PT_HR_PERSISTENT_AVAIL: // number of additional persistent objects that could be loaded // into NV memory *value = NvCapGetPersistentAvail(); break; case TPM_PT_NV_COUNTERS: // number of defined NV indexes that have NV TPMA_NV_COUNTER // attribute SET *value = NvCapGetCounterNumber(); break; case TPM_PT_NV_COUNTERS_AVAIL: // number of additional NV indexes that can be defined with their // TPMA_NV_COUNTER attribute SET *value = NvCapGetCounterAvail(); break; case TPM_PT_ALGORITHM_SET: // region code for the TPM *value = gp.algorithmSet; break; case TPM_PT_LOADED_CURVES: #if ALG_ECC // number of loaded ECC curves *value = ECC_CURVE_COUNT; #else // ALG_ECC *value = 0; #endif // ALG_ECC break; case TPM_PT_LOCKOUT_COUNTER: // current value of the lockout counter *value = gp.failedTries; break; case TPM_PT_MAX_AUTH_FAIL: // number of authorization failures before DA lockout is invoked *value = gp.maxTries; break; case TPM_PT_LOCKOUT_INTERVAL: // number of seconds before the value reported by // TPM_PT_LOCKOUT_COUNTER is decremented *value = gp.recoveryTime; break; case TPM_PT_LOCKOUT_RECOVERY: // number of seconds after a lockoutAuth failure before use of // lockoutAuth may be attempted again *value = gp.lockoutRecovery; break; case TPM_PT_NV_WRITE_RECOVERY: // number of milliseconds before the TPM will accept another command // that will modify NV. // This should make a call to the platform code that is doing rate // limiting of NV. Rate limiting is not implemented in the reference // code so no call is made. *value = 0; break; case TPM_PT_AUDIT_COUNTER_0: // high-order 32 bits of the command audit counter *value = (UINT32)(gp.auditCounter >> 32); break; case TPM_PT_AUDIT_COUNTER_1: // low-order 32 bits of the command audit counter *value = (UINT32)(gp.auditCounter); break; default: // property is not defined return FALSE; break; } return TRUE; } /* 9.14.3.2 TPMCapGetProperties() */ /* This function is used to get the TPM_PT values. The search of properties will start at property and continue until propertyList has as many values as will fit, or the last property has been reported, or the list has as many values as requested in count. */ /* Return Values Meaning */ /* YES more properties are available */ /* NO no more properties to be reported */ TPMI_YES_NO TPMCapGetProperties( TPM_PT property, // IN: the starting TPM property UINT32 count, // IN: maximum number of returned // properties TPML_TAGGED_TPM_PROPERTY *propertyList // OUT: property list ) { TPMI_YES_NO more = NO; UINT32 i; UINT32 nextGroup; // initialize output property list propertyList->count = 0; // maximum count of properties we may return is MAX_PCR_PROPERTIES if(count > MAX_TPM_PROPERTIES) count = MAX_TPM_PROPERTIES; // if property is less than PT_FIXED, start from PT_FIXED if(property < PT_FIXED) property = PT_FIXED; // There is only the fixed and variable groups with the variable group coming // last if(property >= (PT_VAR + PT_GROUP)) return more; // Don't read past the end of the selected group nextGroup = ((property / PT_GROUP) * PT_GROUP) + PT_GROUP; // Scan through the TPM properties of the requested group. for(i = property; i < nextGroup; i++) { UINT32 value; // if we have hit the end of the group, quit if(i != property && ((i % PT_GROUP) == 0)) break; if(TPMPropertyIsDefined((TPM_PT)i, &value)) { if(propertyList->count < count) { // If the list is not full, add this property propertyList->tpmProperty[propertyList->count].property = (TPM_PT)i; propertyList->tpmProperty[propertyList->count].value = value; propertyList->count++; } else { // If the return list is full but there are more properties // available, set the indication and exit the loop. more = YES; break; } } } return more; } libtpms-0.9.3/src/tpm2/PropertyCap_fp.h000066400000000000000000000072451421143571500177670ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: PropertyCap_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 */ /* */ /********************************************************************************/ #ifndef PROPERTYCAP_FP_H #define PROPERTYCAP_FP_H TPMI_YES_NO TPMCapGetProperties( TPM_PT property, // IN: the starting TPM property UINT32 count, // IN: maximum number of returned // properties TPML_TAGGED_TPM_PROPERTY *propertyList // OUT: property list ); #endif libtpms-0.9.3/src/tpm2/Quote_fp.h000066400000000000000000000077141421143571500166150ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Quote_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef QUOTE_FP_H #define QUOTE_FP_H typedef struct { TPMI_DH_OBJECT signHandle; TPM2B_DATA qualifyingData; TPMT_SIG_SCHEME inScheme; TPML_PCR_SELECTION PCRselect; } Quote_In; #define RC_Quote_signHandle (TPM_RC_H + TPM_RC_1) #define RC_Quote_qualifyingData (TPM_RC_P + TPM_RC_1) #define RC_Quote_inScheme (TPM_RC_P + TPM_RC_2) #define RC_Quote_PCRselect (TPM_RC_P + TPM_RC_3) typedef struct { TPM2B_ATTEST quoted; TPMT_SIGNATURE signature; } Quote_Out; TPM_RC TPM2_Quote( Quote_In *in, // IN: input parameter list Quote_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/RSA_Decrypt_fp.h000066400000000000000000000077611421143571500176410ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: RSA_Decrypt_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef RSA_DECRYPT_FP_H #define RSA_DECRYPT_FP_H typedef struct { TPMI_DH_OBJECT keyHandle; TPM2B_PUBLIC_KEY_RSA cipherText; TPMT_RSA_DECRYPT inScheme; TPM2B_DATA label; } RSA_Decrypt_In; #define RC_RSA_Decrypt_keyHandle (TPM_RC_H + TPM_RC_1) #define RC_RSA_Decrypt_cipherText (TPM_RC_P + TPM_RC_1) #define RC_RSA_Decrypt_inScheme (TPM_RC_P + TPM_RC_2) #define RC_RSA_Decrypt_label (TPM_RC_P + TPM_RC_3) typedef struct { TPM2B_PUBLIC_KEY_RSA message; } RSA_Decrypt_Out; TPM_RC TPM2_RSA_Decrypt( RSA_Decrypt_In *in, // IN: input parameter list RSA_Decrypt_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/RSA_Encrypt_fp.h000066400000000000000000000077521421143571500176530ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: RSA_Encrypt_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef RSA_ENCRYPT_FP_H #define RSA_ENCRYPT_FP_H typedef struct { TPMI_DH_OBJECT keyHandle; TPM2B_PUBLIC_KEY_RSA message; TPMT_RSA_DECRYPT inScheme; TPM2B_DATA label; } RSA_Encrypt_In; #define RC_RSA_Encrypt_keyHandle (TPM_RC_H + TPM_RC_1) #define RC_RSA_Encrypt_message (TPM_RC_P + TPM_RC_1) #define RC_RSA_Encrypt_inScheme (TPM_RC_P + TPM_RC_2) #define RC_RSA_Encrypt_label (TPM_RC_P + TPM_RC_3) typedef struct { TPM2B_PUBLIC_KEY_RSA outData; } RSA_Encrypt_Out; TPM_RC TPM2_RSA_Encrypt( RSA_Encrypt_In *in, // IN: input parameter list RSA_Encrypt_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/RandomCommands.c000066400000000000000000000105021421143571500177150ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: RandomCommands.c 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2018 */ /* */ /********************************************************************************/ #include "Tpm.h" #include "GetRandom_fp.h" #if CC_GetRandom // Conditional expansion of this file TPM_RC TPM2_GetRandom( GetRandom_In *in, // IN: input parameter list GetRandom_Out *out // OUT: output parameter list ) { // Command Output // if the requested bytes exceed the output buffer size, generates the // maximum bytes that the output buffer allows if(in->bytesRequested > sizeof(TPMU_HA)) out->randomBytes.t.size = sizeof(TPMU_HA); else out->randomBytes.t.size = in->bytesRequested; CryptRandomGenerate(out->randomBytes.t.size, out->randomBytes.t.buffer); return TPM_RC_SUCCESS; } #endif // CC_GetRandom #include "Tpm.h" #include "StirRandom_fp.h" #if CC_StirRandom // Conditional expansion of this file TPM_RC TPM2_StirRandom( StirRandom_In *in // IN: input parameter list ) { // Internal Data Update CryptRandomStir(in->inData.t.size, in->inData.t.buffer); return TPM_RC_SUCCESS; } #endif // CC_StirRandom libtpms-0.9.3/src/tpm2/ReadClock_fp.h000066400000000000000000000070521421143571500173420ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: ReadClock_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef READCLOCK_FP_H #define READCLOCK_FP_H typedef struct { TPMS_TIME_INFO currentTime; } ReadClock_Out; TPM_RC TPM2_ReadClock( ReadClock_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/ReadPublic_fp.h000066400000000000000000000074161421143571500175310ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: ReadPublic_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef READPUBLIC_FP_H #define READPUBLIC_FP_H typedef struct { TPMI_DH_OBJECT objectHandle; } ReadPublic_In; #define RC_ReadPublic_objectHandle (TPM_RC_H + TPM_RC_1) typedef struct { TPM2B_PUBLIC outPublic; TPM2B_NAME name; TPM2B_NAME qualifiedName; } ReadPublic_Out; TPM_RC TPM2_ReadPublic( ReadPublic_In *in, // IN: input parameter list ReadPublic_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/Response.c000066400000000000000000000114361421143571500166200ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Response.c 1259 2018-07-10 19:11:09Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2018 */ /* */ /********************************************************************************/ /* 9.15 Response.c */ /* 9.15.1 Description */ /* This file contains the common code for building a response header, including setting the size of the structure. command may be NULL if result is not TPM_RC_SUCCESS. */ /* 9.15.2 Includes and Defines */ #include "Tpm.h" /* 9.15.3 BuildResponseHeader() */ /* Adds the response header to the response. It will update command->parameterSize to indicate the total size of the response. */ void BuildResponseHeader( COMMAND *command, // IN: main control structure BYTE *buffer, // OUT: the output buffer TPM_RC result // IN: the response code ) { TPM_ST tag; UINT32 size; if(result != TPM_RC_SUCCESS) { tag = TPM_ST_NO_SESSIONS; size = 10; } else { tag = command->tag; // Compute the overall size of the response size = STD_RESPONSE_HEADER + command->handleNum * sizeof(TPM_HANDLE); size += command->parameterSize; size += (command->tag == TPM_ST_SESSIONS) ? command->authSize + sizeof(UINT32) : 0; } TPM_ST_Marshal(&tag, &buffer, NULL); UINT32_Marshal(&size, &buffer, NULL); TPM_RC_Marshal(&result, &buffer, NULL); if(result == TPM_RC_SUCCESS) { if(command->handleNum > 0) TPM_HANDLE_Marshal(&command->handles[0], &buffer, NULL); if(tag == TPM_ST_SESSIONS) UINT32_Marshal((UINT32 *)&command->parameterSize, &buffer, NULL); } command->parameterSize = size; } libtpms-0.9.3/src/tpm2/ResponseCodeProcessing.c000066400000000000000000000077341421143571500214560ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Miscellaneous Functions For Processing Response Codes */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: ResponseCodeProcessing.c 1259 2018-07-10 19:11:09Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2018 */ /* */ /********************************************************************************/ /* 9.16 ResponseCodeProcessing.c */ /* 9.16.1 Description */ /* This file contains the miscellaneous functions for processing response codes. */ /* NOTE: Currently, there is only one. */ /* 9.16.2 Includes and Defines */ #include "Tpm.h" /* 9.16.3 RcSafeAddToResult() */ /* Adds a modifier to a response code as long as the response code allows a modifier and no modifier has already been added. */ TPM_RC RcSafeAddToResult( TPM_RC responseCode, TPM_RC modifier ) { if((responseCode & RC_FMT1) && !(responseCode & 0xf40)) return responseCode + modifier; else return responseCode; } libtpms-0.9.3/src/tpm2/ResponseCodeProcessing_fp.h000066400000000000000000000067631421143571500221510ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: ResponseCodeProcessing_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 */ /* */ /********************************************************************************/ #ifndef RESPONSECODEPROCESSING_FP_H #define RESPONSECODEPROCESSING_FP_H TPM_RC RcSafeAddToResult( TPM_RC responseCode, TPM_RC modifier ); #endif libtpms-0.9.3/src/tpm2/Response_fp.h000066400000000000000000000071201421143571500173050ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Response_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 */ /* */ /********************************************************************************/ #ifndef RESPONSE_FP_H #define RESPONSE_FP_H void BuildResponseHeader( COMMAND *command, // IN: main control structure BYTE *buffer, // OUT: the output buffer TPM_RC result // IN: the response code ); #endif libtpms-0.9.3/src/tpm2/Rewrap_fp.h000066400000000000000000000100641421143571500167500ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Rewrap_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef REWRAP_FP_H #define REWRAP_FP_H typedef struct { TPMI_DH_OBJECT oldParent; TPMI_DH_OBJECT newParent; TPM2B_PRIVATE inDuplicate; TPM2B_NAME name; TPM2B_ENCRYPTED_SECRET inSymSeed; } Rewrap_In; #define RC_Rewrap_oldParent (TPM_RC_H + TPM_RC_1) #define RC_Rewrap_newParent (TPM_RC_H + TPM_RC_2) #define RC_Rewrap_inDuplicate (TPM_RC_P + TPM_RC_1) #define RC_Rewrap_name (TPM_RC_P + TPM_RC_2) #define RC_Rewrap_inSymSeed (TPM_RC_P + TPM_RC_3) typedef struct { TPM2B_PRIVATE outDuplicate; TPM2B_ENCRYPTED_SECRET outSymSeed; } Rewrap_Out; TPM_RC TPM2_Rewrap( Rewrap_In *in, // IN: input parameter list Rewrap_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/RsaTestData.h000066400000000000000000000745211421143571500172120ustar00rootroot00000000000000/********************************************************************************/ /* */ /* RSA Test Vectors */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: RsaTestData.h 1259 2018-07-10 19:11:09Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2018 */ /* */ /********************************************************************************/ #ifndef RSATESTDATA_H #define RSATESTDATA_H /* 10.1.9 RsaTestData.h */ /* RSA Test Vectors */ #define RSA_TEST_KEY_SIZE 256 typedef struct { UINT16 size; BYTE buffer[RSA_TEST_KEY_SIZE]; } TPM2B_RSA_TEST_KEY; typedef TPM2B_RSA_TEST_KEY TPM2B_RSA_TEST_VALUE; typedef struct { UINT16 size; BYTE buffer[RSA_TEST_KEY_SIZE / 2]; } TPM2B_RSA_TEST_PRIME; const TPM2B_RSA_TEST_KEY c_rsaPublicModulus = {256, { 0x91,0x12,0xf5,0x07,0x9d,0x5f,0x6b,0x1c,0x90,0xf6,0xcc,0x87,0xde,0x3a,0x7a,0x15, 0xdc,0x54,0x07,0x6c,0x26,0x8f,0x25,0xef,0x7e,0x66,0xc0,0xe3,0x82,0x12,0x2f,0xab, 0x52,0x82,0x1e,0x85,0xbc,0x53,0xba,0x2b,0x01,0xad,0x01,0xc7,0x8d,0x46,0x4f,0x7d, 0xdd,0x7e,0xdc,0xb0,0xad,0xf6,0x0c,0xa1,0x62,0x92,0x97,0x8a,0x3e,0x6f,0x7e,0x3e, 0xf6,0x9a,0xcc,0xf9,0xa9,0x86,0x77,0xb6,0x85,0x43,0x42,0x04,0x13,0x65,0xe2,0xad, 0x36,0xc9,0xbf,0xc1,0x97,0x84,0x6f,0xee,0x7c,0xda,0x58,0xd2,0xae,0x07,0x00,0xaf, 0xc5,0x5f,0x4d,0x3a,0x98,0xb0,0xed,0x27,0x7c,0xc2,0xce,0x26,0x5d,0x87,0xe1,0xe3, 0xa9,0x69,0x88,0x4f,0x8c,0x08,0x31,0x18,0xae,0x93,0x16,0xe3,0x74,0xde,0xd3,0xf6, 0x16,0xaf,0xa3,0xac,0x37,0x91,0x8d,0x10,0xc6,0x6b,0x64,0x14,0x3a,0xd9,0xfc,0xe4, 0xa0,0xf2,0xd1,0x01,0x37,0x4f,0x4a,0xeb,0xe5,0xec,0x98,0xc5,0xd9,0x4b,0x30,0xd2, 0x80,0x2a,0x5a,0x18,0x5a,0x7d,0xd4,0x3d,0xb7,0x62,0x98,0xce,0x6d,0xa2,0x02,0x6e, 0x45,0xaa,0x95,0x73,0xe0,0xaa,0x75,0x57,0xb1,0x3d,0x1b,0x05,0x75,0x23,0x6b,0x20, 0x69,0x9e,0x14,0xb0,0x7f,0xac,0xae,0xd2,0xc7,0x48,0x3b,0xe4,0x56,0x11,0x34,0x1e, 0x05,0x1a,0x30,0x20,0xef,0x68,0x93,0x6b,0x9d,0x7e,0xdd,0xba,0x96,0x50,0xcc,0x1c, 0x81,0xb4,0x59,0xb9,0x74,0x36,0xd9,0x97,0xdc,0x8f,0x17,0x82,0x72,0xb3,0x59,0xf6, 0x23,0xfa,0x84,0xf7,0x6d,0xf2,0x05,0xff,0xf1,0xb9,0xcc,0xe9,0xa2,0x82,0x01,0xfb}}; const TPM2B_RSA_TEST_PRIME c_rsaPrivatePrime = {RSA_TEST_KEY_SIZE / 2, { 0xb7,0xa0,0x90,0xc7,0x92,0x09,0xde,0x71,0x03,0x37,0x4a,0xb5,0x2f,0xda,0x61,0xb8, 0x09,0x1b,0xba,0x99,0x70,0x45,0xc1,0x0b,0x15,0x12,0x71,0x8a,0xb3,0x2a,0x4d,0x5a, 0x41,0x9b,0x73,0x89,0x80,0x0a,0x8f,0x18,0x4c,0x8b,0xa2,0x5b,0xda,0xbd,0x43,0xbe, 0xdc,0x76,0x4d,0x71,0x0f,0xb9,0xfc,0x7a,0x09,0xfe,0x4f,0xac,0x63,0xd9,0x2e,0x50, 0x3a,0xa1,0x37,0xc6,0xf2,0xa1,0x89,0x12,0xe7,0x72,0x64,0x2b,0xba,0xc1,0x1f,0xca, 0x9d,0xb7,0xaa,0x3a,0xa9,0xd3,0xa6,0x6f,0x73,0x02,0xbb,0x85,0x5d,0x9a,0xb9,0x5c, 0x08,0x83,0x22,0x20,0x49,0x91,0x5f,0x4b,0x86,0xbc,0x3f,0x76,0x43,0x08,0x97,0xbf, 0x82,0x55,0x36,0x2d,0x8b,0x6e,0x9e,0xfb,0xc1,0x67,0x6a,0x43,0xa2,0x46,0x81,0x71}}; const BYTE c_RsaTestValue[RSA_TEST_KEY_SIZE] = { 0x2a,0x24,0x3a,0xbb,0x50,0x1d,0xd4,0x2a,0xf9,0x18,0x32,0x34,0xa2,0x0f,0xea,0x5c, 0x91,0x77,0xe9,0xe1,0x09,0x83,0xdc,0x5f,0x71,0x64,0x5b,0xeb,0x57,0x79,0xa0,0x41, 0xc9,0xe4,0x5a,0x0b,0xf4,0x9f,0xdb,0x84,0x04,0xa6,0x48,0x24,0xf6,0x3f,0x66,0x1f, 0xa8,0x04,0x5c,0xf0,0x7a,0x6b,0x4a,0x9c,0x7e,0x21,0xb6,0xda,0x6b,0x65,0x9c,0x3a, 0x68,0x50,0x13,0x1e,0xa4,0xb7,0xca,0xec,0xd3,0xcc,0xb2,0x9b,0x8c,0x87,0xa4,0x6a, 0xba,0xc2,0x06,0x3f,0x40,0x48,0x7b,0xa8,0xb8,0x2c,0x03,0x14,0x33,0xf3,0x1d,0xe9, 0xbd,0x6f,0x54,0x66,0xb4,0x69,0x5e,0xbc,0x80,0x7c,0xe9,0x6a,0x43,0x7f,0xb8,0x6a, 0xa0,0x5f,0x5d,0x7a,0x20,0xfd,0x7a,0x39,0xe1,0xea,0x0e,0x94,0x91,0x28,0x63,0x7a, 0xac,0xc9,0xa5,0x3a,0x6d,0x31,0x7b,0x7c,0x54,0x56,0x99,0x56,0xbb,0xb7,0xa1,0x2d, 0xd2,0x5c,0x91,0x5f,0x1c,0xd3,0x06,0x7f,0x34,0x53,0x2f,0x4c,0xd1,0x8b,0xd2,0x9e, 0xdc,0xc3,0x94,0x0a,0xe1,0x0f,0xa5,0x15,0x46,0x2a,0x8e,0x10,0xc2,0xfe,0xb7,0x5e, 0x2d,0x0d,0xd1,0x25,0xfc,0xe4,0xf7,0x02,0x19,0xfe,0xb6,0xe4,0x95,0x9c,0x17,0x4a, 0x9b,0xdb,0xab,0xc7,0x79,0xe3,0x5e,0x40,0xd0,0x56,0x6d,0x25,0x0a,0x72,0x65,0x80, 0x92,0x9a,0xa8,0x07,0x70,0x32,0x14,0xfb,0xfe,0x08,0xeb,0x13,0xb4,0x07,0x68,0xb4, 0x58,0x39,0xbe,0x8e,0x78,0x3a,0x59,0x3f,0x9c,0x4c,0xe9,0xa8,0x64,0x68,0xf7,0xb9, 0x6e,0x20,0xf5,0xcb,0xca,0x47,0xf2,0x17,0xaa,0x8b,0xbc,0x13,0x14,0x84,0xf6,0xab}; const TPM2B_RSA_TEST_VALUE c_RsaepKvt = {RSA_TEST_KEY_SIZE, { 0x73,0xbd,0x65,0x49,0xda,0x7b,0xb8,0x50,0x9e,0x87,0xf0,0x0a,0x8a,0x9a,0x07,0xb6, 0x00,0x82,0x10,0x14,0x60,0xd8,0x01,0xfc,0xc5,0x18,0xea,0x49,0x5f,0x13,0xcf,0x65, 0x66,0x30,0x6c,0x60,0x3f,0x24,0x3c,0xfb,0xe2,0x31,0x16,0x99,0x7e,0x31,0x98,0xab, 0x93,0xb8,0x07,0x53,0xcc,0xdb,0x7f,0x44,0xd9,0xee,0x5d,0xe8,0x5f,0x97,0x5f,0xe8, 0x1f,0x88,0x52,0x24,0x7b,0xac,0x62,0x95,0xb7,0x7d,0xf5,0xf8,0x9f,0x5a,0xa8,0x24, 0x9a,0x76,0x71,0x2a,0x35,0x2a,0xa1,0x08,0xbb,0x95,0xe3,0x64,0xdc,0xdb,0xc2,0x33, 0xa9,0x5f,0xbe,0x4c,0xc4,0xcc,0x28,0xc9,0x25,0xff,0xee,0x17,0x15,0x9a,0x50,0x90, 0x0e,0x15,0xb4,0xea,0x6a,0x09,0xe6,0xff,0xa4,0xee,0xc7,0x7e,0xce,0xa9,0x73,0xe4, 0xa0,0x56,0xbd,0x53,0x2a,0xe4,0xc0,0x2b,0xa8,0x9b,0x09,0x30,0x72,0x62,0x0f,0xf9, 0xf6,0xa1,0x52,0xd2,0x8a,0x37,0xee,0xa5,0xc8,0x47,0xe1,0x99,0x21,0x47,0xeb,0xdd, 0x37,0xaa,0xe4,0xbd,0x55,0x46,0x5a,0x5a,0x5d,0xfb,0x7b,0xfc,0xff,0xbf,0x26,0x71, 0xf6,0x1e,0xad,0xbc,0xbf,0x33,0xca,0xe1,0x92,0x8f,0x2a,0x89,0x6c,0x45,0x24,0xd1, 0xa6,0x52,0x56,0x24,0x5e,0x90,0x47,0xe5,0xcb,0x12,0xb0,0x32,0xf9,0xa6,0xbb,0xea, 0x37,0xa9,0xbd,0xef,0x23,0xef,0x63,0x07,0x6c,0xc4,0x4e,0x64,0x3c,0xc6,0x11,0x84, 0x7d,0x65,0xd6,0x5d,0x7a,0x17,0x58,0xa5,0xf7,0x74,0x3b,0x42,0xe3,0xd2,0xda,0x5f, 0x6f,0xe0,0x1e,0x4b,0xcf,0x46,0xe2,0xdf,0x3e,0x41,0x8e,0x0e,0xb0,0x3f,0x8b,0x65}}; #define OAEP_TEST_LABEL "OAEP Test Value" #if ALG_SHA1_VALUE == DEFAULT_TEST_HASH const TPM2B_RSA_TEST_VALUE c_OaepKvt = {RSA_TEST_KEY_SIZE, { 0x32,0x68,0x84,0x0b,0x9c,0xc9,0x25,0x26,0xd9,0xc0,0xd0,0xb1,0xde,0x60,0x55,0xae, 0x33,0xe5,0xcf,0x6c,0x85,0xbe,0x0d,0x71,0x11,0xe1,0x45,0x60,0xbb,0x42,0x3d,0xf3, 0xb1,0x18,0x84,0x7b,0xc6,0x5d,0xce,0x1d,0x5f,0x9a,0x97,0xcf,0xb1,0x97,0x9a,0x85, 0x7c,0xa7,0xa1,0x63,0x23,0xb6,0x74,0x0f,0x1a,0xee,0x29,0x51,0xeb,0x50,0x8f,0x3c, 0x8e,0x4e,0x31,0x38,0xdc,0x11,0xfc,0x9a,0x4e,0xaf,0x93,0xc9,0x7f,0x6e,0x35,0xf3, 0xc9,0xe4,0x89,0x14,0x53,0xe2,0xc2,0x1a,0xf7,0x6b,0x9b,0xf0,0x7a,0xa4,0x69,0x52, 0xe0,0x24,0x8f,0xea,0x31,0xa7,0x5c,0x43,0xb0,0x65,0xc9,0xfe,0xba,0xfe,0x80,0x9e, 0xa5,0xc0,0xf5,0x8d,0xce,0x41,0xf9,0x83,0x0d,0x8e,0x0f,0xef,0x3d,0x1f,0x6a,0xcc, 0x8a,0x3d,0x3b,0xdf,0x22,0x38,0xd7,0x34,0x58,0x7b,0x55,0xc9,0xf6,0xbc,0x7c,0x4c, 0x3f,0xd7,0xde,0x4e,0x30,0xa9,0x69,0xf3,0x5f,0x56,0x8f,0xc2,0xe7,0x75,0x79,0xb8, 0xa5,0xc8,0x0d,0xc0,0xcd,0xb6,0xc9,0x63,0xad,0x7c,0xe4,0x8f,0x39,0x60,0x4d,0x7d, 0xdb,0x34,0x49,0x2a,0x47,0xde,0xc0,0x42,0x4a,0x19,0x94,0x2e,0x50,0x21,0x03,0x47, 0xff,0x73,0xb3,0xb7,0x89,0xcc,0x7b,0x2c,0xeb,0x03,0xa7,0x9a,0x06,0xfd,0xed,0x19, 0xbb,0x82,0xa0,0x13,0xe9,0xfa,0xac,0x06,0x5f,0xc5,0xa9,0x2b,0xda,0x88,0x23,0xa2, 0x5d,0xc2,0x7f,0xda,0xc8,0x5a,0x94,0x31,0xc1,0x21,0xd7,0x1e,0x6b,0xd7,0x89,0xb1, 0x93,0x80,0xab,0xd1,0x37,0xf2,0x6f,0x50,0xcd,0x2a,0xea,0xb1,0xc4,0xcd,0xcb,0xb5}}; const TPM2B_RSA_TEST_VALUE c_RsaesKvt = {RSA_TEST_KEY_SIZE, { 0x29,0xa4,0x2f,0xbb,0x8a,0x14,0x05,0x1e,0x3c,0x72,0x76,0x77,0x38,0xe7,0x73,0xe3, 0x6e,0x24,0x4b,0x38,0xd2,0x1a,0xcf,0x23,0x58,0x78,0x36,0x82,0x23,0x6e,0x6b,0xef, 0x2c,0x3d,0xf2,0xe8,0xd6,0xc6,0x87,0x8e,0x78,0x9b,0x27,0x39,0xc0,0xd6,0xef,0x4d, 0x0b,0xfc,0x51,0x27,0x18,0xf3,0x51,0x5e,0x4d,0x96,0x3a,0xe2,0x15,0xe2,0x7e,0x42, 0xf4,0x16,0xd5,0xc6,0x52,0x5d,0x17,0x44,0x76,0x09,0x7a,0xcf,0xe3,0x30,0xe3,0x84, 0xf6,0x6f,0x3a,0x33,0xfb,0x32,0x0d,0x1d,0xe7,0x7c,0x80,0x82,0x4f,0xed,0xda,0x87, 0x11,0x9c,0xc3,0x7e,0x85,0xbd,0x18,0x58,0x08,0x2b,0x23,0x37,0xe7,0x9d,0xd0,0xd1, 0x79,0xe2,0x05,0xbd,0xf5,0x4f,0x0e,0x0f,0xdb,0x4a,0x74,0xeb,0x09,0x01,0xb3,0xca, 0xbd,0xa6,0x7b,0x09,0xb1,0x13,0x77,0x30,0x4d,0x87,0x41,0x06,0x57,0x2e,0x5f,0x36, 0x6e,0xfc,0x35,0x69,0xfe,0x0a,0x24,0x6c,0x98,0x8c,0xda,0x97,0xf4,0xfb,0xc7,0x83, 0x2d,0x3e,0x7d,0xc0,0x5c,0x34,0xfd,0x11,0x2a,0x12,0xa7,0xae,0x4a,0xde,0xc8,0x4e, 0xcf,0xf4,0x85,0x63,0x77,0xc6,0x33,0x34,0xe0,0x27,0xe4,0x9e,0x91,0x0b,0x4b,0x85, 0xf0,0xb0,0x79,0xaa,0x7c,0xc6,0xff,0x3b,0xbc,0x04,0x73,0xb8,0x95,0xd7,0x31,0x54, 0x3b,0x56,0xec,0x52,0x15,0xd7,0x3e,0x62,0xf5,0x82,0x99,0x3e,0x2a,0xc0,0x4b,0x2e, 0x06,0x57,0x6d,0x3f,0x3e,0x77,0x1f,0x2b,0x2d,0xc5,0xb9,0x3b,0x68,0x56,0x73,0x70, 0x32,0x6b,0x6b,0x65,0x25,0x76,0x45,0x6c,0x45,0xf1,0x6c,0x59,0xfc,0x94,0xa7,0x15}}; const TPM2B_RSA_TEST_VALUE c_RsapssKvt = {RSA_TEST_KEY_SIZE, { 0x01,0xfe,0xd5,0x83,0x0b,0x15,0xba,0x90,0x2c,0xdf,0xf7,0x26,0xb7,0x8f,0xb1,0xd7, 0x0b,0xfd,0x83,0xf9,0x95,0xd5,0xd7,0xb5,0xc5,0xc5,0x4a,0xde,0xd5,0xe6,0x20,0x78, 0xca,0x73,0x77,0x3d,0x61,0x36,0x48,0xae,0x3e,0x8f,0xee,0x43,0x29,0x96,0xdf,0x3f, 0x1c,0x97,0x5a,0xbe,0xe5,0xa2,0x7e,0x5b,0xd0,0xc0,0x29,0x39,0x83,0x81,0x77,0x24, 0x43,0xdb,0x3c,0x64,0x4d,0xf0,0x23,0xe4,0xae,0x0f,0x78,0x31,0x8c,0xda,0x0c,0xec, 0xf1,0xdf,0x09,0xf2,0x14,0x6a,0x4d,0xaf,0x36,0x81,0x6e,0xbd,0xbe,0x36,0x79,0x88, 0x98,0xb6,0x6f,0x5a,0xad,0xcf,0x7c,0xee,0xe0,0xdd,0x00,0xbe,0x59,0x97,0x88,0x00, 0x34,0xc0,0x8b,0x48,0x42,0x05,0x04,0x5a,0xb7,0x85,0x38,0xa0,0x35,0xd7,0x3b,0x51, 0xb8,0x7b,0x81,0x83,0xee,0xff,0x76,0x6f,0x50,0x39,0x4d,0xab,0x89,0x63,0x07,0x6d, 0xf5,0xe5,0x01,0x10,0x56,0xfe,0x93,0x06,0x8f,0xd3,0xc9,0x41,0xab,0xc9,0xdf,0x6e, 0x59,0xa8,0xc3,0x1d,0xbf,0x96,0x4a,0x59,0x80,0x3c,0x90,0x3a,0x59,0x56,0x4c,0x6d, 0x44,0x6d,0xeb,0xdc,0x73,0xcd,0xc1,0xec,0xb8,0x41,0xbf,0x89,0x8c,0x03,0x69,0x4c, 0xaf,0x3f,0xc1,0xc5,0xc7,0xe7,0x7d,0xa7,0x83,0x39,0x70,0xa2,0x6b,0x83,0xbc,0xbe, 0xf5,0xbf,0x1c,0xee,0x6e,0xa3,0x22,0x1e,0x25,0x2f,0x16,0x68,0x69,0x5a,0x1d,0xfa, 0x2c,0x3a,0x0f,0x67,0xe1,0x77,0x12,0xe8,0x3d,0xba,0xaa,0xef,0x96,0x9c,0x1f,0x64, 0x32,0xf4,0xa7,0xb3,0x3f,0x7d,0x61,0xbb,0x9a,0x27,0xad,0xfb,0x2f,0x33,0xc4,0x70}}; const TPM2B_RSA_TEST_VALUE c_RsassaKvt = {RSA_TEST_KEY_SIZE, { 0x67,0x4e,0xdd,0xc2,0xd2,0x6d,0xe0,0x03,0xc4,0xc2,0x41,0xd3,0xd4,0x61,0x30,0xd0, 0xe1,0x68,0x31,0x4a,0xda,0xd9,0xc2,0x5d,0xaa,0xa2,0x7b,0xfb,0x44,0x02,0xf5,0xd6, 0xd8,0x2e,0xcd,0x13,0x36,0xc9,0x4b,0xdb,0x1a,0x4b,0x66,0x1b,0x4f,0x9c,0xb7,0x17, 0xac,0x53,0x37,0x4f,0x21,0xbd,0x0c,0x66,0xac,0x06,0x65,0x52,0x9f,0x04,0xf6,0xa5, 0x22,0x5b,0xf7,0xe6,0x0d,0x3c,0x9f,0x41,0x19,0x09,0x88,0x7c,0x41,0x4c,0x2f,0x9c, 0x8b,0x3c,0xdd,0x7c,0x28,0x78,0x24,0xd2,0x09,0xa6,0x5b,0xf7,0x3c,0x88,0x7e,0x73, 0x5a,0x2d,0x36,0x02,0x4f,0x65,0xb0,0xcb,0xc8,0xdc,0xac,0xa2,0xda,0x8b,0x84,0x91, 0x71,0xe4,0x30,0x8b,0xb6,0x12,0xf2,0xf0,0xd0,0xa0,0x38,0xcf,0x75,0xb7,0x20,0xcb, 0x35,0x51,0x52,0x6b,0xc4,0xf4,0x21,0x95,0xc2,0xf7,0x9a,0x13,0xc1,0x1a,0x7b,0x8f, 0x77,0xda,0x19,0x48,0xbb,0x6d,0x14,0x5d,0xba,0x65,0xb4,0x9e,0x43,0x42,0x58,0x98, 0x0b,0x91,0x46,0xd8,0x4c,0xf3,0x4c,0xaf,0x2e,0x02,0xa6,0xb2,0x49,0x12,0x62,0x43, 0x4e,0xa8,0xac,0xbf,0xfd,0xfa,0x37,0x24,0xea,0x69,0x1c,0xf5,0xae,0xfa,0x08,0x82, 0x30,0xc3,0xc0,0xf8,0x9a,0x89,0x33,0xe1,0x40,0x6d,0x18,0x5c,0x7b,0x90,0x48,0xbf, 0x37,0xdb,0xea,0xfb,0x0e,0xd4,0x2e,0x11,0xfa,0xa9,0x86,0xff,0x00,0x0b,0x7b,0xca, 0x09,0x64,0x6a,0x8f,0x0c,0x0e,0x09,0x14,0x36,0x4a,0x74,0x31,0x18,0x5b,0x18,0xeb, 0xea,0x83,0xc3,0x66,0x68,0xa6,0x7d,0x43,0x06,0x0f,0x99,0x60,0xce,0x65,0x08,0xf6}}; #endif // SHA1 #if ALG_SHA256_VALUE == DEFAULT_TEST_HASH const TPM2B_RSA_TEST_VALUE c_OaepKvt = {RSA_TEST_KEY_SIZE, { 0x33,0x20,0x6e,0x21,0xc3,0xf6,0xcd,0xf8,0xd7,0x5d,0x9f,0xe9,0x05,0x14,0x8c,0x7c, 0xbb,0x69,0x24,0x9e,0x52,0x8f,0xaf,0x84,0x73,0x21,0x2c,0x85,0xa5,0x30,0x4d,0xb6, 0xb8,0xfa,0x15,0x9b,0xc7,0x8f,0xc9,0x7a,0x72,0x4b,0x85,0xa4,0x1c,0xc5,0xd8,0xe4, 0x92,0xb3,0xec,0xd9,0xa8,0xca,0x5e,0x74,0x73,0x89,0x7f,0xb4,0xac,0x7e,0x68,0x12, 0xb2,0x53,0x27,0x4b,0xbf,0xd0,0x71,0x69,0x46,0x9f,0xef,0xf4,0x70,0x60,0xf8,0xd7, 0xae,0xc7,0x5a,0x27,0x38,0x25,0x2d,0x25,0xab,0x96,0x56,0x66,0x3a,0x23,0x40,0xa8, 0xdb,0xbc,0x86,0xe8,0xf3,0xd2,0x58,0x0b,0x44,0xfc,0x94,0x1e,0xb7,0x5d,0xb4,0x57, 0xb5,0xf3,0x56,0xee,0x9b,0xcf,0x97,0x91,0x29,0x36,0xe3,0x06,0x13,0xa2,0xea,0xd6, 0xd6,0x0b,0x86,0x0b,0x1a,0x27,0xe6,0x22,0xc4,0x7b,0xff,0xde,0x0f,0xbf,0x79,0xc8, 0x1b,0xed,0xf1,0x27,0x62,0xb5,0x8b,0xf9,0xd9,0x76,0x90,0xf6,0xcc,0x83,0x0f,0xce, 0xce,0x2e,0x63,0x7a,0x9b,0xf4,0x48,0x5b,0xd7,0x81,0x2c,0x3a,0xdb,0x59,0x0d,0x4d, 0x9e,0x46,0xe9,0x9e,0x92,0x22,0x27,0x1c,0xb0,0x67,0x8a,0xe6,0x8a,0x16,0x8a,0xdf, 0x95,0x76,0x24,0x82,0xad,0xf1,0xbc,0x97,0xbf,0xd3,0x5e,0x6e,0x14,0x0c,0x5b,0x25, 0xfe,0x58,0xfa,0x64,0xe5,0x14,0x46,0xb7,0x58,0xc6,0x3f,0x7f,0x42,0xd2,0x8e,0x45, 0x13,0x41,0x85,0x12,0x2e,0x96,0x19,0xd0,0x5e,0x7d,0x34,0x06,0x32,0x2b,0xc8,0xd9, 0x0d,0x6c,0x06,0x36,0xa0,0xff,0x47,0x57,0x2c,0x25,0xbc,0x8a,0xa5,0xe2,0xc7,0xe3}}; const TPM2B_RSA_TEST_VALUE c_RsaesKvt = {RSA_TEST_KEY_SIZE, { 0x39,0xfc,0x10,0x5d,0xf4,0x45,0x3d,0x94,0x53,0x06,0x89,0x24,0xe7,0xe8,0xfd,0x03, 0xac,0xfd,0xbd,0xb2,0x28,0xd3,0x4a,0x52,0xc5,0xd4,0xdb,0x17,0xd4,0x24,0x05,0xc4, 0xeb,0x6a,0xce,0x1d,0xbb,0x37,0xcb,0x09,0xd8,0x6c,0x83,0x19,0x93,0xd4,0xe2,0x88, 0x88,0x9b,0xaf,0x92,0x16,0xc4,0x15,0xbd,0x49,0x13,0x22,0xb7,0x84,0xcf,0x23,0xf2, 0x6f,0x0c,0x3e,0x8f,0xde,0x04,0x09,0x31,0x2d,0x99,0xdf,0xe6,0x74,0x70,0x30,0xde, 0x8c,0xad,0x32,0x86,0xe2,0x7c,0x12,0x90,0x21,0xf3,0x86,0xb7,0xe2,0x64,0xca,0x98, 0xcc,0x64,0x4b,0xef,0x57,0x4f,0x5a,0x16,0x6e,0xd7,0x2f,0x5b,0xf6,0x07,0xad,0x33, 0xb4,0x8f,0x3b,0x3a,0x8b,0xd9,0x06,0x2b,0xed,0x3c,0x3c,0x76,0xf6,0x21,0x31,0xe3, 0xfb,0x2c,0x45,0x61,0x42,0xba,0xe0,0xc3,0x72,0x63,0xd0,0x6b,0x8f,0x36,0x26,0xfb, 0x9e,0x89,0x0e,0x44,0x9a,0xc1,0x84,0x5e,0x84,0x8d,0xb6,0xea,0xf1,0x0d,0x66,0xc7, 0xdb,0x44,0xbd,0x19,0x7c,0x05,0xbe,0xc4,0xab,0x88,0x32,0xbe,0xc7,0x63,0x31,0xe6, 0x38,0xd4,0xe5,0xb8,0x4b,0xf5,0x0e,0x55,0x9a,0x3a,0xe6,0x0a,0xec,0xee,0xe2,0xa8, 0x88,0x04,0xf2,0xb8,0xaa,0x5a,0xd8,0x97,0x5d,0xa0,0xa8,0x42,0xfb,0xd9,0xde,0x80, 0xae,0x4c,0xb3,0xa1,0x90,0x47,0x57,0x03,0x10,0x78,0xa6,0x8f,0x11,0xba,0x4b,0xce, 0x2d,0x56,0xa4,0xe1,0xbd,0xf8,0xa0,0xa4,0xd5,0x48,0x3c,0x63,0x20,0x00,0x38,0xa0, 0xd1,0xe6,0x12,0xe9,0x1d,0xd8,0x49,0xe3,0xd5,0x24,0xb5,0xc5,0x3a,0x1f,0xb0,0xd4}}; const TPM2B_RSA_TEST_VALUE c_RsapssKvt = {RSA_TEST_KEY_SIZE, { 0x74,0x89,0x29,0x3e,0x1b,0xac,0xc6,0x85,0xca,0xf0,0x63,0x43,0x30,0x7d,0x1c,0x9b, 0x2f,0xbd,0x4d,0x69,0x39,0x5e,0x85,0xe2,0xef,0x86,0x0a,0xc6,0x6b,0xa6,0x08,0x19, 0x6c,0x56,0x38,0x24,0x55,0x92,0x84,0x9b,0x1b,0x8b,0x04,0xcf,0x24,0x14,0x24,0x13, 0x0e,0x8b,0x82,0x6f,0x96,0xc8,0x9a,0x68,0xfc,0x4c,0x02,0xf0,0xdc,0xcd,0x36,0x25, 0x31,0xd5,0x82,0xcf,0xc9,0x69,0x72,0xf6,0x1d,0xab,0x68,0x20,0x2e,0x2d,0x19,0x49, 0xf0,0x2e,0xad,0xd2,0xda,0xaf,0xff,0xb6,0x92,0x83,0x5b,0x8a,0x06,0x2d,0x0c,0x32, 0x11,0x32,0x3b,0x77,0x17,0xf6,0x50,0xfb,0xf8,0x57,0xc9,0xc7,0x9b,0x9e,0xc6,0xd1, 0xa9,0x55,0xf0,0x22,0x35,0xda,0xca,0x3c,0x8e,0xc6,0x9a,0xd8,0x25,0xc8,0x5e,0x93, 0x0d,0xaa,0xa7,0x06,0xaf,0x11,0x29,0x99,0xe7,0x7c,0xee,0x49,0x82,0x30,0xba,0x2c, 0xe2,0x40,0x8f,0x0a,0xa6,0x7b,0x24,0x75,0xc5,0xcd,0x03,0x12,0xf4,0xb2,0x4b,0x3a, 0xd1,0x91,0x3c,0x20,0x0e,0x58,0x2b,0x31,0xf8,0x8b,0xee,0xbc,0x1f,0x95,0x35,0x58, 0x6a,0x73,0xee,0x99,0xb0,0x01,0x42,0x4f,0x66,0xc0,0x66,0xbb,0x35,0x86,0xeb,0xd9, 0x7b,0x55,0x77,0x2d,0x54,0x78,0x19,0x49,0xe8,0xcc,0xfd,0xb1,0xcb,0x49,0xc9,0xea, 0x20,0xab,0xed,0xb5,0xed,0xfe,0xb2,0xb5,0xa8,0xcf,0x05,0x06,0xd5,0x7d,0x2b,0xbb, 0x0b,0x65,0x6b,0x2b,0x6d,0x55,0x95,0x85,0x44,0x8b,0x12,0x05,0xf3,0x4b,0xd4,0x8e, 0x3d,0x68,0x2d,0x29,0x9c,0x05,0x79,0xd6,0xfc,0x72,0x90,0x6a,0xab,0x46,0x38,0x81}}; const TPM2B_RSA_TEST_VALUE c_RsassaKvt = {RSA_TEST_KEY_SIZE, { 0x8a,0xb1,0x0a,0xb5,0xe4,0x02,0xf7,0xdd,0x45,0x2a,0xcc,0x2b,0x6b,0x8c,0x0e,0x9a, 0x92,0x4f,0x9b,0xc5,0xe4,0x8b,0x82,0xb9,0xb0,0xd9,0x87,0x8c,0xcb,0xf0,0xb0,0x59, 0xa5,0x92,0x21,0xa0,0xa7,0x61,0x5c,0xed,0xa8,0x6e,0x22,0x29,0x46,0xc7,0x86,0x37, 0x4b,0x1b,0x1e,0x94,0x93,0xc8,0x4c,0x17,0x7a,0xae,0x59,0x91,0xf8,0x83,0x84,0xc4, 0x8c,0x38,0xc2,0x35,0x0e,0x7e,0x50,0x67,0x76,0xe7,0xd3,0xec,0x6f,0x0d,0xa0,0x5c, 0x2f,0x0a,0x80,0x28,0xd3,0xc5,0x7d,0x2d,0x1a,0x0b,0x96,0xd6,0xe5,0x98,0x05,0x8c, 0x4d,0xa0,0x1f,0x8c,0xb6,0xfb,0xb1,0xcf,0xe9,0xcb,0x38,0x27,0x60,0x64,0x17,0xca, 0xf4,0x8b,0x61,0xb7,0x1d,0xb6,0x20,0x9d,0x40,0x2a,0x1c,0xfd,0x55,0x40,0x4b,0x95, 0x39,0x52,0x18,0x3b,0xab,0x44,0xe8,0x83,0x4b,0x7c,0x47,0xfb,0xed,0x06,0x9c,0xcd, 0x4f,0xba,0x81,0xd6,0xb7,0x31,0xcf,0x5c,0x23,0xf8,0x25,0xab,0x95,0x77,0x0a,0x8f, 0x46,0xef,0xfb,0x59,0xb8,0x04,0xd7,0x1e,0xf5,0xaf,0x6a,0x1a,0x26,0x9b,0xae,0xf4, 0xf5,0x7f,0x84,0x6f,0x3c,0xed,0xf8,0x24,0x0b,0x43,0xd1,0xba,0x74,0x89,0x4e,0x39, 0xfe,0xab,0xa5,0x16,0xa5,0x28,0xee,0x96,0x84,0x3e,0x16,0x6d,0x5f,0x4e,0x0b,0x7d, 0x94,0x16,0x1b,0x8c,0xf9,0xaa,0x9b,0xc0,0x49,0x02,0x4c,0x3e,0x62,0xff,0xfe,0xa2, 0x20,0x33,0x5e,0xa6,0xdd,0xda,0x15,0x2d,0xb7,0xcd,0xda,0xff,0xb1,0x0b,0x45,0x7b, 0xd3,0xa0,0x42,0x29,0xab,0xa9,0x73,0xe9,0xa4,0xd9,0x8d,0xac,0xa1,0x88,0x2c,0x2d}}; #endif // SHA256 #if ALG_SHA384_VALUE == DEFAULT_TEST_HASH const TPM2B_RSA_TEST_VALUE c_OaepKvt = {RSA_TEST_KEY_SIZE, { 0x0f,0x3c,0x42,0x4d,0x8c,0x91,0x96,0x05,0x3c,0xfd,0x59,0x3b,0x7f,0x29,0xbc,0x03, 0x67,0xc1,0xff,0x74,0xe7,0x09,0xf4,0x13,0x45,0xbe,0x13,0x1d,0xc9,0x86,0x94,0xfe, 0xed,0xa6,0xe8,0x3a,0xcb,0x89,0x4d,0xec,0x86,0x63,0x4c,0xdb,0xf1,0x95,0xee,0xc1, 0x46,0xc5,0x3b,0xd8,0xf8,0xa2,0x41,0x6a,0x60,0x8b,0x9e,0x5e,0x7f,0x20,0x16,0xe3, 0x69,0xb6,0x2d,0x92,0xfc,0x60,0xa2,0x74,0x88,0xd5,0xc7,0xa6,0xd1,0xff,0xe3,0x45, 0x02,0x51,0x39,0xd9,0xf3,0x56,0x0b,0x91,0x80,0xe0,0x6c,0xa8,0xc3,0x78,0xef,0x34, 0x22,0x8c,0xf5,0xfb,0x47,0x98,0x5d,0x57,0x8e,0x3a,0xb9,0xff,0x92,0x04,0xc7,0xc2, 0x6e,0xfa,0x14,0xc1,0xb9,0x68,0x15,0x5c,0x12,0xe8,0xa8,0xbe,0xea,0xe8,0x8d,0x9b, 0x48,0x28,0x35,0xdb,0x4b,0x52,0xc1,0x2d,0x85,0x47,0x83,0xd0,0xe9,0xae,0x90,0x6e, 0x65,0xd4,0x34,0x7f,0x81,0xce,0x69,0xf0,0x96,0x62,0xf7,0xec,0x41,0xd5,0xc2,0xe3, 0x4b,0xba,0x9c,0x8a,0x02,0xce,0xf0,0x5d,0x14,0xf7,0x09,0x42,0x8e,0x4a,0x27,0xfe, 0x3e,0x66,0x42,0x99,0x03,0xe1,0x69,0xbd,0xdb,0x7f,0x9b,0x70,0xeb,0x4e,0x9c,0xac, 0x45,0x67,0x91,0x9f,0x75,0x10,0xc6,0xfc,0x14,0xe1,0x28,0xc1,0x0e,0xe0,0x7e,0xc0, 0x5c,0x1d,0xee,0xe8,0xff,0x45,0x79,0x51,0x86,0x08,0xe6,0x39,0xac,0xb5,0xfd,0xb8, 0xf1,0xdd,0x2e,0xf4,0xb2,0x1a,0x69,0x0d,0xd9,0x98,0x8e,0xdb,0x85,0x61,0x70,0x20, 0x82,0x91,0x26,0x87,0x80,0xc4,0x6a,0xd8,0x3b,0x91,0x4d,0xd3,0x33,0x84,0xad,0xb7}}; const TPM2B_RSA_TEST_VALUE c_RsaesKvt = {RSA_TEST_KEY_SIZE, { 0x44,0xd5,0x9f,0xbc,0x48,0x03,0x3d,0x9f,0x22,0x91,0x2a,0xab,0x3c,0x31,0x71,0xab, 0x86,0x3f,0x0f,0x6f,0x59,0x5b,0x93,0x27,0xbc,0xbc,0xcd,0x29,0x38,0x43,0x2a,0x3b, 0x3b,0xd2,0xb3,0x45,0x40,0xba,0x15,0xb4,0x45,0xe3,0x56,0xab,0xff,0xb3,0x20,0x26, 0x39,0xcc,0x48,0xc5,0x5d,0x41,0x0d,0x2f,0x57,0x7f,0x9d,0x16,0x2e,0x26,0x57,0xc7, 0x6b,0xf3,0x36,0x54,0xbd,0xb6,0x1d,0x46,0x4e,0x13,0x50,0xd7,0x61,0x9d,0x8d,0x7b, 0xeb,0x21,0x9f,0x79,0xf3,0xfd,0xe0,0x1b,0xa8,0xed,0x6d,0x29,0x33,0x0d,0x65,0x94, 0x24,0x1e,0x62,0x88,0x6b,0x2b,0x4e,0x39,0xf5,0x80,0x39,0xca,0x76,0x95,0xbc,0x7c, 0x27,0x1d,0xdd,0x3a,0x11,0xf1,0x3e,0x54,0x03,0xb7,0x43,0x91,0x99,0x33,0xfe,0x9d, 0x14,0x2c,0x87,0x9a,0x95,0x18,0x1f,0x02,0x04,0x6a,0xe2,0xb7,0x81,0x14,0x13,0x45, 0x16,0xfb,0xe4,0xb7,0x8f,0xab,0x2b,0xd7,0x60,0x34,0x8a,0x55,0xbc,0x01,0x8c,0x49, 0x02,0x29,0xf1,0x9c,0x94,0x98,0x44,0xd0,0x94,0xcb,0xd4,0x85,0x4c,0x3b,0x77,0x72, 0x99,0xd5,0x4b,0xc6,0x3b,0xe4,0xd2,0xc8,0xe9,0x6a,0x23,0x18,0x3b,0x3b,0x5e,0x32, 0xec,0x70,0x84,0x5d,0xbb,0x6a,0x8f,0x0c,0x5f,0x55,0xa5,0x30,0x34,0x48,0xbb,0xc2, 0xdf,0x12,0xb9,0x81,0xad,0x36,0x3f,0xf0,0x24,0x16,0x48,0x04,0x4a,0x7f,0xfd,0x9f, 0x4c,0xea,0xfe,0x1d,0x83,0xd0,0x81,0xad,0x25,0x6c,0x5f,0x45,0x36,0x91,0xf0,0xd5, 0x8b,0x53,0x0a,0xdf,0xec,0x9f,0x04,0x58,0xc4,0x35,0xa0,0x78,0x1f,0x68,0xe0,0x22}}; const TPM2B_RSA_TEST_VALUE c_RsapssKvt = {RSA_TEST_KEY_SIZE, { 0x3f,0x3a,0x82,0x6d,0x42,0xe3,0x8b,0x4f,0x45,0x9c,0xda,0x6c,0xbe,0xbe,0xcd,0x00, 0x98,0xfb,0xbe,0x59,0x30,0xc6,0x3c,0xaa,0xb3,0x06,0x27,0xb5,0xda,0xfa,0xb2,0xc3, 0x43,0xb7,0xbd,0xe9,0xd3,0x23,0xed,0x80,0xce,0x74,0xb3,0xb8,0x77,0x8d,0xe6,0x8d, 0x3c,0xe5,0xf5,0xd7,0x80,0xcf,0x38,0x55,0x76,0xd7,0x87,0xa8,0xd6,0x3a,0xcf,0xfd, 0xd8,0x91,0x65,0xab,0x43,0x66,0x50,0xb7,0x9a,0x13,0x6b,0x45,0x80,0x76,0x86,0x22, 0x27,0x72,0xf7,0xbb,0x65,0x22,0x5c,0x55,0x60,0xd8,0x84,0x9f,0xf2,0x61,0x52,0xac, 0xf2,0x4f,0x5b,0x7b,0x21,0xe1,0xf5,0x4b,0x8f,0x01,0xf2,0x4b,0xcf,0xd3,0xfb,0x74, 0x5e,0x6e,0x96,0xb4,0xa8,0x0f,0x01,0x9b,0x26,0x54,0x0a,0x70,0x55,0x26,0xb7,0x0b, 0xe8,0x01,0x68,0x66,0x0d,0x6f,0xb5,0xfc,0x66,0xbd,0x9e,0x44,0xed,0x6a,0x1e,0x3c, 0x3b,0x61,0x5d,0xe8,0xdb,0x99,0x5b,0x67,0xbf,0x94,0xfb,0xe6,0x8c,0x4b,0x07,0xcb, 0x43,0x3a,0x0d,0xb1,0x1b,0x10,0x66,0x81,0xe2,0x0d,0xe7,0xd1,0xca,0x85,0xa7,0x50, 0x82,0x2d,0xbf,0xed,0xcf,0x43,0x6d,0xdb,0x2c,0x7b,0x73,0x20,0xfe,0x73,0x3f,0x19, 0xc6,0xdb,0x69,0xb8,0xc3,0xd3,0xf4,0xe5,0x64,0xf8,0x36,0x8e,0xd5,0xd8,0x09,0x2a, 0x5f,0x26,0x70,0xa1,0xd9,0x5b,0x14,0xf8,0x22,0xe9,0x9d,0x22,0x51,0xf4,0x52,0xc1, 0x6f,0x53,0xf5,0xca,0x0d,0xda,0x39,0x8c,0x29,0x42,0xe8,0x58,0x89,0xbb,0xd1,0x2e, 0xc5,0xdb,0x86,0x8d,0xaf,0xec,0x58,0x36,0x8d,0x8d,0x57,0x23,0xd5,0xdd,0xb9,0x24}}; const TPM2B_RSA_TEST_VALUE c_RsassaKvt = {RSA_TEST_KEY_SIZE, { 0x39,0x10,0x58,0x7d,0x6d,0xa8,0xd5,0x90,0x07,0xd6,0x2b,0x13,0xe9,0xd8,0x93,0x7e, 0xf3,0x5d,0x71,0xe0,0xf0,0x33,0x3a,0x4a,0x22,0xf3,0xe6,0x95,0xd3,0x8e,0x8c,0x41, 0xe7,0xb3,0x13,0xde,0x4a,0x45,0xd3,0xd1,0xfb,0xb1,0x3f,0x9b,0x39,0xa5,0x50,0x58, 0xef,0xb6,0x3a,0x43,0xdd,0x54,0xab,0xda,0x9d,0x32,0x49,0xe4,0x57,0x96,0xe5,0x1b, 0x1d,0x8f,0x33,0x8e,0x07,0x67,0x56,0x14,0xc1,0x18,0x78,0xa2,0x52,0xe6,0x2e,0x07, 0x81,0xbe,0xd8,0xca,0x76,0x63,0x68,0xc5,0x47,0xa2,0x92,0x5e,0x4c,0xfd,0x14,0xc7, 0x46,0x14,0xbe,0xc7,0x85,0xef,0xe6,0xb8,0x46,0xcb,0x3a,0x67,0x66,0x89,0xc6,0xee, 0x9d,0x64,0xf5,0x0d,0x09,0x80,0x9a,0x6f,0x0e,0xeb,0xe4,0xb9,0xe9,0xab,0x90,0x4f, 0xe7,0x5a,0xc8,0xca,0xf6,0x16,0x0a,0x82,0xbd,0xb7,0x76,0x59,0x08,0x2d,0xd9,0x40, 0x5d,0xaa,0xa5,0xef,0xfb,0xe3,0x81,0x2c,0x2c,0x5c,0xa8,0x16,0xbd,0x63,0x20,0xc2, 0x4d,0x3b,0x51,0xaa,0x62,0x1f,0x06,0xe5,0xbb,0x78,0x44,0x04,0x0c,0x5c,0xe1,0x1b, 0x6b,0x9d,0x21,0x10,0xaf,0x48,0x48,0x98,0x97,0x77,0xc2,0x73,0xb4,0x98,0x64,0xcc, 0x94,0x2c,0x29,0x28,0x45,0x36,0xd1,0xc5,0xd0,0x2f,0x97,0x27,0x92,0x65,0x22,0xbb, 0x63,0x79,0xea,0xf5,0xff,0x77,0x0f,0x4b,0x56,0x8a,0x9f,0xad,0x1a,0x97,0x67,0x39, 0x69,0xb8,0x4c,0x6c,0xc2,0x56,0xc5,0x7a,0xa8,0x14,0x5a,0x24,0x7a,0xa4,0x6e,0x55, 0xb2,0x86,0x1d,0xf4,0x62,0x5a,0x2d,0x87,0x6d,0xde,0x99,0x78,0x2d,0xef,0xd7,0xdc}}; #endif // SHA384 #if ALG_SHA512_VALUE == DEFAULT_TEST_HASH const TPM2B_RSA_TEST_VALUE c_OaepKvt = {RSA_TEST_KEY_SIZE, { 0x48,0x45,0xa7,0x70,0xb2,0x41,0xb7,0x48,0x5e,0x79,0x8c,0xdf,0x1c,0xc6,0x7e,0xbb, 0x11,0x80,0x82,0x52,0xbf,0x40,0x3d,0x90,0x03,0x6e,0x20,0x3a,0xb9,0x65,0xc8,0x51, 0x4c,0xbd,0x9c,0xa9,0x43,0x89,0xd0,0x57,0x0c,0xa3,0x69,0x22,0x7e,0x82,0x2a,0x1c, 0x1d,0x5a,0x80,0x84,0x81,0xbb,0x5e,0x5e,0xd0,0xc1,0x66,0x9a,0xac,0x00,0xba,0x14, 0xa2,0xe9,0xd0,0x3a,0x89,0x5a,0x63,0xe2,0xec,0x92,0x05,0xf4,0x47,0x66,0x12,0x7f, 0xdb,0xa7,0x3c,0x5b,0x67,0xe1,0x55,0xca,0x0a,0x27,0xbf,0x39,0x89,0x11,0x05,0xba, 0x9b,0x5a,0x9b,0x65,0x44,0xad,0x78,0xcf,0x8f,0x94,0xf6,0x9a,0xb4,0x52,0x39,0x0e, 0x00,0xba,0xbc,0xe0,0xbd,0x6f,0x81,0x2d,0x76,0x42,0x66,0x70,0x07,0x77,0xbf,0x09, 0x88,0x2a,0x0c,0xb1,0x56,0x3e,0xee,0xfd,0xdc,0xb6,0x3c,0x0d,0xc5,0xa4,0x0d,0x10, 0x32,0x80,0x3e,0x1e,0xfe,0x36,0x8f,0xb5,0x42,0xc1,0x21,0x7b,0xdf,0xdf,0x4a,0xd2, 0x68,0x0c,0x01,0x9f,0x4a,0xfd,0xd4,0xec,0xf7,0x49,0x06,0xab,0xed,0xc6,0xd5,0x1b, 0x63,0x76,0x38,0xc8,0x6c,0xc7,0x4f,0xcb,0x29,0x8a,0x0e,0x6f,0x33,0xaf,0x69,0x31, 0x8e,0xa7,0xdd,0x9a,0x36,0xde,0x9b,0xf1,0x0b,0xfb,0x20,0xa0,0x6d,0x33,0x31,0xc9, 0x9e,0xb4,0x2e,0xc5,0x40,0x0e,0x60,0x71,0x36,0x75,0x05,0xf9,0x37,0xe0,0xca,0x8e, 0x8f,0x56,0xe0,0xea,0x9b,0xeb,0x17,0xf3,0xca,0x40,0xc3,0x48,0x01,0xba,0xdc,0xc6, 0x4b,0x2b,0x5b,0x7b,0x5c,0x81,0xa6,0xbb,0xc7,0x43,0xc0,0xbe,0xc0,0x30,0x7b,0x55}}; const TPM2B_RSA_TEST_VALUE c_RsaesKvt = {RSA_TEST_KEY_SIZE, { 0x74,0x83,0xfa,0x52,0x65,0x50,0x68,0xd0,0x82,0x05,0x72,0x70,0x78,0x1c,0xac,0x10, 0x23,0xc5,0x07,0xf8,0x93,0xd2,0xeb,0x65,0x87,0xbb,0x47,0xc2,0xfb,0x30,0x9e,0x61, 0x4c,0xac,0x04,0x57,0x5a,0x7c,0xeb,0x29,0x08,0x84,0x86,0x89,0x1e,0x8f,0x07,0x32, 0xa3,0x8b,0x70,0xe7,0xa2,0x9f,0x9c,0x42,0x71,0x3d,0x23,0x59,0x82,0x5e,0x8a,0xde, 0xd6,0xfb,0xd8,0xc5,0x8b,0xc0,0xdb,0x10,0x38,0x87,0xd3,0xbf,0x04,0xb0,0x66,0xb9, 0x85,0x81,0x54,0x4c,0x69,0xdc,0xba,0x78,0xf3,0x4a,0xdb,0x25,0xa2,0xf2,0x34,0x55, 0xdd,0xaa,0xa5,0xc4,0xed,0x55,0x06,0x0e,0x2a,0x30,0x77,0xab,0x82,0x79,0xf0,0xcd, 0x9d,0x6f,0x09,0xa0,0xc8,0x82,0xc9,0xe0,0x61,0xda,0x40,0xcd,0x17,0x59,0xc0,0xef, 0x95,0x6d,0xa3,0x6d,0x1c,0x2b,0xee,0x24,0xef,0xd8,0x4a,0x55,0x6c,0xd6,0x26,0x42, 0x32,0x17,0xfd,0x6a,0xb3,0x4f,0xde,0x07,0x2f,0x10,0xd4,0xac,0x14,0xea,0x89,0x68, 0xcc,0xd3,0x07,0xb7,0xcf,0xba,0x39,0x20,0x63,0x20,0x7b,0x44,0x8b,0x48,0x60,0x5d, 0x3a,0x2a,0x0a,0xe9,0x68,0xab,0x15,0x46,0x27,0x64,0xb5,0x82,0x06,0x29,0xe7,0x25, 0xca,0x46,0x48,0x6e,0x2a,0x34,0x57,0x4b,0x81,0x75,0xae,0xb6,0xfd,0x6f,0x51,0x5f, 0x04,0x59,0xc7,0x15,0x1f,0xe0,0x68,0xf7,0x36,0x2d,0xdf,0xc8,0x9d,0x05,0x27,0x2d, 0x3f,0x2b,0x59,0x5d,0xcb,0xf3,0xc4,0x92,0x6e,0x00,0xa8,0x8d,0xd0,0x69,0xe5,0x59, 0xda,0xba,0x4f,0x38,0xf5,0xa0,0x8b,0xf1,0x73,0xe9,0x0d,0xee,0x64,0xe5,0xa2,0xd8}}; const TPM2B_RSA_TEST_VALUE c_RsapssKvt = {RSA_TEST_KEY_SIZE, { 0x1b,0xca,0x8b,0x18,0x15,0x3b,0x95,0x5b,0x0a,0x89,0x10,0x03,0x7f,0x7c,0xa0,0xc9, 0x66,0x57,0x86,0x6a,0xc9,0xeb,0x82,0x71,0xf3,0x8d,0x6f,0xa9,0xa4,0x2d,0xd0,0x22, 0xdf,0xe9,0xc6,0x71,0x5b,0xf4,0x27,0x38,0x5b,0x2c,0x8a,0x54,0xcc,0x85,0x11,0x69, 0x6d,0x6f,0x42,0xe7,0x22,0xcb,0xd6,0xad,0x1a,0xc5,0xab,0x6a,0xa5,0xfc,0xa5,0x70, 0x72,0x4a,0x62,0x25,0xd0,0xa2,0x16,0x61,0xab,0xac,0x31,0xa0,0x46,0x24,0x4f,0xdd, 0x9a,0x36,0x55,0xb6,0x00,0x9e,0x23,0x50,0x0d,0x53,0x01,0xb3,0x46,0x56,0xb2,0x1d, 0x33,0x5b,0xca,0x41,0x7f,0x65,0x7e,0x00,0x5c,0x12,0xff,0x0a,0x70,0x5d,0x8c,0x69, 0x4a,0x02,0xee,0x72,0x30,0xa7,0x5c,0xa4,0xbb,0xbe,0x03,0x0c,0xe4,0x5f,0x33,0xb6, 0x78,0x91,0x9d,0xd8,0xec,0x34,0x03,0x2e,0x63,0x32,0xc7,0x2a,0x36,0x50,0xd5,0x8b, 0x0e,0x7f,0x54,0x4e,0xf4,0x29,0x11,0x1b,0xcd,0x0f,0x37,0xa5,0xbc,0x61,0x83,0x50, 0xfa,0x18,0x75,0xd9,0xfe,0xa7,0xe8,0x9b,0xc1,0x4f,0x96,0x37,0x81,0x71,0xdf,0x71, 0x8b,0x89,0x81,0xf4,0x95,0xb5,0x29,0x66,0x41,0x0c,0x73,0xd7,0x0b,0x21,0xb4,0xfb, 0xf9,0x63,0x2f,0xe9,0x7b,0x38,0xaa,0x20,0xc3,0x96,0xcc,0xb7,0xb2,0x24,0xa1,0xe0, 0x59,0x9c,0x10,0x9e,0x5a,0xf7,0xe3,0x02,0xe6,0x23,0xe2,0x44,0x21,0x3f,0x6e,0x5e, 0x79,0xb2,0x93,0x7d,0xce,0xed,0xe2,0xe1,0xab,0x98,0x07,0xa7,0xbd,0xbc,0xd8,0xf7, 0x06,0xeb,0xc5,0xa6,0x37,0x18,0x11,0x88,0xf7,0x63,0x39,0xb9,0x57,0x29,0xdc,0x03}}; const TPM2B_RSA_TEST_VALUE c_RsassaKvt = {RSA_TEST_KEY_SIZE, { 0x05,0x55,0x00,0x62,0x01,0xc6,0x04,0x31,0x55,0x73,0x3f,0x2a,0xf9,0xd4,0x0f,0xc1, 0x2b,0xeb,0xd8,0xc8,0xdb,0xb2,0xab,0x6c,0x26,0xde,0x2d,0x89,0xc2,0x2d,0x36,0x62, 0xc8,0x22,0x5d,0x58,0x03,0xb1,0x46,0x14,0xa5,0xd4,0xbc,0x25,0x6b,0x7f,0x8f,0x14, 0x7e,0x03,0x2f,0x3d,0xb8,0x39,0xa5,0x79,0x13,0x7e,0x22,0x2a,0xb9,0x3e,0x8f,0xaa, 0x01,0x7c,0x03,0x12,0x21,0x6c,0x2a,0xb4,0x39,0x98,0x6d,0xff,0x08,0x6c,0x59,0x2d, 0xdc,0xc6,0xf1,0x77,0x62,0x10,0xa6,0xcc,0xe2,0x71,0x8e,0x97,0x00,0x87,0x5b,0x0e, 0x20,0x00,0x3f,0x18,0x63,0x83,0xf0,0xe4,0x0a,0x64,0x8c,0xe9,0x8c,0x91,0xe7,0x89, 0x04,0x64,0x2c,0x8b,0x41,0xc8,0xac,0xf6,0x5a,0x75,0xe6,0xa5,0x76,0x43,0xcb,0xa5, 0x33,0x8b,0x07,0xc9,0x73,0x0f,0x45,0xa4,0xc3,0xac,0xc1,0xc3,0xe6,0xe7,0x21,0x66, 0x1c,0xba,0xbf,0xea,0x3e,0x39,0xfa,0xb2,0xe2,0x8f,0xfe,0x9c,0xb4,0x85,0x89,0x33, 0x2a,0x0c,0xc8,0x5d,0x58,0xe1,0x89,0x12,0xe9,0x4d,0x42,0xb3,0x1f,0x99,0x0c,0x3e, 0xd8,0xb2,0xeb,0xf5,0x88,0xfb,0xe1,0x4b,0x8e,0xdc,0xd3,0xa8,0xda,0xbe,0x04,0x45, 0xbf,0x56,0xc6,0x54,0x70,0x00,0xb8,0x66,0x46,0x3a,0xa3,0x1e,0xb6,0xeb,0x1a,0xa0, 0x0b,0xd3,0x9a,0x9a,0x52,0xda,0x60,0x69,0xb7,0xef,0x93,0x47,0x38,0xab,0x1a,0xa0, 0x22,0x6e,0x76,0x06,0xb6,0x74,0xaf,0x74,0x8f,0x51,0xc0,0x89,0x5a,0x4b,0xbe,0x6a, 0x91,0x18,0x25,0x7d,0xa6,0x77,0xe6,0xfd,0xc2,0x62,0x36,0x07,0xc6,0xef,0x79,0xc9}}; #endif // SHA512 #endif libtpms-0.9.3/src/tpm2/RunCommand.c000066400000000000000000000126631421143571500170700ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Platform specific entry and fail processing */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: RunCommand.c 1476 2019-06-10 19:32:03Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ /* C.11 RunCommand.c */ /* C.11.1. Introduction */ /* This module provides the platform specific entry and fail processing. The _plat__RunCommand() function is used to call to ExecuteCommand() in the TPM code. This function does whatever processing is necessary to set up the platform in anticipation of the call to the TPM including setup for error processing. */ /* The _plat__Fail() function is called when there is a failure in the TPM. The TPM code will have set the flag to indicate that the TPM is in failure mode. This call will then recursively call ExecuteCommand() in order to build the failure mode response. When ExecuteCommand() returns to _plat__Fail(), the platform will do some platform specif operation to return to the environment in which the TPM is executing. For a simulator, setjmp/longjmp is used. For an OS, a system exit to the OS would be appropriate. */ /* C.11.2. Includes and locals */ #include "Platform.h" #include #include "ExecCommand_fp.h" jmp_buf s_jumpBuffer; /* C.11.3. Functions */ /* C.11.3.1. _plat__RunCommand() */ /* This version of RunCommand() will set up a jum_buf and call ExecuteCommand(). If the command executes without failing, it will return and RunCommand() will return. If there is a failure in the command, then _plat__Fail() is called and it will longjump back to RunCommand() which will call ExecuteCommand() again. However, this time, the TPM will be in failure mode so ExecuteCommand() will simply build a failure response and return. */ LIB_EXPORT void _plat__RunCommand( uint32_t requestSize, // IN: command buffer size unsigned char *request, // IN: command buffer uint32_t *responseSize, // IN/OUT: response buffer size unsigned char **response // IN/OUT: response buffer ) { setjmp(s_jumpBuffer); ExecuteCommand(requestSize, request, responseSize, response); } /* C.11.3.2. _plat__Fail() */ /* This is the platform depended failure exit for the TPM. */ LIB_EXPORT NORETURN void _plat__Fail( void ) { longjmp(&s_jumpBuffer[0], 1); } libtpms-0.9.3/src/tpm2/SelfTest.h000066400000000000000000000140241421143571500165540ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Structure definitions for the self-test */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: SelfTest.h 1594 2020-03-26 22:15:48Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2020 */ /* */ /********************************************************************************/ #ifndef SELFTEST_H #define SELFTEST_H /* 10.1.10 SelfTest.h */ /* 10.1.10.1 Introduction */ /* This file contains the structure definitions for the self-test. It also contains macros for use when the self-test is implemented. */ #define SELF_TEST_FAILURE FAIL(FATAL_ERROR_SELF_TEST) // Use the definition of key sizes to set algorithm values for key size. #define AES_ENTRIES (AES_128 + AES_192 + AES_256) #define SM4_ENTRIES (SM4_128) #define CAMELLIA_ENTRIES (CAMELLIA_128 + CAMELLIA_192 + CAMELLIA_256) #define TDES_ENTRIES (TDES_128 * 2 + TDES_192 * 2) /* libtpms changed */ #define NUM_SYMS (AES_ENTRIES + SM4_ENTRIES + CAMELLIA_ENTRIES + TDES_ENTRIES) typedef UINT32 SYM_INDEX; /* These two defines deal with the fact that the TPM_ALG_ID table does not delimit the symmetric mode values with a SYM_MODE_FIRST and SYM_MODE_LAST */ #define SYM_MODE_FIRST ALG_CTR_VALUE #define SYM_MODE_LAST ALG_ECB_VALUE #define NUM_SYM_MODES (SYM_MODE_LAST - SYM_MODE_FIRST + 1) /* Define a type to hold a bit vector for the modes. */ #if NUM_SYM_MODES <= 0 #error "No symmetric modes implemented" #elif NUM_SYM_MODES <= 8 typedef BYTE SYM_MODES; #elif NUM_SYM_MODES <= 16 typedef UINT16 SYM_MODES; #elif NUM_SYM_MODES <= 32 typedef UINT32 SYM_MODES; #else #error "Too many symmetric modes" #endif typedef struct SYMMETRIC_TEST_VECTOR { const TPM_ALG_ID alg; // the algorithm const UINT16 keyBits; // bits in the key const BYTE *key; // The test key const UINT32 ivSize; // block size of the algorithm const UINT32 dataInOutSize; // size to encrypt/decrypt const BYTE *dataIn; // data to encrypt const BYTE *dataOut[NUM_SYM_MODES];// data to decrypt } SYMMETRIC_TEST_VECTOR; #if ALG_SHA512 # define DEFAULT_TEST_HASH ALG_SHA512_VALUE # define DEFAULT_TEST_DIGEST_SIZE SHA512_DIGEST_SIZE # define DEFAULT_TEST_HASH_BLOCK_SIZE SHA512_BLOCK_SIZE #elif ALG_SHA384 # define DEFAULT_TEST_HASH ALG_SHA384_VALUE # define DEFAULT_TEST_DIGEST_SIZE SHA384_DIGEST_SIZE # define DEFAULT_TEST_HASH_BLOCK_SIZE SHA384_BLOCK_SIZE #elif ALG_SHA256 # define DEFAULT_TEST_HASH ALG_SHA256_VALUE # define DEFAULT_TEST_DIGEST_SIZE SHA256_DIGEST_SIZE # define DEFAULT_TEST_HASH_BLOCK_SIZE SHA256_BLOCK_SIZE #elif ALG_SHA1 # define DEFAULT_TEST_HASH ALG_SHA1_VALUE # define DEFAULT_TEST_DIGEST_SIZE SHA1_DIGEST_SIZE # define DEFAULT_TEST_HASH_BLOCK_SIZE SHA1_BLOCK_SIZE #endif #endif libtpms-0.9.3/src/tpm2/SelfTest_fp.h000066400000000000000000000071221421143571500172420ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: SelfTest_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef SELFTEST_FP_H #define SELFTEST_FP_H typedef struct{ TPMI_YES_NO fullTest; } SelfTest_In; #define RC_SelfTest_fullTest (TPM_RC_P + TPM_RC_1) TPM_RC TPM2_SelfTest( SelfTest_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/SequenceComplete_fp.h000066400000000000000000000100021421143571500207410ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: SequenceComplete_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef SEQUENCECOMPLETE_FP_H #define SEQUENCECOMPLETE_FP_H typedef struct { TPMI_DH_OBJECT sequenceHandle; TPM2B_MAX_BUFFER buffer; TPMI_RH_HIERARCHY hierarchy; } SequenceComplete_In; #define RC_SequenceComplete_sequenceHandle (TPM_RC_H + TPM_RC_1) #define RC_SequenceComplete_buffer (TPM_RC_P + TPM_RC_1) #define RC_SequenceComplete_hierarchy (TPM_RC_P + TPM_RC_2) typedef struct { TPM2B_DIGEST result; TPMT_TK_HASHCHECK validation; } SequenceComplete_Out; TPM_RC TPM2_SequenceComplete( SequenceComplete_In *in, // IN: input parameter list SequenceComplete_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/SequenceUpdate_fp.h000066400000000000000000000073311421143571500204260ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: SequenceUpdate_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef SEQUENCEUPDATE_FP_H #define SEQUENCEUPDATE_FP_H typedef struct { TPMI_DH_OBJECT sequenceHandle; TPM2B_MAX_BUFFER buffer; } SequenceUpdate_In; #define RC_SequenceUpdate_sequenceHandle (TPM_RC_P + TPM_RC_1) #define RC_SequenceUpdate_buffer (TPM_RC_P + TPM_RC_2) TPM_RC TPM2_SequenceUpdate( SequenceUpdate_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/Session.c000066400000000000000000001031061421143571500164410ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Manage the session context counter */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Session.c 1594 2020-03-26 22:15:48Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2020 */ /* */ /********************************************************************************/ /* 8.9.2 Includes, Defines, and Local Variables */ #define SESSION_C #include "Tpm.h" /* 8.9.3 File Scope Function -- ContextIdSetOldest() */ static void ContextIdSetOldest( void ) { CONTEXT_SLOT lowBits; CONTEXT_SLOT entry; CONTEXT_SLOT smallest = CONTEXT_SLOT_MASKED(~0); // libtpms changed UINT32 i; pAssert(s_ContextSlotMask == 0xff || s_ContextSlotMask == 0xffff); // libtpms added // Set oldestSaveContext to a value indicating none assigned s_oldestSavedSession = MAX_ACTIVE_SESSIONS + 1; lowBits = CONTEXT_SLOT_MASKED(gr.contextCounter); // libtpms changed for(i = 0; i < MAX_ACTIVE_SESSIONS; i++) { entry = gr.contextArray[i]; // only look at entries that are saved contexts if(entry > MAX_LOADED_SESSIONS) { // Use a less than or equal in case the oldest // is brand new (= lowBits-1) and equal to our initial // value for smallest. if(CONTEXT_SLOT_MASKED(entry - lowBits) <= smallest) // libtpms changed { smallest = CONTEXT_SLOT_MASKED(entry - lowBits); // libtpms changed s_oldestSavedSession = i; } } } // When we finish, either the s_oldestSavedSession still has its initial // value, or it has the index of the oldest saved context. } /* 8.9.4 Startup Function -- SessionStartup() */ /* This function initializes the session subsystem on TPM2_Startup(). */ BOOL SessionStartup( STARTUP_TYPE type ) { UINT32 i; // Initialize session slots. At startup, all the in-memory session slots // are cleared and marked as not occupied for(i = 0; i < MAX_LOADED_SESSIONS; i++) s_sessions[i].occupied = FALSE; // session slot is not occupied // The free session slots the number of maximum allowed loaded sessions s_freeSessionSlots = MAX_LOADED_SESSIONS; // Initialize context ID data. On a ST_SAVE or hibernate sequence, it will // scan the saved array of session context counts, and clear any entry that // references a session that was in memory during the state save since that // memory was not preserved over the ST_SAVE. if(type == SU_RESUME || type == SU_RESTART) { // On ST_SAVE we preserve the contexts that were saved but not the ones // in memory for(i = 0; i < MAX_ACTIVE_SESSIONS; i++) { // If the array value is unused or references a loaded session then // that loaded session context is lost and the array entry is // reclaimed. if(gr.contextArray[i] <= MAX_LOADED_SESSIONS) gr.contextArray[i] = 0; } // Find the oldest session in context ID data and set it in // s_oldestSavedSession ContextIdSetOldest(); } else { // For STARTUP_CLEAR, clear out the contextArray for(i = 0; i < MAX_ACTIVE_SESSIONS; i++) gr.contextArray[i] = 0; // reset the context counter gr.contextCounter = MAX_LOADED_SESSIONS + 1; // Initialize oldest saved session s_oldestSavedSession = MAX_ACTIVE_SESSIONS + 1; // Initialize the context slot mask for UINT16 s_ContextSlotMask = 0xffff; // libtpms added } return TRUE; } /* 8.9.5 Access Functions */ /* 8.9.5.1 SessionIsLoaded() */ /* This function test a session handle references a loaded session. The handle must have previously been checked to make sure that it is a valid handle for an authorization session. */ /* NOTE: A PWAP authorization does not have a session. */ /* Return Values Meaning */ /* TRUE if session is loaded */ /* FALSE if it is not loaded */ BOOL SessionIsLoaded( TPM_HANDLE handle // IN: session handle ) { pAssert(HandleGetType(handle) == TPM_HT_POLICY_SESSION || HandleGetType(handle) == TPM_HT_HMAC_SESSION); handle = handle & HR_HANDLE_MASK; // if out of range of possible active session, or not assigned to a loaded // session return false if(handle >= MAX_ACTIVE_SESSIONS || gr.contextArray[handle] == 0 || gr.contextArray[handle] > MAX_LOADED_SESSIONS) return FALSE; return TRUE; } /* 8.9.5.2 SessionIsSaved() */ /* This function test a session handle references a saved session. The handle must have previously been checked to make sure that it is a valid handle for an authorization session. */ /* NOTE: A password authorization does not have a session. */ /* This function requires that the handle be a valid session handle. */ /* Return Values Meaning */ /* TRUE if session is saved */ /* FALSE if it is not saved */ BOOL SessionIsSaved( TPM_HANDLE handle // IN: session handle ) { pAssert(HandleGetType(handle) == TPM_HT_POLICY_SESSION || HandleGetType(handle) == TPM_HT_HMAC_SESSION); handle = handle & HR_HANDLE_MASK; // if out of range of possible active session, or not assigned, or // assigned to a loaded session, return false if(handle >= MAX_ACTIVE_SESSIONS || gr.contextArray[handle] == 0 || gr.contextArray[handle] <= MAX_LOADED_SESSIONS ) return FALSE; return TRUE; } /* 8.9.5.3 SequenceNumberForSavedContextIsValid() */ BOOL SequenceNumberForSavedContextIsValid( TPMS_CONTEXT *context // IN: pointer to a context // structure to be validated ) { #define MAX_CONTEXT_GAP ((UINT64)(CONTEXT_SLOT_MASKED(~0) + 1)) /* libtpms changed */ pAssert(s_ContextSlotMask == 0xff || s_ContextSlotMask == 0xffff); // libtpms added TPM_HANDLE handle = context->savedHandle & HR_HANDLE_MASK; if(// Handle must be with the range of active sessions handle >= MAX_ACTIVE_SESSIONS // the array entry must be for a saved context || gr.contextArray[handle] <= MAX_LOADED_SESSIONS // the array entry must agree with the sequence number || gr.contextArray[handle] != CONTEXT_SLOT_MASKED(context->sequence) // libtpms changed // the provided sequence number has to be less than the current counter || context->sequence > gr.contextCounter // but not so much that it could not be a valid sequence number || gr.contextCounter - context->sequence > MAX_CONTEXT_GAP) return FALSE; return TRUE; } /* 8.9.5.4 SessionPCRValueIsCurrent() */ /* This function is used to check if PCR values have been updated since the last time they were checked in a policy session. */ /* This function requires the session is loaded. */ /* Return Values Meaning */ /* TRUE if PCR value is current */ /* FALSE if PCR value is not current */ BOOL SessionPCRValueIsCurrent( SESSION *session // IN: session structure ) { if(session->pcrCounter != 0 && session->pcrCounter != gr.pcrCounter ) return FALSE; else return TRUE; } /* 8.9.5.5 SessionGet() */ /* This function returns a pointer to the session object associated with a session handle. */ /* The function requires that the session is loaded. */ SESSION * SessionGet( TPM_HANDLE handle // IN: session handle ) { size_t slotIndex; CONTEXT_SLOT sessionIndex; pAssert(HandleGetType(handle) == TPM_HT_POLICY_SESSION || HandleGetType(handle) == TPM_HT_HMAC_SESSION ); slotIndex = handle & HR_HANDLE_MASK; pAssert(slotIndex < MAX_ACTIVE_SESSIONS); // get the contents of the session array. Because session is loaded, we // should always get a valid sessionIndex sessionIndex = gr.contextArray[slotIndex] - 1; pAssert(sessionIndex < MAX_LOADED_SESSIONS); return &s_sessions[sessionIndex].session; } /* 8.9.6 Utility Functions */ /* 8.9.6.1 ContextIdSessionCreate() */ /* This function is called when a session is created. It will check to see if the current gap would prevent a context from being saved. If so it will return TPM_RC_CONTEXT_GAP. Otherwise, it will try to find an open slot in contextArray, set contextArray to the slot. This routine requires that the caller has determined the session array index for the session. */ /* TPM_RC_CONTEXT_GAP can't assign a new contextID until the oldest saved session context is recycled */ /* TPM_RC_SESSION_HANDLE there is no slot available in the context array for tracking of this session context */ static TPM_RC ContextIdSessionCreate( TPM_HANDLE *handle, /* OUT: receives the assigned handle. This will be an index that must be adjusted by the caller according to the type of the session created */ UINT32 sessionIndex /* IN: The session context array entry that will be occupied by the created session */ ) { pAssert(sessionIndex < MAX_LOADED_SESSIONS); // check to see if creating the context is safe // Is this going to be an assignment for the last session context // array entry? If so, then there will be no room to recycle the // oldest context if needed. If the gap is not at maximum, then // it will be possible to save a context if it becomes necessary. if(s_oldestSavedSession < MAX_ACTIVE_SESSIONS && s_freeSessionSlots == 1) { // See if the gap is at maximum // The current value of the contextCounter will be assigned to the next // saved context. If the value to be assigned would make the same as an // existing context, then we can't use it because of the ambiguity it would // create. if(CONTEXT_SLOT_MASKED(gr.contextCounter) // libtpms changed == gr.contextArray[s_oldestSavedSession]) return TPM_RC_CONTEXT_GAP; } // Find an unoccupied entry in the contextArray for(*handle = 0; *handle < MAX_ACTIVE_SESSIONS; (*handle)++) { if(gr.contextArray[*handle] == 0) { // indicate that the session associated with this handle // references a loaded session gr.contextArray[*handle] = CONTEXT_SLOT_MASKED(sessionIndex + 1); // libtpms changed return TPM_RC_SUCCESS; } } return TPM_RC_SESSION_HANDLES; } /* 8.9.6.2 SessionCreate() */ /* This function does the detailed work for starting an authorization session. This is done in a support routine rather than in the action code because the session management may differ in implementations. This implementation uses a fixed memory allocation to hold sessions and a fixed allocation to hold the contextID for the saved contexts. */ /* Error Returns Meaning */ /* TPM_RC_CONTEXT_GAP need to recycle sessions */ /* TPM_RC_SESSION_HANDLE active session space is full */ /* TPM_RC_SESSION_MEMORY loaded session space is full */ TPM_RC SessionCreate( TPM_SE sessionType, // IN: the session type TPMI_ALG_HASH authHash, // IN: the hash algorithm TPM2B_NONCE *nonceCaller, // IN: initial nonceCaller TPMT_SYM_DEF *symmetric, // IN: the symmetric algorithm TPMI_DH_ENTITY bind, // IN: the bind object TPM2B_DATA *seed, // IN: seed data TPM_HANDLE *sessionHandle, // OUT: the session handle TPM2B_NONCE *nonceTpm // OUT: the session nonce ) { TPM_RC result = TPM_RC_SUCCESS; CONTEXT_SLOT slotIndex; SESSION *session = NULL; pAssert(sessionType == TPM_SE_HMAC || sessionType == TPM_SE_POLICY || sessionType == TPM_SE_TRIAL); // If there are no open spots in the session array, then no point in searching if(s_freeSessionSlots == 0) return TPM_RC_SESSION_MEMORY; // Find a space for loading a session for(slotIndex = 0; slotIndex < MAX_LOADED_SESSIONS; slotIndex++) { // Is this available? if(s_sessions[slotIndex].occupied == FALSE) { session = &s_sessions[slotIndex].session; break; } } // if no spot found, then this is an internal error if(slotIndex >= MAX_LOADED_SESSIONS) { // libtpms changed FAIL(FATAL_ERROR_INTERNAL); // should never get here due to longjmp in FAIL() libtpms added begin; cppcheck return TPM_RC_FAILURE; } // libtpms added end // Call context ID function to get a handle. TPM_RC_SESSION_HANDLE may be // returned from ContextIdHandelAssign() result = ContextIdSessionCreate(sessionHandle, slotIndex); if(result != TPM_RC_SUCCESS) return result; //*** Only return from this point on is TPM_RC_SUCCESS // Can now indicate that the session array entry is occupied. s_freeSessionSlots--; s_sessions[slotIndex].occupied = TRUE; // Initialize the session data MemorySet(session, 0, sizeof(SESSION)); // Initialize internal session data session->authHashAlg = authHash; // Initialize session type if(sessionType == TPM_SE_HMAC) { *sessionHandle += HMAC_SESSION_FIRST; } else { *sessionHandle += POLICY_SESSION_FIRST; // For TPM_SE_POLICY or TPM_SE_TRIAL session->attributes.isPolicy = SET; if(sessionType == TPM_SE_TRIAL) session->attributes.isTrialPolicy = SET; SessionSetStartTime(session); // Initialize policyDigest. policyDigest is initialized with a string of 0 // of session algorithm digest size. Since the session is already clear. // Just need to set the size session->u2.policyDigest.t.size = CryptHashGetDigestSize(session->authHashAlg); } // Create initial session nonce session->nonceTPM.t.size = nonceCaller->t.size; CryptRandomGenerate(session->nonceTPM.t.size, session->nonceTPM.t.buffer); MemoryCopy2B(&nonceTpm->b, &session->nonceTPM.b, sizeof(nonceTpm->t.buffer)); // Set up session parameter encryption algorithm session->symmetric = *symmetric; // If there is a bind object or a session secret, then need to compute // a sessionKey. if(bind != TPM_RH_NULL || seed->t.size != 0) { // sessionKey = KDFa(hash, (authValue || seed), "ATH", nonceTPM, // nonceCaller, bits) // The HMAC key for generating the sessionSecret can be the concatenation // of an authorization value and a seed value TPM2B_TYPE(KEY, (sizeof(TPMT_HA) + sizeof(seed->t.buffer))); TPM2B_KEY key; // Get hash size, which is also the length of sessionKey session->sessionKey.t.size = CryptHashGetDigestSize(session->authHashAlg); // Get authValue of associated entity EntityGetAuthValue(bind, (TPM2B_AUTH *)&key); pAssert(key.t.size + seed->t.size <= sizeof(key.t.buffer)); // Concatenate authValue and seed MemoryConcat2B(&key.b, &seed->b, sizeof(key.t.buffer)); // Compute the session key CryptKDFa(session->authHashAlg, &key.b, SESSION_KEY, &session->nonceTPM.b, &nonceCaller->b, session->sessionKey.t.size * 8, session->sessionKey.t.buffer, NULL, FALSE); } // Copy the name of the entity that the HMAC session is bound to // Policy session is not bound to an entity if(bind != TPM_RH_NULL && sessionType == TPM_SE_HMAC) { session->attributes.isBound = SET; SessionComputeBoundEntity(bind, &session->u1.boundEntity); } // If there is a bind object and it is subject to DA, then use of this session // is subject to DA regardless of how it is used. session->attributes.isDaBound = (bind != TPM_RH_NULL) && (IsDAExempted(bind) == FALSE); // If the session is bound, then check to see if it is bound to lockoutAuth session->attributes.isLockoutBound = (session->attributes.isDaBound == SET) && (bind == TPM_RH_LOCKOUT); return TPM_RC_SUCCESS; } /* 8.9.6.3 SessionContextSave() */ /* This function is called when a session context is to be saved. The contextID of the saved session is returned. If no contextID can be assigned, then the routine returns TPM_RC_CONTEXT_GAP. If the function completes normally, the session slot will be freed. */ /* This function requires that handle references a loaded session. Otherwise, it should not be called at the first place. */ /* Error Returns Meaning */ /* TPM_RC_CONTEXT_GAP a contextID could not be assigned. */ /* TPM_RC_TOO_MANY_CONTEXTS the counter maxed out */ TPM_RC SessionContextSave( TPM_HANDLE handle, // IN: session handle CONTEXT_COUNTER *contextID // OUT: assigned contextID ) { UINT32 contextIndex; CONTEXT_SLOT slotIndex; pAssert(SessionIsLoaded(handle)); pAssert(s_ContextSlotMask == 0xff || s_ContextSlotMask == 0xffff); // libtpms added // check to see if the gap is already maxed out // Need to have a saved session if(s_oldestSavedSession < MAX_ACTIVE_SESSIONS // if the oldest saved session has the same value as the low bits // of the contextCounter, then the GAP is maxed out. && gr.contextArray[s_oldestSavedSession] == CONTEXT_SLOT_MASKED(gr.contextCounter)) // libtpms changed return TPM_RC_CONTEXT_GAP; // if the caller wants the context counter, set it if(contextID != NULL) *contextID = gr.contextCounter; contextIndex = handle & HR_HANDLE_MASK; pAssert(contextIndex < MAX_ACTIVE_SESSIONS); // Extract the session slot number referenced by the contextArray // because we are going to overwrite this with the low order // contextID value. slotIndex = gr.contextArray[contextIndex] - 1; // Set the contextID for the contextArray gr.contextArray[contextIndex] = CONTEXT_SLOT_MASKED(gr.contextCounter); // libtpms changed // Increment the counter gr.contextCounter++; // In the unlikely event that the 64-bit context counter rolls over... if(gr.contextCounter == 0) { // back it up gr.contextCounter--; // return an error return TPM_RC_TOO_MANY_CONTEXTS; } // if the low-order bits wrapped, need to advance the value to skip over // the values used to indicate that a session is loaded if(CONTEXT_SLOT_MASKED(gr.contextCounter) == 0) // libtpms changed gr.contextCounter += MAX_LOADED_SESSIONS + 1; // If no other sessions are saved, this is now the oldest. if(s_oldestSavedSession >= MAX_ACTIVE_SESSIONS) s_oldestSavedSession = contextIndex; // Mark the session slot as unoccupied s_sessions[slotIndex].occupied = FALSE; // and indicate that there is an additional open slot s_freeSessionSlots++; return TPM_RC_SUCCESS; } /* 8.9.6.4 SessionContextLoad() */ /* This function is used to load a session from saved context. The session handle must be for a saved context. */ /* If the gap is at a maximum, then the only session that can be loaded is the oldest session, otherwise TPM_RC_CONTEXT_GAP is returned. */ /* This function requires that handle references a valid saved session. */ /* Error Returns Meaning */ /* TPM_RC_SESSION_MEMORY no free session slots */ /* TPM_RC_CONTEXT_GAP the gap count is maximum and this is not the oldest saved context */ TPM_RC SessionContextLoad( SESSION_BUF *session, // IN: session structure from saved context TPM_HANDLE *handle // IN/OUT: session handle ) { UINT32 contextIndex; CONTEXT_SLOT slotIndex; pAssert(s_ContextSlotMask == 0xff || s_ContextSlotMask == 0xffff); // libtpms added pAssert(HandleGetType(*handle) == TPM_HT_POLICY_SESSION || HandleGetType(*handle) == TPM_HT_HMAC_SESSION); // Don't bother looking if no openings if(s_freeSessionSlots == 0) return TPM_RC_SESSION_MEMORY; // Find a free session slot to load the session for(slotIndex = 0; slotIndex < MAX_LOADED_SESSIONS; slotIndex++) if(s_sessions[slotIndex].occupied == FALSE) break; // if no spot found, then this is an internal error pAssert(slotIndex < MAX_LOADED_SESSIONS); // libtpms: besides the s_freeSessionSlots guard add another array index guard if (slotIndex >= MAX_LOADED_SESSIONS) { // libtpms added begin; cppcheck FAIL(FATAL_ERROR_INTERNAL); // should never get here due to longjmp in FAIL() return TPM_RC_FAILURE; } // libtpms added end contextIndex = *handle & HR_HANDLE_MASK; // extract the index // If there is only one slot left, and the gap is at maximum, the only session // context that we can safely load is the oldest one. if(s_oldestSavedSession < MAX_ACTIVE_SESSIONS && s_freeSessionSlots == 1 && CONTEXT_SLOT_MASKED(gr.contextCounter) == gr.contextArray[s_oldestSavedSession] // libtpms changed && contextIndex != s_oldestSavedSession) return TPM_RC_CONTEXT_GAP; pAssert(contextIndex < MAX_ACTIVE_SESSIONS); // set the contextArray value to point to the session slot where // the context is loaded gr.contextArray[contextIndex] = slotIndex + 1; // if this was the oldest context, find the new oldest if(contextIndex == s_oldestSavedSession) ContextIdSetOldest(); // Copy session data to session slot MemoryCopy(&s_sessions[slotIndex].session, session, sizeof(SESSION)); // Set session slot as occupied s_sessions[slotIndex].occupied = TRUE; // Reduce the number of open spots s_freeSessionSlots--; return TPM_RC_SUCCESS; } /* 8.9.6.5 SessionFlush() */ /* This function is used to flush a session referenced by its handle. If the session associated with handle is loaded, the session array entry is marked as available. */ /* This function requires that handle be a valid active session. */ void SessionFlush( TPM_HANDLE handle // IN: loaded or saved session handle ) { CONTEXT_SLOT slotIndex; UINT32 contextIndex; // Index into contextArray pAssert((HandleGetType(handle) == TPM_HT_POLICY_SESSION || HandleGetType(handle) == TPM_HT_HMAC_SESSION ) && (SessionIsLoaded(handle) || SessionIsSaved(handle)) ); // Flush context ID of this session // Convert handle to an index into the contextArray contextIndex = handle & HR_HANDLE_MASK; pAssert(contextIndex < sizeof(gr.contextArray) / sizeof(gr.contextArray[0])); // Get the current contents of the array slotIndex = gr.contextArray[contextIndex]; // Mark context array entry as available gr.contextArray[contextIndex] = 0; // Is this a saved session being flushed if(slotIndex > MAX_LOADED_SESSIONS) { // Flushing the oldest session? if(contextIndex == s_oldestSavedSession) // If so, find a new value for oldest. ContextIdSetOldest(); } else { // Adjust slot index to point to session array index slotIndex -= 1; // Free session array index s_sessions[slotIndex].occupied = FALSE; s_freeSessionSlots++; } return; } /* 8.9.6.6 SessionComputeBoundEntity() */ /* This function computes the binding value for a session. The binding value for a reserved handle is the handle itself. For all the other entities, the authValue at the time of binding is included to prevent squatting. For those values, the Name and the authValue are concatenated into the bind buffer. If they will not both fit, the will be overlapped by XORing() bytes. If XOR is required, the bind value will be full. */ void SessionComputeBoundEntity( TPMI_DH_ENTITY entityHandle, // IN: handle of entity TPM2B_NAME *bind // OUT: binding value ) { TPM2B_AUTH auth; BYTE *pAuth = auth.t.buffer; UINT16 i; // Get name EntityGetName(entityHandle, bind); // // The bound value of a reserved handle is the handle itself // if(bind->t.size == sizeof(TPM_HANDLE)) return; // For all the other entities, concatenate the authorization value to the name. // Get a local copy of the authorization value because some overlapping // may be necessary. EntityGetAuthValue(entityHandle, &auth); // Make sure that the extra space is zeroed MemorySet(&bind->t.name[bind->t.size], 0, sizeof(bind->t.name) - bind->t.size); // XOR the authValue at the end of the name for(i = sizeof(bind->t.name) - auth.t.size; i < sizeof(bind->t.name); i++) bind->t.name[i] ^= *pAuth++; // Set the bind value to the maximum size bind->t.size = sizeof(bind->t.name); return; } /* 8.9.6.7 SessionSetStartTime() */ /* This function is used to initialize the session timing */ void SessionSetStartTime( SESSION *session // IN: the session to update ) { session->startTime = g_time; session->epoch = g_timeEpoch; session->timeout = 0; } /* 8.9.6.8 SessionResetPolicyData() */ /* This function is used to reset the policy data without changing the nonce or the start time of the session. */ void SessionResetPolicyData( SESSION *session // IN: the session to reset ) { SESSION_ATTRIBUTES oldAttributes; pAssert(session != NULL); // Will need later oldAttributes = session->attributes; // No command session->commandCode = 0; // No locality selected MemorySet(&session->commandLocality, 0, sizeof(session->commandLocality)); // The cpHash size to zero session->u1.cpHash.b.size = 0; // No timeout session->timeout = 0; // Reset the pcrCounter session->pcrCounter = 0; // Reset the policy hash MemorySet(&session->u2.policyDigest.t.buffer, 0, session->u2.policyDigest.t.size); // Reset the session attributes MemorySet(&session->attributes, 0, sizeof(SESSION_ATTRIBUTES)); // Restore the policy attributes session->attributes.isPolicy = SET; session->attributes.isTrialPolicy = oldAttributes.isTrialPolicy; // Restore the bind attributes session->attributes.isDaBound = oldAttributes.isDaBound; session->attributes.isLockoutBound = oldAttributes.isLockoutBound; } /* 8.9.6.9 SessionCapGetLoaded() */ /* This function returns a list of handles of loaded session, started from input handle */ /* Handle must be in valid loaded session handle range, but does not have to point to a loaded session. */ /* Return Values Meaning */ /* YES if there are more handles available */ /* NO all the available handles has been returned */ TPMI_YES_NO SessionCapGetLoaded( TPMI_SH_POLICY handle, // IN: start handle UINT32 count, // IN: count of returned handles TPML_HANDLE *handleList // OUT: list of handle ) { TPMI_YES_NO more = NO; UINT32 i; pAssert(HandleGetType(handle) == TPM_HT_LOADED_SESSION); // Initialize output handle list handleList->count = 0; // The maximum count of handles we may return is MAX_CAP_HANDLES if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES; // Iterate session context ID slots to get loaded session handles for(i = handle & HR_HANDLE_MASK; i < MAX_ACTIVE_SESSIONS; i++) { // If session is active if(gr.contextArray[i] != 0) { // If session is loaded if(gr.contextArray[i] <= MAX_LOADED_SESSIONS) { if(handleList->count < count) { SESSION *session; // If we have not filled up the return list, add this // session handle to it // assume that this is going to be an HMAC session handle = i + HMAC_SESSION_FIRST; session = SessionGet(handle); if(session->attributes.isPolicy) handle = i + POLICY_SESSION_FIRST; handleList->handle[handleList->count] = handle; handleList->count++; } else { // If the return list is full but we still have loaded object // available, report this and stop iterating more = YES; break; } } } } return more; } /* 8.9.6.10 SessionCapGetSaved() */ /* This function returns a list of handles for saved session, starting at handle. */ /* Handle must be in a valid handle range, but does not have to point to a saved session */ /* Return Values Meaning */ /* YES if there are more handles available */ /* NO all the available handles has been returned */ TPMI_YES_NO SessionCapGetSaved( TPMI_SH_HMAC handle, // IN: start handle UINT32 count, // IN: count of returned handles TPML_HANDLE *handleList // OUT: list of handle ) { TPMI_YES_NO more = NO; UINT32 i; #ifdef TPM_HT_SAVED_SESSION pAssert(HandleGetType(handle) == TPM_HT_SAVED_SESSION); #else pAssert(HandleGetType(handle) == TPM_HT_ACTIVE_SESSION); #endif // Initialize output handle list handleList->count = 0; // The maximum count of handles we may return is MAX_CAP_HANDLES if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES; // Iterate session context ID slots to get loaded session handles for(i = handle & HR_HANDLE_MASK; i < MAX_ACTIVE_SESSIONS; i++) { // If session is active if(gr.contextArray[i] != 0) { // If session is saved if(gr.contextArray[i] > MAX_LOADED_SESSIONS) { if(handleList->count < count) { // If we have not filled up the return list, add this // session handle to it handleList->handle[handleList->count] = i + HMAC_SESSION_FIRST; handleList->count++; } else { // If the return list is full but we still have loaded object // available, report this and stop iterating more = YES; break; } } } } return more; } /* 8.9.6.11 SessionCapGetLoadedNumber() */ /* This function return the number of authorization sessions currently loaded into TPM RAM. */ UINT32 SessionCapGetLoadedNumber( void ) { return MAX_LOADED_SESSIONS - s_freeSessionSlots; } /* 8.9.6.12 SessionCapGetLoadedAvail() */ /* This function returns the number of additional authorization sessions, of any type, that could be loaded into TPM RAM. */ /* NOTE: In other implementations, this number may just be an estimate. The only requirement for the estimate is, if it is one or more, then at least one session must be loadable. */ UINT32 SessionCapGetLoadedAvail( void ) { return s_freeSessionSlots; } /* 8.9.6.13 SessionCapGetActiveNumber() */ /* This function returns the number of active authorization sessions currently being tracked by the TPM. */ UINT32 SessionCapGetActiveNumber( void ) { UINT32 i; UINT32 num = 0; // Iterate the context array to find the number of non-zero slots for(i = 0; i < MAX_ACTIVE_SESSIONS; i++) { if(gr.contextArray[i] != 0) num++; } return num; } /* 8.9.6.14 SessionCapGetActiveAvail() */ /* This function returns the number of additional authorization sessions, of any type, that could be created. This not the number of slots for sessions, but the number of additional sessions that the TPM is capable of tracking. */ UINT32 SessionCapGetActiveAvail( void ) { UINT32 i; UINT32 num = 0; // Iterate the context array to find the number of zero slots for(i = 0; i < MAX_ACTIVE_SESSIONS; i++) { if(gr.contextArray[i] == 0) num++; } return num; } libtpms-0.9.3/src/tpm2/SessionCommands.c000066400000000000000000000200101421143571500201130ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Session Commands */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: SessionCommands.c 1519 2019-11-15 20:43:51Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ #include "Tpm.h" #include "StartAuthSession_fp.h" #if CC_StartAuthSession // Conditional expansion of this file TPM_RC TPM2_StartAuthSession( StartAuthSession_In *in, // IN: input parameter buffer StartAuthSession_Out *out // OUT: output parameter buffer ) { TPM_RC result = TPM_RC_SUCCESS; OBJECT *tpmKey; // TPM key for decrypt salt TPM2B_DATA salt; // Input Validation // Check input nonce size. IT should be at least 16 bytes but not larger // than the digest size of session hash. if(in->nonceCaller.t.size < 16 || in->nonceCaller.t.size > CryptHashGetDigestSize(in->authHash)) return TPM_RCS_SIZE + RC_StartAuthSession_nonceCaller; // If an decrypt key is passed in, check its validation if(in->tpmKey != TPM_RH_NULL) { // Get pointer to loaded decrypt key tpmKey = HandleToObject(in->tpmKey); // key must be asymmetric with its sensitive area loaded. Since this // command does not require authorization, the presence of the sensitive // area was not already checked as it is with most other commands that // use the sensitive are so check it here if(!CryptIsAsymAlgorithm(tpmKey->publicArea.type)) return TPM_RCS_KEY + RC_StartAuthSession_tpmKey; // secret size cannot be 0 if(in->encryptedSalt.t.size == 0) return TPM_RCS_VALUE + RC_StartAuthSession_encryptedSalt; // Decrypting salt requires accessing the private portion of a key. // Therefore, tmpKey can not be a key with only public portion loaded if(tpmKey->attributes.publicOnly) return TPM_RCS_HANDLE + RC_StartAuthSession_tpmKey; // HMAC session input handle check. // tpmKey should be a decryption key if(!IS_ATTRIBUTE(tpmKey->publicArea.objectAttributes, TPMA_OBJECT, decrypt)) return TPM_RCS_ATTRIBUTES + RC_StartAuthSession_tpmKey; // Secret Decryption. A TPM_RC_VALUE, TPM_RC_KEY or Unmarshal errors // may be returned at this point result = CryptSecretDecrypt(tpmKey, &in->nonceCaller, SECRET_KEY, &in->encryptedSalt, &salt); if(result != TPM_RC_SUCCESS) return TPM_RCS_VALUE + RC_StartAuthSession_encryptedSalt; } else { // secret size must be 0 if(in->encryptedSalt.t.size != 0) return TPM_RCS_VALUE + RC_StartAuthSession_encryptedSalt; salt.t.size = 0; } switch(HandleGetType(in->bind)) { case TPM_HT_TRANSIENT: { OBJECT *object = HandleToObject(in->bind); // If the bind handle references a transient object, make sure that we // can get to the authorization value. Also, make sure that the object // has a proper Name (nameAlg != TPM_ALG_NULL). If it doesn't, then // it might be possible to bind to an object where the authValue is // known. This does not create a real issue in that, if you know the // authorization value, you can actually bind to the object. However, // there is a potential if(object->attributes.publicOnly == SET) return TPM_RCS_HANDLE + RC_StartAuthSession_bind; break; } case TPM_HT_NV_INDEX: // a PIN index can't be a bind object { NV_INDEX *nvIndex = NvGetIndexInfo(in->bind, NULL); if(IsNvPinPassIndex(nvIndex->publicArea.attributes) || IsNvPinFailIndex(nvIndex->publicArea.attributes)) return TPM_RCS_HANDLE + RC_StartAuthSession_bind; break; } default: break; } // If 'symmetric' is a symmetric block cipher (not TPM_ALG_NULL or TPM_ALG_XOR) // then the mode must be CFB. if(in->symmetric.algorithm != TPM_ALG_NULL && in->symmetric.algorithm != TPM_ALG_XOR && in->symmetric.mode.sym != TPM_ALG_CFB) return TPM_RCS_MODE + RC_StartAuthSession_symmetric; // Internal Data Update and command output // Create internal session structure. TPM_RC_CONTEXT_GAP, TPM_RC_NO_HANDLES // or TPM_RC_SESSION_MEMORY errors may be returned at this point. // // The detailed actions for creating the session context are not shown here // as the details are implementation dependent // SessionCreate sets the output handle and nonceTPM result = SessionCreate(in->sessionType, in->authHash, &in->nonceCaller, &in->symmetric, in->bind, &salt, &out->sessionHandle, &out->nonceTPM); return result; } #endif // CC_StartAuthSession #include "Tpm.h" #include "PolicyRestart_fp.h" #if CC_PolicyRestart // Conditional expansion of this file TPM_RC TPM2_PolicyRestart( PolicyRestart_In *in // IN: input parameter list ) { // Initialize policy session data SessionResetPolicyData(SessionGet(in->sessionHandle)); return TPM_RC_SUCCESS; } #endif // CC_PolicyRestart libtpms-0.9.3/src/tpm2/SessionProcess.c000066400000000000000000002253771421143571500200170ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Process the Authorization Sessions */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: SessionProcess.c 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2021 */ /* */ /********************************************************************************/ /* 6.4 SessionProcess.c */ /* 6.4.1 Introduction */ /* This file contains the subsystem that process the authorization sessions including implementation of the Dictionary Attack logic. ExecCommand() uses ParseSessionBuffer() to process the authorization session area of a command and BuildResponseSession() to create the authorization session area of a response */ #define SESSION_PROCESS_C #include "Tpm.h" #include "ACT.h" /* 6.4.3.1 IsDAExempted() */ /* This function indicates if a handle is exempted from DA logic. A handle is exempted if it is */ /* a) a primary seed handle, */ /* b) an object with noDA bit SET, */ /* c) an NV Index with TPMA_NV_NO_DA bit SET, or */ /* d) a PCR handle. */ BOOL IsDAExempted( TPM_HANDLE handle // IN: entity handle ) { BOOL result = FALSE; // switch(HandleGetType(handle)) { case TPM_HT_PERMANENT: // All permanent handles, other than TPM_RH_LOCKOUT, are exempt from // DA protection. result = (handle != TPM_RH_LOCKOUT); break; // When this function is called, a persistent object will have been loaded // into an object slot and assigned a transient handle. case TPM_HT_TRANSIENT: { TPMA_OBJECT attributes = ObjectGetPublicAttributes(handle); result = IS_ATTRIBUTE(attributes, TPMA_OBJECT, noDA); break; } case TPM_HT_NV_INDEX: { NV_INDEX *nvIndex = NvGetIndexInfo(handle, NULL); result = IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, NO_DA); break; } case TPM_HT_PCR: // PCRs are always exempted from DA. result = TRUE; break; default: break; } return result; } /* 6.4.3.2 IncrementLockout() */ /* This function is called after an authorization failure that involves use of an authValue. If the entity referenced by the handle is not exempt from DA protection, then the failedTries counter will be incremented. */ static TPM_RC IncrementLockout( UINT32 sessionIndex ) { TPM_HANDLE handle = s_associatedHandles[sessionIndex]; TPM_HANDLE sessionHandle = s_sessionHandles[sessionIndex]; SESSION *session = NULL; // // Don't increment lockout unless the handle associated with the session // is DA protected or the session is bound to a DA protected entity. if(sessionHandle == TPM_RS_PW) { if(IsDAExempted(handle)) return TPM_RC_BAD_AUTH; } else { session = SessionGet(sessionHandle); // If the session is bound to lockout, then use that as the relevant // handle. This means that an authorization failure with a bound session // bound to lockoutAuth will take precedence over any other // lockout check if(session->attributes.isLockoutBound == SET) handle = TPM_RH_LOCKOUT; if(session->attributes.isDaBound == CLEAR && (IsDAExempted(handle) || session->attributes.includeAuth == CLEAR)) // If the handle was changed to TPM_RH_LOCKOUT, this will not return // TPM_RC_BAD_AUTH return TPM_RC_BAD_AUTH; } if(handle == TPM_RH_LOCKOUT) { pAssert(gp.lockOutAuthEnabled == TRUE); // lockout is no longer enabled gp.lockOutAuthEnabled = FALSE; // For TPM_RH_LOCKOUT, if lockoutRecovery is 0, no need to update NV since // the lockout authorization will be reset at startup. if(gp.lockoutRecovery != 0) { if(NV_IS_AVAILABLE) // Update NV. NV_SYNC_PERSISTENT(lockOutAuthEnabled); else // No NV access for now. Put the TPM in pending mode. s_DAPendingOnNV = TRUE; } } else { if(gp.recoveryTime != 0) { gp.failedTries++; if(NV_IS_AVAILABLE) // Record changes to NV. NvWrite will SET g_updateNV NV_SYNC_PERSISTENT(failedTries); else // No NV access for now. Put the TPM in pending mode. s_DAPendingOnNV = TRUE; } } // Register a DA failure and reset the timers. DARegisterFailure(handle); return TPM_RC_AUTH_FAIL; } /* 6.4.3.3 IsSessionBindEntity() */ /* This function indicates if the entity associated with the handle is the entity, to which this session is bound. The binding would occur by making the bind parameter in TPM2_StartAuthSession() not equal to TPM_RH_NULL. The binding only occurs if the session is an HMAC session. The bind value is a combination of the Name and the authValue of the entity. */ static BOOL IsSessionBindEntity( TPM_HANDLE associatedHandle, // IN: handle to be authorized SESSION *session // IN: associated session ) { TPM2B_NAME entity; // The bind value for the entity // If the session is not bound, return FALSE. if(session->attributes.isBound) { // Compute the bind value for the entity. SessionComputeBoundEntity(associatedHandle, &entity); // Compare to the bind value in the session. return MemoryEqual2B(&entity.b, &session->u1.boundEntity.b); } return FALSE; } /* 6.4.3.4 IsPolicySessionRequired() */ /* Checks if a policy session is required for a command. If a command requires DUP or ADMIN role authorization, then the handle that requires that role is the first handle in the command. This simplifies this checking. If a new command is created that requires multiple ADMIN role authorizations, then it will have to be special-cased in this function. A policy session is required if: */ /* a) the command requires the DUP role, */ /* b) the command requires the ADMIN role and the authorized entity is an object and its adminWithPolicy bit is SET, or */ /* c) the command requires the ADMIN role and the authorized entity is a permanent handle or an NV Index. */ /* d) The authorized entity is a PCR belonging to a policy group, and has its policy initialized */ /* Return Values Meaning */ /* TRUE policy session is required */ /* FALSE policy session is not required */ static BOOL IsPolicySessionRequired( COMMAND_INDEX commandIndex, // IN: command index UINT32 sessionIndex // IN: session index ) { AUTH_ROLE role = CommandAuthRole(commandIndex, sessionIndex); TPM_HT type = HandleGetType(s_associatedHandles[sessionIndex]); if(role == AUTH_DUP) return TRUE; if(role == AUTH_ADMIN) { // We allow an exception for ADMIN role in a transient object. If the object // allows ADMIN role actions with authorization, then policy is not // required. For all other cases, there is no way to override the command // requirement that a policy be used if(type == TPM_HT_TRANSIENT) { OBJECT *object = HandleToObject(s_associatedHandles[sessionIndex]); if(!IS_ATTRIBUTE(object->publicArea.objectAttributes, TPMA_OBJECT, adminWithPolicy)) return FALSE; } return TRUE; } if(type == TPM_HT_PCR) { if(PCRPolicyIsAvailable(s_associatedHandles[sessionIndex])) { TPM2B_DIGEST policy; TPMI_ALG_HASH policyAlg; policyAlg = PCRGetAuthPolicy(s_associatedHandles[sessionIndex], &policy); if(policyAlg != TPM_ALG_NULL) return TRUE; } } return FALSE; } /* 6.4.3.5 IsAuthValueAvailable() */ /* This function indicates if authValue is available and allowed for USER role authorization of an entity. */ /* This function is similar to IsAuthPolicyAvailable() except that it does not check the size of the authValue as IsAuthPolicyAvailable() does (a null authValue is a valid authorization, but a null policy is not a valid policy). */ /* This function does not check that the handle reference is valid or if the entity is in an enabled hierarchy. Those checks are assumed to have been performed during the handle unmarshaling. */ static BOOL IsAuthValueAvailable( TPM_HANDLE handle, // IN: handle of entity COMMAND_INDEX commandIndex, // IN: command index UINT32 sessionIndex // IN: session index ) { BOOL result = FALSE; // switch(HandleGetType(handle)) { case TPM_HT_PERMANENT: switch(handle) { // At this point hierarchy availability has already been // checked so primary seed handles are always available here case TPM_RH_OWNER: case TPM_RH_ENDORSEMENT: case TPM_RH_PLATFORM: #ifdef VENDOR_PERMANENT // This vendor defined handle associated with the // manufacturer's shared secret case VENDOR_PERMANENT: #endif // The DA checking has been performed on LockoutAuth but we // bypass the DA logic if we are using lockout policy. The // policy would allow execution to continue an lockoutAuth // could be used, even if direct use of lockoutAuth is disabled case TPM_RH_LOCKOUT: // NullAuth is always available. case TPM_RH_NULL: result = TRUE; break; #ifndef __ACT_DISABLED // libtpms added begin FOR_EACH_ACT(CASE_ACT_HANDLE) { // The ACT auth value is not available if the platform is disabled result = g_phEnable == SET; break; } #endif // libtpms added end default: // Otherwise authValue is not available. break; } break; case TPM_HT_TRANSIENT: // A persistent object has already been loaded and the internal // handle changed. { OBJECT *object; TPMA_OBJECT attributes; // object = HandleToObject(handle); attributes = object->publicArea.objectAttributes; // authValue is always available for a sequence object. // An alternative for this is to // SET_ATTRIBUTE(object->publicArea, TPMA_OBJECT, userWithAuth) when the // sequence is started. if(ObjectIsSequence(object)) { result = TRUE; break; } // authValue is available for an object if it has its sensitive // portion loaded and // 1. userWithAuth bit is SET, or // 2. ADMIN role is required if(object->attributes.publicOnly == CLEAR && (IS_ATTRIBUTE(attributes, TPMA_OBJECT, userWithAuth) || (CommandAuthRole(commandIndex, sessionIndex) == AUTH_ADMIN && !IS_ATTRIBUTE(attributes, TPMA_OBJECT, adminWithPolicy)))) result = TRUE; } break; case TPM_HT_NV_INDEX: // NV Index. { NV_REF locator; NV_INDEX *nvIndex = NvGetIndexInfo(handle, &locator); TPMA_NV nvAttributes; // pAssert(nvIndex != 0); nvAttributes = nvIndex->publicArea.attributes; if(IsWriteOperation(commandIndex)) { // AuthWrite can't be set for a PIN index if(IS_ATTRIBUTE(nvAttributes, TPMA_NV, AUTHWRITE)) result = TRUE; } else { // A "read" operation // For a PIN Index, the authValue is available as long as the // Index has been written and the pinCount is less than pinLimit if(IsNvPinFailIndex(nvAttributes) || IsNvPinPassIndex(nvAttributes)) { NV_PIN pin; if(!IS_ATTRIBUTE(nvAttributes, TPMA_NV, WRITTEN)) break; // return false // get the index values pin.intVal = NvGetUINT64Data(nvIndex, locator); if(pin.pin.pinCount < pin.pin.pinLimit) result = TRUE; } // For non-PIN Indexes, need to allow use of the authValue else if(IS_ATTRIBUTE(nvAttributes, TPMA_NV, AUTHREAD)) result = TRUE; } } break; case TPM_HT_PCR: // PCR handle. // authValue is always allowed for PCR result = TRUE; break; default: // Otherwise, authValue is not available break; } return result; } /* 6.4.3.6 IsAuthPolicyAvailable() */ /* This function indicates if an authPolicy is available and allowed. */ /* This function does not check that the handle reference is valid or if the entity is in an enabled hierarchy. Those checks are assumed to have been performed during the handle unmarshaling. */ /* Return Values Meaning */ /* TRUE authPolicy is available */ /* FALSE authPolicy is not available */ static BOOL IsAuthPolicyAvailable( TPM_HANDLE handle, // IN: handle of entity COMMAND_INDEX commandIndex, // IN: command index UINT32 sessionIndex // IN: session index ) { BOOL result = FALSE; // switch(HandleGetType(handle)) { case TPM_HT_PERMANENT: switch(handle) { // At this point hierarchy availability has already been checked. case TPM_RH_OWNER: if(gp.ownerPolicy.t.size != 0) result = TRUE; break; case TPM_RH_ENDORSEMENT: if(gp.endorsementPolicy.t.size != 0) result = TRUE; break; case TPM_RH_PLATFORM: if(gc.platformPolicy.t.size != 0) result = TRUE; break; #define ACT_GET_POLICY(N) \ case TPM_RH_ACT_##N: \ if(go.ACT_##N.authPolicy.t.size != 0) \ result = TRUE; \ break; FOR_EACH_ACT(ACT_GET_POLICY) case TPM_RH_LOCKOUT: if(gp.lockoutPolicy.t.size != 0) result = TRUE; break; default: break; } break; case TPM_HT_TRANSIENT: { // Object handle. // An evict object would already have been loaded and given a // transient object handle by this point. OBJECT *object = HandleToObject(handle); // Policy authorization is not available for an object with only // public portion loaded. if(object->attributes.publicOnly == CLEAR) { // Policy authorization is always available for an object but // is never available for a sequence. if(!ObjectIsSequence(object)) result = TRUE; } break; } case TPM_HT_NV_INDEX: // An NV Index. { NV_INDEX *nvIndex = NvGetIndexInfo(handle, NULL); TPMA_NV nvAttributes = nvIndex->publicArea.attributes; // // If the policy size is not zero, check if policy can be used. if(nvIndex->publicArea.authPolicy.t.size != 0) { // If policy session is required for this handle, always // uses policy regardless of the attributes bit setting if(IsPolicySessionRequired(commandIndex, sessionIndex)) result = TRUE; // Otherwise, the presence of the policy depends on the NV // attributes. else if(IsWriteOperation(commandIndex)) { if(IS_ATTRIBUTE(nvAttributes, TPMA_NV, POLICYWRITE)) result = TRUE; } else { if(IS_ATTRIBUTE(nvAttributes, TPMA_NV, POLICYREAD)) result = TRUE; } } } break; case TPM_HT_PCR: // PCR handle. if(PCRPolicyIsAvailable(handle)) result = TRUE; break; default: break; } return result; } /* 6.4.4 Session Parsing Functions */ /* 6.4.4.1 ClearCpRpHashes() */ void ClearCpRpHashes( COMMAND *command ) { // The macros expand according to the implemented hash algorithms. An IDE may // complain that COMMAND does not contain SHA1CpHash or SHA1RpHash because of the // complexity of the macro expansion where the data space is defined; but, if SHA1 // is implemented, it actually does and the compiler is happy. #define CLEAR_CP_HASH(HASH, Hash) command->Hash##CpHash.b.size = 0; FOR_EACH_HASH(CLEAR_CP_HASH) #define CLEAR_RP_HASH(HASH, Hash) command->Hash##RpHash.b.size = 0; FOR_EACH_HASH(CLEAR_RP_HASH) } /* 6.4.4.2 GetCpHashPointer() */ /* Function to get a pointer to the cpHash of the command */ static TPM2B_DIGEST * GetCpHashPointer( COMMAND *command, TPMI_ALG_HASH hashAlg ) { TPM2B_DIGEST *retVal; // // Define the macro that will expand for each implemented algorithm in the switch // statement below. #define GET_CP_HASH_POINTER(HASH, Hash) \ case ALG_##HASH##_VALUE: \ retVal = (TPM2B_DIGEST *)&command->Hash##CpHash; \ break; switch(hashAlg) { // For each implemented hash, this will expand as defined above // by GET_CP_HASH_POINTER. Your IDE may complain that // 'struct "COMMAND" has no field "SHA1CpHash"' but the compiler says // it does, so... FOR_EACH_HASH(GET_CP_HASH_POINTER) default: retVal = NULL; break; } return retVal; } /* 6.4.4.3 GetRpHashPointer() */ /* Function to get a pointer to the RpHash() of the command */ static TPM2B_DIGEST * GetRpHashPointer( COMMAND *command, TPMI_ALG_HASH hashAlg ) { TPM2B_DIGEST *retVal; // // Define the macro that will expand for each implemented algorithm in the switch // statement below. #define GET_RP_HASH_POINTER(HASH, Hash) \ case ALG_##HASH##_VALUE: \ retVal = (TPM2B_DIGEST *)&command->Hash##RpHash; \ break; switch(hashAlg) { // For each implemented hash, this will expand as defined above // by GET_RP_HASH_POINTER. Your IDE may complain that // 'struct "COMMAND" has no field 'SHA1RpHash'" but the compiler says // it does, so... FOR_EACH_HASH(GET_RP_HASH_POINTER) default: retVal = NULL; break; } return retVal; } /* 6.4.4.4 ComputeCpHash() */ /* This function computes the cpHash as defined in Part 2 and described in Part 1. */ static TPM2B_DIGEST * ComputeCpHash( COMMAND *command, // IN: command parsing structure TPMI_ALG_HASH hashAlg // IN: hash algorithm ) { UINT32 i; HASH_STATE hashState; TPM2B_NAME name; TPM2B_DIGEST *cpHash; // cpHash = hash(commandCode [ || authName1 // [ || authName2 // [ || authName 3 ]]] // [ || parameters]) // A cpHash can contain just a commandCode only if the lone session is // an audit session. // Get pointer to the hash value cpHash = GetCpHashPointer(command, hashAlg); if(cpHash->t.size == 0) { cpHash->t.size = CryptHashStart(&hashState, hashAlg); // Add commandCode. CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), command->code); // Add authNames for each of the handles. for(i = 0; i < command->handleNum; i++) CryptDigestUpdate2B(&hashState, &EntityGetName(command->handles[i], &name)->b); // Add the parameters. CryptDigestUpdate(&hashState, command->parameterSize, command->parameterBuffer); // Complete the hash. CryptHashEnd2B(&hashState, &cpHash->b); } return cpHash; } /* 6.4.4.5 GetCpHash() */ /* This function is used to access a precomputed cpHash. */ static TPM2B_DIGEST * GetCpHash( COMMAND *command, TPMI_ALG_HASH hashAlg ) { TPM2B_DIGEST *cpHash = GetCpHashPointer(command, hashAlg); // pAssert(cpHash->t.size != 0); return cpHash; } /* 6.4.4.6 CompareTemplateHash() */ /* This function computes the template hash and compares it to the session templateHash. It is the hash of the second parameter assuming that the command is TPM2_Create(), TPM2_CreatePrimary(), or TPM2_CreateLoaded() */ static BOOL CompareTemplateHash( COMMAND *command, // IN: parsing structure SESSION *session // IN: session data ) { BYTE *pBuffer = command->parameterBuffer; INT32 pSize = command->parameterSize; TPM2B_DIGEST tHash; UINT16 size; // // Only try this for the three commands for which it is intended if(command->code != TPM_CC_Create && command->code != TPM_CC_CreatePrimary #if CC_CreateLoaded && command->code != TPM_CC_CreateLoaded #endif ) return FALSE; // Assume that the first parameter is a TPM2B and unmarshal the size field // Note: this will not affect the parameter buffer and size in the calling // function. if(UINT16_Unmarshal(&size, &pBuffer, &pSize) != TPM_RC_SUCCESS) return FALSE; // reduce the space in the buffer. // NOTE: this could make pSize go negative if the parameters are not correct but // the unmarshaling code does not try to unmarshal if the remaining size is // negative. pSize -= size; // Advance the pointer pBuffer += size; // Get the size of what should be the template if(UINT16_Unmarshal(&size, &pBuffer, &pSize) != TPM_RC_SUCCESS) return FALSE; // See if this is reasonable if(size > pSize) return FALSE; // Hash the template data tHash.t.size = CryptHashBlock(session->authHashAlg, size, pBuffer, sizeof(tHash.t.buffer), tHash.t.buffer); return(MemoryEqual2B(&session->u1.templateHash.b, &tHash.b)); } /* 6.4.4.7 CompareNameHash() */ /* This function computes the name hash and compares it to the nameHash in the session data. */ BOOL CompareNameHash( COMMAND *command, // IN: main parsing structure SESSION *session // IN: session structure with nameHash ) { HASH_STATE hashState; TPM2B_DIGEST nameHash; UINT32 i; TPM2B_NAME name; // nameHash.t.size = CryptHashStart(&hashState, session->authHashAlg); // Add names. for(i = 0; i < command->handleNum; i++) CryptDigestUpdate2B(&hashState, &EntityGetName(command->handles[i], &name)->b); // Complete hash. CryptHashEnd2B(&hashState, &nameHash.b); // and compare return MemoryEqual(session->u1.nameHash.t.buffer, nameHash.t.buffer, nameHash.t.size); } /* 6.4.4.8 CheckPWAuthSession() */ /* This function validates the authorization provided in a PWAP session. It compares the input value to authValue of the authorized entity. Argument sessionIndex is used to get handles handle of the referenced entities from s_inputAuthValues[] and s_associatedHandles[]. */ /* Error Returns Meaning */ /* TPM_RC_AUTH_FAIL authorization fails and increments DA failure count */ /* TPM_RC_BAD_AUTH authorization fails but DA does not apply */ static TPM_RC CheckPWAuthSession( UINT32 sessionIndex // IN: index of session to be processed ) { TPM2B_AUTH authValue; TPM_HANDLE associatedHandle = s_associatedHandles[sessionIndex]; // Strip trailing zeros from the password. MemoryRemoveTrailingZeros(&s_inputAuthValues[sessionIndex]); // Get the authValue with trailing zeros removed EntityGetAuthValue(associatedHandle, &authValue); // Success if the values are identical. if(MemoryEqual2B(&s_inputAuthValues[sessionIndex].b, &authValue.b)) { return TPM_RC_SUCCESS; } else // if the digests are not identical { // Invoke DA protection if applicable. return IncrementLockout(sessionIndex); } } /* 6.4.4.9 ComputeCommandHMAC() */ /* This function computes the HMAC for an authorization session in a command. */ static TPM2B_DIGEST * ComputeCommandHMAC( COMMAND *command, // IN: primary control structure UINT32 sessionIndex, // IN: index of session to be processed TPM2B_DIGEST *hmac // OUT: authorization HMAC ) { TPM2B_TYPE(KEY, (sizeof(AUTH_VALUE) * 2)); TPM2B_KEY key; BYTE marshalBuffer[sizeof(TPMA_SESSION)]; BYTE *buffer; UINT32 marshalSize; HMAC_STATE hmacState; TPM2B_NONCE *nonceDecrypt; TPM2B_NONCE *nonceEncrypt; SESSION *session; nonceDecrypt = NULL; nonceEncrypt = NULL; // Determine if extra nonceTPM values are going to be required. // If this is the first session (sessionIndex = 0) and it is an authorization // session that uses an HMAC, then check if additional session nonces are to be // included. if(sessionIndex == 0 && s_associatedHandles[sessionIndex] != TPM_RH_UNASSIGNED) { // If there is a decrypt session and if this is not the decrypt session, // then an extra nonce may be needed. if(s_decryptSessionIndex != UNDEFINED_INDEX && s_decryptSessionIndex != sessionIndex) { // Will add the nonce for the decrypt session. SESSION *decryptSession = SessionGet(s_sessionHandles[s_decryptSessionIndex]); nonceDecrypt = &decryptSession->nonceTPM; } // Now repeat for the encrypt session. if(s_encryptSessionIndex != UNDEFINED_INDEX && s_encryptSessionIndex != sessionIndex && s_encryptSessionIndex != s_decryptSessionIndex) { // Have to have the nonce for the encrypt session. SESSION *encryptSession = SessionGet(s_sessionHandles[s_encryptSessionIndex]); nonceEncrypt = &encryptSession->nonceTPM; } } // Continue with the HMAC processing. session = SessionGet(s_sessionHandles[sessionIndex]); // Generate HMAC key. MemoryCopy2B(&key.b, &session->sessionKey.b, sizeof(key.t.buffer)); // Check if the session has an associated handle and if the associated entity // is the one to which the session is bound. If not, add the authValue of // this entity to the HMAC key. // If the session is bound to the object or the session is a policy session // with no authValue required, do not include the authValue in the HMAC key. // Note: For a policy session, its isBound attribute is CLEARED. // Include the entity authValue if it is needed if(session->attributes.includeAuth == SET) { TPM2B_AUTH authValue; // Get the entity authValue with trailing zeros removed EntityGetAuthValue(s_associatedHandles[sessionIndex], &authValue); // add the authValue to the HMAC key MemoryConcat2B(&key.b, &authValue.b, sizeof(key.t.buffer)); } // if the HMAC key size is 0, a NULL string HMAC is allowed if(key.t.size == 0 && s_inputAuthValues[sessionIndex].t.size == 0) { hmac->t.size = 0; return hmac; } // Start HMAC hmac->t.size = CryptHmacStart2B(&hmacState, session->authHashAlg, &key.b); // Add cpHash CryptDigestUpdate2B(&hmacState.hashState, &ComputeCpHash(command, session->authHashAlg)->b); // Add nonces as required CryptDigestUpdate2B(&hmacState.hashState, &s_nonceCaller[sessionIndex].b); CryptDigestUpdate2B(&hmacState.hashState, &session->nonceTPM.b); if(nonceDecrypt != NULL) CryptDigestUpdate2B(&hmacState.hashState, &nonceDecrypt->b); if(nonceEncrypt != NULL) CryptDigestUpdate2B(&hmacState.hashState, &nonceEncrypt->b); // Add sessionAttributes buffer = marshalBuffer; marshalSize = TPMA_SESSION_Marshal(&(s_attributes[sessionIndex]), &buffer, NULL); CryptDigestUpdate(&hmacState.hashState, marshalSize, marshalBuffer); // Complete the HMAC computation CryptHmacEnd2B(&hmacState, &hmac->b); return hmac; } /* 6.4.4.10 CheckSessionHMAC() */ /* This function checks the HMAC of in a session. It uses ComputeCommandHMAC() to compute the expected HMAC value and then compares the result with the HMAC in the authorization session. The authorization is successful if they are the same. */ /* If the authorizations are not the same, IncrementLockout() is called. It will return TPM_RC_AUTH_FAIL if the failure caused the failureCount to increment. Otherwise, it will return TPM_RC_BAD_AUTH. */ /* Error Returns Meaning */ /* TPM_RC_AUTH_FAIL authorization failure caused failureCount increment */ /* TPM_RC_BAD_AUTH authorization failure did not cause failureCount increment */ static TPM_RC CheckSessionHMAC( COMMAND *command, // IN: primary control structure UINT32 sessionIndex // IN: index of session to be processed ) { TPM2B_DIGEST hmac; // authHMAC for comparing // Compute authHMAC ComputeCommandHMAC(command, sessionIndex, &hmac); // Compare the input HMAC with the authHMAC computed above. if(!MemoryEqual2B(&s_inputAuthValues[sessionIndex].b, &hmac.b)) { // If an HMAC session has a failure, invoke the anti-hammering // if it applies to the authorized entity or the session. // Otherwise, just indicate that the authorization is bad. return IncrementLockout(sessionIndex); } return TPM_RC_SUCCESS; } /* 6.4.4.11 CheckPolicyAuthSession() */ /* This function is used to validate the authorization in a policy session. This function performs the following comparisons to see if a policy authorization is properly provided. The check are: */ /* a) compare policyDigest in session with authPolicy associated with the entity to be authorized; */ /* b) compare timeout if applicable; */ /* c) compare commandCode if applicable; */ /* d) compare cpHash if applicable; and */ /* e) see if PCR values have changed since computed. */ /* If all the above checks succeed, the handle is authorized. The order of these comparisons is not important because any failure will result in the same error code. */ /* Error Returns Meaning */ /* TPM_RC_PCR_CHANGED PCR value is not current */ /* TPM_RC_POLICY_FAIL policy session fails */ /* TPM_RC_LOCALITY command locality is not allowed */ /* TPM_RC_POLICY_CC CC doesn't match */ /* TPM_RC_EXPIRED policy session has expired */ /* TPM_RC_PP PP is required but not asserted */ /* TPM_RC_NV_UNAVAILABLE NV is not available for write */ /* TPM_RC_NV_RATE NV is rate limiting */ static TPM_RC CheckPolicyAuthSession( COMMAND *command, // IN: primary parsing structure UINT32 sessionIndex // IN: index of session to be processed ) { SESSION *session; TPM2B_DIGEST authPolicy; TPMI_ALG_HASH policyAlg; UINT8 locality; // Initialize pointer to the authorization session. session = SessionGet(s_sessionHandles[sessionIndex]); // If the command is TPM2_PolicySecret(), make sure that // either password or authValue is required if(command->code == TPM_CC_PolicySecret && session->attributes.isPasswordNeeded == CLEAR && session->attributes.isAuthValueNeeded == CLEAR) return TPM_RC_MODE; // See if the PCR counter for the session is still valid. if(!SessionPCRValueIsCurrent(session)) return TPM_RC_PCR_CHANGED; // Get authPolicy. policyAlg = EntityGetAuthPolicy(s_associatedHandles[sessionIndex], &authPolicy); // Compare authPolicy. if(!MemoryEqual2B(&session->u2.policyDigest.b, &authPolicy.b)) return TPM_RC_POLICY_FAIL; // Policy is OK so check if the other factors are correct // Compare policy hash algorithm. if(policyAlg != session->authHashAlg) return TPM_RC_POLICY_FAIL; // Compare timeout. if(session->timeout != 0) { // Cannot compare time if clock stop advancing. An TPM_RC_NV_UNAVAILABLE // or TPM_RC_NV_RATE error may be returned here. This doesn't mean that // a new nonce will be created just that, because TPM time can't advance // we can't do time-based operations. RETURN_IF_NV_IS_NOT_AVAILABLE; if((session->timeout < g_time) || (session->epoch != g_timeEpoch)) return TPM_RC_EXPIRED; } // If command code is provided it must match if(session->commandCode != 0) { if(session->commandCode != command->code) return TPM_RC_POLICY_CC; } else { // If command requires a DUP or ADMIN authorization, the session must have // command code set. AUTH_ROLE role = CommandAuthRole(command->index, sessionIndex); if(role == AUTH_ADMIN || role == AUTH_DUP) return TPM_RC_POLICY_FAIL; } // Check command locality. { BYTE sessionLocality[sizeof(TPMA_LOCALITY)]; BYTE *buffer = sessionLocality; // Get existing locality setting in canonical form sessionLocality[0] = 0; TPMA_LOCALITY_Marshal(&session->commandLocality, &buffer, NULL); // See if the locality has been set if(sessionLocality[0] != 0) { // If so, get the current locality locality = _plat__LocalityGet(); if(locality < 5) { if(((sessionLocality[0] & (1 << locality)) == 0) || sessionLocality[0] > 31) return TPM_RC_LOCALITY; } else if(locality > 31) { if(sessionLocality[0] != locality) return TPM_RC_LOCALITY; } else { // Could throw an assert here but a locality error is just // as good. It just means that, whatever the locality is, it isn't // the locality requested so... return TPM_RC_LOCALITY; } } } // end of locality check // Check physical presence. if(session->attributes.isPPRequired == SET && !_plat__PhysicalPresenceAsserted()) return TPM_RC_PP; // Compare cpHash/nameHash if defined, or if the command requires an ADMIN or // DUP role for this handle. if(session->u1.cpHash.b.size != 0) { BOOL OK; if(session->attributes.isCpHashDefined) // Compare cpHash. OK = MemoryEqual2B(&session->u1.cpHash.b, &ComputeCpHash(command, session->authHashAlg)->b); else if(session->attributes.isTemplateSet) OK = CompareTemplateHash(command, session); else OK = CompareNameHash(command, session); if(!OK) return TPM_RCS_POLICY_FAIL; } if(session->attributes.checkNvWritten) { NV_REF locator; NV_INDEX *nvIndex; // If this is not an NV index, the policy makes no sense so fail it. if(HandleGetType(s_associatedHandles[sessionIndex]) != TPM_HT_NV_INDEX) return TPM_RC_POLICY_FAIL; // Get the index data nvIndex = NvGetIndexInfo(s_associatedHandles[sessionIndex], &locator); // Make sure that the TPMA_WRITTEN_ATTRIBUTE has the desired state if((IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITTEN)) != (session->attributes.nvWrittenState == SET)) return TPM_RC_POLICY_FAIL; } return TPM_RC_SUCCESS; } /* 6.4.4.12 RetrieveSessionData() */ /* This function will unmarshal the sessions in the session area of a command. The values are placed in the arrays that are defined at the beginning of this file. The normal unmarshaling errors are possible. */ /* Error Returns Meaning */ /* TPM_RC_SUCCSS unmarshaled without error */ /* TPM_RC_SIZE the number of bytes unmarshaled is not the same as the value for authorizationSize in the command */ static TPM_RC RetrieveSessionData( COMMAND *command // IN: main parsing structure for command ) { int i; TPM_RC result; SESSION *session; TPMA_SESSION sessionAttributes; TPM_HT sessionType; INT32 sessionIndex; TPM_RC errorIndex; s_decryptSessionIndex = UNDEFINED_INDEX; s_encryptSessionIndex = UNDEFINED_INDEX; s_auditSessionIndex = UNDEFINED_INDEX; for(sessionIndex = 0; command->authSize > 0; sessionIndex++) { errorIndex = TPM_RC_S + g_rcIndex[sessionIndex]; // If maximum allowed number of sessions has been parsed, return a size // error with a session number that is larger than the number of allowed // sessions if(sessionIndex == MAX_SESSION_NUM) return TPM_RCS_SIZE + errorIndex; // make sure that the associated handle for each session starts out // unassigned s_associatedHandles[sessionIndex] = TPM_RH_UNASSIGNED; // First parameter: Session handle. result = TPMI_SH_AUTH_SESSION_Unmarshal( &s_sessionHandles[sessionIndex], &command->parameterBuffer, &command->authSize, TRUE); if(result != TPM_RC_SUCCESS) return result + TPM_RC_S + g_rcIndex[sessionIndex]; // Second parameter: Nonce. result = TPM2B_NONCE_Unmarshal(&s_nonceCaller[sessionIndex], &command->parameterBuffer, &command->authSize); if(result != TPM_RC_SUCCESS) return result + TPM_RC_S + g_rcIndex[sessionIndex]; // Third parameter: sessionAttributes. result = TPMA_SESSION_Unmarshal(&s_attributes[sessionIndex], &command->parameterBuffer, &command->authSize); if(result != TPM_RC_SUCCESS) return result + TPM_RC_S + g_rcIndex[sessionIndex]; // Fourth parameter: authValue (PW or HMAC). result = TPM2B_AUTH_Unmarshal(&s_inputAuthValues[sessionIndex], &command->parameterBuffer, &command->authSize); if(result != TPM_RC_SUCCESS) return result + errorIndex; sessionAttributes = s_attributes[sessionIndex]; if(s_sessionHandles[sessionIndex] == TPM_RS_PW) { // A PWAP session needs additional processing. // Can't have any attributes set other than continueSession bit if(IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, encrypt) || IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, decrypt) || IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, audit) || IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, auditExclusive) || IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, auditReset)) return TPM_RCS_ATTRIBUTES + errorIndex; // The nonce size must be zero. if(s_nonceCaller[sessionIndex].t.size != 0) return TPM_RCS_NONCE + errorIndex; continue; } // For not password sessions... // Find out if the session is loaded. if(!SessionIsLoaded(s_sessionHandles[sessionIndex])) return TPM_RC_REFERENCE_S0 + sessionIndex; sessionType = HandleGetType(s_sessionHandles[sessionIndex]); session = SessionGet(s_sessionHandles[sessionIndex]); // Check if the session is an HMAC/policy session. if((session->attributes.isPolicy == SET && sessionType == TPM_HT_HMAC_SESSION) || (session->attributes.isPolicy == CLEAR && sessionType == TPM_HT_POLICY_SESSION)) return TPM_RCS_HANDLE + errorIndex; // Check that this handle has not previously been used. for(i = 0; i < sessionIndex; i++) { if(s_sessionHandles[i] == s_sessionHandles[sessionIndex]) return TPM_RCS_HANDLE + errorIndex; } // If the session is used for parameter encryption or audit as well, set // the corresponding Indexes. // First process decrypt. if(IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, decrypt)) { // Check if the commandCode allows command parameter encryption. if(DecryptSize(command->index) == 0) return TPM_RCS_ATTRIBUTES + errorIndex; // Encrypt attribute can only appear in one session if(s_decryptSessionIndex != UNDEFINED_INDEX) return TPM_RCS_ATTRIBUTES + errorIndex; // Can't decrypt if the session's symmetric algorithm is TPM_ALG_NULL if(session->symmetric.algorithm == TPM_ALG_NULL) return TPM_RCS_SYMMETRIC + errorIndex; // All checks passed, so set the index for the session used to decrypt // a command parameter. s_decryptSessionIndex = sessionIndex; } // Now process encrypt. if(IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, encrypt)) { // Check if the commandCode allows response parameter encryption. if(EncryptSize(command->index) == 0) return TPM_RCS_ATTRIBUTES + errorIndex; // Encrypt attribute can only appear in one session. if(s_encryptSessionIndex != UNDEFINED_INDEX) return TPM_RCS_ATTRIBUTES + errorIndex; // Can't encrypt if the session's symmetric algorithm is TPM_ALG_NULL if(session->symmetric.algorithm == TPM_ALG_NULL) return TPM_RCS_SYMMETRIC + errorIndex; // All checks passed, so set the index for the session used to encrypt // a response parameter. s_encryptSessionIndex = sessionIndex; } // At last process audit. if(IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, audit)) { // Audit attribute can only appear in one session. if(s_auditSessionIndex != UNDEFINED_INDEX) return TPM_RCS_ATTRIBUTES + errorIndex; // An audit session can not be policy session. if(HandleGetType(s_sessionHandles[sessionIndex]) == TPM_HT_POLICY_SESSION) return TPM_RCS_ATTRIBUTES + errorIndex; // If this is a reset of the audit session, or the first use // of the session as an audit session, it doesn't matter what // the exclusive state is. The session will become exclusive. if(!IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, auditReset) && session->attributes.isAudit == SET) { // Not first use or reset. If auditExlusive is SET, then this // session must be the current exclusive session. if(IS_ATTRIBUTE(sessionAttributes, TPMA_SESSION, auditExclusive) && g_exclusiveAuditSession != s_sessionHandles[sessionIndex]) return TPM_RC_EXCLUSIVE; } s_auditSessionIndex = sessionIndex; } // Initialize associated handle as undefined. This will be changed when // the handles are processed. s_associatedHandles[sessionIndex] = TPM_RH_UNASSIGNED; } command->sessionNum = sessionIndex; return TPM_RC_SUCCESS; } /* 6.4.4.13 CheckLockedOut() */ /* This function checks to see if the TPM is in lockout. This function should only be called if the entity being checked is subject to DA protection. The TPM is in lockout if the NV is not available and a DA write is pending. Otherwise the TPM is locked out if checking for lockoutAuth (lockoutAuthCheck == TRUE) and use of lockoutAuth is disabled, or failedTries >= maxTries */ /* Error Returns Meaning */ /* TPM_RC_NV_RATE NV is rate limiting */ /* TPM_RC_NV_UNAVAILABLE NV is not available at this time */ /* TPM_RC_LOCKOUT TPM is in lockout */ static TPM_RC CheckLockedOut( BOOL lockoutAuthCheck // IN: TRUE if checking is for lockoutAuth ) { // If NV is unavailable, and current cycle state recorded in NV is not // SU_NONE_VALUE, refuse to check any authorization because we would // not be able to handle a DA failure. if(!NV_IS_AVAILABLE && NV_IS_ORDERLY) return g_NvStatus; // Check if DA info needs to be updated in NV. if(s_DAPendingOnNV) { // If NV is accessible, RETURN_IF_NV_IS_NOT_AVAILABLE; // ... write the pending DA data and proceed. NV_SYNC_PERSISTENT(lockOutAuthEnabled); NV_SYNC_PERSISTENT(failedTries); s_DAPendingOnNV = FALSE; } // Lockout is in effect if checking for lockoutAuth and use of lockoutAuth // is disabled... if(lockoutAuthCheck) { if(gp.lockOutAuthEnabled == FALSE) return TPM_RC_LOCKOUT; } else { // ... or if the number of failed tries has been maxed out. if(gp.failedTries >= gp.maxTries) return TPM_RC_LOCKOUT; #if USE_DA_USED // If the daUsed flag is not SET, then no DA validation until the // daUsed state is written to NV if(!g_daUsed) { RETURN_IF_NV_IS_NOT_AVAILABLE; g_daUsed = TRUE; gp.orderlyState = SU_DA_USED_VALUE; NV_SYNC_PERSISTENT(orderlyState); return TPM_RC_RETRY; } #endif } return TPM_RC_SUCCESS; } /* 6.4.4.14 CheckAuthSession() */ /* This function checks that the authorization session properly authorizes the use of the associated handle. */ /* Error Returns Meaning */ /* TPM_RC_LOCKOUT entity is protected by DA and TPM is in lockout, or TPM is locked out on NV update pending on DA parameters */ /* TPM_RC_PP Physical Presence is required but not provided */ /* TPM_RC_AUTH_FAIL HMAC or PW authorization failed with DA side-effects (can be a policy session) */ /* TPM_RC_BAD_AUTH HMAC or PW authorization failed without DA side-effects (can be a policy session) */ /* TPM_RC_POLICY_FAIL if policy session fails */ /* TPM_RC_POLICY_CC command code of policy was wrong */ /* TPM_RC_EXPIRED the policy session has expired */ /* TPM_RC_PCR ??? */ /* TPM_RC_AUTH_UNAVAILABLE authValue or authPolicy unavailable */ static TPM_RC CheckAuthSession( COMMAND *command, // IN: primary parsing structure UINT32 sessionIndex // IN: index of session to be processed ) { TPM_RC result = TPM_RC_SUCCESS; SESSION *session = NULL; TPM_HANDLE sessionHandle = s_sessionHandles[sessionIndex]; TPM_HANDLE associatedHandle = s_associatedHandles[sessionIndex]; TPM_HT sessionHandleType = HandleGetType(sessionHandle); BOOL authUsed; pAssert(sessionHandle != TPM_RH_UNASSIGNED); // Take care of physical presence if(associatedHandle == TPM_RH_PLATFORM) { // If the physical presence is required for this command, check for PP // assertion. If it isn't asserted, no point going any further. if(PhysicalPresenceIsRequired(command->index) && !_plat__PhysicalPresenceAsserted()) return TPM_RC_PP; } if(sessionHandle != TPM_RS_PW) { session = SessionGet(sessionHandle); // Set includeAuth to indicate if DA checking will be required and if the // authValue will be included in any HMAC. if(sessionHandleType == TPM_HT_POLICY_SESSION) { // For a policy session, will check the DA status of the entity if either // isAuthValueNeeded or isPasswordNeeded is SET. session->attributes.includeAuth = session->attributes.isAuthValueNeeded || session->attributes.isPasswordNeeded; } else { // For an HMAC session, need to check unless the session // is bound. session->attributes.includeAuth = !IsSessionBindEntity(s_associatedHandles[sessionIndex], session); } authUsed = session->attributes.includeAuth; } else // Password session authUsed = TRUE; // If the authorization session is going to use an authValue, then make sure // that access to that authValue isn't locked out. if(authUsed) { // See if entity is subject to lockout. if(!IsDAExempted(associatedHandle)) { // See if in lockout result = CheckLockedOut(associatedHandle == TPM_RH_LOCKOUT); if(result != TPM_RC_SUCCESS) return result; } } // Policy or HMAC+PW? if(sessionHandleType != TPM_HT_POLICY_SESSION) { // for non-policy session make sure that a policy session is not required if(IsPolicySessionRequired(command->index, sessionIndex)) return TPM_RC_AUTH_TYPE; // The authValue must be available. // Note: The authValue is going to be "used" even if it is an EmptyAuth. // and the session is bound. if(!IsAuthValueAvailable(associatedHandle, command->index, sessionIndex)) return TPM_RC_AUTH_UNAVAILABLE; } else { // ... see if the entity has a policy, ... // Note: IsAuthPolicyAvailable will return FALSE if the sensitive area of the // object is not loaded if(!IsAuthPolicyAvailable(associatedHandle, command->index, sessionIndex)) return TPM_RC_AUTH_UNAVAILABLE; // ... and check the policy session. result = CheckPolicyAuthSession(command, sessionIndex); if(result != TPM_RC_SUCCESS) return result; } // Check authorization according to the type if((TPM_RS_PW == sessionHandle) || (session->attributes.isPasswordNeeded == SET)) result = CheckPWAuthSession(sessionIndex); else result = CheckSessionHMAC(command, sessionIndex); // Do processing for PIN Indexes are only three possibilities for 'result' at // this point: TPM_RC_SUCCESS, TPM_RC_AUTH_FAIL, TPM_RC_BAD_AUTH // For all these cases, we would have to process a PIN index if the // authValue of the index was used for authorization. if((TPM_HT_NV_INDEX == HandleGetType(associatedHandle)) && authUsed) { NV_REF locator; NV_INDEX *nvIndex = NvGetIndexInfo(associatedHandle, &locator); NV_PIN pinData; TPMA_NV nvAttributes; pAssert(nvIndex != NULL); nvAttributes = nvIndex->publicArea.attributes; // If this is a PIN FAIL index and the value has been written // then we can update the counter (increment or clear) if(IsNvPinFailIndex(nvAttributes) && IS_ATTRIBUTE(nvAttributes, TPMA_NV, WRITTEN)) { pinData.intVal = NvGetUINT64Data(nvIndex, locator); if(result != TPM_RC_SUCCESS) pinData.pin.pinCount++; else pinData.pin.pinCount = 0; NvWriteUINT64Data(nvIndex, pinData.intVal); } // If this is a PIN PASS Index, increment if we have used the // authorization value. // NOTE: If the counter has already hit the limit, then we // would not get here because the authorization value would not // be available and the TPM would have returned before it gets here else if(IsNvPinPassIndex(nvAttributes) && IS_ATTRIBUTE(nvAttributes, TPMA_NV, WRITTEN) && result == TPM_RC_SUCCESS) { // If the access is valid, then increment the use counter pinData.intVal = NvGetUINT64Data(nvIndex, locator); pinData.pin.pinCount++; NvWriteUINT64Data(nvIndex, pinData.intVal); } } return result; } #if CC_GetCommandAuditDigest /* 6.4.4.15 CheckCommandAudit() */ /* This function is called before the command is processed if audit is enabled for the command. It will check to see if the audit can be performed and will ensure that the cpHash is available for the audit. */ /* Error Returns Meaning */ /* TPM_RC_NV_UNAVAILABLE NV is not available for write */ /* TPM_RC_NV_RATE NV is rate limiting */ static TPM_RC CheckCommandAudit( COMMAND *command ) { // If the audit digest is clear and command audit is required, NV must be // available so that TPM2_GetCommandAuditDigest() is able to increment // audit counter. If NV is not available, the function bails out to prevent // the TPM from attempting an operation that would fail anyway. if(gr.commandAuditDigest.t.size == 0 || GetCommandCode(command->index) == TPM_CC_GetCommandAuditDigest) { RETURN_IF_NV_IS_NOT_AVAILABLE; } // Make sure that the cpHash is computed for the algorithm ComputeCpHash(command, gp.auditHashAlg); return TPM_RC_SUCCESS; } #endif /* 6.4.4.16 ParseSessionBuffer() */ /* This function is the entry function for command session processing. It iterates sessions in session area and reports if the required authorization has been properly provided. It also processes audit session and passes the information of encryption sessions to parameter encryption module. */ /* Error Returns Meaning */ /* various parsing failure or authorization failure */ TPM_RC ParseSessionBuffer( COMMAND *command // IN: the structure that contains ) { TPM_RC result; UINT32 i; INT32 size = 0; TPM2B_AUTH extraKey; UINT32 sessionIndex; TPM_RC errorIndex; SESSION *session = NULL; // Check if a command allows any session in its session area. if(!IsSessionAllowed(command->index)) return TPM_RC_AUTH_CONTEXT; // Default-initialization. command->sessionNum = 0; result = RetrieveSessionData(command); if(result != TPM_RC_SUCCESS) return result; // There is no command in the TPM spec that has more handles than // MAX_SESSION_NUM. pAssert(command->handleNum <= MAX_SESSION_NUM); // Associate the session with an authorization handle. for(i = 0; i < command->handleNum; i++) { if(CommandAuthRole(command->index, i) != AUTH_NONE) { // If the received session number is less than the number of handles // that requires authorization, an error should be returned. // Note: for all the TPM 2.0 commands, handles requiring // authorization come first in a command input and there are only ever // two values requiring authorization if(i > (command->sessionNum - 1)) return TPM_RC_AUTH_MISSING; // Record the handle associated with the authorization session s_associatedHandles[i] = command->handles[i]; } } // Consistency checks are done first to avoid authorization failure when the // command will not be executed anyway. for(sessionIndex = 0; sessionIndex < command->sessionNum; sessionIndex++) { errorIndex = TPM_RC_S + g_rcIndex[sessionIndex]; // PW session must be an authorization session if(s_sessionHandles[sessionIndex] == TPM_RS_PW) { if(s_associatedHandles[sessionIndex] == TPM_RH_UNASSIGNED) return TPM_RCS_HANDLE + errorIndex; // a password session can't be audit, encrypt or decrypt if(IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, audit) || IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, encrypt) || IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, decrypt)) return TPM_RCS_ATTRIBUTES + errorIndex; session = NULL; } else { session = SessionGet(s_sessionHandles[sessionIndex]); // A trial session can not appear in session area, because it cannot // be used for authorization, audit or encrypt/decrypt. if(session->attributes.isTrialPolicy == SET) return TPM_RCS_ATTRIBUTES + errorIndex; // See if the session is bound to a DA protected entity // NOTE: Since a policy session is never bound, a policy is still // usable even if the object is DA protected and the TPM is in // lockout. if(session->attributes.isDaBound == SET) { result = CheckLockedOut(session->attributes.isLockoutBound == SET); if(result != TPM_RC_SUCCESS) return result; } // If this session is for auditing, make sure the cpHash is computed. if(IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, audit)) ComputeCpHash(command, session->authHashAlg); } // if the session has an associated handle, check the authorization if(s_associatedHandles[sessionIndex] != TPM_RH_UNASSIGNED) { result = CheckAuthSession(command, sessionIndex); if(result != TPM_RC_SUCCESS) return RcSafeAddToResult(result, errorIndex); } else { // a session that is not for authorization must either be encrypt, // decrypt, or audit if(!IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, audit) && !IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, encrypt) && !IS_ATTRIBUTE(s_attributes[sessionIndex], TPMA_SESSION, decrypt)) return TPM_RCS_ATTRIBUTES + errorIndex; // no authValue included in any of the HMAC computations pAssert(session != NULL); session->attributes.includeAuth = CLEAR; // check HMAC for encrypt/decrypt/audit only sessions result = CheckSessionHMAC(command, sessionIndex); if(result != TPM_RC_SUCCESS) return RcSafeAddToResult(result, errorIndex); } } #if CC_GetCommandAuditDigest // Check if the command should be audited. Need to do this before any parameter // encryption so that the cpHash for the audit is correct if(CommandAuditIsRequired(command->index)) { result = CheckCommandAudit(command); if(result != TPM_RC_SUCCESS) return result; // No session number to reference } #endif // Decrypt the first parameter if applicable. This should be the last operation // in session processing. // If the encrypt session is associated with a handle and the handle's // authValue is available, then authValue is concatenated with sessionKey to // generate encryption key, no matter if the handle is the session bound entity // or not. if(s_decryptSessionIndex != UNDEFINED_INDEX) { // If this is an authorization session, include the authValue in the // generation of the decryption key if(s_associatedHandles[s_decryptSessionIndex] != TPM_RH_UNASSIGNED) { EntityGetAuthValue(s_associatedHandles[s_decryptSessionIndex], &extraKey); } else { extraKey.b.size = 0; } size = DecryptSize(command->index); result = CryptParameterDecryption(s_sessionHandles[s_decryptSessionIndex], &s_nonceCaller[s_decryptSessionIndex].b, command->parameterSize, (UINT16)size, &extraKey, command->parameterBuffer); if(result != TPM_RC_SUCCESS) return RcSafeAddToResult(result, TPM_RC_S + g_rcIndex[s_decryptSessionIndex]); } return TPM_RC_SUCCESS; } /* 6.4.4.17 CheckAuthNoSession() */ /* Function to process a command with no session associated. The function makes sure all the handles in the command require no authorization. */ /* Error Returns Meaning */ /* TPM_RC_AUTH_MISSING failure - one or more handles require authorization */ TPM_RC CheckAuthNoSession( COMMAND *command // IN: command parsing structure ) { UINT32 i; TPM_RC result = TPM_RC_SUCCESS; // Check if the command requires authorization for(i = 0; i < command->handleNum; i++) { if(CommandAuthRole(command->index, i) != AUTH_NONE) return TPM_RC_AUTH_MISSING; } #if CC_GetCommandAuditDigest // Check if the command should be audited. if(CommandAuditIsRequired(command->index)) { result = CheckCommandAudit(command); if(result != TPM_RC_SUCCESS) return result; } #endif // Initialize number of sessions to be 0 command->sessionNum = 0; return TPM_RC_SUCCESS; } /* 6.4.5 Response Session Processing */ /* 6.4.5.1 Introduction */ /* The following functions build the session area in a response and handle the audit sessions (if present). */ /* 6.4.5.2 ComputeRpHash() */ /* Function to compute rpHash (Response Parameter Hash). The rpHash is only computed if there is an HMAC authorization session and the return code is TPM_RC_SUCCESS. */ static TPM2B_DIGEST * ComputeRpHash( COMMAND *command, // IN: command structure TPM_ALG_ID hashAlg // IN: hash algorithm to compute rpHash ) { TPM2B_DIGEST *rpHash = GetRpHashPointer(command, hashAlg); HASH_STATE hashState; if(rpHash->t.size == 0) { // rpHash := hash(responseCode || commandCode || parameters) // Initiate hash creation. rpHash->t.size = CryptHashStart(&hashState, hashAlg); // Add hash constituents. CryptDigestUpdateInt(&hashState, sizeof(TPM_RC), TPM_RC_SUCCESS); CryptDigestUpdateInt(&hashState, sizeof(TPM_CC), command->code); CryptDigestUpdate(&hashState, command->parameterSize, command->parameterBuffer); // Complete hash computation. CryptHashEnd2B(&hashState, &rpHash->b); } return rpHash; } /* 6.4.5.3 InitAuditSession() */ /* This function initializes the audit data in an audit session. */ static void InitAuditSession( SESSION *session // session to be initialized ) { // Mark session as an audit session. session->attributes.isAudit = SET; // Audit session can not be bound. session->attributes.isBound = CLEAR; // Size of the audit log is the size of session hash algorithm digest. session->u2.auditDigest.t.size = CryptHashGetDigestSize(session->authHashAlg); // Set the original digest value to be 0. MemorySet(&session->u2.auditDigest.t.buffer, 0, session->u2.auditDigest.t.size); return; } /* 6.4.5.4 UpdateAuditDigest */ /* Function to update an audit digest */ static void UpdateAuditDigest( COMMAND *command, TPMI_ALG_HASH hashAlg, TPM2B_DIGEST *digest ) { HASH_STATE hashState; TPM2B_DIGEST *cpHash = GetCpHash(command, hashAlg); TPM2B_DIGEST *rpHash = ComputeRpHash(command, hashAlg); // pAssert(cpHash != NULL); // digestNew := hash (digestOld || cpHash || rpHash) // Start hash computation. digest->t.size = CryptHashStart(&hashState, hashAlg); // Add old digest. CryptDigestUpdate2B(&hashState, &digest->b); // Add cpHash CryptDigestUpdate2B(&hashState, &cpHash->b); // Add rpHash CryptDigestUpdate2B(&hashState, &rpHash->b); // Finalize the hash. CryptHashEnd2B(&hashState, &digest->b); } /* 6.4.5.5 Audit() */ /* This function updates the audit digest in an audit session. */ static void Audit( COMMAND *command, // IN: primary control structure SESSION *auditSession // IN: loaded audit session ) { UpdateAuditDigest(command, auditSession->authHashAlg, &auditSession->u2.auditDigest); return; } #if CC_GetCommandAuditDigest /* 6.4.5.6 CommandAudit() */ /* This function updates the command audit digest. */ static void CommandAudit( COMMAND *command // IN: ) { // If the digest.size is one, it indicates the special case of changing // the audit hash algorithm. For this case, no audit is done on exit. // NOTE: When the hash algorithm is changed, g_updateNV is set in order to // force an update to the NV on exit so that the change in digest will // be recorded. So, it is safe to exit here without setting any flags // because the digest change will be written to NV when this code exits. if(gr.commandAuditDigest.t.size == 1) { gr.commandAuditDigest.t.size = 0; return; } // If the digest size is zero, need to start a new digest and increment // the audit counter. if(gr.commandAuditDigest.t.size == 0) { gr.commandAuditDigest.t.size = CryptHashGetDigestSize(gp.auditHashAlg); MemorySet(gr.commandAuditDigest.t.buffer, 0, gr.commandAuditDigest.t.size); // Bump the counter and save its value to NV. gp.auditCounter++; NV_SYNC_PERSISTENT(auditCounter); } UpdateAuditDigest(command, gp.auditHashAlg, &gr.commandAuditDigest); return; } #endif /* 6.4.5.7 UpdateAuditSessionStatus() */ /* Function to update the internal audit related states of a session. It */ /* a) initializes the session as audit session and sets it to be exclusive if this is the first time it is used for audit or audit reset was requested; */ /* b) reports exclusive audit session; */ /* c) extends audit log; and */ /* d) clears exclusive audit session if no audit session found in the command. */ static void UpdateAuditSessionStatus( COMMAND *command // IN: primary control structure ) { UINT32 i; TPM_HANDLE auditSession = TPM_RH_UNASSIGNED; // Iterate through sessions for(i = 0; i < command->sessionNum; i++) { SESSION *session; // PW session do not have a loaded session and can not be an audit // session either. Skip it. if(s_sessionHandles[i] == TPM_RS_PW) continue; session = SessionGet(s_sessionHandles[i]); // If a session is used for audit if(IS_ATTRIBUTE(s_attributes[i], TPMA_SESSION, audit)) { // An audit session has been found auditSession = s_sessionHandles[i]; // If the session has not been an audit session yet, or // the auditSetting bits indicate a reset, initialize it and set // it to be the exclusive session if(session->attributes.isAudit == CLEAR || IS_ATTRIBUTE(s_attributes[i], TPMA_SESSION, auditReset)) { InitAuditSession(session); g_exclusiveAuditSession = auditSession; } else { // Check if the audit session is the current exclusive audit // session and, if not, clear previous exclusive audit session. if(g_exclusiveAuditSession != auditSession) g_exclusiveAuditSession = TPM_RH_UNASSIGNED; } // Report audit session exclusivity. if(g_exclusiveAuditSession == auditSession) { SET_ATTRIBUTE(s_attributes[i], TPMA_SESSION, auditExclusive); } else { CLEAR_ATTRIBUTE(s_attributes[i], TPMA_SESSION, auditExclusive); } // Extend audit log. Audit(command, session); } } // If no audit session is found in the command, and the command allows // a session then, clear the current exclusive // audit session. if(auditSession == TPM_RH_UNASSIGNED && IsSessionAllowed(command->index)) { g_exclusiveAuditSession = TPM_RH_UNASSIGNED; } return; } /* 6.4.5.8 ComputeResponseHMAC() */ /* Function to compute HMAC for authorization session in a response. */ static void ComputeResponseHMAC( COMMAND *command, // IN: command structure UINT32 sessionIndex, // IN: session index to be processed SESSION *session, // IN: loaded session TPM2B_DIGEST *hmac // OUT: authHMAC ) { TPM2B_TYPE(KEY, (sizeof(AUTH_VALUE) * 2)); TPM2B_KEY key; // HMAC key BYTE marshalBuffer[sizeof(TPMA_SESSION)]; BYTE *buffer; UINT32 marshalSize; HMAC_STATE hmacState; TPM2B_DIGEST *rpHash = ComputeRpHash(command, session->authHashAlg); // Generate HMAC key MemoryCopy2B(&key.b, &session->sessionKey.b, sizeof(key.t.buffer)); // Add the object authValue if required if(session->attributes.includeAuth == SET) { // Note: includeAuth may be SET for a policy that is used in // UndefineSpaceSpecial(). At this point, the Index has been deleted // so the includeAuth will have no meaning. However, the // s_associatedHandles[] value for the session is now set to TPM_RH_NULL so // this will return the authValue associated with TPM_RH_NULL and that is // and empty buffer. TPM2B_AUTH authValue; // Get the authValue with trailing zeros removed EntityGetAuthValue(s_associatedHandles[sessionIndex], &authValue); // Add it to the key MemoryConcat2B(&key.b, &authValue.b, sizeof(key.t.buffer)); } // if the HMAC key size is 0, the response HMAC is computed according to the // input HMAC if(key.t.size == 0 && s_inputAuthValues[sessionIndex].t.size == 0) { hmac->t.size = 0; return; } // Start HMAC computation. hmac->t.size = CryptHmacStart2B(&hmacState, session->authHashAlg, &key.b); // Add hash components. CryptDigestUpdate2B(&hmacState.hashState, &rpHash->b); CryptDigestUpdate2B(&hmacState.hashState, &session->nonceTPM.b); CryptDigestUpdate2B(&hmacState.hashState, &s_nonceCaller[sessionIndex].b); // Add session attributes. buffer = marshalBuffer; marshalSize = TPMA_SESSION_Marshal(&s_attributes[sessionIndex], &buffer, NULL); CryptDigestUpdate(&hmacState.hashState, marshalSize, marshalBuffer); // Finalize HMAC. CryptHmacEnd2B(&hmacState, &hmac->b); return; } /* 6.4.5.9 UpdateInternalSession() */ /* Updates internal sessions: */ /* a) Restarts session time. */ /* b) Clears a policy session since nonce is rolling. */ static void UpdateInternalSession( SESSION *session, // IN: the session structure UINT32 i // IN: session number ) { // If nonce is rolling in a policy session, the policy related data // will be re-initialized. if(HandleGetType(s_sessionHandles[i]) == TPM_HT_POLICY_SESSION && IS_ATTRIBUTE(s_attributes[i], TPMA_SESSION, continueSession)) { // When the nonce rolls it starts a new timing interval for the // policy session. SessionResetPolicyData(session); SessionSetStartTime(session); } return; } /* 6.4.5.10 BuildSingleResponseAuth() */ /* Function to compute response HMAC value for a policy or HMAC session. */ static TPM2B_NONCE * BuildSingleResponseAuth( COMMAND *command, // IN: command structure UINT32 sessionIndex, // IN: session index to be processed TPM2B_AUTH *auth // OUT: authHMAC ) { // Fill in policy/HMAC based session response. SESSION *session = SessionGet(s_sessionHandles[sessionIndex]); // If the session is a policy session with isPasswordNeeded SET, the // authorization field is empty. if(HandleGetType(s_sessionHandles[sessionIndex]) == TPM_HT_POLICY_SESSION && session->attributes.isPasswordNeeded == SET) auth->t.size = 0; else // Compute response HMAC. ComputeResponseHMAC(command, sessionIndex, session, auth); UpdateInternalSession(session, sessionIndex); return &session->nonceTPM; } /* 6.4.5.11 UpdateAllNonceTPM() */ /* Updates TPM nonce for all sessions in command. */ static void UpdateAllNonceTPM( COMMAND *command // IN: controlling structure ) { UINT32 i; SESSION *session; for(i = 0; i < command->sessionNum; i++) { // If not a PW session, compute the new nonceTPM. if(s_sessionHandles[i] != TPM_RS_PW) { session = SessionGet(s_sessionHandles[i]); // Update nonceTPM in both internal session and response. CryptRandomGenerate(session->nonceTPM.t.size, session->nonceTPM.t.buffer); } } return; } /* 6.4.5.12 BuildResponseSession() */ /* Function to build Session buffer in a response. The authorization data is added to the end of command->responseBuffer. The size of the authorization area is accumulated in command->authSize. When this is called, command->responseBuffer is pointing at the next location in the response buffer to be filled. This is where the authorization sessions will go, if any. command->parameterSize is the number of bytes that have been marshaled as parameters in the output buffer. */ void BuildResponseSession( COMMAND *command // IN: structure that has relevant command // information ) { pAssert(command->authSize == 0); // Reset the parameter buffer to point to the start of the parameters so that // there is a starting point for any rpHash that might be generated and so there // is a place where parameter encryption would start command->parameterBuffer = command->responseBuffer - command->parameterSize; // Session nonces should be updated before parameter encryption if(command->tag == TPM_ST_SESSIONS) { UpdateAllNonceTPM(command); // Encrypt first parameter if applicable. Parameter encryption should // happen after nonce update and before any rpHash is computed. // If the encrypt session is associated with a handle, the authValue of // this handle will be concatenated with sessionKey to generate // encryption key, no matter if the handle is the session bound entity // or not. The authValue is added to sessionKey only when the authValue // is available. if(s_encryptSessionIndex != UNDEFINED_INDEX) { UINT32 size; TPM2B_AUTH extraKey; extraKey.b.size = 0; // If this is an authorization session, include the authValue in the // generation of the encryption key if(s_associatedHandles[s_encryptSessionIndex] != TPM_RH_UNASSIGNED) { EntityGetAuthValue(s_associatedHandles[s_encryptSessionIndex], &extraKey); } size = EncryptSize(command->index); CryptParameterEncryption(s_sessionHandles[s_encryptSessionIndex], &s_nonceCaller[s_encryptSessionIndex].b, (UINT16)size, &extraKey, command->parameterBuffer); } } // Audit sessions should be processed regardless of the tag because // a command with no session may cause a change of the exclusivity state. UpdateAuditSessionStatus(command); #if CC_GetCommandAuditDigest // Command Audit if(CommandAuditIsRequired(command->index)) CommandAudit(command); #endif // Process command with sessions. if(command->tag == TPM_ST_SESSIONS) { UINT32 i; pAssert(command->sessionNum > 0); // Iterate over each session in the command session area, and create // corresponding sessions for response. for(i = 0; i < command->sessionNum; i++) { TPM2B_NONCE *nonceTPM; TPM2B_DIGEST responseAuth; // Make sure that continueSession is SET on any Password session. // This makes it marginally easier for the management software // to keep track of the closed sessions. if(s_sessionHandles[i] == TPM_RS_PW) { SET_ATTRIBUTE(s_attributes[i], TPMA_SESSION, continueSession); responseAuth.t.size = 0; nonceTPM = (TPM2B_NONCE *)&responseAuth; } else { // Compute the response HMAC and get a pointer to the nonce used. // This function will also update the values if needed. Note, the nonceTPM = BuildSingleResponseAuth(command, i, &responseAuth); } command->authSize += TPM2B_NONCE_Marshal(nonceTPM, &command->responseBuffer, NULL); command->authSize += TPMA_SESSION_Marshal(&s_attributes[i], &command->responseBuffer, NULL); command->authSize += TPM2B_DIGEST_Marshal(&responseAuth, &command->responseBuffer, NULL); if(!IS_ATTRIBUTE(s_attributes[i], TPMA_SESSION, continueSession)) SessionFlush(s_sessionHandles[i]); } } return; } /* 6.4.5.13 SessionRemoveAssociationToHandle() */ /* This function deals with the case where an entity associated with an authorization is deleted during command processing. The primary use of this is to support UndefineSpaceSpecial(). */ void SessionRemoveAssociationToHandle( TPM_HANDLE handle ) { UINT32 i; for(i = 0; i < MAX_SESSION_NUM; i++) { if(s_associatedHandles[i] == handle) { s_associatedHandles[i] = TPM_RH_NULL; } } } libtpms-0.9.3/src/tpm2/SessionProcess_fp.h000066400000000000000000000101371421143571500204730ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: SessionProcess_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 */ /* */ /********************************************************************************/ #ifndef SESSIONPROCESS_FP_H #define SESSIONPROCESS_FP_H BOOL IsDAExempted( TPM_HANDLE handle // IN: entity handle ); void ClearCpRpHashes( COMMAND *command ); BOOL CompareNameHash( COMMAND *command, // IN: main parsing structure SESSION *session // IN: session structure with nameHash ); TPM_RC ParseSessionBuffer( COMMAND *command // IN: the structure that contains ); TPM_RC CheckAuthNoSession( COMMAND *command // IN: command parsing structure ); void BuildResponseSession( COMMAND *command // IN: structure that has relevant command // information ); void SessionRemoveAssociationToHandle( TPM_HANDLE handle ); #endif libtpms-0.9.3/src/tpm2/Session_fp.h000066400000000000000000000136621421143571500171420ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Session_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ #ifndef SESSION_FP_H #define SESSION_FP_H BOOL SessionStartup( STARTUP_TYPE type ); BOOL SessionIsLoaded( TPM_HANDLE handle // IN: session handle ); BOOL SessionIsSaved( TPM_HANDLE handle // IN: session handle ); BOOL SequenceNumberForSavedContextIsValid( TPMS_CONTEXT *context // IN: pointer to a context structure to be // validated ); BOOL SessionPCRValueIsCurrent( SESSION *session // IN: session structure ); SESSION * SessionGet( TPM_HANDLE handle // IN: session handle ); TPM_RC SessionCreate( TPM_SE sessionType, // IN: the session type TPMI_ALG_HASH authHash, // IN: the hash algorithm TPM2B_NONCE *nonceCaller, // IN: initial nonceCaller TPMT_SYM_DEF *symmetric, // IN: the symmetric algorithm TPMI_DH_ENTITY bind, // IN: the bind object TPM2B_DATA *seed, // IN: seed data TPM_HANDLE *sessionHandle, // OUT: the session handle TPM2B_NONCE *nonceTpm // OUT: the session nonce ); TPM_RC SessionContextSave( TPM_HANDLE handle, // IN: session handle CONTEXT_COUNTER *contextID // OUT: assigned contextID ); TPM_RC SessionContextLoad( SESSION_BUF *session, // IN: session structure from saved context TPM_HANDLE *handle // IN/OUT: session handle ); void SessionFlush( TPM_HANDLE handle // IN: loaded or saved session handle ); void SessionComputeBoundEntity( TPMI_DH_ENTITY entityHandle, // IN: handle of entity TPM2B_NAME *bind // OUT: binding value ); void SessionSetStartTime( SESSION *session // IN: the session to update ); void SessionResetPolicyData( SESSION *session // IN: the session to reset ); TPMI_YES_NO SessionCapGetLoaded( TPMI_SH_POLICY handle, // IN: start handle UINT32 count, // IN: count of returned handles TPML_HANDLE *handleList // OUT: list of handle ); TPMI_YES_NO SessionCapGetSaved( TPMI_SH_HMAC handle, // IN: start handle UINT32 count, // IN: count of returned handles TPML_HANDLE *handleList // OUT: list of handle ); UINT32 SessionCapGetLoadedNumber( void ); UINT32 SessionCapGetLoadedAvail( void ); UINT32 SessionCapGetActiveNumber( void ); UINT32 SessionCapGetActiveAvail( void ); #endif libtpms-0.9.3/src/tpm2/SetAlgorithmSet_fp.h000066400000000000000000000073341421143571500205740ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: SetAlgorithmSet_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef SETALGORITHMSET_FP_H #define SETALGORITHMSET_FP_H typedef struct { TPMI_RH_PLATFORM authHandle; UINT32 algorithmSet; } SetAlgorithmSet_In; #define RC_SetAlgorithmSet_authHandle (TPM_RC_H + TPM_RC_1) #define RC_SetAlgorithmSet_algorithmSet (TPM_RC_P + TPM_RC_1) TPM_RC TPM2_SetAlgorithmSet( SetAlgorithmSet_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/SetCommandCodeAuditStatus_fp.h000066400000000000000000000077221421143571500225370ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: SetCommandCodeAuditStatus_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef SETCOMMANDCODEAUDITSTATUS_FP_H #define SETCOMMANDCODEAUDITSTATUS_FP_H typedef struct { TPMI_RH_PROVISION auth; TPMI_ALG_HASH auditAlg; TPML_CC setList; TPML_CC clearList; } SetCommandCodeAuditStatus_In; #define RC_SetCommandCodeAuditStatus_auth (TPM_RC_H + TPM_RC_1) #define RC_SetCommandCodeAuditStatus_auditAlg (TPM_RC_P + TPM_RC_1) #define RC_SetCommandCodeAuditStatus_setList (TPM_RC_P + TPM_RC_2) #define RC_SetCommandCodeAuditStatus_clearList (TPM_RC_P + TPM_RC_3) TPM_RC TPM2_SetCommandCodeAuditStatus( SetCommandCodeAuditStatus_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/SetPrimaryPolicy_fp.h000066400000000000000000000075341421143571500207770ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM2_SetPrimaryPolicy Command Header */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: SetPrimaryPolicy_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012 - 2019 */ /* */ /********************************************************************************/ #ifndef SETPRIMARYPOLICY_FP_H #define SETPRIMARYPOLICY_FP_H typedef struct { TPMI_RH_HIERARCHY_POLICY authHandle; TPM2B_DIGEST authPolicy; TPMI_ALG_HASH hashAlg; } SetPrimaryPolicy_In; #define RC_SetPrimaryPolicy_authHandle (TPM_RC_H + TPM_RC_1) #define RC_SetPrimaryPolicy_authPolicy (TPM_RC_P + TPM_RC_1) #define RC_SetPrimaryPolicy_hashAlg (TPM_RC_P + TPM_RC_2) TPM_RC TPM2_SetPrimaryPolicy( SetPrimaryPolicy_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/Shutdown_fp.h000066400000000000000000000071211421143571500173230ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Shutdown_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef SHUTDOWN_FP_H #define SHUTDOWN_FP_H typedef struct{ TPM_SU shutdownType; } Shutdown_In; #define RC_Shutdown_shutdownType (TPM_RC_P + TPM_RC_1) TPM_RC TPM2_Shutdown( Shutdown_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/Sign_fp.h000066400000000000000000000076331421143571500164200ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Sign_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef SIGN_FP_H #define SIGN_FP_H typedef struct { TPMI_DH_OBJECT keyHandle; TPM2B_DIGEST digest; TPMT_SIG_SCHEME inScheme; TPMT_TK_HASHCHECK validation; } Sign_In; #define RC_Sign_keyHandle (TPM_RC_H + TPM_RC_1) #define RC_Sign_digest (TPM_RC_P + TPM_RC_1) #define RC_Sign_inScheme (TPM_RC_P + TPM_RC_2) #define RC_Sign_validation (TPM_RC_P + TPM_RC_3) typedef struct { TPMT_SIGNATURE signature; } Sign_Out; TPM_RC TPM2_Sign( Sign_In *in, // IN: input parameter list Sign_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/SigningCommands.c000066400000000000000000000156751421143571500201130ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Signing and Signature Verification */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: SigningCommands.c 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2021 */ /* */ /********************************************************************************/ #include "Tpm.h" #include "VerifySignature_fp.h" #if CC_VerifySignature // Conditional expansion of this file TPM_RC TPM2_VerifySignature( VerifySignature_In *in, // IN: input parameter list VerifySignature_Out *out // OUT: output parameter list ) { TPM_RC result; OBJECT *signObject = HandleToObject(in->keyHandle); TPMI_RH_HIERARCHY hierarchy; // Input Validation // The object to validate the signature must be a signing key. if(!IS_ATTRIBUTE(signObject->publicArea.objectAttributes, TPMA_OBJECT, sign)) return TPM_RCS_ATTRIBUTES + RC_VerifySignature_keyHandle; // Validate Signature. TPM_RC_SCHEME, TPM_RC_HANDLE or TPM_RC_SIGNATURE // error may be returned by CryptCVerifySignatrue() result = CryptValidateSignature(in->keyHandle, &in->digest, &in->signature); if(result != TPM_RC_SUCCESS) return RcSafeAddToResult(result, RC_VerifySignature_signature); // Command Output hierarchy = GetHieriarchy(in->keyHandle); if(hierarchy == TPM_RH_NULL || signObject->publicArea.nameAlg == TPM_ALG_NULL) { // produce empty ticket if hierarchy is TPM_RH_NULL or nameAlg is // TPM_ALG_NULL out->validation.tag = TPM_ST_VERIFIED; out->validation.hierarchy = TPM_RH_NULL; out->validation.digest.t.size = 0; } else { // Compute ticket TicketComputeVerified(hierarchy, &in->digest, &signObject->name, &out->validation); } return TPM_RC_SUCCESS; } #endif // CC_VerifySignature #include "Tpm.h" #include "Sign_fp.h" #if CC_Sign // Conditional expansion of this file #include "Attest_spt_fp.h" TPM_RC TPM2_Sign( Sign_In *in, // IN: input parameter list Sign_Out *out // OUT: output parameter list ) { TPM_RC result; TPMT_TK_HASHCHECK ticket; OBJECT *signObject = HandleToObject(in->keyHandle); // // Input Validation if(!IsSigningObject(signObject)) return TPM_RCS_KEY + RC_Sign_keyHandle; // A key that will be used for x.509 signatures can't be used in TPM2_Sign(). if(IS_ATTRIBUTE(signObject->publicArea.objectAttributes, TPMA_OBJECT, x509sign)) return TPM_RCS_ATTRIBUTES + RC_Sign_keyHandle; // pick a scheme for sign. If the input sign scheme is not compatible with // the default scheme, return an error. if(!CryptSelectSignScheme(signObject, &in->inScheme)) return TPM_RCS_SCHEME + RC_Sign_inScheme; // If validation is provided, or the key is restricted, check the ticket if(in->validation.digest.t.size != 0 || IS_ATTRIBUTE(signObject->publicArea.objectAttributes, TPMA_OBJECT, restricted)) { // Compute and compare ticket TicketComputeHashCheck(in->validation.hierarchy, in->inScheme.details.any.hashAlg, &in->digest, &ticket); if(!MemoryEqual2B(&in->validation.digest.b, &ticket.digest.b)) return TPM_RCS_TICKET + RC_Sign_validation; } else // If we don't have a ticket, at least verify that the provided 'digest' // is the size of the scheme hashAlg digest. // NOTE: this does not guarantee that the 'digest' is actually produced using // the indicated hash algorithm, but at least it might be. { if(in->digest.t.size != CryptHashGetDigestSize(in->inScheme.details.any.hashAlg)) return TPM_RCS_SIZE + RC_Sign_digest; } // Command Output // Sign the hash. A TPM_RC_VALUE or TPM_RC_SCHEME // error may be returned at this point result = CryptSign(signObject, &in->inScheme, &in->digest, &out->signature); return result; } #endif // CC_Sign libtpms-0.9.3/src/tpm2/Simulator_fp.h000066400000000000000000000170651421143571500174770ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Simulator_fp.h 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2021 */ /* */ /********************************************************************************/ /* D.2 Simulator_fp.h */ #ifndef _SIMULATOR_FP_H_ #define _SIMULATOR_FP_H_ #include #ifdef TPM_WINDOWS #include #include #endif #ifdef TPM_POSIX #include #include #include #include #include #endif /* D.2.1. From TcpServer.c */ /* D.2.1.1. PlatformServer() */ /* Moved to TpmServer_fp.h because it's different for Windows and Unix */ /* D.2.2. From TPMCmdp.c */ /* D.2.2.1. Signal_PowerOn() */ /* This function processes a power-on indication. Among other things, it calls the _TPM_Init() handler. */ void _rpc__Signal_PowerOn( bool isReset ); /* D.2.2.2. Signal_Restart() */ /* This function processes the clock restart indication. All it does is call the platform function. */ void _rpc__Signal_Restart( void ); /* D.2.2.3. Signal_PowerOff() */ /* This function processes the power off indication. Its primary function is to set a flag indicating that the next power on indication should cause _TPM_Init() to be called. */ void _rpc__Signal_PowerOff( void ); #if 0 /* libtpms added */ /* D.2.2.4. _rpc__ForceFailureMode() */ /* This function is used to debug the Failure Mode logic of the TPM. It will set a flag in the TPM code such that the next call to TPM2_SelfTest() will result in a failure, putting the TPM into Failure Mode. */ void _rpc__ForceFailureMode( void ); /* D.2.2.5. _rpc__Signal_PhysicalPresenceOn() */ /* This function is called to simulate activation of the physical presence pin. */ void _rpc__Signal_PhysicalPresenceOn( void ); /* D.2.2.6. _rpc__Signal_PhysicalPresenceOff() */ /* This function is called to simulate deactivation of the physical presence pin. */ void _rpc__Signal_PhysicalPresenceOff( void ); /* D.2.2.7. _rpc__Signal_Hash_Start() */ /* This function is called to simulate a _TPM_Hash_Start() event. It will call */ void _rpc__Signal_Hash_Start( void ); /* D.2.2.8. _rpc__Signal_Hash_Data() */ /* This function is called to simulate a _TPM_Hash_Data() event. */ void _rpc__Signal_Hash_Data( _IN_BUFFER input ); /* D.2.2.9. _rpc__Signal_HashEnd() */ /* This function is called to simulate a _TPM_Hash_End() event. */ void _rpc__Signal_HashEnd( void ); #endif /* libtpms added */ /* rpc__Send_Command() This is the interface to the TPM code. */ void _rpc__Send_Command( unsigned char locality, _IN_BUFFER request, _OUT_BUFFER *response ); /* D.2.2.10. _rpc__Signal_CancelOn() */ /* This function is used to turn on the indication to cancel a command in process. An executing command is not interrupted. The command code may periodically check this indication to see if it should abort the current command processing and returned TPM_RC_CANCELLED. */ void _rpc__Signal_CancelOn( void ); /* D.2.2.11. _rpc__Signal_CancelOff() */ /* This function is used to turn off the indication to cancel a command in process. */ void _rpc__Signal_CancelOff( void ); /* D.2.2.12. _rpc__Signal_NvOn() */ /* In a system where the NV memory used by the TPM is not within the TPM, the NV may not always be available. This function turns on the indicator that indicates that NV is available. */ void _rpc__Signal_NvOn( void ); #if 0 /* libtpms added */ /* D.2.2.13. _rpc__Signal_NvOff() */ /* This function is used to set the indication that NV memory is no longer available. */ void _rpc__Signal_NvOff( void ); /* D.2.2.14. _rpc__RsaKeyCacheControl() */ /* This function is used to enable/disable the use of the RSA key cache during simulation. */ void _rpc__RsaKeyCacheControl( int state ); /* D.4.2.15. _rpc__ACT_GetSignaled() */ bool _rpc__ACT_GetSignaled( uint32_t actHandle ); /* D.2.3. From TPMCmds.c */ /* D.2.3.1. main() */ /* This is the main entry point for the simulator. */ int main( int argc, char *argv[] ); #endif /* libtpms added */ /* libtpms added begin */ void _rpc__Signal_SetTPMEstablished(void); bool _rpc__Signal_GetTPMEstablished(void); void _rpc__Signal_ResetTPMEstablished(void); bool _rpc__Signal_IsPowerOn(void); /* libtpms added end */ #endif // _SIMULATOR_FP_H_ libtpms-0.9.3/src/tpm2/StartAuthSession_fp.h000066400000000000000000000105651421143571500210010ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: StartAuthSession_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef STARTAUTHSESSION_FP_H #define STARTAUTHSESSION_FP_H typedef struct { TPMI_DH_OBJECT tpmKey; TPMI_DH_ENTITY bind; TPM2B_NONCE nonceCaller; TPM2B_ENCRYPTED_SECRET encryptedSalt; TPM_SE sessionType; TPMT_SYM_DEF symmetric; TPMI_ALG_HASH authHash; } StartAuthSession_In; typedef struct { TPMI_SH_AUTH_SESSION sessionHandle; TPM2B_NONCE nonceTPM; } StartAuthSession_Out; #define RC_StartAuthSession_tpmKey (TPM_RC_H + TPM_RC_1) #define RC_StartAuthSession_bind (TPM_RC_H + TPM_RC_2) #define RC_StartAuthSession_nonceCaller (TPM_RC_P + TPM_RC_1) #define RC_StartAuthSession_encryptedSalt (TPM_RC_P + TPM_RC_2) #define RC_StartAuthSession_sessionType (TPM_RC_P + TPM_RC_3) #define RC_StartAuthSession_symmetric (TPM_RC_P + TPM_RC_4) #define RC_StartAuthSession_authHash (TPM_RC_P + TPM_RC_5) TPM_RC TPM2_StartAuthSession( StartAuthSession_In *in, // IN: input parameter buffer StartAuthSession_Out *out // OUT: output parameter buffer ); #endif libtpms-0.9.3/src/tpm2/StartupCommands.c000066400000000000000000000337341421143571500201530ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Startup Commands */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: StartupCommands.c 1594 2020-03-26 22:15:48Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2020 */ /* */ /********************************************************************************/ /* 9.2 _TPM_Init */ #include "Tpm.h" #include "PlatformACT_fp.h" /* added kgold */ #include "_TPM_Init_fp.h" #include "StateMarshal.h" /* libtpms added */ // This function is used to process a _TPM_Init indication. LIB_EXPORT void _TPM_Init( void ) { BOOL restored = FALSE; /* libtpms added */ g_powerWasLost = g_powerWasLost | _plat__WasPowerLost(); #if SIMULATION && !defined NDEBUG /* libtpms changed */ // If power was lost and this was a simulation, put canary in RAM used by NV // so that uninitialized memory can be detected more easily if(g_powerWasLost) { memset(&gc, 0xbb, sizeof(gc)); memset(&gr, 0xbb, sizeof(gr)); memset(&gp, 0xbb, sizeof(gp)); memset(&go, 0xbb, sizeof(go)); } #endif #if SIMULATION // Clear the flag that forces failure on self-test g_forceFailureMode = FALSE; #endif // Disable the tick processing _plat__ACT_EnableTicks(FALSE); // Set initialization state TPMInit(); // Set g_DRTMHandle as unassigned g_DRTMHandle = TPM_RH_UNASSIGNED; // No H-CRTM, yet. g_DrtmPreStartup = FALSE; // Initialize the NvEnvironment. g_nvOk = NvPowerOn(); // Initialize cryptographic functions g_inFailureMode |= (CryptInit() == FALSE); /* libtpms changed */ if(!g_inFailureMode) { // Load the persistent data NvReadPersistent(); // Load the orderly data (clock and DRBG state). // If this is not done here, things break NvRead(&go, NV_ORDERLY_DATA, sizeof(go)); // Start clock. Need to do this after NV has been restored. TimePowerOn(); /* libtpms added begin */ VolatileLoad(&restored); if (restored) NVShadowRestore(); /* libtpms added end */ } return; } #include "Tpm.h" #include "Startup_fp.h" #if CC_Startup // Conditional expansion of this file TPM_RC TPM2_Startup( Startup_In *in // IN: input parameter list ) { STARTUP_TYPE startup; BYTE locality = _plat__LocalityGet(); BOOL OK = TRUE; // The command needs NV update. RETURN_IF_NV_IS_NOT_AVAILABLE; // Get the flags for the current startup locality and the H-CRTM. // Rather than generalizing the locality setting, this code takes advantage // of the fact that the PC Client specification only allows Startup() // from locality 0 and 3. To generalize this probably would require a // redo of the NV space and since this is a feature that is hardly ever used // outside of the PC Client, this code just support the PC Client needs. // Input Validation // Check that the locality is a supported value if(locality != 0 && locality != 3) return TPM_RC_LOCALITY; // If there was a H-CRTM, then treat the locality as being 3 // regardless of what the Startup() was. This is done to preserve the // H-CRTM PCR so that they don't get overwritten with the normal // PCR startup initialization. This basically means that g_StartupLocality3 // and g_DrtmPreStartup can't both be SET at the same time. if(g_DrtmPreStartup) locality = 0; g_StartupLocality3 = (locality == 3); #if USE_DA_USED // If there was no orderly shutdown, then there might have been a write to // failedTries that didn't get recorded but only if g_daUsed was SET in the // shutdown state g_daUsed = (gp.orderlyState == SU_DA_USED_VALUE); if(g_daUsed) gp.orderlyState = SU_NONE_VALUE; #endif g_prevOrderlyState = gp.orderlyState; // If there was a proper shutdown, then the startup modifiers are in the // orderlyState. Turn them off in the copy. if(IS_ORDERLY(g_prevOrderlyState)) g_prevOrderlyState &= ~(PRE_STARTUP_FLAG | STARTUP_LOCALITY_3); // If this is a Resume, if(in->startupType == TPM_SU_STATE) { // then there must have been a prior TPM2_ShutdownState(STATE) if(g_prevOrderlyState != TPM_SU_STATE) return TPM_RCS_VALUE + RC_Startup_startupType; // and the part of NV used for state save must have been recovered // correctly. // NOTE: if this fails, then the caller will need to do Startup(CLEAR). The // code for Startup(Clear) cannot fail if the NV can't be read correctly // because that would prevent the TPM from ever getting unstuck. if(g_nvOk == FALSE) return TPM_RC_NV_UNINITIALIZED; // For Resume, the H-CRTM has to be the same as the previous boot if(g_DrtmPreStartup != ((gp.orderlyState & PRE_STARTUP_FLAG) != 0)) return TPM_RCS_VALUE + RC_Startup_startupType; if(g_StartupLocality3 != ((gp.orderlyState & STARTUP_LOCALITY_3) != 0)) return TPM_RC_LOCALITY; } // Clean up the gp state gp.orderlyState = g_prevOrderlyState; // Internal Date Update if((gp.orderlyState == TPM_SU_STATE) && (g_nvOk == TRUE)) { // Always read the data that is only cleared on a Reset because this is not // a reset NvRead(&gr, NV_STATE_RESET_DATA, sizeof(gr)); if(in->startupType == TPM_SU_STATE) { // If this is a startup STATE (a Resume) need to read the data // that is cleared on a startup CLEAR because this is not a Reset // or Restart. NvRead(&gc, NV_STATE_CLEAR_DATA, sizeof(gc)); startup = SU_RESUME; } else startup = SU_RESTART; } else // Will do a TPM reset if Shutdown(CLEAR) and Startup(CLEAR) or no shutdown // or there was a failure reading the NV data. startup = SU_RESET; // Startup for cryptographic library. Don't do this until after the orderly // state has been read in from NV. OK = OK && CryptStartup(startup); // When the cryptographic library has been started, indicate that a TPM2_Startup // command has been received. OK = OK && TPMRegisterStartup(); // Read the platform unique value that is used as VENDOR_PERMANENT // authorization value g_platformUniqueDetails.t.size = (UINT16)_plat__GetUnique(1, sizeof(g_platformUniqueDetails.t.buffer), g_platformUniqueDetails.t.buffer); // Start up subsystems // Start set the safe flag OK = OK && TimeStartup(startup); // Start dictionary attack subsystem OK = OK && DAStartup(startup); // Enable hierarchies OK = OK && HierarchyStartup(startup); // Restore/Initialize PCR OK = OK && PCRStartup(startup, locality); // Restore/Initialize command audit information OK = OK && CommandAuditStartup(startup); // Restore the ACT OK = OK && ActStartup(startup); //// The following code was moved from Time.c where it made no sense if (OK) { switch (startup) { case SU_RESUME: // Resume sequence gr.restartCount++; break; case SU_RESTART: // Hibernate sequence gr.clearCount++; gr.restartCount++; break; default: // Reset object context ID to 0 gr.objectContextID = 0; // Reset clearCount to 0 gr.clearCount = 0; // Reset sequence // Increase resetCount gp.resetCount++; // Write resetCount to NV NV_SYNC_PERSISTENT(resetCount); gp.totalResetCount++; // We do not expect the total reset counter overflow during the life // time of TPM. if it ever happens, TPM will be put to failure mode // and there is no way to recover it. // The reason that there is no recovery is that we don't increment // the NV totalResetCount when incrementing would make it 0. When the // TPM starts up again, the old value of totalResetCount will be read // and we will get right back to here with the increment failing. #if 0 // libtpms added if(gp.totalResetCount == 0) FAIL(FATAL_ERROR_INTERNAL); #endif // libtpms added // Write total reset counter to NV NV_SYNC_PERSISTENT(totalResetCount); // Reset restartCount gr.restartCount = 0; break; } } // Initialize session table OK = OK && SessionStartup(startup); // Initialize object table OK = OK && ObjectStartup(); // Initialize index/evict data. This function clears read/write locks // in NV index OK = OK && NvEntityStartup(startup); // Initialize the orderly shut down flag for this cycle to SU_NONE_VALUE. gp.orderlyState = SU_NONE_VALUE; OK = OK && NV_SYNC_PERSISTENT(orderlyState); // This can be reset after the first completion of a TPM2_Startup() after // a power loss. It can probably be reset earlier but this is an OK place. if (OK) g_powerWasLost = FALSE; return (OK) ? TPM_RC_SUCCESS : TPM_RC_FAILURE; } #endif // CC_Startup #include "Tpm.h" #include "Shutdown_fp.h" #if CC_Shutdown // Conditional expansion of this file TPM_RC TPM2_Shutdown( Shutdown_In *in // IN: input parameter list ) { // The command needs NV update. Check if NV is available. // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at // this point RETURN_IF_NV_IS_NOT_AVAILABLE; // Input Validation // If PCR bank has been reconfigured, a CLEAR state save is required if(g_pcrReConfig && in->shutdownType == TPM_SU_STATE) return TPM_RCS_TYPE + RC_Shutdown_shutdownType; // Internal Data Update gp.orderlyState = in->shutdownType; #if USE_DA_USED // CLEAR g_daUsed so that any future DA-protected access will cause the // shutdown to become non-orderly. It is not sufficient to invalidate the // shutdown state after a DA failure because an attacker can inhibit access // to NV and use the fact that an update of failedTries was attempted as an // indication of an authorization failure. By making sure that the orderly state // is CLEAR before any DA attempt, this prevents the possibility of this 'attack.' g_daUsed = FALSE; #endif // PCR private date state save PCRStateSave(in->shutdownType); // Save the ACT state ActShutdown(in->shutdownType); // Save RAM backed NV index data NvUpdateIndexOrderlyData(); #if ACCUMULATE_SELF_HEAL_TIMER // Save the current time value go.time = g_time; #endif // Save all orderly data NvWrite(NV_ORDERLY_DATA, sizeof(ORDERLY_DATA), &go); if(in->shutdownType == TPM_SU_STATE) { // Save STATE_RESET and STATE_CLEAR data NvWrite(NV_STATE_CLEAR_DATA, sizeof(STATE_CLEAR_DATA), &gc); NvWrite(NV_STATE_RESET_DATA, sizeof(STATE_RESET_DATA), &gr); // Save the startup flags for resume if(g_DrtmPreStartup) gp.orderlyState = TPM_SU_STATE | PRE_STARTUP_FLAG; else if(g_StartupLocality3) gp.orderlyState = TPM_SU_STATE | STARTUP_LOCALITY_3; } // only two shutdown options else if(in->shutdownType != TPM_SU_CLEAR) { return TPM_RCS_VALUE + RC_Shutdown_shutdownType; } NV_SYNC_PERSISTENT(orderlyState); return TPM_RC_SUCCESS; } #endif // CC_Shutdown libtpms-0.9.3/src/tpm2/Startup_fp.h000066400000000000000000000071511421143571500171550ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Startup_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef STARTUP_FP_H #define STARTUP_FP_H void _TPM_Init( void ); typedef struct { TPM_SU startupType; } Startup_In; #define RC_Startup_startupType (TPM_RC_P + TPM_RC_1) TPM_RC TPM2_Startup( Startup_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/StateMarshal.c000066400000000000000000000066051421143571500174140ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Marshalling and unmarshalling of state */ /* Written by Stefan Berger */ /* IBM Thomas J. Watson Research Center */ /* */ /* (c) Copyright IBM Corporation 2017,2018. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include #include "config.h" #include "StateMarshal.h" #include "Volatile.h" #define TPM_HAVE_TPM2_DECLARATIONS #include "tpm_library_intern.h" #include "tpm_nvfilename.h" #include "tpm_error.h" #include "tpm_memory.h" UINT16 VolatileSave(BYTE **buffer, INT32 *size) { return VolatileState_Save(buffer, size); } TPM_RC VolatileLoad(BOOL *restored) { TPM_RC rc = TPM_RC_SUCCESS; #ifdef TPM_LIBTPMS_CALLBACKS unsigned char *data = NULL; uint32_t length = 0; struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks(); TPM_RESULT ret = TPM_SUCCESS; bool is_empty_state; *restored = FALSE; /* try to get state blob set via TPMLIB_SetState() */ GetCachedState(TPMLIB_STATE_VOLATILE, &data, &length, &is_empty_state); if (is_empty_state) return rc; if (!data && cbs->tpm_nvram_loaddata) { uint32_t tpm_number = 0; const char *name = TPM_VOLATILESTATE_NAME; ret = cbs->tpm_nvram_loaddata(&data, &length, tpm_number, name); } if (data && ret == TPM_SUCCESS) { unsigned char *p = data; rc = VolatileState_Load(&data, (INT32 *)&length); /* * if this failed, VolatileState_Load will have started * failure mode. */ free(p); *restored = (rc == 0); } #endif /* TPM_LIBTPMS_CALLBACKS */ return rc; } libtpms-0.9.3/src/tpm2/StateMarshal.h000066400000000000000000000045501421143571500174160ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Marshalling and unmarshalling of state */ /* Written by Stefan Berger */ /* IBM Thomas J. Watson Research Center */ /* */ /* (c) Copyright IBM Corporation 2017,2018. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef STATE_MARSHAL_H #define STATE_MARSHAL_H #include "Tpm.h" #include "TpmTypes.h" /* * we keep these in a separate file to avoid symbol clashes when * included from the interface code. */ TPM_RC VolatileLoad(BOOL *restored); UINT16 VolatileSave(BYTE **buffer, INT32 *size); #endif /* STATE_MARSHAL_H */ libtpms-0.9.3/src/tpm2/StirRandom_fp.h000066400000000000000000000071241421143571500175750ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: StirRandom_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef STIRRANDOM_FP_H #define STIRRANDOM_FP_H typedef struct { TPM2B_SENSITIVE_DATA inData; } StirRandom_In; #define RC_StirRandom_inData (TPM_RC_P + TPM_RC_1) TPM_RC TPM2_StirRandom( StirRandom_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/SupportLibraryFunctionPrototypes_fp.h000066400000000000000000000164131421143571500243340ustar00rootroot00000000000000/********************************************************************************/ /* */ /* For Selected Math Library */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: SupportLibraryFunctionPrototypes_fp.h 1529 2019-11-21 23:29:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ #ifndef SUPPORT_LIBRARY_FUNCTION_PROTOTYPES_H #define SUPPORT_LIBRARY_FUNCTION_PROTOTYPES_H /* 10.1.11 SupportLibraryFunctionPrototypes_fp.h */ /* 10.1.11.1 Introduction */ /* This file contains the function prototypes for the functions that need to be present in the selected math library. For each function listed, there should be a small stub function. That stub provides the interface between the TPM code and the support library. In most cases, the stub function will only need to do a format conversion between the TPM big number and the support library big number. The TPM big number format was chosen to make this relatively simple and fast. */ /* 10.1.11.2 SupportLibInit() */ /* This function is called by CryptInit() so that necessary initializations can be performed on the cryptographic library. */ LIB_EXPORT int SupportLibInit(void); /* 10.1.11.3 MathLibraryCompatibililtyCheck() */ /* This function is only used during development to make sure that the library that is being referenced is using the same size of data structures as the TPM. */ BOOL MathLibraryCompatibilityCheck( void ); /* 10.1.1114 BnModMult() */ /* Does multiply op1 * op2 and divide by modulus returning the remainder of the divide. */ LIB_EXPORT BOOL BnModMult(bigNum result, bigConst op1, bigConst op2, bigConst modulus); /* 10.1.11.5 BnMult() */ /* Multiplies two numbers and returns the result */ LIB_EXPORT BOOL BnMult(bigNum result, bigConst multiplicand, bigConst multiplier); /* 10.1.11.6 BnDiv() */ /* This function divides two bigNum values. The function returns FALSE if there is an error in the operation. */ LIB_EXPORT BOOL BnDiv(bigNum quotient, bigNum remainder, bigConst dividend, bigConst divisor); /* 10.1.11.7 BnMod() */ #define BnMod(a, b) BnDiv(NULL, (a), (a), (b)) /* 10.1.11.8 BnGcd() */ /* Get the greatest common divisor of two numbers. This function is only needed when the TPM implements RSA. */ LIB_EXPORT BOOL BnGcd(bigNum gcd, bigConst number1, bigConst number2); /* 10.1.11.9 BnModExp() */ /* Do modular exponentiation using bigNum values. This function is only needed when the TPM implements RSA. */ LIB_EXPORT BOOL BnModExp(bigNum result, bigConst number, bigConst exponent, bigConst modulus); /* 10.1.11.10 BnModInverse() */ /* Modular multiplicative inverse. This function is only needed when the TPM implements RSA. */ LIB_EXPORT BOOL BnModInverse(bigNum result, bigConst number, bigConst modulus); /* 10.1.11.11 BnEccModMult() */ /* This function does a point multiply of the form R = [d]S. A return of FALSE indicates that the result was the point at infinity. This function is only needed if the TPM supports ECC. */ LIB_EXPORT BOOL BnEccModMult(bigPoint R, pointConst S, bigConst d, bigCurve E); /* 10.1.11.13 BnEccModMult2() */ /* This function does a point multiply of the form R = [d]S + [u]Q. A return of FALSE indicates that the result was the point at infinity. This function is only needed if the TPM supports ECC */ LIB_EXPORT BOOL BnEccModMult2(bigPoint R, pointConst S, bigConst d, pointConst Q, bigConst u, bigCurve E); /* 10.1.11.14 BnEccAdd() */ /* This function does a point add R = S + Q. A return of FALSE indicates that the result was the point at infinity. This function is only needed if the TPM supports ECC. */ LIB_EXPORT BOOL BnEccAdd(bigPoint R, pointConst S, pointConst Q, bigCurve E); /* 10.1.11.15 BnCurveInitialize() */ /* This function is used to initialize the pointers of a bnCurve_t structure. The structure is a set of pointers to bigNum values. The curve-dependent values are set by a different function. This function is only needed if the TPM supports ECC.*/ LIB_EXPORT bigCurve BnCurveInitialize(bigCurve E, TPM_ECC_CURVE curveId); /* 10.1.11.16 BnCurveFree() */ /* This function will free the allocated components of the curve and end the frame in which the curve data exists */ LIB_EXPORT void BnCurveFree(bigCurve E); #endif libtpms-0.9.3/src/tpm2/SymmetricCommands.c000066400000000000000000000336561421143571500204700ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Symmetric Commands */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: SymmetricCommands.c 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2021 */ /* */ /********************************************************************************/ #include "Tpm.h" #include "EncryptDecrypt_fp.h" #if CC_EncryptDecrypt2 #include "EncryptDecrypt_spt_fp.h" #endif #if CC_EncryptDecrypt // Conditional expansion of this file TPM_RC TPM2_EncryptDecrypt( EncryptDecrypt_In *in, // IN: input parameter list EncryptDecrypt_Out *out // OUT: output parameter list ) { #if CC_EncryptDecrypt2 return EncryptDecryptShared(in->keyHandle, in->decrypt, in->mode, &in->ivIn, &in->inData, out); #else OBJECT *symKey; UINT16 keySize; UINT16 blockSize; BYTE *key; TPM_ALG_ID alg; TPM_ALG_ID mode; TPM_RC result; BOOL OK; TPMA_OBJECT attributes; // Input Validation symKey = HandleToObject(in->keyHandle); mode = symKey->publicArea.parameters.symDetail.sym.mode.sym; attributes = symKey->publicArea.objectAttributes; // The input key should be a symmetric key if(symKey->publicArea.type != TPM_ALG_SYMCIPHER) return TPM_RCS_KEY + RC_EncryptDecrypt_keyHandle; // The key must be unrestricted and allow the selected operation OK = IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted) if(YES == in->decrypt) OK = OK && IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt); else OK = OK && IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign); if(!OK) return TPM_RCS_ATTRIBUTES + RC_EncryptDecrypt_keyHandle; // If the key mode is not TPM_ALG_NULL... // or TPM_ALG_NULL if(mode != TPM_ALG_NULL) { // then the input mode has to be TPM_ALG_NULL or the same as the key if((in->mode != TPM_ALG_NULL) && (in->mode != mode)) return TPM_RCS_MODE + RC_EncryptDecrypt_mode; } else { // if the key mode is null, then the input can't be null if(in->mode == TPM_ALG_NULL) return TPM_RCS_MODE + RC_EncryptDecrypt_mode; mode = in->mode; } // The input iv for ECB mode should be an Empty Buffer. All the other modes // should have an iv size same as encryption block size keySize = symKey->publicArea.parameters.symDetail.sym.keyBits.sym; alg = symKey->publicArea.parameters.symDetail.sym.algorithm; blockSize = CryptGetSymmetricBlockSize(alg, keySize); // reverify the algorithm. This is mainly to keep static analysis tools happy if(blockSize == 0) return TPM_RCS_KEY + RC_EncryptDecrypt_keyHandle; // Note: When an algorithm is not supported by a TPM, the TPM_ALG_xxx for that // algorithm is not defined. However, it is assumed that the TPM_ALG_xxx for // the algorithm is always defined. Both have the same numeric value. // TPM_ALG_xxx is used here so that the code does not get cluttered with // #ifdef's. Having this check does not mean that the algorithm is supported. // If it was not supported the unmarshaling code would have rejected it before // this function were called. This means that, depending on the implementation, // the check could be redundant but it doesn't hurt. if(((mode == TPM_ALG_ECB) && (in->ivIn.t.size != 0)) || ((mode != TPM_ALG_ECB) && (in->ivIn.t.size != blockSize))) return TPM_RCS_SIZE + RC_EncryptDecrypt_ivIn; // The input data size of CBC mode or ECB mode must be an even multiple of // the symmetric algorithm's block size if(((mode == TPM_ALG_CBC) || (mode == TPM_ALG_ECB)) && ((in->inData.t.size % blockSize) != 0)) return TPM_RCS_SIZE + RC_EncryptDecrypt_inData; // Copy IV // Note: This is copied here so that the calls to the encrypt/decrypt functions // will modify the output buffer, not the input buffer out->ivOut = in->ivIn; // Command Output key = symKey->sensitive.sensitive.sym.t.buffer; // For symmetric encryption, the cipher data size is the same as plain data // size. out->outData.t.size = in->inData.t.size; if(in->decrypt == YES) { // Decrypt data to output result = CryptSymmetricDecrypt(out->outData.t.buffer, alg, keySize, key, &(out->ivOut), mode, in->inData.t.size, in->inData.t.buffer); } else { // Encrypt data to output result = CryptSymmetricEncrypt(out->outData.t.buffer, alg, keySize, key, &(out->ivOut), mode, in->inData.t.size, in->inData.t.buffer); } return result; #endif // CC_EncryptDecrypt2 } #endif // CC_EncryptDecrypt #include "Tpm.h" #include "EncryptDecrypt2_fp.h" #include "EncryptDecrypt_spt_fp.h" #if CC_EncryptDecrypt2 // Conditional expansion of this file TPM_RC TPM2_EncryptDecrypt2( EncryptDecrypt2_In *in, // IN: input parameter list EncryptDecrypt2_Out *out // OUT: output parameter list ) { TPM_RC result; // EncryptDecyrptShared() performs the operations as shown in // TPM2_EncrypDecrypt result = EncryptDecryptShared(in->keyHandle, in->decrypt, in->mode, &in->ivIn, &in->inData, (EncryptDecrypt_Out *)out); // Handle response code swizzle. switch(result) { case TPM_RCS_MODE + RC_EncryptDecrypt_mode: result = TPM_RCS_MODE + RC_EncryptDecrypt2_mode; break; case TPM_RCS_SIZE + RC_EncryptDecrypt_ivIn: result = TPM_RCS_SIZE + RC_EncryptDecrypt2_ivIn; break; case TPM_RCS_SIZE + RC_EncryptDecrypt_inData: result = TPM_RCS_SIZE + RC_EncryptDecrypt2_inData; break; default: break; } return result; } #endif // CC_EncryptDecrypt2 #include "Tpm.h" #include "Hash_fp.h" #if CC_Hash // Conditional expansion of this file TPM_RC TPM2_Hash( Hash_In *in, // IN: input parameter list Hash_Out *out // OUT: output parameter list ) { HASH_STATE hashState; // Command Output // Output hash // Start hash stack out->outHash.t.size = CryptHashStart(&hashState, in->hashAlg); // Adding hash data CryptDigestUpdate2B(&hashState, &in->data.b); // Complete hash CryptHashEnd2B(&hashState, &out->outHash.b); // Output ticket out->validation.tag = TPM_ST_HASHCHECK; out->validation.hierarchy = in->hierarchy; if(in->hierarchy == TPM_RH_NULL) { // Ticket is not required out->validation.hierarchy = TPM_RH_NULL; out->validation.digest.t.size = 0; } else if(in->data.t.size >= sizeof(TPM_GENERATED_VALUE) && !TicketIsSafe(&in->data.b)) { // Ticket is not safe out->validation.hierarchy = TPM_RH_NULL; out->validation.digest.t.size = 0; } else { // Compute ticket TicketComputeHashCheck(in->hierarchy, in->hashAlg, &out->outHash, &out->validation); } return TPM_RC_SUCCESS; } #endif // CC_Hash #include "Tpm.h" #include "HMAC_fp.h" #if CC_HMAC // Conditional expansion of this file TPM_RC TPM2_HMAC( HMAC_In *in, // IN: input parameter list HMAC_Out *out // OUT: output parameter list ) { HMAC_STATE hmacState; OBJECT *hmacObject; TPMI_ALG_HASH hashAlg; TPMT_PUBLIC *publicArea; // Input Validation // Get HMAC key object and public area pointers hmacObject = HandleToObject(in->handle); publicArea = &hmacObject->publicArea; // Make sure that the key is an HMAC key if(publicArea->type != TPM_ALG_KEYEDHASH) return TPM_RCS_TYPE + RC_HMAC_handle; // and that it is unrestricted if (IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted)) return TPM_RCS_ATTRIBUTES + RC_HMAC_handle; // and that it is a signing key if (!IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign)) return TPM_RCS_KEY + RC_HMAC_handle; // See if the key has a default if(publicArea->parameters.keyedHashDetail.scheme.scheme == TPM_ALG_NULL) // it doesn't so use the input value hashAlg = in->hashAlg; else { // key has a default so use it hashAlg = publicArea->parameters.keyedHashDetail.scheme.details.hmac.hashAlg; // and verify that the input was either the TPM_ALG_NULL or the default if(in->hashAlg != TPM_ALG_NULL && in->hashAlg != hashAlg) hashAlg = TPM_ALG_NULL; } // if we ended up without a hash algorithm then return an error if(hashAlg == TPM_ALG_NULL) return TPM_RCS_VALUE + RC_HMAC_hashAlg; // Command Output // Start HMAC stack out->outHMAC.t.size = CryptHmacStart2B(&hmacState, hashAlg, &hmacObject->sensitive.sensitive.bits.b); // Adding HMAC data CryptDigestUpdate2B(&hmacState.hashState, &in->buffer.b); // Complete HMAC CryptHmacEnd2B(&hmacState, &out->outHMAC.b); return TPM_RC_SUCCESS; } #endif // CC_HMAC #include "Tpm.h" #include "MAC_fp.h" #if CC_MAC // Conditional expansion of this file /* Error Returns Meaning */ /* TPM_RC_ATTRIBUTES key referenced by handle is a restricted key */ /* TPM_RC_KEY handle does not reference a signing key */ /* TPM_RC_TYPE key referenced by handle is not an HMAC key */ /* TPM_RC_VALUE hashAlg is not compatible with the hash algorithm of the scheme of the object referenced by handle */ TPM_RC TPM2_MAC( MAC_In *in, // IN: input parameter list MAC_Out *out // OUT: output parameter list ) { OBJECT *keyObject; HMAC_STATE state; TPMT_PUBLIC *publicArea; TPM_RC result; // Input Validation // Get MAC key object and public area pointers keyObject = HandleToObject(in->handle); publicArea = &keyObject->publicArea; // If the key is not able to do a MAC, indicate that the handle selects an // object that can't do a MAC result = CryptSelectMac(publicArea, &in->inScheme); if(result == TPM_RCS_TYPE) return TPM_RCS_TYPE + RC_MAC_handle; // If there is another error type, indicate that the scheme and key are not // compatible if(result != TPM_RC_SUCCESS) return RcSafeAddToResult(result, RC_MAC_inScheme); // Make sure that the key is not restricted if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted)) return TPM_RCS_ATTRIBUTES + RC_MAC_handle; // and that it is a signing key if(!IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign)) return TPM_RCS_KEY + RC_MAC_handle; // Command Output out->outMAC.t.size = CryptMacStart(&state, &publicArea->parameters, in->inScheme, &keyObject->sensitive.sensitive.any.b); // If the mac can't start, treat it as a fatal error if(out->outMAC.t.size == 0) return TPM_RC_FAILURE; CryptDigestUpdate2B(&state.hashState, &in->buffer.b); // If the MAC result is not what was expected, it is a fatal error if(CryptHmacEnd2B(&state, &out->outMAC.b) != out->outMAC.t.size) return TPM_RC_FAILURE; return TPM_RC_SUCCESS; } #endif // CC_MAC libtpms-0.9.3/src/tpm2/SymmetricTest.h000066400000000000000000000151211421143571500176360ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Structures and data definitions for the symmetric tests */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: SymmetricTest.h 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2021 */ /* */ /********************************************************************************/ /* 10.1.11 SymmetricTest.h */ /* 10.1.11.1 Introduction */ /* This file contains the structures and data definitions for the symmetric tests. This file references the header file that contains the actual test vectors. This organization was chosen so that the program that is used to generate the test vector values does not have to also re-generate this data. */ #ifndef SELF_TEST_DATA #error "This file may only be included in AlgorithmTests.c" #endif #ifndef _SYMMETRIC_TEST_H #define _SYMMETRIC_TEST_H #include "SymmetricTestData.h" /* 10.1.11.2 Symmetric Test Structures */ const SYMMETRIC_TEST_VECTOR c_symTestValues[NUM_SYMS + 1] = { #if ALG_AES && AES_128 {TPM_ALG_AES, 128, key_AES128, 16, sizeof(dataIn_AES128), dataIn_AES128, {dataOut_AES128_CTR, dataOut_AES128_OFB, dataOut_AES128_CBC, dataOut_AES128_CFB, dataOut_AES128_ECB}}, #endif #if ALG_AES && AES_192 {TPM_ALG_AES_, 192, key_AES192, 16, sizeof(dataIn_AES192), dataIn_AES192, {dataOut_AES192_CTR, dataOut_AES192_OFB, dataOut_AES192_CBC, dataOut_AES192_CFB, dataOut_AES192_ECB}}, #endif #if ALG_AES && AES_256 {TPM_ALG_AES, 256, key_AES256, 16, sizeof(dataIn_AES256), dataIn_AES256, {dataOut_AES256_CTR, dataOut_AES256_OFB, dataOut_AES256_CBC, dataOut_AES256_CFB, dataOut_AES256_ECB}}, #endif #if ALG_SM4 && SM4_128 // libtpms activated {TPM_ALG_SM4, 128, key_SM4128, 16, sizeof(dataIn_SM4128), dataIn_SM4128, {dataOut_SM4128_CTR, dataOut_SM4128_OFB, dataOut_SM4128_CBC, dataOut_SM4128_CFB, dataOut_AES128_ECB}}, #endif // libtpms added begin #if ALG_TDES && TDES_128 {TPM_ALG_TDES, 128, key_TDES128, 8, sizeof(dataIn_TDES128), dataIn_TDES128, {dataOut_TDES128_CTR, dataOut_TDES128_OFB, dataOut_TDES128_CBC, dataOut_TDES128_CFB, dataOut_TDES128_ECB}}, {TPM_ALG_TDES, 128, key_TDES128, 8, sizeof(dataInShort_TDES128), dataInShort_TDES128, {NULL, dataOutShort_TDES128_OFB, NULL, dataOutShort_TDES128_CFB, NULL}}, #endif #if ALG_TDES && TDES_192 {TPM_ALG_TDES, 192, key_TDES192, 8, sizeof(dataIn_TDES192), dataIn_TDES192, {dataOut_TDES192_CTR, dataOut_TDES192_OFB, dataOut_TDES192_CBC, dataOut_TDES192_CFB, dataOut_TDES192_ECB}}, {TPM_ALG_TDES, 192, key_TDES192, 8, sizeof(dataInShort_TDES192), dataInShort_TDES192, {NULL, dataOutShort_TDES192_OFB, NULL, dataOutShort_TDES192_CFB, NULL}}, #endif #if ALG_CAMELLIA && CAMELLIA_128 {TPM_ALG_CAMELLIA, 128, key_CAMELLIA128, 16, sizeof(dataIn_CAMELLIA128), dataIn_CAMELLIA128, {dataOut_CAMELLIA128_CTR, dataOut_CAMELLIA128_OFB, dataOut_CAMELLIA128_CBC, dataOut_CAMELLIA128_CFB, dataOut_CAMELLIA128_ECB}}, #endif #if ALG_CAMELLIA && CAMELLIA_192 {TPM_ALG_CAMELLIA, 192, key_CAMELLIA192, 16, sizeof(dataIn_CAMELLIA192), dataIn_CAMELLIA192, {dataOut_CAMELLIA192_CTR, dataOut_CAMELLIA192_OFB, dataOut_CAMELLIA192_CBC, dataOut_CAMELLIA192_CFB, dataOut_CAMELLIA192_ECB}}, #endif #if ALG_CAMELLIA && CAMELLIA_256 {TPM_ALG_CAMELLIA, 256, key_CAMELLIA256, 16, sizeof(dataIn_CAMELLIA256), dataIn_CAMELLIA256, {dataOut_CAMELLIA256_CTR, dataOut_CAMELLIA256_OFB, dataOut_CAMELLIA256_CBC, dataOut_CAMELLIA256_CFB, dataOut_CAMELLIA256_ECB}}, #endif // libtpms added end {0} }; #endif // _SYMMETRIC_TEST_H libtpms-0.9.3/src/tpm2/SymmetricTestData.h000066400000000000000000000455151421143571500204420ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Vector for testing Either Encrypt or Decrypt */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: SymmetricTestData.h 1476 2019-06-10 19:32:03Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ #ifndef SYMMETRICTESTDATA_H #define SYMMETRICTESTDATA_H /* 10.1.10 SymmetricTestData.h */ /* This is a vector for testing either encrypt or decrypt. The premise for decrypt is that the IV for decryption is the same as the IV for encryption. However, the ivOut value may be different for encryption and decryption. We will encrypt at least two blocks. This means that the chaining value will be used for each of the schemes (if any) and that implicitly checks that the chaining value is handled properly. */ #if AES_128 const BYTE key_AES128 [] = { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c}; const BYTE dataIn_AES128 [] = { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51}; const BYTE dataOut_AES128_ECB [] = { 0x3a, 0xd7, 0x7b, 0xb4, 0x0d, 0x7a, 0x36, 0x60, 0xa8, 0x9e, 0xca, 0xf3, 0x24, 0x66, 0xef, 0x97, 0xf5, 0xd3, 0xd5, 0x85, 0x03, 0xb9, 0x69, 0x9d, 0xe7, 0x85, 0x89, 0x5a, 0x96, 0xfd, 0xba, 0xaf}; const BYTE dataOut_AES128_CBC [] = { 0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46, 0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d, 0x50, 0x86, 0xcb, 0x9b, 0x50, 0x72, 0x19, 0xee, 0x95, 0xdb, 0x11, 0x3a, 0x91, 0x76, 0x78, 0xb2}; const BYTE dataOut_AES128_CFB [] = { 0x3b, 0x3f, 0xd9, 0x2e, 0xb7, 0x2d, 0xad, 0x20, 0x33, 0x34, 0x49, 0xf8, 0xe8, 0x3c, 0xfb, 0x4a, 0xc8, 0xa6, 0x45, 0x37, 0xa0, 0xb3, 0xa9, 0x3f, 0xcd, 0xe3, 0xcd, 0xad, 0x9f, 0x1c, 0xe5, 0x8b}; const BYTE dataOut_AES128_OFB [] = { 0x3b, 0x3f, 0xd9, 0x2e, 0xb7, 0x2d, 0xad, 0x20, 0x33, 0x34, 0x49, 0xf8, 0xe8, 0x3c, 0xfb, 0x4a, 0x77, 0x89, 0x50, 0x8d, 0x16, 0x91, 0x8f, 0x03, 0xf5, 0x3c, 0x52, 0xda, 0xc5, 0x4e, 0xd8, 0x25}; const BYTE dataOut_AES128_CTR [] = { 0x87, 0x4d, 0x61, 0x91, 0xb6, 0x20, 0xe3, 0x26, 0x1b, 0xef, 0x68, 0x64, 0x99, 0x0d, 0xb6, 0xce, 0x98, 0x06, 0xf6, 0x6b, 0x79, 0x70, 0xfd, 0xff, 0x86, 0x17, 0x18, 0x7b, 0xb9, 0xff, 0xfd, 0xff}; #endif #if AES_192 const BYTE key_AES192 [] = { 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5, 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b}; const BYTE dataIn_AES192 [] = { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51}; const BYTE dataOut_AES192_ECB [] = { 0xbd, 0x33, 0x4f, 0x1d, 0x6e, 0x45, 0xf2, 0x5f, 0xf7, 0x12, 0xa2, 0x14, 0x57, 0x1f, 0xa5, 0xcc, 0x97, 0x41, 0x04, 0x84, 0x6d, 0x0a, 0xd3, 0xad, 0x77, 0x34, 0xec, 0xb3, 0xec, 0xee, 0x4e, 0xef}; const BYTE dataOut_AES192_CBC [] = { 0x4f, 0x02, 0x1d, 0xb2, 0x43, 0xbc, 0x63, 0x3d, 0x71, 0x78, 0x18, 0x3a, 0x9f, 0xa0, 0x71, 0xe8, 0xb4, 0xd9, 0xad, 0xa9, 0xad, 0x7d, 0xed, 0xf4, 0xe5, 0xe7, 0x38, 0x76, 0x3f, 0x69, 0x14, 0x5a}; const BYTE dataOut_AES192_CFB [] = { 0xcd, 0xc8, 0x0d, 0x6f, 0xdd, 0xf1, 0x8c, 0xab, 0x34, 0xc2, 0x59, 0x09, 0xc9, 0x9a, 0x41, 0x74, 0x67, 0xce, 0x7f, 0x7f, 0x81, 0x17, 0x36, 0x21, 0x96, 0x1a, 0x2b, 0x70, 0x17, 0x1d, 0x3d, 0x7a}; const BYTE dataOut_AES192_OFB [] = { 0xcd, 0xc8, 0x0d, 0x6f, 0xdd, 0xf1, 0x8c, 0xab, 0x34, 0xc2, 0x59, 0x09, 0xc9, 0x9a, 0x41, 0x74, 0xfc, 0xc2, 0x8b, 0x8d, 0x4c, 0x63, 0x83, 0x7c, 0x09, 0xe8, 0x17, 0x00, 0xc1, 0x10, 0x04, 0x01}; const BYTE dataOut_AES192_CTR [] = { 0x1a, 0xbc, 0x93, 0x24, 0x17, 0x52, 0x1c, 0xa2, 0x4f, 0x2b, 0x04, 0x59, 0xfe, 0x7e, 0x6e, 0x0b, 0x09, 0x03, 0x39, 0xec, 0x0a, 0xa6, 0xfa, 0xef, 0xd5, 0xcc, 0xc2, 0xc6, 0xf4, 0xce, 0x8e, 0x94}; #endif #if AES_256 const BYTE key_AES256 [] = { 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4}; const BYTE dataIn_AES256 [] = { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51}; const BYTE dataOut_AES256_ECB [] = { 0xf3, 0xee, 0xd1, 0xbd, 0xb5, 0xd2, 0xa0, 0x3c, 0x06, 0x4b, 0x5a, 0x7e, 0x3d, 0xb1, 0x81, 0xf8, 0x59, 0x1c, 0xcb, 0x10, 0xd4, 0x10, 0xed, 0x26, 0xdc, 0x5b, 0xa7, 0x4a, 0x31, 0x36, 0x28, 0x70}; const BYTE dataOut_AES256_CBC [] = { 0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba, 0x77, 0x9e, 0xab, 0xfb, 0x5f, 0x7b, 0xfb, 0xd6, 0x9c, 0xfc, 0x4e, 0x96, 0x7e, 0xdb, 0x80, 0x8d, 0x67, 0x9f, 0x77, 0x7b, 0xc6, 0x70, 0x2c, 0x7d}; const BYTE dataOut_AES256_CFB [] = { 0xdc, 0x7e, 0x84, 0xbf, 0xda, 0x79, 0x16, 0x4b, 0x7e, 0xcd, 0x84, 0x86, 0x98, 0x5d, 0x38, 0x60, 0x39, 0xff, 0xed, 0x14, 0x3b, 0x28, 0xb1, 0xc8, 0x32, 0x11, 0x3c, 0x63, 0x31, 0xe5, 0x40, 0x7b}; const BYTE dataOut_AES256_OFB [] = { 0xdc, 0x7e, 0x84, 0xbf, 0xda, 0x79, 0x16, 0x4b, 0x7e, 0xcd, 0x84, 0x86, 0x98, 0x5d, 0x38, 0x60, 0x4f, 0xeb, 0xdc, 0x67, 0x40, 0xd2, 0x0b, 0x3a, 0xc8, 0x8f, 0x6a, 0xd8, 0x2a, 0x4f, 0xb0, 0x8d}; const BYTE dataOut_AES256_CTR [] = { 0x60, 0x1e, 0xc3, 0x13, 0x77, 0x57, 0x89, 0xa5, 0xb7, 0xa7, 0xf5, 0x04, 0xbb, 0xf3, 0xd2, 0x28, 0xf4, 0x43, 0xe3, 0xca, 0x4d, 0x62, 0xb5, 0x9a, 0xca, 0x84, 0xe9, 0x90, 0xca, 0xca, 0xf5, 0xc5}; #endif // libtpms added begin #if TDES_128 const BYTE key_TDES128 [] = { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c}; const BYTE dataIn_TDES128 [] = { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51}; const BYTE dataOut_TDES128_ECB [] = { 0xdf, 0x8f, 0x88, 0x43, 0x2f, 0xea, 0x61, 0x0c, 0xc1, 0xfa, 0xaf, 0x1a, 0xb1, 0xc0, 0xc0, 0x37, 0x27, 0xf2, 0xe0, 0x8e, 0xda, 0x14, 0xbe, 0x79, 0x91, 0x95, 0xd2, 0x61, 0x2b, 0x46, 0x49, 0x4e, 0x1b, 0x10, 0xa6, 0xcc, 0x02, 0xb6, 0x5a, 0x6c}; const BYTE dataOut_TDES128_CBC [] = { 0x0a, 0xdd, 0xd5, 0x8a, 0x85, 0x33, 0xda, 0x86, 0x68, 0x8f, 0xb9, 0x05, 0xe3, 0x32, 0xe1, 0x58, 0x82, 0x33, 0x72, 0x85, 0xbc, 0x64, 0xcd, 0xd2, 0x25, 0xa2, 0x54, 0x5e, 0x22, 0xe0, 0xde, 0x92, 0x80, 0x69, 0x5e, 0x61, 0x77, 0xb5, 0x94, 0x1b}; const BYTE dataOut_TDES128_CFB [] = { 0x9c, 0xe7, 0x8f, 0x92, 0x6d, 0x37, 0xe4, 0xaa, 0x8e, 0x12, 0x14, 0xdc, 0xb7, 0x46, 0xc3, 0x6d, 0x3f, 0x6f, 0x17, 0x5b, 0x97, 0x9d, 0x9e, 0x8a, 0xb5, 0xc4, 0xcd, 0x2a, 0x7a, 0x3e, 0xad, 0xec}; const BYTE dataOut_TDES128_OFB [] = { 0x9c, 0xe7, 0x8f, 0x92, 0x6d, 0x37, 0xe4, 0xaa, 0x1b, 0x85, 0x9f, 0x7f, 0x80, 0x56, 0x10, 0xbc, 0xa4, 0xaa, 0x05, 0xd0, 0xd8, 0xf1, 0xda, 0x3e, 0x74, 0x82, 0x69, 0xb2, 0x8f, 0xf1, 0x6d, 0xde}; const BYTE dataOut_TDES128_CTR [] = { 0x9e, 0xf8, 0x6f, 0x66, 0x5a, 0xa7, 0x9c, 0x91, 0xe8, 0x07, 0xf9, 0x7a, 0x96, 0xf9, 0x6a, 0x87, 0x19, 0x22, 0x3f, 0x9d, 0x9e, 0x92, 0xc4, 0x25, 0x4a, 0x31, 0x6d, 0x3c, 0x35, 0xa6, 0x3a, 0x03}; const BYTE dataInShort_TDES128 [] = { 0x31, 0x32, 0x33, 0x34, 0x35}; // CBC and ECB need multiple of blocksize input const BYTE dataOutShort_TDES128_CFB[] = { 0xc6, 0x14, 0x02, 0x44, 0x76}; const BYTE dataOutShort_TDES128_OFB[] = { 0xc6, 0x14, 0x02, 0x44, 0x76}; #endif #if TDES_192 const BYTE key_TDES192 [] = { 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5, 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b}; const BYTE dataIn_TDES192 [] = { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51}; const BYTE dataOut_TDES192_ECB [] = { 0x37, 0x62, 0x02, 0x5d, 0xad, 0x85, 0x03, 0xe9, 0xff, 0x0f, 0xce, 0x66, 0x28, 0x74, 0x3f, 0x94, 0x72, 0x42, 0xbb, 0xc5, 0x14, 0xae, 0xc6, 0x2f, 0x61, 0xd1, 0x03, 0x9c, 0xd1, 0xf7, 0xf8, 0x29, 0x62, 0x91, 0x03, 0x74, 0xe7, 0x05, 0xb3, 0xb6}; const BYTE dataOut_TDES192_CBC [] = { 0x6c, 0x30, 0xbb, 0x5e, 0xbc, 0x73, 0xb1, 0x2d, 0x40, 0x24, 0x93, 0x65, 0xd8, 0x9a, 0x27, 0x4f, 0xdd, 0x09, 0xfc, 0x95, 0x28, 0xa3, 0xd9, 0x46, 0xf9, 0x15, 0x43, 0x52, 0x7a, 0x0d, 0xd6, 0x3e, 0xd1, 0xb0, 0x10, 0x64, 0x63, 0x5e, 0xa0, 0xb5}; const BYTE dataOut_TDES192_CFB [] = { 0x89, 0x00, 0xbb, 0xec, 0x56, 0xdc, 0x77, 0x81, 0x59, 0xdb, 0x1d, 0xa4, 0xe2, 0x33, 0x85, 0x2d, 0xbf, 0xfb, 0xe3, 0xe2, 0xe0, 0x46, 0x91, 0x09, 0x15, 0xcb, 0x41, 0x7c, 0xd5, 0x84, 0x60, 0xf1}; const BYTE dataOut_TDES192_OFB [] = { 0x89, 0x00, 0xbb, 0xec, 0x56, 0xdc, 0x77, 0x81, 0xf0, 0x12, 0x4b, 0xe3, 0xc5, 0x83, 0x60, 0x45, 0xda, 0x4d, 0xba, 0x05, 0x78, 0xa3, 0x77, 0xc8, 0x21, 0x57, 0xcd, 0x62, 0xbb, 0x93, 0xc8, 0x4e}; const BYTE dataOut_TDES192_CTR [] = { 0x17, 0x4d, 0xdf, 0xde, 0x7b, 0xe0, 0x2f, 0xb7, 0x58, 0x49, 0x76, 0xe5, 0x80, 0xbd, 0x49, 0x45, 0x64, 0x3a, 0xe4, 0x42, 0xfe, 0x4c, 0x25, 0xd4, 0x79, 0x74, 0xf0, 0xe6, 0x0b, 0x3d, 0x20, 0xac}; const BYTE dataInShort_TDES192 [] = { 0x31, 0x32, 0x33, 0x34, 0x35}; // CBC and ECB need multiple of blocksize input const BYTE dataOutShort_TDES192_CFB[] = { 0xd3, 0xf3, 0x36, 0x3a, 0x4d}; const BYTE dataOutShort_TDES192_OFB[] = { 0xd3, 0xf3, 0x36, 0x3a, 0x4d}; #endif #if CAMELLIA_128 const BYTE key_CAMELLIA128 [] = { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c}; const BYTE dataIn_CAMELLIA128 [] = { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51}; const BYTE dataOut_CAMELLIA128_ECB [] = { 0x43, 0x2f, 0xc5, 0xdc, 0xd6, 0x28, 0x11, 0x5b, 0x7c, 0x38, 0x8d, 0x77, 0x0b, 0x27, 0x0c, 0x96, 0x0b, 0xe1, 0xf1, 0x40, 0x23, 0x78, 0x2a, 0x22, 0xe8, 0x38, 0x4c, 0x5a, 0xbb, 0x7f, 0xab, 0x2b, 0x7e, 0x70, 0x91, 0x4b, 0xf1, 0x6a, 0x5b, 0xf9, 0x66, 0x36, 0x97, 0x11, 0xdf, 0xeb, 0x46, 0xef}; const BYTE dataOut_CAMELLIA128_CBC [] = { 0x16, 0x07, 0xcf, 0x49, 0x4b, 0x36, 0xbb, 0xf0, 0x0d, 0xae, 0xb0, 0xb5, 0x03, 0xc8, 0x31, 0xab, 0xa2, 0xf2, 0xcf, 0x67, 0x16, 0x29, 0xef, 0x78, 0x40, 0xc5, 0xa5, 0xdf, 0xb5, 0x07, 0x48, 0x87, 0xa0, 0x0a, 0xdd, 0x48, 0xf1, 0x12, 0xef, 0xa5, 0xae, 0xc3, 0x5f, 0x22, 0x3c, 0x55, 0x84, 0xc0}; const BYTE dataOut_CAMELLIA128_CFB [] = { 0x14, 0xf7, 0x64, 0x61, 0x87, 0x81, 0x7e, 0xb5, 0x86, 0x59, 0x91, 0x46, 0xb8, 0x2b, 0xd7, 0x19, 0xa5, 0x3d, 0x28, 0xbb, 0x82, 0xdf, 0x74, 0x11, 0x03, 0xea, 0x4f, 0x92, 0x1a, 0x44, 0x88, 0x0b}; const BYTE dataOut_CAMELLIA128_OFB [] = { 0x14, 0xf7, 0x64, 0x61, 0x87, 0x81, 0x7e, 0xb5, 0x86, 0x59, 0x91, 0x46, 0xb8, 0x2b, 0xd7, 0x19, 0x97, 0x32, 0x91, 0x71, 0x6c, 0x4d, 0x82, 0xd0, 0x1a, 0x07, 0x9e, 0x6d, 0xf7, 0x00, 0xe6, 0xeb}; const BYTE dataOut_CAMELLIA128_CTR [] = { 0xb8, 0x09, 0x14, 0x08, 0x77, 0xdd, 0x16, 0xc0, 0x76, 0x78, 0x09, 0x04, 0xf8, 0x3d, 0xed, 0x11, 0xbb, 0x41, 0xe6, 0x4e, 0x9b, 0xf1, 0x76, 0xce, 0x05, 0xd4, 0x18, 0x6b, 0x25, 0x86, 0xd4, 0xc9}; #endif #if CAMELLIA_192 #error Missing test cases for CAMELLIA_192 #endif #if CAMELLIA_256 const BYTE key_CAMELLIA256 [] = { 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4}; const BYTE dataIn_CAMELLIA256 [] = { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51}; const BYTE dataOut_CAMELLIA256_ECB [] = { 0xbe, 0xfd, 0x21, 0x9b, 0x11, 0x2f, 0xa0, 0x00, 0x98, 0x91, 0x9c, 0xd1, 0x01, 0xc9, 0xcc, 0xfa, 0xc9, 0x1d, 0x3a, 0x8f, 0x1a, 0xea, 0x08, 0xa9, 0x38, 0x6c, 0xf4, 0xb6, 0x6c, 0x01, 0x69, 0xea, 0x75, 0xf3, 0x8b, 0xad, 0x6b, 0x72, 0x54, 0xfa, 0xa4, 0xb0, 0x3d, 0x32, 0x0a, 0x0d, 0xb2, 0xdc}; const BYTE dataOut_CAMELLIA256_CBC [] = { 0xe6, 0xcf, 0xa3, 0x5f, 0xc0, 0x2b, 0x13, 0x4a, 0x4d, 0x2c, 0x0b, 0x67, 0x37, 0xac, 0x3e, 0xda, 0x36, 0xcb, 0xeb, 0x73, 0xbd, 0x50, 0x4b, 0x40, 0x70, 0xb1, 0xb7, 0xde, 0x2b, 0x21, 0xeb, 0x50, 0x6a, 0x0c, 0xf7, 0x4b, 0xbc, 0x7f, 0xbb, 0xa3, 0x82, 0x9c, 0x6d, 0x06, 0xcb, 0x4f, 0xb2, 0xc5}; const BYTE dataOut_CAMELLIA256_CFB [] = { 0xcf, 0x61, 0x07, 0xbb, 0x0c, 0xea, 0x7d, 0x7f, 0xb1, 0xbd, 0x31, 0xf5, 0xe7, 0xb0, 0x6c, 0x93, 0x89, 0xbe, 0xdb, 0x4c, 0xcd, 0xd8, 0x64, 0xea, 0x11, 0xba, 0x4c, 0xbe, 0x84, 0x9b, 0x5e, 0x2b}; const BYTE dataOut_CAMELLIA256_OFB [] = { 0xcf, 0x61, 0x07, 0xbb, 0x0c, 0xea, 0x7d, 0x7f, 0xb1, 0xbd, 0x31, 0xf5, 0xe7, 0xb0, 0x6c, 0x93, 0x85, 0x52, 0x1d, 0xb2, 0xf6, 0xbb, 0x67, 0x7f, 0x1e, 0xb2, 0x24, 0x46, 0x58, 0x41, 0x83, 0x40}; const BYTE dataOut_CAMELLIA256_CTR [] = { 0x47, 0xba, 0x6e, 0xea, 0x51, 0xb4, 0x38, 0xfc, 0xf2, 0x1c, 0x3c, 0xc9, 0x88, 0x76, 0x28, 0x17, 0x1a, 0x7b, 0xbb, 0xfc, 0x7f, 0x6e, 0x9e, 0xe5, 0x86, 0x46, 0xc3, 0xef, 0x8d, 0xab, 0xc5, 0x40}; #endif #if SM4_128 // source: https://tools.ietf.org/html/draft-ribose-cfrg-sm4-04#appendix-A.2 const BYTE key_SM4128 [] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}; const BYTE dataIn_SM4128 [] = { 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBB, 0xBB, 0xBB, 0xCC, 0xCC, 0xCC, 0xCC, 0xDD, 0xDD, 0xDD, 0xDD, 0xEE, 0xEE, 0xEE, 0xEE, 0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBB, 0xBB, 0xBB}; const BYTE dataOut_SM4128_ECB [] = { 0x5E, 0xC8, 0x14, 0x3D, 0xE5, 0x09, 0xCF, 0xF7, 0xB5, 0x17, 0x9F, 0x8F, 0x47, 0x4B, 0x86, 0x19, 0x2F, 0x1D, 0x30, 0x5A, 0x7F, 0xB1, 0x7D, 0xF9, 0x85, 0xF8, 0x1C, 0x84, 0x82, 0x19, 0x23, 0x04, 0x00, 0x2A, 0x8A, 0x4E, 0xFA, 0x86, 0x3C, 0xCA, 0xD0, 0x24, 0xAC, 0x03, 0x00, 0xBB, 0x40, 0xD2} const BYTE dataOut_SM4128_CBC [] = { 0x78, 0xEB, 0xB1, 0x1C, 0xC4, 0x0B, 0x0A, 0x48, 0x31, 0x2A, 0xAE, 0xB2, 0x04, 0x02, 0x44, 0xCB, 0x4C, 0xB7, 0x01, 0x69, 0x51, 0x90, 0x92, 0x26, 0x97, 0x9B, 0x0D, 0x15, 0xDC, 0x6A, 0x8F, 0x6D, 0x40, 0xD8, 0x41, 0x32, 0xE9, 0x99, 0x74, 0xA4, 0xA8, 0x80, 0x88, 0x68, 0x42, 0x07, 0x48, 0x59}; const BYTE dataOut_SM4128_CFB [] = { 0xAC, 0x32, 0x36, 0xCB, 0x86, 0x1D, 0xD3, 0x16, 0xE6, 0x41, 0x3B, 0x4E, 0x3C, 0x75, 0x24, 0xB7, 0x69, 0xD4, 0xC5, 0x4E, 0xD4, 0x33, 0xB9, 0xA0, 0x34, 0x60, 0x09, 0xBE, 0xB3, 0x7B, 0x2B, 0x3F}; const BYTE dataOut_SM4128_OFB [] = { 0xAC, 0x32, 0x36, 0xCB, 0x86, 0x1D, 0xD3, 0x16, 0xE6, 0x41, 0x3B, 0x4E, 0x3C, 0x75, 0x24, 0xB7, 0x1D, 0x01, 0xAC, 0xA2, 0x48, 0x7C, 0xA5, 0x82, 0xCB, 0xF5, 0x46, 0x3E, 0x66, 0x98, 0x53, 0x9B}; /* The data are obtained by running the commands as below: echo "AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDDEEEEEEEEFFFFFFFFAAAAAAAABBBBBBBB" | xxd -p -r > plain.txt openssl enc -sm4-ctr -in plain.txt -iv "F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF" -out out.txt -K "0123456789ABCDEFFEDCBA9876543210" */ const BYTE dataOut_SM4_CTR [] = { 0xF4, 0x88, 0x4C, 0x6D, 0x39, 0x7E, 0x0B, 0x06, 0x3D, 0xAC, 0xD9, 0x46, 0x1A, 0xA4, 0xA5, 0x6A, 0x60, 0xDD, 0xA7, 0x5F, 0x86, 0xBC, 0xFE, 0xA4, 0xF1, 0x5D, 0xB4, 0x6A, 0xD1, 0x4E, 0x7C, 0x7F}; #endif // libtpms added end #endif libtpms-0.9.3/src/tpm2/TPMB.h000066400000000000000000000106621421143571500155710ustar00rootroot00000000000000/********************************************************************************/ /* */ /* This file contains extra TPM2B structures */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: TPMB.h 1521 2019-11-15 21:00:47Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ #ifndef TPMB_H #define TPMB_H /* 5.17 TPMB.h */ /* This file contains extra TPM2B structures */ /* TPM2B Types */ typedef struct { UINT16 size; BYTE buffer[1]; } TPM2B, *P2B; typedef const TPM2B *PC2B; /* This macro helps avoid having to type in the structure in order to create a new TPM2B type that is used in a function. */ #define TPM2B_TYPE(name, bytes) \ typedef union { \ struct { \ UINT16 size; \ BYTE buffer[(bytes)]; \ } t; \ TPM2B b; \ } TPM2B_##name /* This macro defines a TPM2B with a constant character value. This macro sets the size of the string to the size minus the terminating zero byte. This lets the user of the label add their terminating 0. This method is chosen so that existing code that provides a label will continue to work correctly. Macro to instance and initialize a TPM2B value */ #define TPM2B_INIT(TYPE, name) \ TPM2B_##TYPE name = {sizeof(name.t.buffer), {0}} #define TPM2B_BYTE_VALUE(bytes) TPM2B_TYPE(bytes##_BYTE_VALUE, bytes) #endif libtpms-0.9.3/src/tpm2/TPMCmdp.c000066400000000000000000000255441421143571500162730ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Process the commands */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: TPMCmdp.c 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2021 */ /* */ /********************************************************************************/ /* D.4 TPMCmdp.c */ /* D.4.1. Description */ /* This file contains the functions that process the commands received on the control port or the command port of the simulator. The control port is used to allow simulation of hardware events (such as, _TPM_Hash_Start()) to test the simulated TPM's reaction to those events. This improves code coverage of the testing. */ /* D.4.2. Includes and Data Definitions */ #include #include #include #include #include "TpmBuildSwitches.h" #ifdef TPM_WINDOWS #include #include #endif #include "Platform_fp.h" #include "PlatformACT_fp.h" #include "ExecCommand_fp.h" #include "Manufacture_fp.h" #include "_TPM_Init_fp.h" #include "_TPM_Hash_Start_fp.h" #include "_TPM_Hash_Data_fp.h" #include "_TPM_Hash_End_fp.h" #include "TpmFail_fp.h" #include "TpmTcpProtocol.h" #include "Simulator_fp.h" #ifdef TPM_WINDOWS #include "TcpServer_fp.h" /* kgold */ #endif #ifdef TPM_POSIX #include "TcpServerPosix_fp.h" /* kgold */ #endif #include "TpmProfile.h" /* kgold */ static bool s_isPowerOn = false; /* D.4.3. Functions */ /* D.4.3.1. Signal_PowerOn() */ /* This function processes a power-on indication. Among other things, it calls the _TPM_Init() handler. */ void _rpc__Signal_PowerOn( bool isReset ) { // if power is on and this is not a call to do TPM reset then return if(s_isPowerOn && !isReset) return; // If this is a reset but power is not on, then return if(isReset && !s_isPowerOn) return; // Unless this is just a reset, pass power on signal to platform if(!isReset) _plat__Signal_PowerOn(); // Power on and reset both lead to _TPM_Init() _plat__Signal_Reset(); // Set state as power on s_isPowerOn = true; } #if 0 /* libtpms added */ /* D.4.3.2. Signal_Restart() */ /* This function processes the clock restart indication. All it does is call the platform function. */ void _rpc__Signal_Restart( void ) { _plat__TimerRestart(); } #endif /* libtpms added */ /* D.4.3.3. Signal_PowerOff() */ /* This function processes the power off indication. Its primary function is to set a flag indicating that the next power on indication should cause _TPM_Init() to be called. */ void _rpc__Signal_PowerOff( void ) { if(s_isPowerOn) // Pass power off signal to platform _plat__Signal_PowerOff(); // This could be redundant, but... s_isPowerOn = false; return; } #if 0 /* libtpms added */ /* D.4.3.4. _rpc__ForceFailureMode() */ /* This function is used to debug the Failure Mode logic of the TPM. It will set a flag in the TPM code such that the next call to TPM2_SelfTest() will result in a failure, putting the TPM into Failure Mode. */ void _rpc__ForceFailureMode( void ) { SetForceFailureMode(); return; } /* D.4.3.5. _rpc__Signal_PhysicalPresenceOn() */ /* This function is called to simulate activation of the physical presence pin. */ void _rpc__Signal_PhysicalPresenceOn( void ) { // If TPM power is on if(s_isPowerOn) // Pass physical presence on to platform _plat__Signal_PhysicalPresenceOn(); return; } /* D.4.3.6. _rpc__Signal_PhysicalPresenceOff() */ /* This function is called to simulate deactivation of the physical presence pin. */ void _rpc__Signal_PhysicalPresenceOff( void ) { // If TPM power is on if(s_isPowerOn) // Pass physical presence off to platform _plat__Signal_PhysicalPresenceOff(); return; } /* D.4.3.7. _rpc__Signal_Hash_Start() */ /* This function is called to simulate a _TPM_Hash_Start() event. It will call */ void _rpc__Signal_Hash_Start( void ) { // If TPM power is on if(s_isPowerOn) // Pass _TPM_Hash_Start signal to TPM _TPM_Hash_Start(); return; } /* D.4.3.8. _rpc__Signal_Hash_Data() */ /* This function is called to simulate a _TPM_Hash_Data() event. */ void _rpc__Signal_Hash_Data( _IN_BUFFER input ) { // If TPM power is on if(s_isPowerOn) // Pass _TPM_Hash_Data signal to TPM _TPM_Hash_Data(input.BufferSize, input.Buffer); return; } /* D.4.3.9. _rpc__Signal_HashEnd() */ /* This function is called to simulate a _TPM_Hash_End() event. */ void _rpc__Signal_HashEnd( void ) { // If TPM power is on if(s_isPowerOn) // Pass _TPM_HashEnd signal to TPM _TPM_Hash_End(); return; } #endif /* libtpms added */ /* D.4.3.10. rpc_Send_Command() */ /* This is the interface to the TPM code. */ void _rpc__Send_Command( unsigned char locality, _IN_BUFFER request, _OUT_BUFFER *response ) { // If TPM is power off, reject any commands. if(!s_isPowerOn) { response->BufferSize = 0; return; } // Set the locality of the command so that it doesn't change during the command _plat__LocalitySet(locality); // Do implementation-specific command dispatch _plat__RunCommand(request.BufferSize, request.Buffer, &response->BufferSize, &response->Buffer); return; } /* D.4.3.10. _rpc__Signal_CancelOn() */ /* This function is used to turn on the indication to cancel a command in process. An executing command is not interrupted. The command code may periodically check this indication to see if it should abort the current command processing and returned TPM_RC_CANCELLED. */ void _rpc__Signal_CancelOn( void ) { // If TPM is power off, reject this signal if(s_isPowerOn) // Set the platform canceling flag. _plat__SetCancel(); return; } /* D.4.3.11. _rpc__Signal_CancelOff() */ /* This function is used to turn off the indication to cancel a command in process. */ void _rpc__Signal_CancelOff( void ) { // If TPM power is n if(s_isPowerOn) // Set the platform canceling flag. _plat__ClearCancel(); return; } /* D.4.3.12. _rpc__Signal_NvOn() */ /* In a system where the NV memory used by the TPM is not within the TPM, the NV may not always be available. This function turns on the indicator that indicates that NV is available. */ void _rpc__Signal_NvOn( void ) { // If TPM power is on if(s_isPowerOn) // Make the NV available _plat__SetNvAvail(); return; } #if 0 /* libtpms added */ /* D.4.3.13. _rpc__Signal_NvOff() */ /* This function is used to set the indication that NV memory is no longer available. */ void _rpc__Signal_NvOff( void ) { // If TPM power is on if(s_isPowerOn) // Make NV not available _plat__ClearNvAvail(); return; } void RsaKeyCacheControl(int state); /* D.4.3.14. _rpc__RsaKeyCacheControl() */ /* This function is used to enable/disable the use of the RSA key cache during simulation. */ void _rpc__RsaKeyCacheControl( int state ) { #if USE_RSA_KEY_CACHE RsaKeyCacheControl(state); #else NOT_REFERENCED(state); #endif } #define TPM_RH_ACT_0 0x40000110 /* D.4.2.15. _rpc__ACT_GetSignaled() */ /* This function is used to count the ACT second tick. */ bool _rpc__ACT_GetSignaled( uint32_t actHandle ) { // If TPM power is on if (s_isPowerOn) // Query the platform return _plat__ACT_GetSignaled(actHandle - TPM_RH_ACT_0); return false; } #endif /* libtpms added */ /* libtpms added begin */ static bool tpmEstablished; void _rpc__Signal_SetTPMEstablished(void) { tpmEstablished = TRUE; } void _rpc__Signal_ResetTPMEstablished(void) { /* check for locality 3 or 4 already done by caller */ tpmEstablished = FALSE; } bool _rpc__Signal_GetTPMEstablished(void) { return tpmEstablished; } bool _rpc__Signal_IsPowerOn(void) { return s_isPowerOn; } /* libtpms added end */ libtpms-0.9.3/src/tpm2/TcpServerPosix_fp.h000066400000000000000000000110441421143571500204470ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Socket Interface to a TPM Simulator */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: TcpServerPosix_fp.h 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2021 */ /* */ /********************************************************************************/ #ifndef TCPSERVERPOSIX_FP_H #define TCPSERVERPOSIX_FP_H #include #include #include #include #include #include "CompilerDependencies.h" #include "BaseTypes.h" bool PlatformServer( SOCKET s ); int PlatformSvcRoutine( void *port ); int PlatformSignalService( int *PortNumberPlatform ); int RegularCommandService( int *PortNumber ); int StartTcpServer( int *PortNumber, int *PortNumberPlatform ); bool ReadBytes( SOCKET s, char *buffer, int NumBytes ); bool WriteBytes( SOCKET s, char *buffer, int NumBytes ); bool WriteUINT32( SOCKET s, UINT32 val ); bool ReadVarBytes( SOCKET s, char *buffer, UINT32 *BytesReceived, int MaxLen ); bool WriteVarBytes( SOCKET s, char *buffer, int BytesToSend ); bool TpmServer( SOCKET s ); #endif libtpms-0.9.3/src/tpm2/TestParms_fp.h000066400000000000000000000071401421143571500174330ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: TestParms_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef TESTPARMS_FP_H #define TESTPARMS_FP_H typedef struct { TPMT_PUBLIC_PARMS parameters; } TestParms_In; #define RC_TestParms_parameters (TPM_RC_P + TPM_RC_1) TPM_RC TPM2_TestParms( TestParms_In *in // IN: input parameter list ); #endif libtpms-0.9.3/src/tpm2/TestingCommands.c000066400000000000000000000114331421143571500201160ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: TestingCommands.c 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016-2018 */ /* */ /********************************************************************************/ #include "Tpm.h" #include "SelfTest_fp.h" #if CC_SelfTest // Conditional expansion of this file TPM_RC TPM2_SelfTest( SelfTest_In *in // IN: input parameter list ) { // Command Output // Call self test function in crypt module return CryptSelfTest(in->fullTest); } #endif // CC_SelfTest #include "Tpm.h" #include "IncrementalSelfTest_fp.h" #if CC_IncrementalSelfTest // Conditional expansion of this file TPM_RC TPM2_IncrementalSelfTest( IncrementalSelfTest_In *in, // IN: input parameter list IncrementalSelfTest_Out *out // OUT: output parameter list ) { TPM_RC result; // Command Output // Call incremental self test function in crypt module. If this function // returns TPM_RC_VALUE, it means that an algorithm on the 'toTest' list is // not implemented. result = CryptIncrementalSelfTest(&in->toTest, &out->toDoList); if(result == TPM_RC_VALUE) return TPM_RCS_VALUE + RC_IncrementalSelfTest_toTest; return result; } #endif // CC_IncrementalSelfTest #include "Tpm.h" #include "GetTestResult_fp.h" #if CC_GetTestResult // Conditional expansion of this file TPM_RC TPM2_GetTestResult( GetTestResult_Out *out // OUT: output parameter list ) { // Command Output // Call incremental self test function in crypt module out->testResult = CryptGetTestResult(&out->outData); return TPM_RC_SUCCESS; } #endif // CC_GetTestResult libtpms-0.9.3/src/tpm2/Ticket.c000066400000000000000000000233561421143571500162510ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Functions used for ticket computations. */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Ticket.c 1594 2020-03-26 22:15:48Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2020 */ /* */ /********************************************************************************/ /* 10.2.23 Ticket.c */ /* 10.2.23.1 Introduction */ /* This clause contains the functions used for ticket computations. */ /* 10.2.23.2 Includes */ #include "Tpm.h" /* 10.2.23.3 Functions */ /* 10.2.23.3.1 TicketIsSafe() */ /* This function indicates if producing a ticket is safe. It checks if the leading bytes of an input buffer is TPM_GENERATED_VALUE or its substring of canonical form. If so, it is not safe to produce ticket for an input buffer claiming to be TPM generated buffer */ /* Return Values Meaning */ /* TRUE It is safe to produce ticket */ /* FALSE It is not safe to produce ticket */ BOOL TicketIsSafe( TPM2B *buffer ) { TPM_CONSTANTS32 valueToCompare = TPM_GENERATED_VALUE; BYTE bufferToCompare[sizeof(valueToCompare)]; BYTE *marshalBuffer; // // If the buffer size is less than the size of TPM_GENERATED_VALUE, assume // it is not safe to generate a ticket if(buffer->size < sizeof(valueToCompare)) return FALSE; marshalBuffer = bufferToCompare; TPM_CONSTANTS32_Marshal(&valueToCompare, &marshalBuffer, NULL); if(MemoryEqual(buffer->buffer, bufferToCompare, sizeof(valueToCompare))) return FALSE; else return TRUE; } /* 10.2.23.3.2 TicketComputeVerified() */ /* This function creates a TPMT_TK_VERIFIED ticket. */ void TicketComputeVerified( TPMI_RH_HIERARCHY hierarchy, // IN: hierarchy constant for ticket TPM2B_DIGEST *digest, // IN: digest TPM2B_NAME *keyName, // IN: name of key that signed the values TPMT_TK_VERIFIED *ticket // OUT: verified ticket ) { TPM2B_PROOF *proof; HMAC_STATE hmacState; // // Fill in ticket fields ticket->tag = TPM_ST_VERIFIED; ticket->hierarchy = hierarchy; proof = HierarchyGetProof(hierarchy); // Start HMAC using the proof value of the hierarchy as the HMAC key ticket->digest.t.size = CryptHmacStart2B(&hmacState, CONTEXT_INTEGRITY_HASH_ALG, &proof->b); // TPM_ST_VERIFIED CryptDigestUpdateInt(&hmacState, sizeof(TPM_ST), ticket->tag); // digest CryptDigestUpdate2B(&hmacState.hashState, &digest->b); // key name CryptDigestUpdate2B(&hmacState.hashState, &keyName->b); // done CryptHmacEnd2B(&hmacState, &ticket->digest.b); return; } /* 10.2.23.3.3 TicketComputeAuth() */ /* This function creates a TPMT_TK_AUTH ticket. */ void TicketComputeAuth( TPM_ST type, // IN: the type of ticket. TPMI_RH_HIERARCHY hierarchy, // IN: hierarchy constant for ticket UINT64 timeout, // IN: timeout BOOL expiresOnReset,// IN: flag to indicate if ticket expires on // TPM Reset TPM2B_DIGEST *cpHashA, // IN: input cpHashA TPM2B_NONCE *policyRef, // IN: input policyRef TPM2B_NAME *entityName, // IN: name of entity TPMT_TK_AUTH *ticket // OUT: Created ticket ) { TPM2B_PROOF *proof; HMAC_STATE hmacState; // // Get proper proof proof = HierarchyGetProof(hierarchy); // Fill in ticket fields ticket->tag = type; ticket->hierarchy = hierarchy; // Start HMAC with hierarchy proof as the HMAC key ticket->digest.t.size = CryptHmacStart2B(&hmacState, CONTEXT_INTEGRITY_HASH_ALG, &proof->b); // TPM_ST_AUTH_SECRET or TPM_ST_AUTH_SIGNED, CryptDigestUpdateInt(&hmacState, sizeof(UINT16), ticket->tag); // cpHash CryptDigestUpdate2B(&hmacState.hashState, &cpHashA->b); // policyRef CryptDigestUpdate2B(&hmacState.hashState, &policyRef->b); // keyName CryptDigestUpdate2B(&hmacState.hashState, &entityName->b); // timeout CryptDigestUpdateInt(&hmacState, sizeof(timeout), timeout); if(timeout != 0) { // epoch CryptDigestUpdateInt(&hmacState.hashState, sizeof(CLOCK_NONCE), g_timeEpoch); // reset count if(expiresOnReset) CryptDigestUpdateInt(&hmacState.hashState, sizeof(gp.totalResetCount), gp.totalResetCount); } // done CryptHmacEnd2B(&hmacState, &ticket->digest.b); return; } /* 10.2.23.3.4 TicketComputeHashCheck() */ /* This function creates a TPMT_TK_HASHCHECK ticket. */ void TicketComputeHashCheck( TPMI_RH_HIERARCHY hierarchy, // IN: hierarchy constant for ticket TPM_ALG_ID hashAlg, // IN: the hash algorithm for 'digest' TPM2B_DIGEST *digest, // IN: input digest TPMT_TK_HASHCHECK *ticket // OUT: Created ticket ) { TPM2B_PROOF *proof; HMAC_STATE hmacState; // // Get proper proof proof = HierarchyGetProof(hierarchy); // Fill in ticket fields ticket->tag = TPM_ST_HASHCHECK; ticket->hierarchy = hierarchy; // Start HMAC using hierarchy proof as HMAC key ticket->digest.t.size = CryptHmacStart2B(&hmacState, CONTEXT_INTEGRITY_HASH_ALG, &proof->b); // TPM_ST_HASHCHECK CryptDigestUpdateInt(&hmacState, sizeof(TPM_ST), ticket->tag); // hash algorithm CryptDigestUpdateInt(&hmacState, sizeof(hashAlg), hashAlg); // digest CryptDigestUpdate2B(&hmacState.hashState, &digest->b); // done CryptHmacEnd2B(&hmacState, &ticket->digest.b); return; } /* 10.2.23.3.5 TicketComputeCreation() */ /* This function creates a TPMT_TK_CREATION ticket. */ void TicketComputeCreation( TPMI_RH_HIERARCHY hierarchy, // IN: hierarchy for ticket TPM2B_NAME *name, // IN: object name TPM2B_DIGEST *creation, // IN: creation hash TPMT_TK_CREATION *ticket // OUT: created ticket ) { TPM2B_PROOF *proof; HMAC_STATE hmacState; // Get proper proof proof = HierarchyGetProof(hierarchy); // Fill in ticket fields ticket->tag = TPM_ST_CREATION; ticket->hierarchy = hierarchy; // Start HMAC using hierarchy proof as HMAC key ticket->digest.t.size = CryptHmacStart2B(&hmacState, CONTEXT_INTEGRITY_HASH_ALG, &proof->b); // TPM_ST_CREATION CryptDigestUpdateInt(&hmacState, sizeof(TPM_ST), ticket->tag); // name if provided if(name != NULL) CryptDigestUpdate2B(&hmacState.hashState, &name->b); // creation hash CryptDigestUpdate2B(&hmacState.hashState, &creation->b); // Done CryptHmacEnd2B(&hmacState, &ticket->digest.b); return; } libtpms-0.9.3/src/tpm2/Ticket_fp.h000066400000000000000000000116731421143571500167420ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Ticket_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 */ /* */ /********************************************************************************/ #ifndef TICKET_FP_H #define TICKET_FP_H BOOL TicketIsSafe( TPM2B *buffer ); void TicketComputeVerified( TPMI_RH_HIERARCHY hierarchy, // IN: hierarchy constant for ticket TPM2B_DIGEST *digest, // IN: digest TPM2B_NAME *keyName, // IN: name of key that signed the values TPMT_TK_VERIFIED *ticket // OUT: verified ticket ); void TicketComputeAuth( TPM_ST type, // IN: the type of ticket. TPMI_RH_HIERARCHY hierarchy, // IN: hierarchy constant for ticket UINT64 timeout, // IN: timeout BOOL expiresOnReset,// IN: flag to indicate if ticket expires on // TPM Reset TPM2B_DIGEST *cpHashA, // IN: input cpHashA TPM2B_NONCE *policyRef, // IN: input policyRef TPM2B_NAME *entityName, // IN: name of entity TPMT_TK_AUTH *ticket // OUT: Created ticket ); void TicketComputeHashCheck( TPMI_RH_HIERARCHY hierarchy, // IN: hierarchy constant for ticket TPM_ALG_ID hashAlg, // IN: the hash algorithm for 'digest' TPM2B_DIGEST *digest, // IN: input digest TPMT_TK_HASHCHECK *ticket // OUT: Created ticket ); void TicketComputeCreation( TPMI_RH_HIERARCHY hierarchy, // IN: hierarchy for ticket TPM2B_NAME *name, // IN: object name TPM2B_DIGEST *creation, // IN: creation hash TPMT_TK_CREATION *ticket // OUT: created ticket ); #endif libtpms-0.9.3/src/tpm2/Time.c000066400000000000000000000255171421143571500157250ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Functions relating to the TPM's time functions */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Time.c 1519 2019-11-15 20:43:51Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ /* 8.10.1 Introduction */ /* This file contains the functions relating to the TPM's time functions including the interface to the implementation-specific time functions. */ /* 8.10.2 Includes */ #include "Tpm.h" #include "PlatformClock.h" /* 8.10.3 Functions */ /* 8.10.3.1 TimePowerOn() */ /* This function initialize time info at _TPM_Init(). */ /* This function is called at _TPM_Init() so that the TPM time can start counting as soon as the TPM comes out of reset and doesn't have to wait until TPM2_Startup() in order to begin the new time epoch. This could be significant for systems that could get powered up but not run any TPM commands for some period of time. */ void TimePowerOn( void ) { g_time = _plat__TimerRead(); } /* 8.10.3.2 TimeNewEpoch() */ /* This function does the processing to generate a new time epoch nonce and set NV for update. This function is only called when NV is known to be available and the clock is running. The epoch is updated to persistent data. */ static void TimeNewEpoch( void ) { #if CLOCK_STOPS CryptRandomGenerate(sizeof(CLOCK_NONCE), (BYTE *)&g_timeEpoch); #else // if the epoch is kept in NV, update it. gp.timeEpoch++; NV_SYNC_PERSISTENT(timeEpoch); #endif // Clean out any lingering state _plat__TimerWasStopped(); } /* 8.10.3.3 TimeStartup() */ /* This function updates the resetCount and restartCount components of TPMS_CLOCK_INFO structure at TPM2_Startup(). */ /* This function will deal with the deferred creation of a new epoch. TimeUpdateToCurrent() will not start a new epoch even if one is due when TPM_Startup() has not been run. This is because the state of NV is not known until startup completes. When Startup is done, then it will create the epoch nonce to complete the initializations by calling this function. */ BOOL TimeStartup( STARTUP_TYPE type // IN: start up type ) { NOT_REFERENCED(type); // If the previous cycle is orderly shut down, the value of the safe bit // the same as previously saved. Otherwise, it is not safe. if(!NV_IS_ORDERLY) go.clockSafe = NO; return TRUE; } /* 8.10.3.4 TimeClockUpdate() */ /* This function updates go.clock. If newTime requires an update of NV, then NV is checked for availability. If it is not available or is rate limiting, then go.clock is not updated and the function returns an error. If newTime would not cause an NV write, then go.clock is updated. If an NV write occurs, then go.safe is SET. */ void TimeClockUpdate( UINT64 newTime // IN: New time value in mS. ) { #define CLOCK_UPDATE_MASK ((1ULL << NV_CLOCK_UPDATE_INTERVAL)- 1) // Check to see if the update will cause a need for an nvClock update if((newTime | CLOCK_UPDATE_MASK) > (go.clock | CLOCK_UPDATE_MASK)) { pAssert(g_NvStatus == TPM_RC_SUCCESS); // Going to update the NV time state so SET the safe flag go.clockSafe = YES; // update the time go.clock = newTime; /* libtpms: Changing the clock alone does not cause the permanent * state to be written to storage, there must be other * reasons as well. */ UPDATE_TYPE old_g_updateNV = g_updateNV; // libtpms added NvWrite(NV_ORDERLY_DATA, sizeof(go), &go); g_updateNV = old_g_updateNV; // libtpms added } else // No NV update needed so just update go.clock = newTime; } /* 8.10.3.5 TimeUpdate() */ /* This function is used to update the time and clock values. If the TPM has run TPM2_Startup(), this function is called at the start of each command. If the TPM has not run TPM2_Startup(), this is called from TPM2_Startup() to get the clock values initialized. It is not called on command entry because, in this implementation, the go structure is not read from NV until TPM2_Startup(). The reason for this is that the initialization code (_TPM_Init()) may run before NV is accessible. */ void TimeUpdate( void ) { UINT64 elapsed; // // Make sure that we consume the current _plat__TimerWasStopped() state. if(_plat__TimerWasStopped()) { TimeNewEpoch(); } // Get the difference between this call and the last time we updated the tick // timer. elapsed = _plat__TimerRead() - g_time; // Don't read + g_time += elapsed; // Don't need to check the result because it has to be success because have // already checked that NV is available. TimeClockUpdate(go.clock + elapsed); // Call self healing logic for dictionary attack parameters DASelfHeal(); } /* 8.10.3.6 TimeUpdateToCurrent() */ /* This function updates the Time and Clock in the global TPMS_TIME_INFO structure. */ /* In this implementation, Time and Clock are updated at the beginning of each command and the values are unchanged for the duration of the command. */ /* Because Clock updates may require a write to NV memory, Time and Clock are not allowed to advance if NV is not available. When clock is not advancing, any function that uses Clock will fail and return TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE. */ /* This implementation does not do rate limiting. If the implementation does do rate limiting, then the Clock update should not be inhibited even when doing rate limiting. */ void TimeUpdateToCurrent( void ) { // Can't update time during the dark interval or when rate limiting so don't // make any modifications to the internal clock value. Also, defer any clock // processing until TPM has run TPM2_Startup() if(!NV_IS_AVAILABLE || !TPMIsStarted()) return; TimeUpdate(); } /* 8.10.3.7 TimeSetAdjustRate() */ /* This function is used to perform rate adjustment on Time and Clock. */ void TimeSetAdjustRate( TPM_CLOCK_ADJUST adjust // IN: adjust constant ) { switch(adjust) { case TPM_CLOCK_COARSE_SLOWER: _plat__ClockAdjustRate(CLOCK_ADJUST_COARSE); break; case TPM_CLOCK_COARSE_FASTER: _plat__ClockAdjustRate(-CLOCK_ADJUST_COARSE); break; case TPM_CLOCK_MEDIUM_SLOWER: _plat__ClockAdjustRate(CLOCK_ADJUST_MEDIUM); break; case TPM_CLOCK_MEDIUM_FASTER: _plat__ClockAdjustRate(-CLOCK_ADJUST_MEDIUM); break; case TPM_CLOCK_FINE_SLOWER: _plat__ClockAdjustRate(CLOCK_ADJUST_FINE); break; case TPM_CLOCK_FINE_FASTER: _plat__ClockAdjustRate(-CLOCK_ADJUST_FINE); break; case TPM_CLOCK_NO_CHANGE: break; default: FAIL(FATAL_ERROR_INTERNAL); break; } return; } /* 8.10.3.8 TimeGetMarshaled() */ /* This function is used to access TPMS_TIME_INFO in canonical form. The function collects the time information and marshals it into dataBuffer and returns the marshaled size */ /* Return Value Meaning */ UINT16 TimeGetMarshaled( TIME_INFO *dataBuffer // OUT: result buffer ) { TPMS_TIME_INFO timeInfo; // Fill TPMS_TIME_INFO structure timeInfo.time = g_time; TimeFillInfo(&timeInfo.clockInfo); // Marshal TPMS_TIME_INFO to canonical form return TPMS_TIME_INFO_Marshal(&timeInfo, (BYTE **)&dataBuffer, NULL); } /* 8.10.3.9 TimeFillInfo */ /* This function gathers information to fill in a TPMS_CLOCK_INFO structure. */ void TimeFillInfo( TPMS_CLOCK_INFO *clockInfo ) { clockInfo->clock = go.clock; clockInfo->resetCount = gp.resetCount; clockInfo->restartCount = gr.restartCount; // If NV is not available, clock stopped advancing and the value reported is // not "safe". if(NV_IS_AVAILABLE) clockInfo->safe = go.clockSafe; else clockInfo->safe = NO; return; } libtpms-0.9.3/src/tpm2/Time_fp.h000066400000000000000000000076011421143571500164110ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Functions relating to the TPM's time functions */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Time_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ #ifndef TIME_FP_H #define TIME_FP_H void TimePowerOn( void ); BOOL TimeStartup( STARTUP_TYPE type // IN: start up type ); void TimeClockUpdate( UINT64 newTime ); void TimeUpdate( void ); void TimeUpdateToCurrent( void ); void TimeSetAdjustRate( TPM_CLOCK_ADJUST adjust // IN: adjust constant ); UINT16 TimeGetMarshaled( TIME_INFO *dataBuffer // OUT: result buffer ); void TimeFillInfo( TPMS_CLOCK_INFO *clockInfo ); #endif libtpms-0.9.3/src/tpm2/Tpm.h000066400000000000000000000077561421143571500156010ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Root header file for building any TPM.lib code */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Tpm.h 1594 2020-03-26 22:15:48Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2020 */ /* */ /********************************************************************************/ /* 5.18 Tpm.h */ /* Root header file for building any TPM.lib code */ #ifndef _TPM_H_ #define _TPM_H_ #include "TpmBuildSwitches.h" #include "BaseTypes.h" #include "TPMB.h" #include "MinMax.h" #include "TpmProfile.h" #include "TpmAlgorithmDefines.h" #include "LibSupport.h" // Types from the library. These need to come before // Global.h because some of the structures in // that file depend on the structures used by the // cryptographic libraries. #include "GpMacros.h" // Define additional macros #include "Global.h" // Define other TPM types #include "InternalRoutines.h" // Function prototypes #endif // _TPM_H_ libtpms-0.9.3/src/tpm2/TpmAlgorithmDefines.h000066400000000000000000000534401421143571500207350ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Algorithm Values from the TCG Algorithm Registry */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: TpmAlgorithmDefines.h 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2019 - 2021 */ /* */ /********************************************************************************/ // 10.1.18 TpmAlgorithmDefines.h // This file contains the algorithm values from the TCG Algorithm Registry. #ifndef _TPM_ALGORITHM_DEFINES_H_ #define _TPM_ALGORITHM_DEFINES_H_ // Table 2:3 - Definition of Base Types #define ECC_CURVES \ {TPM_ECC_BN_P256, TPM_ECC_BN_P638, TPM_ECC_NIST_P192, \ TPM_ECC_NIST_P224, TPM_ECC_NIST_P256, TPM_ECC_NIST_P384, \ TPM_ECC_NIST_P521, TPM_ECC_SM2_P256} #define ECC_CURVE_COUNT \ (ECC_BN_P256 + ECC_BN_P638 + ECC_NIST_P192 + ECC_NIST_P224 + \ ECC_NIST_P256 + ECC_NIST_P384 + ECC_NIST_P521 + ECC_SM2_P256) #define MAX_ECC_KEY_BITS \ MAX(ECC_BN_P256 * 256, MAX(ECC_BN_P638 * 638, \ MAX(ECC_NIST_P192 * 192, MAX(ECC_NIST_P224 * 224, \ MAX(ECC_NIST_P256 * 256, MAX(ECC_NIST_P384 * 384, \ MAX(ECC_NIST_P521 * 521, MAX(ECC_SM2_P256 * 256, \ 0)))))))) #define MAX_ECC_KEY_BYTES BITS_TO_BYTES(MAX_ECC_KEY_BITS) // Table 0:6 - Defines for PLATFORM Values #define PLATFORM_FAMILY TPM_SPEC_FAMILY #define PLATFORM_LEVEL TPM_SPEC_LEVEL #define PLATFORM_VERSION TPM_SPEC_VERSION #define PLATFORM_YEAR TPM_SPEC_YEAR #define PLATFORM_DAY_OF_YEAR TPM_SPEC_DAY_OF_YEAR // Table 1:12 - Defines for SHA1 Hash Values #define SHA1_DIGEST_SIZE 20 #define SHA1_BLOCK_SIZE 64 // Table 1:13 - Defines for SHA256 Hash Values #define SHA256_DIGEST_SIZE 32 #define SHA256_BLOCK_SIZE 64 // Table 1:14 - Defines for SHA384 Hash Values #define SHA384_DIGEST_SIZE 48 #define SHA384_BLOCK_SIZE 128 // Table 1:15 - Defines for SHA512 Hash Values #define SHA512_DIGEST_SIZE 64 #define SHA512_BLOCK_SIZE 128 // Table 1:16 - Defines for SM3_256 Hash Values #define SM3_256_DIGEST_SIZE 32 #define SM3_256_BLOCK_SIZE 64 // Table 1:16 - Defines for SHA3_256 Hash Values #define SHA3_256_DIGEST_SIZE 32 #define SHA3_256_BLOCK_SIZE 136 // Table 1:16 - Defines for SHA3_384 Hash Values #define SHA3_384_DIGEST_SIZE 48 #define SHA3_384_BLOCK_SIZE 104 // Table 1:16 - Defines for SHA3_512 Hash Values #define SHA3_512_DIGEST_SIZE 64 #define SHA3_512_BLOCK_SIZE 72 // Table 1:00 - Defines for RSA Asymmetric Cipher Algorithm Constants #define RSA_KEY_SIZES_BITS \ (1024 * RSA_1024), (2048 * RSA_2048), (3072 * RSA_3072), \ (4096 * RSA_4096), (16384 * RSA_16384) #if RSA_16384 # define RSA_MAX_KEY_SIZE_BITS 16384 #elif RSA_4096 # define RSA_MAX_KEY_SIZE_BITS 4096 #elif RSA_3072 # define RSA_MAX_KEY_SIZE_BITS 3072 #elif RSA_2048 # define RSA_MAX_KEY_SIZE_BITS 2048 #elif RSA_1024 # define RSA_MAX_KEY_SIZE_BITS 1024 #else # define RSA_MAX_KEY_SIZE_BITS 0 #endif #define MAX_RSA_KEY_BITS RSA_MAX_KEY_SIZE_BITS #define MAX_RSA_KEY_BYTES ((RSA_MAX_KEY_SIZE_BITS + 7) / 8) // Table 1:17 - Defines for AES Symmetric Cipher Algorithm Constants #define AES_KEY_SIZES_BITS \ (128 * AES_128), (192 * AES_192), (256 * AES_256) #if AES_256 # define AES_MAX_KEY_SIZE_BITS 256 #elif AES_192 # define AES_MAX_KEY_SIZE_BITS 192 #elif AES_128 # define AES_MAX_KEY_SIZE_BITS 128 #else # define AES_MAX_KEY_SIZE_BITS 0 #endif #define MAX_AES_KEY_BITS AES_MAX_KEY_SIZE_BITS #define MAX_AES_KEY_BYTES ((AES_MAX_KEY_SIZE_BITS + 7) / 8) #define AES_128_BLOCK_SIZE_BYTES (AES_128 * 16) #define AES_192_BLOCK_SIZE_BYTES (AES_192 * 16) #define AES_256_BLOCK_SIZE_BYTES (AES_256 * 16) #define AES_BLOCK_SIZES \ AES_128_BLOCK_SIZE_BYTES, AES_192_BLOCK_SIZE_BYTES, \ AES_256_BLOCK_SIZE_BYTES #if ALG_AES # define AES_MAX_BLOCK_SIZE 16 #else # define AES_MAX_BLOCK_SIZE 0 #endif #define MAX_AES_BLOCK_SIZE_BYTES AES_MAX_BLOCK_SIZE // 1:18 - Defines for SM4 Symmetric Cipher Algorithm Constants #define SM4_KEY_SIZES_BITS (128 * SM4_128) #if SM4_128 # define SM4_MAX_KEY_SIZE_BITS 128 #else # define SM4_MAX_KEY_SIZE_BITS 0 #endif #define MAX_SM4_KEY_BITS SM4_MAX_KEY_SIZE_BITS #define MAX_SM4_KEY_BYTES ((SM4_MAX_KEY_SIZE_BITS + 7) / 8) #define SM4_128_BLOCK_SIZE_BYTES (SM4_128 * 16) #define SM4_BLOCK_SIZES SM4_128_BLOCK_SIZE_BYTES #if ALG_SM4 # define SM4_MAX_BLOCK_SIZE 16 #else # define SM4_MAX_BLOCK_SIZE 0 #endif #define MAX_SM4_BLOCK_SIZE_BYTES SM4_MAX_BLOCK_SIZE // 1:19 - Defines for CAMELLIA Symmetric Cipher Algorithm Constants #define CAMELLIA_KEY_SIZES_BITS \ (128 * CAMELLIA_128), (192 * CAMELLIA_192), (256 * CAMELLIA_256) #if CAMELLIA_256 # define CAMELLIA_MAX_KEY_SIZE_BITS 256 #elif CAMELLIA_192 # define CAMELLIA_MAX_KEY_SIZE_BITS 192 #elif CAMELLIA_128 # define CAMELLIA_MAX_KEY_SIZE_BITS 128 #else # define CAMELLIA_MAX_KEY_SIZE_BITS 0 #endif #define MAX_CAMELLIA_KEY_BITS CAMELLIA_MAX_KEY_SIZE_BITS #define MAX_CAMELLIA_KEY_BYTES ((CAMELLIA_MAX_KEY_SIZE_BITS + 7) / 8) #define CAMELLIA_128_BLOCK_SIZE_BYTES (CAMELLIA_128 * 16) #define CAMELLIA_192_BLOCK_SIZE_BYTES (CAMELLIA_192 * 16) #define CAMELLIA_256_BLOCK_SIZE_BYTES (CAMELLIA_256 * 16) #define CAMELLIA_BLOCK_SIZES \ CAMELLIA_128_BLOCK_SIZE_BYTES, CAMELLIA_192_BLOCK_SIZE_BYTES, \ CAMELLIA_256_BLOCK_SIZE_BYTES #if ALG_CAMELLIA # define CAMELLIA_MAX_BLOCK_SIZE 16 #else # define CAMELLIA_MAX_BLOCK_SIZE 0 #endif #define MAX_CAMELLIA_BLOCK_SIZE_BYTES CAMELLIA_MAX_BLOCK_SIZE // 1:17 - Defines for TDES Symmetric Cipher Algorithm Constants #define TDES_KEY_SIZES_BITS (128 * TDES_128), (192 * TDES_192) #if TDES_192 # define TDES_MAX_KEY_SIZE_BITS 192 #elif TDES_128 # define TDES_MAX_KEY_SIZE_BITS 128 #else # define TDES_MAX_KEY_SIZE_BITS 0 #endif #define MAX_TDES_KEY_BITS TDES_MAX_KEY_SIZE_BITS #define MAX_TDES_KEY_BYTES ((TDES_MAX_KEY_SIZE_BITS + 7) / 8) #define TDES_128_BLOCK_SIZE_BYTES (TDES_128 * 8) #define TDES_192_BLOCK_SIZE_BYTES (TDES_192 * 8) #define TDES_BLOCK_SIZES \ TDES_128_BLOCK_SIZE_BYTES, TDES_192_BLOCK_SIZE_BYTES #if ALG_TDES # define TDES_MAX_BLOCK_SIZE 8 #else # define TDES_MAX_BLOCK_SIZE 0 #endif #define MAX_TDES_BLOCK_SIZE_BYTES TDES_MAX_BLOCK_SIZE // Additional values for benefit of code #define TPM_CC_FIRST 0x0000011F #define TPM_CC_LAST 0x0000019A #if COMPRESSED_LISTS #define ADD_FILL 0 #else #define ADD_FILL 1 #endif // Size the array of library commands based on whether or not the array is packed (only defined // commands) or dense (having entries for unimplemented commands) #define LIBRARY_COMMAND_ARRAY_SIZE (0 \ + (ADD_FILL || CC_NV_UndefineSpaceSpecial) /* 0x0000011F */ \ + (ADD_FILL || CC_EvictControl) /* 0x00000120 */ \ + (ADD_FILL || CC_HierarchyControl) /* 0x00000121 */ \ + (ADD_FILL || CC_NV_UndefineSpace) /* 0x00000122 */ \ + ADD_FILL /* 0x00000123 */ \ + (ADD_FILL || CC_ChangeEPS) /* 0x00000124 */ \ + (ADD_FILL || CC_ChangePPS) /* 0x00000125 */ \ + (ADD_FILL || CC_Clear) /* 0x00000126 */ \ + (ADD_FILL || CC_ClearControl) /* 0x00000127 */ \ + (ADD_FILL || CC_ClockSet) /* 0x00000128 */ \ + (ADD_FILL || CC_HierarchyChangeAuth) /* 0x00000129 */ \ + (ADD_FILL || CC_NV_DefineSpace) /* 0x0000012A */ \ + (ADD_FILL || CC_PCR_Allocate) /* 0x0000012B */ \ + (ADD_FILL || CC_PCR_SetAuthPolicy) /* 0x0000012C */ \ + (ADD_FILL || CC_PP_Commands) /* 0x0000012D */ \ + (ADD_FILL || CC_SetPrimaryPolicy) /* 0x0000012E */ \ + (ADD_FILL || CC_FieldUpgradeStart) /* 0x0000012F */ \ + (ADD_FILL || CC_ClockRateAdjust) /* 0x00000130 */ \ + (ADD_FILL || CC_CreatePrimary) /* 0x00000131 */ \ + (ADD_FILL || CC_NV_GlobalWriteLock) /* 0x00000132 */ \ + (ADD_FILL || CC_GetCommandAuditDigest) /* 0x00000133 */ \ + (ADD_FILL || CC_NV_Increment) /* 0x00000134 */ \ + (ADD_FILL || CC_NV_SetBits) /* 0x00000135 */ \ + (ADD_FILL || CC_NV_Extend) /* 0x00000136 */ \ + (ADD_FILL || CC_NV_Write) /* 0x00000137 */ \ + (ADD_FILL || CC_NV_WriteLock) /* 0x00000138 */ \ + (ADD_FILL || CC_DictionaryAttackLockReset) /* 0x00000139 */ \ + (ADD_FILL || CC_DictionaryAttackParameters) /* 0x0000013A */ \ + (ADD_FILL || CC_NV_ChangeAuth) /* 0x0000013B */ \ + (ADD_FILL || CC_PCR_Event) /* 0x0000013C */ \ + (ADD_FILL || CC_PCR_Reset) /* 0x0000013D */ \ + (ADD_FILL || CC_SequenceComplete) /* 0x0000013E */ \ + (ADD_FILL || CC_SetAlgorithmSet) /* 0x0000013F */ \ + (ADD_FILL || CC_SetCommandCodeAuditStatus) /* 0x00000140 */ \ + (ADD_FILL || CC_FieldUpgradeData) /* 0x00000141 */ \ + (ADD_FILL || CC_IncrementalSelfTest) /* 0x00000142 */ \ + (ADD_FILL || CC_SelfTest) /* 0x00000143 */ \ + (ADD_FILL || CC_Startup) /* 0x00000144 */ \ + (ADD_FILL || CC_Shutdown) /* 0x00000145 */ \ + (ADD_FILL || CC_StirRandom) /* 0x00000146 */ \ + (ADD_FILL || CC_ActivateCredential) /* 0x00000147 */ \ + (ADD_FILL || CC_Certify) /* 0x00000148 */ \ + (ADD_FILL || CC_PolicyNV) /* 0x00000149 */ \ + (ADD_FILL || CC_CertifyCreation) /* 0x0000014A */ \ + (ADD_FILL || CC_Duplicate) /* 0x0000014B */ \ + (ADD_FILL || CC_GetTime) /* 0x0000014C */ \ + (ADD_FILL || CC_GetSessionAuditDigest) /* 0x0000014D */ \ + (ADD_FILL || CC_NV_Read) /* 0x0000014E */ \ + (ADD_FILL || CC_NV_ReadLock) /* 0x0000014F */ \ + (ADD_FILL || CC_ObjectChangeAuth) /* 0x00000150 */ \ + (ADD_FILL || CC_PolicySecret) /* 0x00000151 */ \ + (ADD_FILL || CC_Rewrap) /* 0x00000152 */ \ + (ADD_FILL || CC_Create) /* 0x00000153 */ \ + (ADD_FILL || CC_ECDH_ZGen) /* 0x00000154 */ \ + (ADD_FILL || CC_HMAC || CC_MAC) /* 0x00000155 */ \ + (ADD_FILL || CC_Import) /* 0x00000156 */ \ + (ADD_FILL || CC_Load) /* 0x00000157 */ \ + (ADD_FILL || CC_Quote) /* 0x00000158 */ \ + (ADD_FILL || CC_RSA_Decrypt) /* 0x00000159 */ \ + ADD_FILL /* 0x0000015A */ \ + (ADD_FILL || CC_HMAC_Start || CC_MAC_Start) /* 0x0000015B */ \ + (ADD_FILL || CC_SequenceUpdate) /* 0x0000015C */ \ + (ADD_FILL || CC_Sign) /* 0x0000015D */ \ + (ADD_FILL || CC_Unseal) /* 0x0000015E */ \ + ADD_FILL /* 0x0000015F */ \ + (ADD_FILL || CC_PolicySigned) /* 0x00000160 */ \ + (ADD_FILL || CC_ContextLoad) /* 0x00000161 */ \ + (ADD_FILL || CC_ContextSave) /* 0x00000162 */ \ + (ADD_FILL || CC_ECDH_KeyGen) /* 0x00000163 */ \ + (ADD_FILL || CC_EncryptDecrypt) /* 0x00000164 */ \ + (ADD_FILL || CC_FlushContext) /* 0x00000165 */ \ + ADD_FILL /* 0x00000166 */ \ + (ADD_FILL || CC_LoadExternal) /* 0x00000167 */ \ + (ADD_FILL || CC_MakeCredential) /* 0x00000168 */ \ + (ADD_FILL || CC_NV_ReadPublic) /* 0x00000169 */ \ + (ADD_FILL || CC_PolicyAuthorize) /* 0x0000016A */ \ + (ADD_FILL || CC_PolicyAuthValue) /* 0x0000016B */ \ + (ADD_FILL || CC_PolicyCommandCode) /* 0x0000016C */ \ + (ADD_FILL || CC_PolicyCounterTimer) /* 0x0000016D */ \ + (ADD_FILL || CC_PolicyCpHash) /* 0x0000016E */ \ + (ADD_FILL || CC_PolicyLocality) /* 0x0000016F */ \ + (ADD_FILL || CC_PolicyNameHash) /* 0x00000170 */ \ + (ADD_FILL || CC_PolicyOR) /* 0x00000171 */ \ + (ADD_FILL || CC_PolicyTicket) /* 0x00000172 */ \ + (ADD_FILL || CC_ReadPublic) /* 0x00000173 */ \ + (ADD_FILL || CC_RSA_Encrypt) /* 0x00000174 */ \ + ADD_FILL /* 0x00000175 */ \ + (ADD_FILL || CC_StartAuthSession) /* 0x00000176 */ \ + (ADD_FILL || CC_VerifySignature) /* 0x00000177 */ \ + (ADD_FILL || CC_ECC_Parameters) /* 0x00000178 */ \ + (ADD_FILL || CC_FirmwareRead) /* 0x00000179 */ \ + (ADD_FILL || CC_GetCapability) /* 0x0000017A */ \ + (ADD_FILL || CC_GetRandom) /* 0x0000017B */ \ + (ADD_FILL || CC_GetTestResult) /* 0x0000017C */ \ + (ADD_FILL || CC_Hash) /* 0x0000017D */ \ + (ADD_FILL || CC_PCR_Read) /* 0x0000017E */ \ + (ADD_FILL || CC_PolicyPCR) /* 0x0000017F */ \ + (ADD_FILL || CC_PolicyRestart) /* 0x00000180 */ \ + (ADD_FILL || CC_ReadClock) /* 0x00000181 */ \ + (ADD_FILL || CC_PCR_Extend) /* 0x00000182 */ \ + (ADD_FILL || CC_PCR_SetAuthValue) /* 0x00000183 */ \ + (ADD_FILL || CC_NV_Certify) /* 0x00000184 */ \ + (ADD_FILL || CC_EventSequenceComplete) /* 0x00000185 */ \ + (ADD_FILL || CC_HashSequenceStart) /* 0x00000186 */ \ + (ADD_FILL || CC_PolicyPhysicalPresence) /* 0x00000187 */ \ + (ADD_FILL || CC_PolicyDuplicationSelect) /* 0x00000188 */ \ + (ADD_FILL || CC_PolicyGetDigest) /* 0x00000189 */ \ + (ADD_FILL || CC_TestParms) /* 0x0000018A */ \ + (ADD_FILL || CC_Commit) /* 0x0000018B */ \ + (ADD_FILL || CC_PolicyPassword) /* 0x0000018C */ \ + (ADD_FILL || CC_ZGen_2Phase) /* 0x0000018D */ \ + (ADD_FILL || CC_EC_Ephemeral) /* 0x0000018E */ \ + (ADD_FILL || CC_PolicyNvWritten) /* 0x0000018F */ \ + (ADD_FILL || CC_PolicyTemplate) /* 0x00000190 */ \ + (ADD_FILL || CC_CreateLoaded) /* 0x00000191 */ \ + (ADD_FILL || CC_PolicyAuthorizeNV) /* 0x00000192 */ \ + (ADD_FILL || CC_EncryptDecrypt2) /* 0x00000193 */ \ + (ADD_FILL || CC_AC_GetCapability) /* 0x00000194 */ \ + (ADD_FILL || CC_AC_Send) /* 0x00000195 */ \ + (ADD_FILL || CC_Policy_AC_SendSelect) /* 0x00000196 */ \ + (ADD_FILL || CC_CertifyX509) /* 0x00000197 */ \ + (ADD_FILL || CC_ACT_SetTimeout) /* 0x00000198 */ \ + (ADD_FILL || CC_ECC_Encrypt) /* 0x00000199 */ \ + (ADD_FILL || CC_ECC_Decrypt) /* 0x0000019A */ \ ) #define VENDOR_COMMAND_ARRAY_SIZE (0 + CC_Vendor_TCG_Test) #define COMMAND_COUNT (LIBRARY_COMMAND_ARRAY_SIZE + VENDOR_COMMAND_ARRAY_SIZE) #define HASH_COUNT \ (ALG_SHA1 + ALG_SHA256 + ALG_SHA384 + ALG_SHA3_256 + \ ALG_SHA3_384 + ALG_SHA3_512 + ALG_SHA512 + ALG_SM3_256) #define MAX_HASH_BLOCK_SIZE \ (MAX(ALG_SHA1 * SHA1_BLOCK_SIZE, \ MAX(ALG_SHA256 * SHA256_BLOCK_SIZE, \ MAX(ALG_SHA384 * SHA384_BLOCK_SIZE, \ MAX(ALG_SHA3_256 * SHA3_256_BLOCK_SIZE, \ MAX(ALG_SHA3_384 * SHA3_384_BLOCK_SIZE, \ MAX(ALG_SHA3_512 * SHA3_512_BLOCK_SIZE, \ MAX(ALG_SHA512 * SHA512_BLOCK_SIZE, \ MAX(ALG_SM3_256 * SM3_256_BLOCK_SIZE, \ 0))))))))) #define MAX_DIGEST_SIZE \ (MAX(ALG_SHA1 * SHA1_DIGEST_SIZE, \ MAX(ALG_SHA256 * SHA256_DIGEST_SIZE, \ MAX(ALG_SHA384 * SHA384_DIGEST_SIZE, \ MAX(ALG_SHA3_256 * SHA3_256_DIGEST_SIZE, \ MAX(ALG_SHA3_384 * SHA3_384_DIGEST_SIZE, \ MAX(ALG_SHA3_512 * SHA3_512_DIGEST_SIZE, \ MAX(ALG_SHA512 * SHA512_DIGEST_SIZE, \ MAX(ALG_SM3_256 * SM3_256_DIGEST_SIZE, \ 0))))))))) #if MAX_DIGEST_SIZE == 0 || MAX_HASH_BLOCK_SIZE == 0 #error "Hash data not valid" #endif // Define the 2B structure that would hold any hash block TPM2B_TYPE(MAX_HASH_BLOCK, MAX_HASH_BLOCK_SIZE); // Following typedef is for some old code typedef TPM2B_MAX_HASH_BLOCK TPM2B_HASH_BLOCK; #define MAX_SYM_KEY_BITS \ (MAX(AES_MAX_KEY_SIZE_BITS, MAX(CAMELLIA_MAX_KEY_SIZE_BITS, \ MAX(SM4_MAX_KEY_SIZE_BITS, MAX(TDES_MAX_KEY_SIZE_BITS, \ 0))))) #define MAX_SYM_KEY_BYTES ((MAX_SYM_KEY_BITS + 7) / 8) #define MAX_SYM_BLOCK_SIZE \ (MAX(AES_MAX_BLOCK_SIZE, MAX(CAMELLIA_MAX_BLOCK_SIZE, \ MAX(SM4_MAX_BLOCK_SIZE, MAX(TDES_MAX_BLOCK_SIZE, \ 0))))) #if MAX_SYM_KEY_BITS == 0 || MAX_SYM_BLOCK_SIZE == 0 # error Bad size for MAX_SYM_KEY_BITS or MAX_SYM_BLOCK #endif #endif // _TPM_ALGORITHM_DEFINES_H_ libtpms-0.9.3/src/tpm2/TpmAsn1.c000066400000000000000000000440601421143571500163040ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM ASN.1 */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: TpmAsn1.c 1519 2019-11-15 20:43:51Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2019 */ /* */ /********************************************************************************/ /* 10.2.23 TpmAsn1.c */ /* 10.2.23.1 Includes */ #include "Tpm.h" #define _OIDS_ #include "OIDs.h" #include "TpmAsn1.h" #include "TpmAsn1_fp.h" /* 10.2.23.2 Unmarshaling Functions */ /* 10.2.23.2.1 ASN1UnmarshalContextInitialize() */ /* Function does standard initialization of a context. */ /* Return Value Meaning */ /* TRUE(1) success */ /* FALSE(0) failure */ BOOL ASN1UnmarshalContextInitialize( ASN1UnmarshalContext *ctx, INT16 size, BYTE *buffer ) { VERIFY(buffer != NULL); VERIFY(size > 0); ctx->buffer = buffer; ctx->size = size; ctx->offset = 0; ctx->tag = 0xFF; return TRUE; Error: return FALSE; } /* 10.2.23.2.2 ASN1DecodeLength() */ /* This function extracts the length of an element from buffer starting at offset. */ /* Return Value Meaning */ /* >=0 the extracted length */ /* <0 an error */ INT16 ASN1DecodeLength( ASN1UnmarshalContext *ctx ) { BYTE first; // Next octet in buffer INT16 value; // VERIFY(ctx->offset < ctx->size); first = NEXT_OCTET(ctx); // If the number of octets of the entity is larger than 127, then the first octet // is the number of octets in the length specifier. if(first >= 0x80) { // Make sure that this length field is contained with the structure being // parsed CHECK_SIZE(ctx, (first & 0x7F)); if(first == 0x82) { // Two octets of size // get the next value value = (INT16)NEXT_OCTET(ctx); // Make sure that the result will fit in an INT16 VERIFY(value < 0x0080); // Shift up and add next octet value = (value << 8) + NEXT_OCTET(ctx); } else if(first == 0x81) value = NEXT_OCTET(ctx); // Sizes larger than will fit in a INT16 are an error else goto Error; } else value = first; // Make sure that the size defined something within the current context CHECK_SIZE(ctx, value); return value; Error: ctx->size = -1; // Makes everything fail from now on. return -1; } /* 10.2.23.2.3 ASN1NextTag() */ /* This function extracts the next type from buffer starting at offset. It advances offset as it parses the type and the length of the type. It returns the length of the type. On return, the length octets starting at offset are the octets of the type. */ /* Return Value Meaning */ /* >=0 the number of octets in type */ /* <0 an error */ INT16 ASN1NextTag( ASN1UnmarshalContext *ctx ) { // A tag to get? VERIFY(ctx->offset < ctx->size); // Get it ctx->tag = NEXT_OCTET(ctx); // Make sure that it is not an extended tag VERIFY((ctx->tag & 0x1F) != 0x1F); // Get the length field and return that return ASN1DecodeLength(ctx); Error: // Attempt to read beyond the end of the context or an illegal tag ctx->size = -1; // Persistent failure ctx->tag = 0xFF; return -1; } /* 10.2.23.2.4 ASN1GetBitStringValue() */ /* Try to parse a bit string of up to 32 bits from a value that is expected to be a bit string. The bit string is left justified so that the MSb of the input is the MSb of the returned value. If there is a general parsing error, the context->size is set to -1. */ /* Return Value Meaning */ /* TRUE(1) success */ /* FALSE(0) failure */ BOOL ASN1GetBitStringValue( ASN1UnmarshalContext *ctx, UINT32 *val ) { int shift; INT16 length; UINT32 value = 0; int inputBits; // length = ASN1NextTag(ctx); VERIFY(length >= 1); VERIFY(ctx->tag == ASN1_BITSTRING); // Get the shift value for the bit field (how many bits to lop off of the end) shift = NEXT_OCTET(ctx); length--; // Get the number of bits in the input inputBits = (8 * length) - shift; // the shift count has to make sense VERIFY((shift < 8) && ((length > 0) || (shift == 0))); // if there are any bytes left for(; length > 1; length--) { // for all but the last octet, just shift and add the new octet VERIFY((value & 0xFF000000) == 0); // can't loose significant bits value = (value << 8) + NEXT_OCTET(ctx); } if(length == 1) { // for the last octet, just shift the accumulated value enough to // accept the significant bits in the last octet and shift the last // octet down VERIFY(((value & (0xFF000000 << (8 - shift)))) == 0); value = (value << (8 - shift)) + (NEXT_OCTET(ctx) >> shift); } // 'Left justify' the result if(inputBits > 0) value <<= (32 - inputBits); *val = value; return TRUE; Error: ctx->size = -1; return FALSE; } /* 10.2.23.3 Marshaling Functions */ /* 10.2.23.3.1 Introduction */ /* Marshaling of an ASN.1 structure is accomplished from the bottom up. That is, the things that will be at the end of the structure are added last. To manage the collecting of the relative sizes, start a context for the outermost container, if there is one, and then placing items in from the bottom up. If the bottom-most item is also within a structure, create a nested context by calling ASN1StartMarshalingContext(). */ /* The context control structure contains a buffer pointer, an offset, an end and a stack. offset is the offset from the start of the buffer of the last added byte. When offset reaches 0, the buffer is full. offset is a signed value so that, when it becomes negative, there is an overflow. Only two functions are allowed to move bytes into the buffer: ASN1PushByte() and ASN1PushBytes(). These functions make sure that no data is written beyond the end of the buffer. */ /* When a new context is started, the current value of end is pushed on the stack and end is set to 'offset. As bytes are added, offset gets smaller. At any time, the count of bytes in the current context is simply end - offset. */ /* Since starting a new context involves setting end = offset, the number of bytes in the context starts at 0. The nominal way of ending a context is to use end - offset to set the length value, and then a tag is added to the buffer. Then the previous end value is popped meaning that the context just ended becomes a member of the now current context. */ /* The nominal strategy for building a completed ASN.1 structure is to push everything into the buffer and then move everything to the start of the buffer. The move is simple as the size of the move is the initial end value minus the final offset value. The destination is buffer and the source is buffer + offset. As Skippy would say "Easy peasy, Joe." */ /* It is not necessary to provide a buffer into which the data is placed. If no buffer is provided, then the marshaling process will return values needed for marshaling. On strategy for filling the buffer would be to execute the process for building the structure without using a buffer. This would return the overall size of the structure. Then that amount of data could be allocated for the buffer and the fill process executed again with the data going into the buffer. At the end, the data would be in its final resting place. */ /* 10.2.23.3.2 ASN1InitialializeMarshalContext() */ /* This creates a structure for handling marshaling of an ASN.1 formatted data structure. */ void ASN1InitialializeMarshalContext( ASN1MarshalContext *ctx, INT16 length, BYTE *buffer ) { ctx->buffer = buffer; if(buffer) ctx->offset = length; else ctx->offset = INT16_MAX; ctx->end = ctx->offset; ctx->depth = -1; } /* 10.2.23.3.3 ASN1StartMarshalContext() */ /* This starts a new constructed element. It is constructed on top of the value that was previously placed in the structure. */ void ASN1StartMarshalContext( ASN1MarshalContext *ctx ) { pAssert((ctx->depth + 1) < MAX_DEPTH); ctx->depth++; ctx->ends[ctx->depth] = ctx->end; ctx->end = ctx->offset; } /* 10.2.23.3.4 ASN1EndMarshalContext() */ /* This function restores the end pointer for an encapsulating structure. */ /* Return Value Meaning */ /* > 0 the size of the encapsulated structure that was just ended */ /* <= 0 an error */ INT16 ASN1EndMarshalContext( ASN1MarshalContext *ctx ) { INT16 length; pAssert(ctx->depth >= 0); length = ctx->end - ctx->offset; ctx->end = ctx->ends[ctx->depth--]; if((ctx->depth == -1) && (ctx->buffer)) { MemoryCopy(ctx->buffer, ctx->buffer + ctx->offset, ctx->end - ctx->offset); } return length; } /* 10.2.23.3.5 ASN1EndEncapsulation() */ /* This function puts a tag and length in the buffer. In this function, an embedded BIT_STRING is assumed to be a collection of octets. To indicate that all bits are used, a byte of zero is prepended. If a raw bit-string is needed, a new function like ASN1PushInteger() would be needed. */ /* Return Value Meaning */ /* > 0 number of octets in the encapsulation */ /* == 0 failure */ UINT16 ASN1EndEncapsulation( ASN1MarshalContext *ctx, BYTE tag ) { // only add a leading zero for an encapsulated BIT STRING if (tag == ASN1_BITSTRING) ASN1PushByte(ctx, 0); ASN1PushTagAndLength(ctx, tag, ctx->end - ctx->offset); return ASN1EndMarshalContext(ctx); } /* 10.2.23.3.6 ASN1PushByte() */ BOOL ASN1PushByte( ASN1MarshalContext *ctx, BYTE b ) { if(ctx->offset > 0) { ctx->offset -= 1; if(ctx->buffer) ctx->buffer[ctx->offset] = b; return TRUE; } ctx->offset = -1; return FALSE; } /* 10.2.23.3.7 ASN1PushBytes() */ /* Push some raw bytes onto the buffer. count cannot be zero. */ /* Return Value Meaning */ /* > 0 count bytes */ /* == 0 failure unless count was zero */ INT16 ASN1PushBytes( ASN1MarshalContext *ctx, INT16 count, const BYTE *buffer ) { // make sure that count is not negative which would mess up the math; and that // if there is a count, there is a buffer VERIFY((count >= 0) && ((buffer != NULL) || (count == 0))); // back up the offset to determine where the new octets will get pushed ctx->offset -= count; // can't go negative VERIFY(ctx->offset >= 0); // if there are buffers, move the data, otherwise, assume that this is just a // test. if(count && buffer && ctx->buffer) MemoryCopy(&ctx->buffer[ctx->offset], buffer, count); return count; Error: ctx->offset = -1; return 0; } /* 10.2.23.3.8 ASN1PushNull() */ /* Return Value Meaning */ /* > 0 count bytes */ /* == 0 failure unless count was zero */ INT16 ASN1PushNull( ASN1MarshalContext *ctx ) { ASN1PushByte(ctx, 0); ASN1PushByte(ctx, ASN1_NULL); return (ctx->offset >= 0) ? 2 : 0; } /* 10.2.23.3.9 ASN1PushLength() */ /* Push a length value. This will only handle length values that fit in an INT16. */ /* Return Value Meaning */ /* > 0 number of bytes added */ /* == 0 failure */ INT16 ASN1PushLength( ASN1MarshalContext *ctx, INT16 len ) { UINT16 start = ctx->offset; VERIFY(len >= 0); if(len <= 127) ASN1PushByte(ctx, (BYTE)len); else { ASN1PushByte(ctx, (BYTE)(len & 0xFF)); len >>= 8; if(len == 0) ASN1PushByte(ctx, 0x81); else { ASN1PushByte(ctx, (BYTE)(len)); ASN1PushByte(ctx, 0x82); } } goto Exit; Error: ctx->offset = -1; Exit: return (ctx->offset > 0) ? start - ctx->offset : 0; } /* 10.2.23.3.10 ASN1PushTagAndLength() */ /* Return Value Meaning */ /* > 0 number of bytes added */ /* == 0 failure */ INT16 ASN1PushTagAndLength( ASN1MarshalContext *ctx, BYTE tag, INT16 length ) { INT16 bytes; bytes = ASN1PushLength(ctx, length); bytes += (INT16)ASN1PushByte(ctx, tag); return (ctx->offset < 0) ? 0 : bytes; } /* 10.2.23.3.11 ASN1PushTaggedOctetString() */ /* This function will push a random octet string. */ /* Return Value Meaning */ /* > 0 number of bytes added */ /* == 0 failure */ INT16 ASN1PushTaggedOctetString( ASN1MarshalContext *ctx, INT16 size, const BYTE *string, BYTE tag ) { ASN1PushBytes(ctx, size, string); // PushTagAndLenght just tells how many octets it added so the total size of this // element is the sum of those octets and input size. size += ASN1PushTagAndLength(ctx, tag, size); return size; } /* 10.2.23.3.12 ASN1PushUINT() */ /* This function pushes an native-endian integer value. This just changes a native-endian integer into a big-endian byte string and calls ASN1PushInteger(). That function will remove leading zeros and make sure that the number is positive. */ /* Return Value Meaning */ /* > 0 count bytes */ /* == 0 failure unless count was zero */ INT16 ASN1PushUINT( ASN1MarshalContext *ctx, UINT32 integer ) { BYTE marshaled[4]; UINT32_TO_BYTE_ARRAY(integer, marshaled); return ASN1PushInteger(ctx, 4, marshaled); } /* 10.2.23.3.13 ASN1PushInteger */ /* Push a big-endian integer on the end of the buffer */ /* Return Value Meaning */ /* > 0 the number of bytes marshaled for the integer */ /* == 0 failure */ INT16 ASN1PushInteger( ASN1MarshalContext *ctx, // IN/OUT: buffer context INT16 iLen, // IN: octets of the integer BYTE *integer // IN: big-endian integer ) { // no leading 0's while((*integer == 0) && (--iLen > 0)) integer++; // Move the bytes to the buffer ASN1PushBytes(ctx, iLen, integer); // if needed, add a leading byte of 0 to make the number positive if(*integer & 0x80) iLen += (INT16)ASN1PushByte(ctx, 0); // PushTagAndLenght just tells how many octets it added so the total size of this // element is the sum of those octets and the adjusted input size. iLen += ASN1PushTagAndLength(ctx, ASN1_INTEGER, iLen); return iLen; } /* 10.2.23.3.14 ASN1PushOID() */ /* This function is used to add an OID. An OID is 0x06 followed by a byte of size followed by size bytes. This is used to avoid having to do anything special in the definition of an OID. */ /* Return Value Meaning */ /* > 0 the number of bytes marshaled for the integer */ /* == 0 failure */ INT16 ASN1PushOID( ASN1MarshalContext *ctx, const BYTE *OID ) { if((*OID == ASN1_OBJECT_IDENTIFIER) && ((OID[1] & 0x80) == 0)) { return ASN1PushBytes(ctx, OID[1] + 2, OID); } ctx->offset = -1; return 0; } libtpms-0.9.3/src/tpm2/TpmAsn1.h000066400000000000000000000153231421143571500163110ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Macro and Structure Definitions for the X509 Commands and Functions. */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: TpmAsn1.h 1519 2019-11-15 20:43:51Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2019 */ /* */ /********************************************************************************/ // 10.1.15 TpmAsn1.h // 10.1.15.1 Introduction // This file contains the macro and structure definitions for the X509 commands and functions. #ifndef _TPMASN1_H_ #define _TPMASN1_H_ // 10.1.15.2 Includes #include "Tpm.h" #include "OIDs.h" // 10.1.15.3 Defined Constants // 10.1.15.3.1 ASN.1 Universal Types (Class 00b #define ASN1_EOC 0x00 #define ASN1_BOOLEAN 0x01 #define ASN1_INTEGER 0x02 #define ASN1_BITSTRING 0x03 #define ASN1_OCTET_STRING 0x04 #define ASN1_NULL 0x05 #define ASN1_OBJECT_IDENTIFIER 0x06 #define ASN1_OBJECT_DESCRIPTOR 0x07 #define ASN1_EXTERNAL 0x08 #define ASN1_REAL 0x09 #define ASN1_ENUMERATED 0x0A #define ASN1_EMBEDDED 0x0B #define ASN1_UTF8String 0x0C #define ASN1_RELATIVE_OID 0x0D #define ASN1_SEQUENCE 0x10 // Primitive + Constructed + 0x10 #define ASN1_SET 0x11 // Primitive + Constructed + 0x11 #define ASN1_NumericString 0x12 #define ASN1_PrintableString 0x13 #define ASN1_T61String 0x14 #define ASN1_VideoString 0x15 #define ASN1_IA5String 0x16 #define ASN1_UTCTime 0x17 #define ASN1_GeneralizeTime 0x18 #define ASN1_VisibleString 0x1A #define ASN1_GeneralString 0x1B #define ASN1_UniversalString 0x1C #define ASN1_CHARACTER STRING 0x1D #define ASN1_BMPString 0x1E #define ASN1_CONSTRUCTED 0x20 #define ASN1_APPLICAIION_SPECIFIC 0xA0 #define ASN1_CONSTRUCTED_SEQUENCE (ASN1_SEQUENCE + ASN1_CONSTRUCTED) #define MAX_DEPTH 10 // maximum push depth for marshaling context. // 10.1.15.4 Macros // 10.1.15.4.1 Unmarshaling Macros #ifndef VERIFY #define VERIFY(_X_) {if(!(_X_)) goto Error; } #endif // Checks the validity of the size making sure that there is no wrap around #define CHECK_SIZE(context, length) \ VERIFY( (((length) + (context)->offset) >= (context)->offset) \ && (((length) + (context)->offset) <= (context)->size)) #define NEXT_OCTET(context) ((context)->buffer[(context)->offset++]) #define PEEK_NEXT(context) ((context)->buffer[(context)->offset]) // 10.1.15.4.2 Marshaling Macros Marshaling works in reverse order. The offset is set to the top of // the buffer and, as the buffer is filled, offset counts down to zero. When the full thing is // encoded it can be moved to the top of the buffer. This happens when the last context is closed. #define CHECK_SPACE(context, length) VERIFY(context->offset > length) // 10.1.15.5 Structures typedef struct ASN1UnmarshalContext { BYTE *buffer; // pointer to the buffer INT16 size; // size of the buffer (a negative number indicates // a parsing failure). INT16 offset; // current offset into the buffer (a negative number // indicates a parsing failure). Not used BYTE tag; // The last unmarshaled tag } ASN1UnmarshalContext; typedef struct ASN1MarshalContext { BYTE *buffer; // pointer to the start of the buffer INT16 offset; // place on the top where the last entry was added // items are added from the bottom up. INT16 end; // the end offset of the current value INT16 depth; // how many pushed end values. INT16 ends[MAX_DEPTH]; } ASN1MarshalContext; #endif // _TPMASN1_H_ libtpms-0.9.3/src/tpm2/TpmAsn1_fp.h000066400000000000000000000126151421143571500167770ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM ASN.1 */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: TpmAsn1_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2019 */ /* */ /********************************************************************************/ #ifndef TPMASN1_FP_H #define TPMASN1_FP_H BOOL ASN1UnmarshalContextInitialize( ASN1UnmarshalContext *ctx, INT16 size, BYTE *buffer ); INT16 ASN1DecodeLength( ASN1UnmarshalContext *ctx ); INT16 ASN1NextTag( ASN1UnmarshalContext *ctx ); BOOL ASN1GetBitStringValue( ASN1UnmarshalContext *ctx, UINT32 *val ); void ASN1InitialializeMarshalContext( ASN1MarshalContext *ctx, INT16 length, BYTE *buffer ); void ASN1StartMarshalContext( ASN1MarshalContext *ctx ); INT16 ASN1EndMarshalContext( ASN1MarshalContext *ctx ); UINT16 ASN1EndEncapsulation( ASN1MarshalContext *ctx, BYTE tag ); BOOL ASN1PushByte( ASN1MarshalContext *ctx, BYTE b ); INT16 ASN1PushBytes( ASN1MarshalContext *ctx, INT16 count, const BYTE *buffer ); INT16 ASN1PushNull( ASN1MarshalContext *ctx ); INT16 ASN1PushLength( ASN1MarshalContext *ctx, INT16 len ); INT16 ASN1PushTagAndLength( ASN1MarshalContext *ctx, BYTE tag, INT16 length ); INT16 ASN1PushTaggedOctetString( ASN1MarshalContext *ctx, INT16 size, const BYTE *string, BYTE tag ); INT16 ASN1PushUINT( ASN1MarshalContext *ctx, UINT32 integer ); INT16 ASN1PushInteger( ASN1MarshalContext *ctx, // IN/OUT: buffer context INT16 iLen, // IN: octets of the integer BYTE *integer // IN: big-endian integer ); INT16 ASN1PushOID( ASN1MarshalContext *ctx, const BYTE *OID ); #endif libtpms-0.9.3/src/tpm2/TpmBuildSwitches.h000066400000000000000000000422721421143571500202630ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Build Switches */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: TpmBuildSwitches.h 1619 2020-05-19 16:51:47Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2020 */ /* */ /********************************************************************************/ /* 5.19 TpmBuildSwitches.h */ /* This file contains the build switches. This contains switches for multiple versions of the crypto-library so some may not apply to your environment. */ /* The switches are guarded so that they can either be set on the command line or set here. If the switch is listed on the command line (-DSOME_SWITCH) with no setting, then the switch will be set to YES. If the switch setting is not on the command line or if the setting is other than YES or NO, then the switch will be set to the default value. The default can either be YES or NO as indicated on each line where the default is selected. */ /* A caution. Do not try to test these macros by inserting #defines in this file. For some curious reason, a variable set on the command line with no setting will have a value of 1. An #if SOME_VARIABLE will work if the variable is not defined or is defined on the command line with no initial setting. However, a #define SOME_VARIABLE is a null string and when used in #if SOME_VARIABLE will not be a proper expression. If you want to test various switches, either use the command line or change the default. */ #ifndef TPMBUILDSWITCHES_H #define TPMBUILDSWITCHES_H #undef YES #define YES 1 #undef NO #define NO 0 /* Allow the command line to specify a profile file */ #ifdef PROFILE # define PROFILE_QUOTE(a) #a # define PROFILE_INCLUDE(a) PROFILE_QUOTE(a) # include PROFILE_INCLUDE(PROFILE) #endif // Need an unambiguous definition for DEBUG. Don't change this #ifndef DEBUG # ifdef NDEBUG # define DEBUG NO # else # define DEBUG YES # endif #elif (DEBUG != NO) && (DEBUG != YES) # undef DEBUG # define DEBUG YES // Default: Either YES or NO #endif #include "CompilerDependencies.h" // This definition is required for the re-factored code #if (!defined USE_BN_ECC_DATA) || ((USE_BN_ECC_DATA != NO) && (USE_BN_ECC_DATA != YES)) # undef USE_BN_ECC_DATA # define USE_BN_ECC_DATA YES // Default: Either YES or NO #endif /* The SIMULATION switch allows certain other macros to be enabled. The things that can be enabled in a simulation include key caching, reproducible random sequences, instrumentation of the RSA key generation process, and certain other debug code. SIMULATION Needs to be defined as either YES or NO. This grouping of macros will make sure that it is set correctly. A simulated TPM would include a Virtual TPM. The interfaces for a Virtual TPM should be modified from the standard ones in the Simulator project. If SIMULATION is in the compile parameters without modifiers, make SIMULATION == YES */ #if !(defined SIMULATION) || ((SIMULATION != NO) && (SIMULATION != YES)) # undef SIMULATION # define SIMULATION NO // Default: Either YES or NO libtpms: NO #endif // Define this to run the function that checks the compatibility between the chosen big number math // library and the TPM code. Not all ports use this. #if !(defined LIBRARY_COMPATIBILITY_CHECK) \ || (( LIBRARY_COMPATIBILITY_CHECK != NO) \ && (LIBRARY_COMPATIBILITY_CHECK != YES)) # undef LIBRARY_COMPATIBILITY_CHECK # define LIBRARY_COMPATIBILITY_CHECK YES // Default: Either YES or NO libtpms: YES #endif #if !(defined FIPS_COMPLIANT) || ((FIPS_COMPLIANT != NO) && (FIPS_COMPLIANT != YES)) # undef FIPS_COMPLIANT # define FIPS_COMPLIANT NO // Default: Either YES or NO libtpms: NO #endif // Definition to allow alternate behavior for non-orderly startup. If there is a chance that the TPM // could not update failedTries /* Removes the behavior of automatically incrementing the failed tries counter after any non-orderly shutdown. When YES, the failed counter is incremented on non-orderly shutdown only if an attempt to access a DA protected object was made on the previous cycle. */ #if !(defined USE_DA_USED) || ((USE_DA_USED != NO) && (USE_DA_USED != YES)) # undef USE_DA_USED # define USE_DA_USED YES // Default: Either YES or NO #endif // Define TABLE_DRIVEN_DISPATCH to use tables rather than case statements for command dispatch and // handle unmarshaling #if !(defined TABLE_DRIVEN_DISPATCH) \ || ((TABLE_DRIVEN_DISPATCH != NO) && (TABLE_DRIVEN_DISPATCH != YES)) # undef TABLE_DRIVEN_DISPATCH # define TABLE_DRIVEN_DISPATCH YES // Default: Either YES or NO #endif /* This switch is used to enable the self-test capability in AlgorithmTests.c */ #if !(defined SELF_TEST) || ((SELF_TEST != NO) && (SELF_TEST != YES)) # undef SELF_TEST # define SELF_TEST YES // Default: Either YES or NO #endif /* Enable the generation of RSA primes using a sieve. */ #if !(defined RSA_KEY_SIEVE) || ((RSA_KEY_SIEVE != NO) && (RSA_KEY_SIEVE != YES)) # undef RSA_KEY_SIEVE # define RSA_KEY_SIEVE YES // Default: Either YES or NO #endif /* Enable the instrumentation of the sieve process. This is used to tune the sieve variables.*/ #if RSA_KEY_SIEVE && SIMULATION # if !(defined RSA_INSTRUMENT) || ((RSA_INSTRUMENT != NO) && (RSA_INSTRUMENT != YES)) # undef RSA_INSTRUMENT # define RSA_INSTRUMENT NO // Default: Either YES or NO # endif #endif /* This switch enables the RNG state save and restore */ #if !(defined _DRBG_STATE_SAVE) \ || ((_DRBG_STATE_SAVE != NO) && (_DRBG_STATE_SAVE != YES)) # undef _DRBG_STATE_SAVE # define _DRBG_STATE_SAVE YES // Default: Either YES or NO #endif /* Switch added to support packed lists that leave out space associated with unimplemented commands. Comment this out to use linear lists. */ /* NOTE: if vendor specific commands are present, the associated list is always in compressed form. */ #if !(defined COMPRESSED_LISTS) \ || ((COMPRESSED_LISTS != NO) && (COMPRESSED_LISTS != YES)) # undef COMPRESSED_LISTS # define COMPRESSED_LISTS YES // Default: Either YES or NO #endif /* This switch indicates where clock epoch value should be stored. If this value defined, then it is assumed that the timer will change at any time so the nonce should be a random number kept in RAM. When it is not defined, then the timer only stops during power outages. */ #if !(defined CLOCK_STOPS) || ((CLOCK_STOPS != NO) && (CLOCK_STOPS != YES)) # undef CLOCK_STOPS # define CLOCK_STOPS NO // Default: Either YES or NO #endif // This switch allows use of #defines in place of pass-through marshaling or unmarshaling code. A // pass-through function just calls another function to do the required function and does no // parameter checking of its own. The table-driven dispatcher calls directly to the lowest level // marshaling/unmarshaling code and by-passes any pass-through functions. #if (defined USE_MARSHALING_DEFINES) && (USE_MARSHALING_DEFINES != NO) # undef USE_MARSHALING_DEFINES # define USE_MARSHALING_DEFINES YES #else # define USE_MARSHALING_DEFINES YES // Default: Either YES or NO #endif // The switches in this group can only be enabled when doing debug during simulation #if SIMULATION && DEBUG /* This forces the use of a smaller context slot size. This reduction reduces the range of the epoch allowing the tester to force the epoch to occur faster than the normal defined in TpmProfile.h */ # if !(defined CONTEXT_SLOT) # define CONTEXT_SLOT UINT8 # endif // Enables use of the key cache. Default is YES # if !(defined USE_RSA_KEY_CACHE) \ || ((USE_RSA_KEY_CACHE != NO) && (USE_RSA_KEY_CACHE != YES)) # undef USE_RSA_KEY_CACHE # define USE_RSA_KEY_CACHE YES // Default: Either YES or NO # endif // Enables use of a file to store the key cache values so that the TPM will start faster during // debug. Default for this is YES # if USE_RSA_KEY_CACHE # if !(defined USE_KEY_CACHE_FILE) \ || ((USE_KEY_CACHE_FILE != NO) && (USE_KEY_CACHE_FILE != YES)) # undef USE_KEY_CACHE_FILE # define USE_KEY_CACHE_FILE YES // Default: Either YES or NO # endif # else # undef USE_KEY_CACHE_FILE # define USE_KEY_CACHE_FILE NO # endif // USE_RSA_KEY_CACHE // This provides fixed seeding of the RNG when doing debug on a simulator. This should allow // consistent results on test runs as long as the input parameters to the functions remains the // same. There is no default value. # if !(defined USE_DEBUG_RNG) || ((USE_DEBUG_RNG != NO) && (USE_DEBUG_RNG != YES)) # undef USE_DEBUG_RNG # define USE_DEBUG_RNG YES // Default: Either YES or NO # endif // Don't change these. They are the settings needed when not doing a simulation and not doing // debug. Can't use the key cache except during debug. Otherwise, all of the key values end up being // the same #else # define USE_RSA_KEY_CACHE NO # define USE_RSA_KEY_CACHE_FILE NO # define USE_DEBUG_RNG NO #endif // DEBUG && SIMULATION #if DEBUG // In some cases, the relationship between two values may be dependent on things that change based // on various selections like the chosen cryptographic libraries. It is possible that these // selections will result in incompatible settings. These are often detectable by the compiler but // it isn't always possible to do the check in the preprocessor code. For example, when the check // requires use of 'sizeof()' then the preprocessor can't do the comparison. For these cases, we // include a special macro that, depending on the compiler will generate a warning to indicate if // the check always passes or always fails because it involves fixed constants. To run these checks, // define COMPILER_CHECKS. # if !(defined COMPILER_CHECKS) \ || ((COMPILER_CHECKS != NO) && (COMPILER_CHECKS != YES)) # undef COMPILER_CHECKS # define COMPILER_CHECKS NO // Default: Either YES or NO # endif // Some of the values (such as sizes) are the result of different options set in // TpmProfile.h. The combination might not be consistent. A function is defined // (TpmSizeChecks()) that is used to verify the sizes at run time. To enable the function, define // this parameter. # if !(defined RUNTIME_SIZE_CHECKS) \ || ((RUNTIME_SIZE_CHECKS != NO) && (RUNTIME_SIZE_CHECKS != YES)) # undef RUNTIME_SIZE_CHECKS # define RUNTIME_SIZE_CHECKS NO // Default: Either YES or NO libtpms: NO # endif // If doing debug, can set the DRBG to print out the intermediate test values. Before enabling this, // make sure that the dbgDumpMemBlock() function has been added someplace (preferably, somewhere in // CryptRand.c) # if !(defined DRBG_DEBUG_PRINT) \ || ((DRBG_DEBUG_PRINT != NO) && (DRBG_DEBUG_PRINT != YES)) # undef DRBG_DEBUG_PRINT # define DRBG_DEBUG_PRINT NO // Default: Either YES or NO # endif // If an assertion event it not going to produce any trace information (function and line number) // then make FAIL_TRACE == NO # if !(defined FAIL_TRACE) || ((FAIL_TRACE != NO) && (FAIL_TRACE != YES)) # undef FAIL_TRACE # define FAIL_TRACE YES // Default: Either YES or NO # endif #endif // DEBUG /* Indicate if the implementation is going to give lockout time credit for time up to the last orderly shutdown. */ #if !(defined ACCUMULATE_SELF_HEAL_TIMER) \ || ((ACCUMULATE_SELF_HEAL_TIMER != NO) && (ACCUMULATE_SELF_HEAL_TIMER != YES)) # undef ACCUMULATE_SELF_HEAL_TIMER # define ACCUMULATE_SELF_HEAL_TIMER YES // Default: Either YES or NO #endif /* If the implementation is to compute the sizes of the proof and primary seed size values based on the implemented algorithms, then use this define. */ #if !(defined USE_SPEC_COMPLIANT_PROOFS) \ || ((USE_SPEC_COMPLIANT_PROOFS != NO) && (USE_SPEC_COMPLIANT_PROOFS != YES)) # undef USE_SPEC_COMPLIANT_PROOFS # define USE_SPEC_COMPLIANT_PROOFS YES // Default: Either YES or NO #endif // Comment this out to allow compile to continue even though the chosen proof values do not match // the compliant values. This is written so that someone would have to proactively ignore errors. #if !(defined SKIP_PROOF_ERRORS) \ || ((SKIP_PROOF_ERRORS != NO) && (SKIP_PROOF_ERRORS != YES)) # undef SKIP_PROOF_ERRORS # define SKIP_PROOF_ERRORS NO // Default: Either YES or NO #endif // This define is used to eliminate the use of bit-fields. It can be enabled for big- or // little-endian machines. For big-endian architectures that number bits in registers from left to // right (MSb0()) this must be enabled. Little-endian machines number from right to left with the // least significant bit having assigned a bit number of 0. These are LSb0() machines (they are also // little-endian so they are also least-significant byte 0 (LSB0) machines. Big-endian (MSB0) // machines may number in either direction (MSb0() or LSb0()). For an MSB0+MSb0() machine this // value is required to be NO #if !(defined USE_BIT_FIELD_STRUCTURES) \ || ((USE_BIT_FIELD_STRUCTURES != NO) && (USE_BIT_FIELD_STRUCTURES != YES)) # undef USE_BIT_FIELD_STRUCTURES # define USE_BIT_FIELD_STRUCTURES NO // Default: Either YES or NO libtpms: NO #endif // This define is used to control the debug for the CertifyX509() command. #if !(defined CERTIFYX509_DEBUG) \ || ((CERTIFYX509_DEBUG != NO) && (CERTIFYX509_DEBUG != YES)) # undef CERTIFYX509_DEBUG # define CERTIFYX509_DEBUG NO // libtpms: NO #endif #if !(defined TABLE_DRIVEN_MARSHAL) \ || ((TABLE_DRIVEN_MARSHAL != NO) && (TABLE_DRIVEN_MARSHAL != YES)) # undef TABLE_DRIVEN_MARSHAL # define TABLE_DRIVEN_MARSHAL NO // Default: Either YES or NO libtpms: NO #endif /* Change these definitions to turn all algorithms or commands ON or OFF. That is, to turn all algorithms on, set ALG_NO to YES. This is mostly useful as a debug feature. */ #define ALG_YES YES #define ALG_NO NO #define CC_YES YES #define CC_NO NO #endif // _TPM_BUILD_SWITCHES_H_ libtpms-0.9.3/src/tpm2/TpmError.h000066400000000000000000000104271421143571500166000ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: TpmError.h 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 */ /* */ /********************************************************************************/ #ifndef TPMERROR_H #define TPMERROR_H /* 5.23 TpmError.h */ #define FATAL_ERROR_ALLOCATION (1) #define FATAL_ERROR_DIVIDE_ZERO (2) #define FATAL_ERROR_INTERNAL (3) #define FATAL_ERROR_PARAMETER (4) #define FATAL_ERROR_ENTROPY (5) #define FATAL_ERROR_SELF_TEST (6) #define FATAL_ERROR_CRYPTO (7) #define FATAL_ERROR_NV_UNRECOVERABLE (8) #define FATAL_ERROR_REMANUFACTURED (9) // indicates that the TPM has // been re-manufactured after an // unrecoverable NV error #define FATAL_ERROR_DRBG (10) #define FATAL_ERROR_MOVE_SIZE (11) #define FATAL_ERROR_COUNTER_OVERFLOW (12) #define FATAL_ERROR_SUBTRACT (13) #define FATAL_ERROR_FORCED (666) #endif libtpms-0.9.3/src/tpm2/TpmFail.c000066400000000000000000000413571421143571500163630ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Failure Mode Handling */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: TpmFail.c 1644 2020-09-11 17:25:11Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ /* 9.17 TpmFail.c */ /* 9.17.1 Includes, Defines, and Types */ #define TPM_FAIL_C #include "Tpm.h" #include /* On MS C compiler, can save the alignment state and set the alignment to 1 for the duration of the TpmTypes.h include. This will avoid a lot of alignment warnings from the compiler for the unaligned structures. The alignment of the structures is not important as this function does not use any of the structures in TpmTypes.h and only include it for the #defines of the capabilities, properties, and command code values. */ #include "TpmTypes.h" #define TPM_HAVE_TPM2_DECLARATIONS #include "tpm_library_intern.h" // libtpms added /* 9.17.2 Typedefs */ /* These defines are used primarily for sizing of the local response buffer. */ typedef struct { TPM_ST tag; UINT32 size; TPM_RC code; } HEADER; typedef struct { BYTE tag[sizeof(TPM_ST)]; BYTE size[sizeof(UINT32)]; BYTE code[sizeof(TPM_RC)]; } PACKED_HEADER; typedef struct { BYTE size[sizeof(UINT16)]; struct { BYTE function[sizeof(UINT32)]; BYTE line[sizeof(UINT32)]; BYTE code[sizeof(UINT32)]; } values; BYTE returnCode[sizeof(TPM_RC)]; } GET_TEST_RESULT_PARAMETERS; typedef struct { BYTE moreData[sizeof(TPMI_YES_NO)]; BYTE capability[sizeof(TPM_CAP)]; // Always TPM_CAP_TPM_PROPERTIES BYTE tpmProperty[sizeof(TPML_TAGGED_TPM_PROPERTY)]; } GET_CAPABILITY_PARAMETERS; typedef struct { BYTE header[sizeof(PACKED_HEADER)]; BYTE getTestResult[sizeof(GET_TEST_RESULT_PARAMETERS)]; } TEST_RESPONSE; typedef struct { BYTE header[sizeof(PACKED_HEADER)]; BYTE getCap[sizeof(GET_CAPABILITY_PARAMETERS)]; } CAPABILITY_RESPONSE; typedef union { BYTE test[sizeof(TEST_RESPONSE)]; BYTE cap[sizeof(CAPABILITY_RESPONSE)]; } RESPONSES; /* Buffer to hold the responses. This may be a little larger than required due to padding that a compiler might add. */ /* NOTE: This is not in Global.c because of the specialized data definitions above. Since the data contained in this structure is not relevant outside of the execution of a single command (when the TPM is in failure mode. There is no compelling reason to move all the typedefs to Global.h and this structure to Global.c. */ #ifndef __IGNORE_STATE__ // Don't define this value static BYTE response[sizeof(RESPONSES)]; #endif /* 9.17.3 Local Functions */ /* 9.17.3.1 MarshalUint16() */ /* Function to marshal a 16 bit value to the output buffer. */ static INT32 MarshalUint16( UINT16 integer, BYTE **buffer ) { UINT16_TO_BYTE_ARRAY(integer, *buffer); *buffer += 2; return 2; } /* 9.17.3.2 MarshalUint32() */ /* Function to marshal a 32 bit value to the output buffer. */ static INT32 MarshalUint32( UINT32 integer, BYTE **buffer ) { UINT32_TO_BYTE_ARRAY(integer, *buffer); *buffer += 4; return 4; } /* 9.17.3.3 Unmarshal32() */ static BOOL Unmarshal32( UINT32 *target, BYTE **buffer, INT32 *size ) { if((*size -= 4) < 0) return FALSE; *target = BYTE_ARRAY_TO_UINT32(*buffer); *buffer += 4; return TRUE; } /* 9.17.3.4 Unmarshal16() */ static BOOL Unmarshal16( UINT16 *target, BYTE **buffer, INT32 *size ) { if((*size -= 2) < 0) return FALSE; *target = BYTE_ARRAY_TO_UINT16(*buffer); *buffer += 2; return TRUE; } /* 9.17.4Public Functions */ #if 0 /* libtpms added */ /* 9.17.4.1 SetForceFailureMode() */ /* This function is called by the simulator to enable failure mode testing. */ LIB_EXPORT void SetForceFailureMode( void ) { #if SIMULATION g_forceFailureMode = TRUE; #endif return; } #endif /* libtpms added */ /* 9.17.4.2 TpmLogFailure() */ /* This function saves the failure values when the code will continue to operate. It if similar to TpmFail() but returns to the caller. The assumption is that the caller will propagate a failure back up the stack. */ void TpmLogFailure( #if FAIL_TRACE const char *function, int line, #endif int code ) { #if 0 // libtpms added // Save the values that indicate where the error occurred. // On a 64-bit machine, this may truncate the address of the string // of the function name where the error occurred. #if FAIL_TRACE memcpy(&s_failFunction, function, sizeof(uint32_t)); /* kgold */ s_failLine = line; #else s_failFunction = 0; s_failLine = 0; #endif s_failCode = code; // We are in failure mode g_inFailureMode = TRUE; #else // libtpms added begin TpmSetFailureMode( #if FAIL_TRACE function, line, #endif code); #endif // libtpms added end return; } /* 9.17.4.2 TpmFail() */ /* This function is called by TPM.lib when a failure occurs. It will set up the failure values to be returned on TPM2_GetTestResult(). */ NORETURN void TpmFail( #if FAIL_TRACE const char *function, int line, #endif int code ) { #if 0 /* libtpms added */ // Save the values that indicate where the error occurred. // On a 64-bit machine, this may truncate the address of the string // of the function name where the error occurred. #if FAIL_TRACE memcpy(&s_failFunction, function, sizeof(uint32_t)); s_failLine = line; #else s_failFunction = (UINT32)NULL; s_failLine = 0; #endif s_failCode = code; // We are in failure mode g_inFailureMode = TRUE; // if asserts are enabled, then do an assert unless the failure mode code // is being tested. #if SIMULATION # ifndef NDEBUG assert(g_forceFailureMode); # endif // Clear this flag g_forceFailureMode = FALSE; #endif #else /* libtpms added begin */ TpmSetFailureMode( #if FAIL_TRACE function, line, #endif code); #endif /* libtpms added end */ // Jump to the failure mode code. // Note: only get here if asserts are off or if we are testing failure mode _plat__Fail(); } /* libtpms added begin */ void TpmSetFailureMode( #if FAIL_TRACE const char *function, int line, #endif int code ) { // Save the values that indicate where the error occurred. // On a 64-bit machine, this may truncate the address of the string // of the function name where the error occurred. #if FAIL_TRACE s_failFunction = *(UINT32 *)function; s_failLine = line; #else s_failFunction = (UINT32)0; s_failLine = 0; #endif s_failCode = code; TPMLIB_LogTPM2Error("Entering failure mode; code: %d" #if FAIL_TRACE ", location: %s line %d" #endif "\n", s_failCode #if FAIL_TRACE , function, s_failLine #endif ); // We are in failure mode g_inFailureMode = TRUE; } /* libtpms added end */ /* 9.17.5 TpmFailureMode */ /* This function is called by the interface code when the platform is in failure mode. */ void TpmFailureMode( unsigned int inRequestSize, // IN: command buffer size unsigned char *inRequest, // IN: command buffer unsigned int *outResponseSize, // OUT: response buffer size unsigned char **outResponse // OUT: response buffer ) { UINT32 marshalSize; UINT32 capability; HEADER header; // unmarshaled command header UINT32 pt; // unmarshaled property type UINT32 count; // unmarshaled property count UINT8 *buffer = inRequest; INT32 size = inRequestSize; // If there is no command buffer, then just return TPM_RC_FAILURE if(inRequestSize == 0 || inRequest == NULL) goto FailureModeReturn; // If the header is not correct for TPM2_GetCapability() or // TPM2_GetTestResult() then just return the in failure mode response; if(! (Unmarshal16(&header.tag, &buffer, &size) && Unmarshal32(&header.size, &buffer, &size) && Unmarshal32(&header.code, &buffer, &size))) goto FailureModeReturn; if(header.tag != TPM_ST_NO_SESSIONS || header.size < 10) goto FailureModeReturn; switch(header.code) { case TPM_CC_GetTestResult: // make sure that the command size is correct if(header.size != 10) goto FailureModeReturn; buffer = &response[10]; marshalSize = MarshalUint16(3 * sizeof(UINT32), &buffer); marshalSize += MarshalUint32(s_failFunction, &buffer); marshalSize += MarshalUint32(s_failLine, &buffer); marshalSize += MarshalUint32(s_failCode, &buffer); if(s_failCode == FATAL_ERROR_NV_UNRECOVERABLE) marshalSize += MarshalUint32(TPM_RC_NV_UNINITIALIZED, &buffer); else marshalSize += MarshalUint32(TPM_RC_FAILURE, &buffer); break; case TPM_CC_GetCapability: // make sure that the size of the command is exactly the size // returned for the capability, property, and count if(header.size != (10 + (3 * sizeof(UINT32))) // also verify that this is requesting TPM properties || !Unmarshal32(&capability, &buffer, &size) || capability != TPM_CAP_TPM_PROPERTIES || !Unmarshal32(&pt, &buffer, &size) || !Unmarshal32(&count, &buffer, &size)) goto FailureModeReturn; // If in failure mode because of an unrecoverable read error, and the // property is 0 and the count is 0, then this is an indication to // re-manufacture the TPM. Do the re-manufacture but stay in failure // mode until the TPM is reset. // Note: this behavior is not required by the specification and it is // OK to leave the TPM permanently bricked due to an unrecoverable NV // error. if(count == 0 && pt == 0 && s_failCode == FATAL_ERROR_NV_UNRECOVERABLE) { g_manufactured = FALSE; TPM_Manufacture(0); } if(count > 0) count = 1; else if(pt > TPM_PT_FIRMWARE_VERSION_2) count = 0; if(pt < TPM_PT_MANUFACTURER) pt = TPM_PT_MANUFACTURER; // set up for return buffer = &response[10]; // if the request was for a PT less than the last one // then we indicate more, otherwise, not. if(pt < TPM_PT_FIRMWARE_VERSION_2) *buffer++ = YES; else *buffer++ = NO; marshalSize = 1; // indicate the capability type marshalSize += MarshalUint32(capability, &buffer); // indicate the number of values that are being returned (0 or 1) marshalSize += MarshalUint32(count, &buffer); // indicate the property marshalSize += MarshalUint32(pt, &buffer); if(count > 0) switch(pt) { case TPM_PT_MANUFACTURER: // the vendor ID unique to each TPM manufacturer #ifdef MANUFACTURER pt = *(UINT32*)MANUFACTURER; #else pt = 0; #endif break; case TPM_PT_VENDOR_STRING_1: // the first four characters of the vendor ID string #ifdef VENDOR_STRING_1 pt = *(UINT32*)VENDOR_STRING_1; #else pt = 0; #endif break; case TPM_PT_VENDOR_STRING_2: // the second four characters of the vendor ID string #ifdef VENDOR_STRING_2 pt = *(UINT32*)VENDOR_STRING_2; #else pt = 0; #endif break; case TPM_PT_VENDOR_STRING_3: // the third four characters of the vendor ID string #ifdef VENDOR_STRING_3 pt = *(UINT32*)VENDOR_STRING_3; #else pt = 0; #endif break; case TPM_PT_VENDOR_STRING_4: // the fourth four characters of the vendor ID string #ifdef VENDOR_STRING_4 pt = *(UINT32*)VENDOR_STRING_4; #else pt = 0; #endif break; case TPM_PT_VENDOR_TPM_TYPE: // vendor-defined value indicating the TPM model // We just make up a number here pt = 1; break; case TPM_PT_FIRMWARE_VERSION_1: // the more significant 32-bits of a vendor-specific value // indicating the version of the firmware #ifdef FIRMWARE_V1 pt = FIRMWARE_V1; #else pt = 0; #endif break; default: // TPM_PT_FIRMWARE_VERSION_2: // the less significant 32-bits of a vendor-specific value // indicating the version of the firmware #ifdef FIRMWARE_V2 pt = FIRMWARE_V2; #else pt = 0; #endif break; } marshalSize += MarshalUint32(pt, &buffer); break; default: // default for switch (cc) goto FailureModeReturn; } // Now do the header buffer = response; marshalSize = marshalSize + 10; // Add the header size to the // stuff already marshaled MarshalUint16(TPM_ST_NO_SESSIONS, &buffer); // structure tag MarshalUint32(marshalSize, &buffer); // responseSize MarshalUint32(TPM_RC_SUCCESS, &buffer); // response code *outResponseSize = marshalSize; *outResponse = (unsigned char *)&response; return; FailureModeReturn: buffer = response; marshalSize = MarshalUint16(TPM_ST_NO_SESSIONS, &buffer); marshalSize += MarshalUint32(10, &buffer); marshalSize += MarshalUint32(TPM_RC_FAILURE, &buffer); *outResponseSize = marshalSize; *outResponse = (unsigned char *)response; return; } #if 0 // libtpms added /* 9.17.6 UnmarshalFail() */ /* This is a stub that is used to catch an attempt to unmarshal an entry that is not defined. Don't ever expect this to be called but... */ void UnmarshalFail( void *type, BYTE **buffer, INT32 *size ) { NOT_REFERENCED(type); NOT_REFERENCED(buffer); NOT_REFERENCED(size); FAIL(FATAL_ERROR_INTERNAL); } #endif // libtpms added libtpms-0.9.3/src/tpm2/TpmFail_fp.h000066400000000000000000000106551421143571500170520ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Failure Mode Handling */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: TpmFail_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ #ifndef TPMFAIL_FP_H #define TPMFAIL_FP_H #include "BaseTypes.h" #if 0 /* libtpms added */ LIB_EXPORT void SetForceFailureMode( void ); #endif /* libtpms added */ void TpmLogFailure( #if FAIL_TRACE const char *function, int line, #endif int code ); NORETURN void TpmFail( #if FAIL_TRACE /* libtpms added begin */ const char *function, int line, #endif int code ); void TpmSetFailureMode( #if FAIL_TRACE /* libtpms added end */ const char *function, int line, #endif int code ); void TpmFailureMode( unsigned int inRequestSize, // IN: command buffer size unsigned char *inRequest, // IN: command buffer unsigned int *outResponseSize, // OUT: response buffer size unsigned char **outResponse // OUT: response buffer ); #if 0 /* libtpms added */ void UnmarshalFail( void *type, BYTE **buffer, INT32 *size ); #endif /* libtpms added */ #endif libtpms-0.9.3/src/tpm2/TpmProfile.h000066400000000000000000000630641421143571500171140ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Constants Reflecting a Particular TPM Implementation (e.g. PC Client) */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: TpmProfile.h 1629 2020-06-01 20:50:13Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2019 - 2020 */ /* */ /********************************************************************************/ // FOR LIBTPMS: DO NOT EDIT THIS FILE! // ANY MODIFICATION WILL LEAD TO AN UNSUPPORTED CONFIGURATION // A.2 TpmProfile.h #ifndef _TPM_PROFILE_H_ #define _TPM_PROFILE_H_ // Table 2:4 - Defines for Logic Values #undef TRUE #define TRUE 1 #undef FALSE #define FALSE 0 #undef YES #define YES 1 #undef NO #define NO 0 #undef SET #define SET 1 #undef CLEAR #define CLEAR 0 // Table 0:1 - Defines for Processor Values #if defined __FreeBSD__ || defined __DragonFly__ /* libtpms added begin */ # include #elif defined __APPLE__ # include #else # include #endif #if defined __linux__ || defined __CYGWIN__ #if __BYTE_ORDER == __LITTLE_ENDIAN #define BIG_ENDIAN_TPM NO #endif #if __BYTE_ORDER == __BIG_ENDIAN #define BIG_ENDIAN_TPM YES #endif #elif defined __OpenBSD__ || defined __FreeBSD__ || defined __NetBSD__ \ || defined __DragonFly__ #if _BYTE_ORDER == _LITTLE_ENDIAN #define BIG_ENDIAN_TPM NO #endif #if _BYTE_ORDER == _BIG_ENDIAN #define BIG_ENDIAN_TPM YES #endif #elif defined __APPLE__ #define BIG_ENDIAN_TPM NO #else #error Unsupported OS #endif /* libtpms added end */ #ifndef BIG_ENDIAN_TPM #define BIG_ENDIAN_TPM NO #endif #ifndef LITTLE_ENDIAN_TPM #define LITTLE_ENDIAN_TPM !BIG_ENDIAN_TPM #endif #ifndef MOST_SIGNIFICANT_BIT_0 #define MOST_SIGNIFICANT_BIT_0 NO #endif #ifndef LEAST_SIGNIFICANT_BIT_0 #define LEAST_SIGNIFICANT_BIT_0 !MOST_SIGNIFICANT_BIT_0 #endif #ifndef AUTO_ALIGN #define AUTO_ALIGN NO #endif // Table 0:4 - Defines for Implemented Curves #ifndef ECC_NIST_P192 #define ECC_NIST_P192 YES /* libtpms enabled */ #endif #ifndef ECC_NIST_P224 #define ECC_NIST_P224 YES /* libtpms enabled */ #endif #ifndef ECC_NIST_P256 #define ECC_NIST_P256 YES #endif #ifndef ECC_NIST_P384 #define ECC_NIST_P384 YES #endif #ifndef ECC_NIST_P521 #define ECC_NIST_P521 YES /* libtpms enabled */ #endif #ifndef ECC_BN_P256 #define ECC_BN_P256 YES #endif #ifndef ECC_BN_P638 #define ECC_BN_P638 YES /* libtpms enabled */ #endif #ifndef ECC_SM2_P256 #define ECC_SM2_P256 YES /* libtpms enabled */ #endif /* Table 0:6 - Defines for Implemented ACT */ #ifndef RH_ACT_0 #define RH_ACT_0 NO /* libtpms: no */ #endif #ifndef RH_ACT_1 #define RH_ACT_1 NO #endif #ifndef RH_ACT_A #define RH_ACT_A NO /* libtpms: no */ #endif // libtpms added begin #if RH_ACT_0 + RH_ACT_1 + RH_ACT_2 + RH_ACT_3 + RH_ACT_4 + \ RH_ACT_1 + RH_ACT_5 + RH_ACT_6 + RH_ACT_7 + RH_ACT_8 + \ RH_ACT_9 + RH_ACT_A + RH_ACT_B + RH_ACT_C + RH_ACT_D + \ RH_ACT_E + RH_ACT_F == 0 #define __ACT_DISABLED #endif // libtpms added end // Table 0:7 - Defines for Implementation Values #ifndef FIELD_UPGRADE_IMPLEMENTED #define FIELD_UPGRADE_IMPLEMENTED NO #endif #ifdef TPM_POSIX // libtpms added begin # include # ifdef THIRTY_TWO_BIT # define RADIX_BITS 32 # endif # ifdef SIXTY_FOUR_BIT_LONG # define RADIX_BITS 64 # endif # ifndef RADIX_BITS # error Need to determine RADIX_BITS value # endif #endif #ifdef TPM_WINDOWS #define RADIX_BITS 32 #endif // libtpms added end #ifndef HASH_LIB #define HASH_LIB Ossl #endif #ifndef SYM_LIB #define SYM_LIB Ossl #endif #ifndef MATH_LIB #define MATH_LIB Ossl #endif #ifndef IMPLEMENTATION_PCR #define IMPLEMENTATION_PCR 24 #endif #ifndef PLATFORM_PCR #define PLATFORM_PCR 24 #endif #ifndef DRTM_PCR #define DRTM_PCR 17 #endif #ifndef HCRTM_PCR #define HCRTM_PCR 0 #endif #ifndef NUM_LOCALITIES #define NUM_LOCALITIES 5 #endif #ifndef MAX_HANDLE_NUM #define MAX_HANDLE_NUM 3 #endif #ifndef MAX_ACTIVE_SESSIONS #define MAX_ACTIVE_SESSIONS 64 #endif #ifndef CONTEXT_SLOT #define CONTEXT_SLOT UINT16 /* libtpms: changed from UINT8 in v0.9.0 */ #endif #ifndef MAX_LOADED_SESSIONS #define MAX_LOADED_SESSIONS 3 #endif #ifndef MAX_SESSION_NUM #define MAX_SESSION_NUM 3 #endif #ifndef MAX_LOADED_OBJECTS #define MAX_LOADED_OBJECTS 3 #endif #ifndef MIN_EVICT_OBJECTS #define MIN_EVICT_OBJECTS 7 /* libtpms changed -- for PC profile */ #endif #ifndef NUM_POLICY_PCR_GROUP #define NUM_POLICY_PCR_GROUP 1 #endif #ifndef NUM_AUTHVALUE_PCR_GROUP #define NUM_AUTHVALUE_PCR_GROUP 1 #endif #ifndef MAX_CONTEXT_SIZE #define MAX_CONTEXT_SIZE 2680 /* libtpms changed */ #endif #ifndef MAX_DIGEST_BUFFER #define MAX_DIGEST_BUFFER 1024 #endif #ifndef MAX_NV_INDEX_SIZE #define MAX_NV_INDEX_SIZE 2048 #endif #ifndef MAX_NV_BUFFER_SIZE #define MAX_NV_BUFFER_SIZE 1024 #endif #ifndef MAX_CAP_BUFFER #define MAX_CAP_BUFFER 1024 #endif /* for PC client, permits 1300 bytes reserved 7 * 2600 persistent objects 4000 NV indexes 60 * 68 nv index metadata */ #ifndef NV_MEMORY_SIZE /* libtmps: 65 OBJECTs in USER NVRAM expanded by 704 bytes due to size * increase of OBJECT from 2048 bit RSA keys to 3072 bit by 704 bytes*/ #define NV_MEMORY_SIZE (128 * 1024 + 65 * 704) /* libtpms changed */ #endif #ifndef MIN_COUNTER_INDICES #define MIN_COUNTER_INDICES 8 #endif #ifndef NUM_STATIC_PCR #define NUM_STATIC_PCR 16 #endif #ifndef MAX_ALG_LIST_SIZE #define MAX_ALG_LIST_SIZE 64 #endif #ifndef PRIMARY_SEED_SIZE #define PRIMARY_SEED_SIZE 64 /* libtpms: 64 per define USE_SPEC_COMPLIANT_PROOFS */ #endif #ifndef CONTEXT_ENCRYPT_ALGORITHM #define CONTEXT_ENCRYPT_ALGORITHM AES #endif #ifndef NV_CLOCK_UPDATE_INTERVAL #define NV_CLOCK_UPDATE_INTERVAL 12 #endif #ifndef NUM_POLICY_PCR #define NUM_POLICY_PCR 1 #endif #ifndef MAX_COMMAND_SIZE #define MAX_COMMAND_SIZE TPM2_GetBufferSize() /* libtpms changed */ #endif #ifndef MAX_RESPONSE_SIZE #define MAX_RESPONSE_SIZE TPM2_GetBufferSize() /* libtpms changed */ #endif #ifndef ORDERLY_BITS #define ORDERLY_BITS 8 #endif #ifndef MAX_SYM_DATA #define MAX_SYM_DATA 128 #endif #ifndef MAX_RNG_ENTROPY_SIZE #define MAX_RNG_ENTROPY_SIZE 64 #endif #ifndef RAM_INDEX_SPACE #define RAM_INDEX_SPACE 512 #endif #ifndef RSA_DEFAULT_PUBLIC_EXPONENT #define RSA_DEFAULT_PUBLIC_EXPONENT 0x00010001 #endif #ifndef ENABLE_PCR_NO_INCREMENT #define ENABLE_PCR_NO_INCREMENT YES #endif #ifndef CRT_FORMAT_RSA #define CRT_FORMAT_RSA YES #endif #ifndef VENDOR_COMMAND_COUNT #define VENDOR_COMMAND_COUNT 0 #endif #ifndef MAX_VENDOR_BUFFER_SIZE #define MAX_VENDOR_BUFFER_SIZE 1024 #endif #ifndef SIZE_OF_X509_SERIAL_NUMBER #define SIZE_OF_X509_SERIAL_NUMBER 20 #endif #ifndef PRIVATE_VENDOR_SPECIFIC_BYTES #define PRIVATE_VENDOR_SPECIFIC_BYTES \ ((MAX_RSA_KEY_BYTES/2) * (3 + CRT_FORMAT_RSA * 2)) /* libtpms: keep as was in rev 150 */ #endif // Table 0:2 - Defines for Implemented Algorithms #ifndef ALG_AES #define ALG_AES ALG_YES #endif #ifndef ALG_CAMELLIA #define ALG_CAMELLIA ALG_YES /* libtpms: YES since v0.9 */ #endif #ifndef ALG_CBC #define ALG_CBC ALG_YES #endif #ifndef ALG_CFB #define ALG_CFB ALG_YES #endif #ifndef ALG_CMAC #define ALG_CMAC ALG_YES #endif #ifndef ALG_CTR #define ALG_CTR ALG_YES #endif #ifndef ALG_ECB #define ALG_ECB ALG_YES #endif #ifndef ALG_ECC #define ALG_ECC ALG_YES #endif #ifndef ALG_ECDAA #define ALG_ECDAA (ALG_YES && ALG_ECC) #endif #ifndef ALG_ECDH #define ALG_ECDH (ALG_YES && ALG_ECC) #endif #ifndef ALG_ECDSA #define ALG_ECDSA (ALG_YES && ALG_ECC) #endif #ifndef ALG_ECMQV #define ALG_ECMQV (ALG_YES && ALG_ECC) /* libtpms enabled */ #endif #ifndef ALG_ECSCHNORR #define ALG_ECSCHNORR (ALG_YES && ALG_ECC) #endif #ifndef ALG_HMAC #define ALG_HMAC ALG_YES #endif #ifndef ALG_KDF1_SP800_108 #define ALG_KDF1_SP800_108 ALG_YES #endif #ifndef ALG_KDF1_SP800_56A #define ALG_KDF1_SP800_56A (ALG_YES && ALG_ECC) #endif #ifndef ALG_KDF2 #define ALG_KDF2 ALG_YES #endif #ifndef ALG_KEYEDHASH #define ALG_KEYEDHASH ALG_YES #endif #ifndef ALG_MGF1 #define ALG_MGF1 ALG_YES #endif #ifndef ALG_OAEP #define ALG_OAEP (ALG_YES && ALG_RSA) #endif #ifndef ALG_OFB #define ALG_OFB ALG_YES #endif #ifndef ALG_RSA #define ALG_RSA ALG_YES #endif #ifndef ALG_RSAES #define ALG_RSAES (ALG_YES && ALG_RSA) #endif #ifndef ALG_RSAPSS #define ALG_RSAPSS (ALG_YES && ALG_RSA) #endif #ifndef ALG_RSASSA #define ALG_RSASSA (ALG_YES && ALG_RSA) #endif #ifndef ALG_SHA #define ALG_SHA ALG_NO /* Not specified by vendor */ #endif #ifndef ALG_SHA1 #define ALG_SHA1 ALG_YES #endif #ifndef ALG_SHA256 #define ALG_SHA256 ALG_YES #endif #ifndef ALG_SHA384 #define ALG_SHA384 ALG_YES #endif #ifndef ALG_SHA3_256 #define ALG_SHA3_256 ALG_NO /* Not specified by vendor */ #endif #ifndef ALG_SHA3_384 #define ALG_SHA3_384 ALG_NO /* Not specified by vendor */ #endif #ifndef ALG_SHA3_512 #define ALG_SHA3_512 ALG_NO /* Not specified by vendor */ #endif #ifndef ALG_SHA512 #define ALG_SHA512 ALG_YES #endif #ifndef ALG_SM2 #define ALG_SM2 (ALG_YES && ALG_ECC) /* libtpms enabled */ #endif #ifndef ALG_SM3_256 #define ALG_SM3_256 ALG_NO /* libtpms: NO */ #endif #ifndef ALG_SM4 #define ALG_SM4 ALG_NO /* libtpms: NO */ #endif #ifndef ALG_SYMCIPHER #define ALG_SYMCIPHER ALG_YES #endif #ifndef ALG_TDES #define ALG_TDES ALG_YES /* libtpms enabled */ #endif #ifndef ALG_XOR #define ALG_XOR ALG_YES #endif // Table 1:00 - Defines for RSA Asymmetric Cipher Algorithm Constants #ifndef RSA_1024 #define RSA_1024 (ALG_RSA && YES) #endif #ifndef RSA_2048 #define RSA_2048 (ALG_RSA && YES) #endif #ifndef RSA_3072 #define RSA_3072 (ALG_RSA && YES) #endif #ifndef RSA_4096 #define RSA_4096 (ALG_RSA && NO) #endif #ifndef RSA_16384 #define RSA_16384 (ALG_RSA && NO) #endif // Table 1:17 - Defines for AES Symmetric Cipher Algorithm Constants #ifndef AES_128 #define AES_128 (ALG_AES && YES) #endif #ifndef AES_192 #define AES_192 (ALG_AES && NO) #endif #ifndef AES_256 #define AES_256 (ALG_AES && YES) #endif // Table 1:18 - Defines for SM4 Symmetric Cipher Algorithm Constants #ifndef SM4_128 #define SM4_128 (ALG_SM4 && YES) #endif // Table 1:19 - Defines for CAMELLIA Symmetric Cipher Algorithm Constants #ifndef CAMELLIA_128 #define CAMELLIA_128 (ALG_CAMELLIA && YES) #endif #ifndef CAMELLIA_192 #define CAMELLIA_192 (ALG_CAMELLIA && NO) #endif #ifndef CAMELLIA_256 #define CAMELLIA_256 (ALG_CAMELLIA && YES) #endif // Table 1:17 - Defines for TDES Symmetric Cipher Algorithm Constants #ifndef TDES_128 #define TDES_128 (ALG_TDES && YES) #endif #ifndef TDES_192 #define TDES_192 (ALG_TDES && YES) #endif // Table 0:5 - Defines for Implemented Commands #ifndef CC_ACT_SetTimeout #define CC_ACT_SetTimeout CC_NO /* libtpms: NO */ #endif #ifndef CC_AC_GetCapability #define CC_AC_GetCapability CC_NO /* kgold */ #endif #ifndef CC_AC_Send #define CC_AC_Send CC_NO /* kgold */ #endif #ifndef CC_ActivateCredential #define CC_ActivateCredential CC_YES #endif #ifndef CC_Certify #define CC_Certify CC_YES #endif #ifndef CC_CertifyCreation #define CC_CertifyCreation CC_YES #endif #ifndef CC_CertifyX509 #define CC_CertifyX509 CC_YES #endif #ifndef CC_ChangeEPS #define CC_ChangeEPS CC_YES #endif #ifndef CC_ChangePPS #define CC_ChangePPS CC_YES #endif #ifndef CC_Clear #define CC_Clear CC_YES #endif #ifndef CC_ClearControl #define CC_ClearControl CC_YES #endif #ifndef CC_ClockRateAdjust #define CC_ClockRateAdjust CC_YES #endif #ifndef CC_ClockSet #define CC_ClockSet CC_YES #endif #ifndef CC_Commit #define CC_Commit (CC_YES && ALG_ECC) #endif #ifndef CC_ContextLoad #define CC_ContextLoad CC_YES #endif #ifndef CC_ContextSave #define CC_ContextSave CC_YES #endif #ifndef CC_Create #define CC_Create CC_YES #endif #ifndef CC_CreateLoaded #define CC_CreateLoaded CC_YES #endif #ifndef CC_CreatePrimary #define CC_CreatePrimary CC_YES #endif #ifndef CC_DictionaryAttackLockReset #define CC_DictionaryAttackLockReset CC_YES #endif #ifndef CC_DictionaryAttackParameters #define CC_DictionaryAttackParameters CC_YES #endif #ifndef CC_Duplicate #define CC_Duplicate CC_YES #endif #ifndef CC_ECC_Decrypt #define CC_ECC_Decrypt (CC_NO && ALG_ECC) #endif #ifndef CC_ECC_Encrypt #define CC_ECC_Encrypt (CC_NO && ALG_ECC) #endif #ifndef CC_ECC_Parameters #define CC_ECC_Parameters (CC_YES && ALG_ECC) #endif #ifndef CC_ECDH_KeyGen #define CC_ECDH_KeyGen (CC_YES && ALG_ECC) #endif #ifndef CC_ECDH_ZGen #define CC_ECDH_ZGen (CC_YES && ALG_ECC) #endif #ifndef CC_EC_Ephemeral #define CC_EC_Ephemeral (CC_YES && ALG_ECC) #endif #ifndef CC_EncryptDecrypt #define CC_EncryptDecrypt CC_YES #endif #ifndef CC_EncryptDecrypt2 #define CC_EncryptDecrypt2 CC_YES #endif #ifndef CC_EventSequenceComplete #define CC_EventSequenceComplete CC_YES #endif #ifndef CC_EvictControl #define CC_EvictControl CC_YES #endif #ifndef CC_FieldUpgradeData #define CC_FieldUpgradeData CC_NO #endif #ifndef CC_FieldUpgradeStart #define CC_FieldUpgradeStart CC_NO #endif #ifndef CC_FirmwareRead #define CC_FirmwareRead CC_NO #endif #ifndef CC_FlushContext #define CC_FlushContext CC_YES #endif #ifndef CC_GetCapability #define CC_GetCapability CC_YES #endif #ifndef CC_GetCommandAuditDigest #define CC_GetCommandAuditDigest CC_YES #endif #ifndef CC_GetRandom #define CC_GetRandom CC_YES #endif #ifndef CC_GetSessionAuditDigest #define CC_GetSessionAuditDigest CC_YES #endif #ifndef CC_GetTestResult #define CC_GetTestResult CC_YES #endif #ifndef CC_GetTime #define CC_GetTime CC_YES #endif #ifndef CC_HMAC #define CC_HMAC (CC_YES && !ALG_CMAC) #endif #ifndef CC_HMAC_Start #define CC_HMAC_Start (CC_YES && !ALG_CMAC) #endif #ifndef CC_Hash #define CC_Hash CC_YES #endif #ifndef CC_HashSequenceStart #define CC_HashSequenceStart CC_YES #endif #ifndef CC_HierarchyChangeAuth #define CC_HierarchyChangeAuth CC_YES #endif #ifndef CC_HierarchyControl #define CC_HierarchyControl CC_YES #endif #ifndef CC_Import #define CC_Import CC_YES #endif #ifndef CC_IncrementalSelfTest #define CC_IncrementalSelfTest CC_YES #endif #ifndef CC_Load #define CC_Load CC_YES #endif #ifndef CC_LoadExternal #define CC_LoadExternal CC_YES #endif #ifndef CC_MAC #define CC_MAC (CC_YES && ALG_CMAC) #endif #ifndef CC_MAC_Start #define CC_MAC_Start (CC_YES && ALG_CMAC) #endif #ifndef CC_MakeCredential #define CC_MakeCredential CC_YES #endif #ifndef CC_NV_Certify #define CC_NV_Certify CC_YES #endif #ifndef CC_NV_ChangeAuth #define CC_NV_ChangeAuth CC_YES #endif #ifndef CC_NV_DefineSpace #define CC_NV_DefineSpace CC_YES #endif #ifndef CC_NV_Extend #define CC_NV_Extend CC_YES #endif #ifndef CC_NV_GlobalWriteLock #define CC_NV_GlobalWriteLock CC_YES #endif #ifndef CC_NV_Increment #define CC_NV_Increment CC_YES #endif #ifndef CC_NV_Read #define CC_NV_Read CC_YES #endif #ifndef CC_NV_ReadLock #define CC_NV_ReadLock CC_YES #endif #ifndef CC_NV_ReadPublic #define CC_NV_ReadPublic CC_YES #endif #ifndef CC_NV_SetBits #define CC_NV_SetBits CC_YES #endif #ifndef CC_NV_UndefineSpace #define CC_NV_UndefineSpace CC_YES #endif #ifndef CC_NV_UndefineSpaceSpecial #define CC_NV_UndefineSpaceSpecial CC_YES #endif #ifndef CC_NV_Write #define CC_NV_Write CC_YES #endif #ifndef CC_NV_WriteLock #define CC_NV_WriteLock CC_YES #endif #ifndef CC_ObjectChangeAuth #define CC_ObjectChangeAuth CC_YES #endif #ifndef CC_PCR_Allocate #define CC_PCR_Allocate CC_YES #endif #ifndef CC_PCR_Event #define CC_PCR_Event CC_YES #endif #ifndef CC_PCR_Extend #define CC_PCR_Extend CC_YES #endif #ifndef CC_PCR_Read #define CC_PCR_Read CC_YES #endif #ifndef CC_PCR_Reset #define CC_PCR_Reset CC_YES #endif #ifndef CC_PCR_SetAuthPolicy #define CC_PCR_SetAuthPolicy CC_YES #endif #ifndef CC_PCR_SetAuthValue #define CC_PCR_SetAuthValue CC_YES #endif #ifndef CC_PP_Commands #define CC_PP_Commands CC_YES #endif #ifndef CC_PolicyAuthValue #define CC_PolicyAuthValue CC_YES #endif #ifndef CC_PolicyAuthorize #define CC_PolicyAuthorize CC_YES #endif #ifndef CC_PolicyAuthorizeNV #define CC_PolicyAuthorizeNV CC_YES #endif #ifndef CC_PolicyCommandCode #define CC_PolicyCommandCode CC_YES #endif #ifndef CC_PolicyCounterTimer #define CC_PolicyCounterTimer CC_YES #endif #ifndef CC_PolicyCpHash #define CC_PolicyCpHash CC_YES #endif #ifndef CC_PolicyDuplicationSelect #define CC_PolicyDuplicationSelect CC_YES #endif #ifndef CC_PolicyGetDigest #define CC_PolicyGetDigest CC_YES #endif #ifndef CC_PolicyLocality #define CC_PolicyLocality CC_YES #endif #ifndef CC_PolicyNV #define CC_PolicyNV CC_YES #endif #ifndef CC_PolicyNameHash #define CC_PolicyNameHash CC_YES #endif #ifndef CC_PolicyNvWritten #define CC_PolicyNvWritten CC_YES #endif #ifndef CC_PolicyOR #define CC_PolicyOR CC_YES #endif #ifndef CC_PolicyPCR #define CC_PolicyPCR CC_YES #endif #ifndef CC_PolicyPassword #define CC_PolicyPassword CC_YES #endif #ifndef CC_PolicyPhysicalPresence #define CC_PolicyPhysicalPresence CC_YES #endif #ifndef CC_PolicyRestart #define CC_PolicyRestart CC_YES #endif #ifndef CC_PolicySecret #define CC_PolicySecret CC_YES #endif #ifndef CC_PolicySigned #define CC_PolicySigned CC_YES #endif #ifndef CC_PolicyTemplate #define CC_PolicyTemplate CC_YES #endif #ifndef CC_PolicyTicket #define CC_PolicyTicket CC_YES #endif #ifndef CC_Policy_AC_SendSelect #define CC_Policy_AC_SendSelect CC_NO /* kgold */ #endif #ifndef CC_Quote #define CC_Quote CC_YES #endif #ifndef CC_RSA_Decrypt #define CC_RSA_Decrypt (CC_YES && ALG_RSA) #endif #ifndef CC_RSA_Encrypt #define CC_RSA_Encrypt (CC_YES && ALG_RSA) #endif #ifndef CC_ReadClock #define CC_ReadClock CC_YES #endif #ifndef CC_ReadPublic #define CC_ReadPublic CC_YES #endif #ifndef CC_Rewrap #define CC_Rewrap CC_YES #endif #ifndef CC_SelfTest #define CC_SelfTest CC_YES #endif #ifndef CC_SequenceComplete #define CC_SequenceComplete CC_YES #endif #ifndef CC_SequenceUpdate #define CC_SequenceUpdate CC_YES #endif #ifndef CC_SetAlgorithmSet #define CC_SetAlgorithmSet CC_YES #endif #ifndef CC_SetCommandCodeAuditStatus #define CC_SetCommandCodeAuditStatus CC_YES #endif #ifndef CC_SetPrimaryPolicy #define CC_SetPrimaryPolicy CC_YES #endif #ifndef CC_Shutdown #define CC_Shutdown CC_YES #endif #ifndef CC_Sign #define CC_Sign CC_YES #endif #ifndef CC_StartAuthSession #define CC_StartAuthSession CC_YES #endif #ifndef CC_Startup #define CC_Startup CC_YES #endif #ifndef CC_StirRandom #define CC_StirRandom CC_YES #endif #ifndef CC_TestParms #define CC_TestParms CC_YES #endif #ifndef CC_Unseal #define CC_Unseal CC_YES #endif #ifndef CC_Vendor_TCG_Test #define CC_Vendor_TCG_Test CC_NO /* libtpms changed */ #endif #ifndef CC_VerifySignature #define CC_VerifySignature CC_YES #endif #ifndef CC_ZGen_2Phase #define CC_ZGen_2Phase (CC_YES && ALG_ECC) #endif #endif // _TPM_PROFIL libtpms-0.9.3/src/tpm2/TpmSizeChecks.c000066400000000000000000000224711421143571500175370ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM Size Checks */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: TpmSizeChecks.c 1628 2020-05-27 19:35:29Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2020 */ /* */ /********************************************************************************/ //** Includes, Defines, and Types #include "Tpm.h" #include "PlatformACT_fp.h" /* kgold */ #include "TpmSizeChecks_fp.h" #include #include #if RUNTIME_SIZE_CHECKS #if TABLE_DRIVEN_MARSHAL extern uint32_t MarshalDataSize; #endif static int once = 0; //** TpmSizeChecks() // This function is used during the development process to make sure that the // vendor-specific values result in a consistent implementation. When possible, // the code contains #if to do compile-time checks. However, in some cases, the // values require the use of "sizeof()" and that can't be used in an #if. BOOL TpmSizeChecks( void ) { BOOL PASS = TRUE; #if DEBUG // if(once++ != 0) return 1; { UINT32 maxAsymSecurityStrength = MAX_ASYM_SECURITY_STRENGTH; UINT32 maxHashSecurityStrength = MAX_HASH_SECURITY_STRENGTH; UINT32 maxSymSecurityStrength = MAX_SYM_SECURITY_STRENGTH; UINT32 maxSecurityStrengthBits = MAX_SECURITY_STRENGTH_BITS; UINT32 proofSize = PROOF_SIZE; UINT32 compliantProofSize = COMPLIANT_PROOF_SIZE; UINT32 compliantPrimarySeedSize = COMPLIANT_PRIMARY_SEED_SIZE; UINT32 primarySeedSize = PRIMARY_SEED_SIZE; UINT32 cmacState = sizeof(tpmCmacState_t); UINT32 hashState = sizeof(HASH_STATE); UINT32 keyScheduleSize = sizeof(tpmCryptKeySchedule_t); // NOT_REFERENCED(cmacState); NOT_REFERENCED(hashState); NOT_REFERENCED(keyScheduleSize); NOT_REFERENCED(maxAsymSecurityStrength); NOT_REFERENCED(maxHashSecurityStrength); NOT_REFERENCED(maxSymSecurityStrength); NOT_REFERENCED(maxSecurityStrengthBits); NOT_REFERENCED(proofSize); NOT_REFERENCED(compliantProofSize); NOT_REFERENCED(compliantPrimarySeedSize); NOT_REFERENCED(primarySeedSize); { TPMT_SENSITIVE *p; // This assignment keeps compiler from complaining about a conditional // comparison being between two constants UINT16 max_rsa_key_bytes = MAX_RSA_KEY_BYTES; if((max_rsa_key_bytes / 2) != (sizeof(p->sensitive.rsa.t.buffer) / 5)) { printf("Sensitive part of TPMT_SENSITIVE is undersized. May be caused" " by use of wrong version of Part 2.\n"); PASS = FALSE; } } #if TABLE_DRIVEN_MARSHAL printf("sizeof(MarshalData) = %zu\n", sizeof(MarshalData_st)); #endif printf("Size of OBJECT = %zu\n", sizeof(OBJECT)); printf("Size of components in TPMT_SENSITIVE = %zu\n", sizeof(TPMT_SENSITIVE)); printf(" TPMI_ALG_PUBLIC %zu\n", sizeof(TPMI_ALG_PUBLIC)); printf(" TPM2B_AUTH %zu\n", sizeof(TPM2B_AUTH)); printf(" TPM2B_DIGEST %zu\n", sizeof(TPM2B_DIGEST)); printf(" TPMU_SENSITIVE_COMPOSITE %zu\n", sizeof(TPMU_SENSITIVE_COMPOSITE)); } // Make sure that the size of the context blob is large enough for the largest // context // TPMS_CONTEXT_DATA contains two TPM2B values. That is not how this is // implemented. Rather, the size field of the TPM2B_CONTEXT_DATA is used to // determine the amount of data in the encrypted data. That part is not // independently sized. This makes the actual size 2 bytes smaller than // calculated using Part 2. Since this is opaque to the caller, it is not // necessary to fix. The actual size is returned by TPM2_GetCapabilties(). // Initialize output handle. At the end of command action, the output // handle of an object will be replaced, while the output handle // for a session will be the same as input // Get the size of fingerprint in context blob. The sequence value in // TPMS_CONTEXT structure is used as the fingerprint { UINT32 fingerprintSize = sizeof(UINT64); UINT32 integritySize = sizeof(UINT16) + CryptHashGetDigestSize(CONTEXT_INTEGRITY_HASH_ALG); UINT32 biggestObject = MAX(MAX(sizeof(HASH_OBJECT), sizeof(OBJECT)), sizeof(SESSION)); UINT32 biggestContext = fingerprintSize + integritySize + biggestObject; // round required size up to nearest 8 byte boundary. biggestContext = 8 * ((biggestContext + 7) / 8); if(MAX_CONTEXT_SIZE < biggestContext) { printf("MAX_CONTEXT_SIZE needs to be increased to at least to %d (%d)\n", biggestContext, MAX_CONTEXT_SIZE); PASS = FALSE; } else if (MAX_CONTEXT_SIZE > biggestContext) { printf("MAX_CONTEXT_SIZE can be reduced to %d (%d)\n", biggestContext, MAX_CONTEXT_SIZE); } } { union u { TPMA_OBJECT attributes; UINT32 uint32Value; } u; // these are defined so that compiler doesn't complain about conditional // expressions comparing two constants. int aSize = sizeof(u.attributes); int uSize = sizeof(u.uint32Value); u.uint32Value = 0; SET_ATTRIBUTE(u.attributes, TPMA_OBJECT, fixedTPM); if(u.uint32Value != 2) { printf("The bit allocation in a TPMA_OBJECT is not as expected"); PASS = FALSE; } if(aSize != uSize) // comparison of two sizeof() values annoys compiler { printf("A TPMA_OBJECT is not the expected size."); PASS = FALSE; } } // Check that the platform implements each of the ACT that the TPM thinks are present { uint32_t act; for(act = 0; act < 16; act++) { switch(act) { FOR_EACH_ACT(CASE_ACT_NUMBER) if(!_plat__ACT_GetImplemented(act)) { printf("TPM_RH_ACT_%1X is not implemented by platform\n", act); PASS = FALSE; } default: break; } } } #endif // DEBUG return (PASS); } #endif // RUNTIME_SIZE_CHECKS libtpms-0.9.3/src/tpm2/TpmSizeChecks_fp.h000066400000000000000000000066551421143571500202370ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Check COmpiler Options */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: TpmSizeChecks_fp.h 1519 2019-11-15 20:43:51Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ #ifndef TPMSIZECHECKS_FP_H #define TPMSIZECHECKS_FP_H BOOL TpmSizeChecks(void); #endif libtpms-0.9.3/src/tpm2/TpmTcpProtocol.h000066400000000000000000000142721421143571500177610ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM commands are communicated as BYTE streams on a TCP connection */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: TpmTcpProtocol.h 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2021 */ /* */ /********************************************************************************/ /* D.3 TpmTcpProtocol.h */ /* D.3.1. Introduction */ /* TPM commands are communicated as uint8_t streams on a TCP connection. The TPM command protocol is enveloped with the interface protocol described in this file. The command is indicated by a uint32_t with one of the values below. Most commands take no parameters and return no TPM errors. In these cases the TPM interface protocol acknowledges that command processing is completed by returning a uint32_t = 0. The command TPM_SIGNAL_HASH_DATA takes a uint32_t-prepended variable length byte array and the interface protocol acknowledges command completion with a uint32_t = 0. Most TPM commands are enveloped using the TPM_SEND_COMMAND interface command. The parameters are as indicated below. The interface layer also appends a uin32_t = 0 to the TPM response for regularity. */ /* D.3.2. Typedefs and Defines */ #ifndef TCP_TPM_PROTOCOL_H #define TCP_TPM_PROTOCOL_H /* D.3.3. TPM Commands All commands acknowledge processing by returning a uint32_t = 0 except where noted */ #define TPM_SIGNAL_POWER_ON 1 #define TPM_SIGNAL_POWER_OFF 2 #define TPM_SIGNAL_PHYS_PRES_ON 3 #define TPM_SIGNAL_PHYS_PRES_OFF 4 #define TPM_SIGNAL_HASH_START 5 #define TPM_SIGNAL_HASH_DATA 6 // {uint32_t BufferSize, uint8_t[BufferSize] Buffer} #define TPM_SIGNAL_HASH_END 7 #define TPM_SEND_COMMAND 8 // {uint8_t Locality, uint32_t InBufferSize, uint8_t[InBufferSize] InBuffer} -> // {uint32_t OutBufferSize, uint8_t[OutBufferSize] OutBuffer} #define TPM_SIGNAL_CANCEL_ON 9 #define TPM_SIGNAL_CANCEL_OFF 10 #define TPM_SIGNAL_NV_ON 11 #define TPM_SIGNAL_NV_OFF 12 #define TPM_SIGNAL_KEY_CACHE_ON 13 #define TPM_SIGNAL_KEY_CACHE_OFF 14 #define TPM_REMOTE_HANDSHAKE 15 #define TPM_SET_ALTERNATIVE_RESULT 16 #define TPM_SIGNAL_RESET 17 #define TPM_SIGNAL_RESTART 18 #define TPM_SESSION_END 20 #define TPM_STOP 21 #define TPM_GET_COMMAND_RESPONSE_SIZES 25 #define TPM_ACT_GET_SIGNALED 26 #define TPM_TEST_FAILURE_MODE 30 // D.3.4. Enumerations and Structures enum TpmEndPointInfo { tpmPlatformAvailable = 0x01, tpmUsesTbs = 0x02, tpmInRawMode = 0x04, tpmSupportsPP = 0x08 }; #ifdef _MSC_VER # pragma warning(push, 3) #endif // Existing RPC interface type definitions retained so that the implementation // can be re-used typedef struct in_buffer { unsigned long BufferSize; unsigned char *Buffer; } _IN_BUFFER; typedef unsigned char *_OUTPUT_BUFFER; typedef struct out_buffer { uint32_t BufferSize; _OUTPUT_BUFFER Buffer; } _OUT_BUFFER; #ifdef _MSC_VER # pragma warning(pop) #endif #ifndef WIN32 typedef unsigned long DWORD; typedef void *LPVOID; #undef WINAPI #endif #endif libtpms-0.9.3/src/tpm2/TpmTypes.h000066400000000000000000003343141421143571500166170ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM Part 2 Headers */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: TpmTypes.h 1606 2020-04-14 16:26:05Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2020 */ /* */ /********************************************************************************/ /* 5.21 TpmTypes.h */ #ifndef TPMTYPES_H #define TPMTYPES_H /* TCG Algorithm Registry: Table 1:2 - Definition of TPM_ALG_ID Constants */ typedef UINT16 TPM_ALG_ID; #define TYPE_OF_TPM_ALG_ID UINT16 #define ALG_ERROR_VALUE 0x0000 #define TPM_ALG_ERROR (TPM_ALG_ID)(ALG_ERROR_VALUE) #define ALG_RSA_VALUE 0x0001 #define TPM_ALG_RSA (TPM_ALG_ID)(ALG_RSA_VALUE) #define ALG_TDES_VALUE 0x0003 #define TPM_ALG_TDES (TPM_ALG_ID)(ALG_TDES_VALUE) #define ALG_SHA_VALUE 0x0004 #define TPM_ALG_SHA (TPM_ALG_ID)(ALG_SHA_VALUE) #define ALG_SHA1_VALUE 0x0004 #define TPM_ALG_SHA1 (TPM_ALG_ID)(ALG_SHA1_VALUE) #define ALG_HMAC_VALUE 0x0005 #define TPM_ALG_HMAC (TPM_ALG_ID)(ALG_HMAC_VALUE) #define ALG_AES_VALUE 0x0006 #define TPM_ALG_AES (TPM_ALG_ID)(ALG_AES_VALUE) #define ALG_MGF1_VALUE 0x0007 #define TPM_ALG_MGF1 (TPM_ALG_ID)(ALG_MGF1_VALUE) #define ALG_KEYEDHASH_VALUE 0x0008 #define TPM_ALG_KEYEDHASH (TPM_ALG_ID)(ALG_KEYEDHASH_VALUE) #define ALG_XOR_VALUE 0x000A #define TPM_ALG_XOR (TPM_ALG_ID)(ALG_XOR_VALUE) #define ALG_SHA256_VALUE 0x000B #define TPM_ALG_SHA256 (TPM_ALG_ID)(ALG_SHA256_VALUE) #define ALG_SHA384_VALUE 0x000C #define TPM_ALG_SHA384 (TPM_ALG_ID)(ALG_SHA384_VALUE) #define ALG_SHA512_VALUE 0x000D #define TPM_ALG_SHA512 (TPM_ALG_ID)(ALG_SHA512_VALUE) #define ALG_NULL_VALUE 0x0010 #define TPM_ALG_NULL (TPM_ALG_ID)(ALG_NULL_VALUE) #define ALG_SM3_256_VALUE 0x0012 #define TPM_ALG_SM3_256 (TPM_ALG_ID)(ALG_SM3_256_VALUE) #define ALG_SM4_VALUE 0x0013 #define TPM_ALG_SM4 (TPM_ALG_ID)(ALG_SM4_VALUE) #define ALG_RSASSA_VALUE 0x0014 #define TPM_ALG_RSASSA (TPM_ALG_ID)(ALG_RSASSA_VALUE) #define ALG_RSAES_VALUE 0x0015 #define TPM_ALG_RSAES (TPM_ALG_ID)(ALG_RSAES_VALUE) #define ALG_RSAPSS_VALUE 0x0016 #define TPM_ALG_RSAPSS (TPM_ALG_ID)(ALG_RSAPSS_VALUE) #define ALG_OAEP_VALUE 0x0017 #define TPM_ALG_OAEP (TPM_ALG_ID)(ALG_OAEP_VALUE) #define ALG_ECDSA_VALUE 0x0018 #define TPM_ALG_ECDSA (TPM_ALG_ID)(ALG_ECDSA_VALUE) #define ALG_ECDH_VALUE 0x0019 #define TPM_ALG_ECDH (TPM_ALG_ID)(ALG_ECDH_VALUE) #define ALG_ECDAA_VALUE 0x001A #define TPM_ALG_ECDAA (TPM_ALG_ID)(ALG_ECDAA_VALUE) #define ALG_SM2_VALUE 0x001B #define TPM_ALG_SM2 (TPM_ALG_ID)(ALG_SM2_VALUE) #define ALG_ECSCHNORR_VALUE 0x001C #define TPM_ALG_ECSCHNORR (TPM_ALG_ID)(ALG_ECSCHNORR_VALUE) #define ALG_ECMQV_VALUE 0x001D #define TPM_ALG_ECMQV (TPM_ALG_ID)(ALG_ECMQV_VALUE) #define ALG_KDF1_SP800_56A_VALUE 0x0020 #define TPM_ALG_KDF1_SP800_56A (TPM_ALG_ID)(ALG_KDF1_SP800_56A_VALUE) #define ALG_KDF2_VALUE 0x0021 #define TPM_ALG_KDF2 (TPM_ALG_ID)(ALG_KDF2_VALUE) #define ALG_KDF1_SP800_108_VALUE 0x0022 #define TPM_ALG_KDF1_SP800_108 (TPM_ALG_ID)(ALG_KDF1_SP800_108_VALUE) #define ALG_ECC_VALUE 0x0023 #define TPM_ALG_ECC (TPM_ALG_ID)(ALG_ECC_VALUE) #define ALG_SYMCIPHER_VALUE 0x0025 #define TPM_ALG_SYMCIPHER (TPM_ALG_ID)(ALG_SYMCIPHER_VALUE) #define ALG_CAMELLIA_VALUE 0x0026 #define TPM_ALG_CAMELLIA (TPM_ALG_ID)(ALG_CAMELLIA_VALUE) #define ALG_SHA3_256_VALUE 0x0027 #define TPM_ALG_SHA3_256 (TPM_ALG_ID)(ALG_SHA3_256_VALUE) #define ALG_SHA3_384_VALUE 0x0028 #define TPM_ALG_SHA3_384 (TPM_ALG_ID)(ALG_SHA3_384_VALUE) #define ALG_SHA3_512_VALUE 0x0029 #define TPM_ALG_SHA3_512 (TPM_ALG_ID)(ALG_SHA3_512_VALUE) #define ALG_CMAC_VALUE 0x003F #define TPM_ALG_CMAC (TPM_ALG_ID)(ALG_CMAC_VALUE) #define ALG_CTR_VALUE 0x0040 #define TPM_ALG_CTR (TPM_ALG_ID)(ALG_CTR_VALUE) #define ALG_OFB_VALUE 0x0041 #define TPM_ALG_OFB (TPM_ALG_ID)(ALG_OFB_VALUE) #define ALG_CBC_VALUE 0x0042 #define TPM_ALG_CBC (TPM_ALG_ID)(ALG_CBC_VALUE) #define ALG_CFB_VALUE 0x0043 #define TPM_ALG_CFB (TPM_ALG_ID)(ALG_CFB_VALUE) #define ALG_ECB_VALUE 0x0044 #define TPM_ALG_ECB (TPM_ALG_ID)(ALG_ECB_VALUE) /* Values derived from Table 1:2 */ #define ALG_FIRST_VALUE 0x0001 #define TPM_ALG_FIRST (TPM_ALG_ID)(ALG_FIRST_VALUE) #define ALG_LAST_VALUE 0x0044 #define TPM_ALG_LAST (TPM_ALG_ID)(ALG_LAST_VALUE) /* TCG Algorithm Registry: Table 1:3 - Definition of TPM_ECC_CURVE Constants */ typedef UINT16 TPM_ECC_CURVE; #define TYPE_OF_TPM_ECC_CURVE UINT16 #define TPM_ECC_NONE (TPM_ECC_CURVE)(0x0000) #define TPM_ECC_NIST_P192 (TPM_ECC_CURVE)(0x0001) #define TPM_ECC_NIST_P224 (TPM_ECC_CURVE)(0x0002) #define TPM_ECC_NIST_P256 (TPM_ECC_CURVE)(0x0003) #define TPM_ECC_NIST_P384 (TPM_ECC_CURVE)(0x0004) #define TPM_ECC_NIST_P521 (TPM_ECC_CURVE)(0x0005) #define TPM_ECC_BN_P256 (TPM_ECC_CURVE)(0x0010) #define TPM_ECC_BN_P638 (TPM_ECC_CURVE)(0x0011) #define TPM_ECC_SM2_P256 (TPM_ECC_CURVE)(0x0020) /* TPM 2.0 Part 2: Table 2:12 - Definition of TPM_CC Constants */ typedef UINT32 TPM_CC; #define TYPE_OF_TPM_CC UINT32 #define TPM_CC_NV_UndefineSpaceSpecial (TPM_CC)(0x0000011F) #define TPM_CC_EvictControl (TPM_CC)(0x00000120) #define TPM_CC_HierarchyControl (TPM_CC)(0x00000121) #define TPM_CC_NV_UndefineSpace (TPM_CC)(0x00000122) #define TPM_CC_ChangeEPS (TPM_CC)(0x00000124) #define TPM_CC_ChangePPS (TPM_CC)(0x00000125) #define TPM_CC_Clear (TPM_CC)(0x00000126) #define TPM_CC_ClearControl (TPM_CC)(0x00000127) #define TPM_CC_ClockSet (TPM_CC)(0x00000128) #define TPM_CC_HierarchyChangeAuth (TPM_CC)(0x00000129) #define TPM_CC_NV_DefineSpace (TPM_CC)(0x0000012A) #define TPM_CC_PCR_Allocate (TPM_CC)(0x0000012B) #define TPM_CC_PCR_SetAuthPolicy (TPM_CC)(0x0000012C) #define TPM_CC_PP_Commands (TPM_CC)(0x0000012D) #define TPM_CC_SetPrimaryPolicy (TPM_CC)(0x0000012E) #define TPM_CC_FieldUpgradeStart (TPM_CC)(0x0000012F) #define TPM_CC_ClockRateAdjust (TPM_CC)(0x00000130) #define TPM_CC_CreatePrimary (TPM_CC)(0x00000131) #define TPM_CC_NV_GlobalWriteLock (TPM_CC)(0x00000132) #define TPM_CC_GetCommandAuditDigest (TPM_CC)(0x00000133) #define TPM_CC_NV_Increment (TPM_CC)(0x00000134) #define TPM_CC_NV_SetBits (TPM_CC)(0x00000135) #define TPM_CC_NV_Extend (TPM_CC)(0x00000136) #define TPM_CC_NV_Write (TPM_CC)(0x00000137) #define TPM_CC_NV_WriteLock (TPM_CC)(0x00000138) #define TPM_CC_DictionaryAttackLockReset (TPM_CC)(0x00000139) #define TPM_CC_DictionaryAttackParameters (TPM_CC)(0x0000013A) #define TPM_CC_NV_ChangeAuth (TPM_CC)(0x0000013B) #define TPM_CC_PCR_Event (TPM_CC)(0x0000013C) #define TPM_CC_PCR_Reset (TPM_CC)(0x0000013D) #define TPM_CC_SequenceComplete (TPM_CC)(0x0000013E) #define TPM_CC_SetAlgorithmSet (TPM_CC)(0x0000013F) #define TPM_CC_SetCommandCodeAuditStatus (TPM_CC)(0x00000140) #define TPM_CC_FieldUpgradeData (TPM_CC)(0x00000141) #define TPM_CC_IncrementalSelfTest (TPM_CC)(0x00000142) #define TPM_CC_SelfTest (TPM_CC)(0x00000143) #define TPM_CC_Startup (TPM_CC)(0x00000144) #define TPM_CC_Shutdown (TPM_CC)(0x00000145) #define TPM_CC_StirRandom (TPM_CC)(0x00000146) #define TPM_CC_ActivateCredential (TPM_CC)(0x00000147) #define TPM_CC_Certify (TPM_CC)(0x00000148) #define TPM_CC_PolicyNV (TPM_CC)(0x00000149) #define TPM_CC_CertifyCreation (TPM_CC)(0x0000014A) #define TPM_CC_Duplicate (TPM_CC)(0x0000014B) #define TPM_CC_GetTime (TPM_CC)(0x0000014C) #define TPM_CC_GetSessionAuditDigest (TPM_CC)(0x0000014D) #define TPM_CC_NV_Read (TPM_CC)(0x0000014E) #define TPM_CC_NV_ReadLock (TPM_CC)(0x0000014F) #define TPM_CC_ObjectChangeAuth (TPM_CC)(0x00000150) #define TPM_CC_PolicySecret (TPM_CC)(0x00000151) #define TPM_CC_Rewrap (TPM_CC)(0x00000152) #define TPM_CC_Create (TPM_CC)(0x00000153) #define TPM_CC_ECDH_ZGen (TPM_CC)(0x00000154) #define TPM_CC_HMAC (TPM_CC)(0x00000155) #define TPM_CC_MAC (TPM_CC)(0x00000155) #define TPM_CC_Import (TPM_CC)(0x00000156) #define TPM_CC_Load (TPM_CC)(0x00000157) #define TPM_CC_Quote (TPM_CC)(0x00000158) #define TPM_CC_RSA_Decrypt (TPM_CC)(0x00000159) #define TPM_CC_HMAC_Start (TPM_CC)(0x0000015B) #define TPM_CC_MAC_Start (TPM_CC)(0x0000015B) #define TPM_CC_SequenceUpdate (TPM_CC)(0x0000015C) #define TPM_CC_Sign (TPM_CC)(0x0000015D) #define TPM_CC_Unseal (TPM_CC)(0x0000015E) #define TPM_CC_PolicySigned (TPM_CC)(0x00000160) #define TPM_CC_ContextLoad (TPM_CC)(0x00000161) #define TPM_CC_ContextSave (TPM_CC)(0x00000162) #define TPM_CC_ECDH_KeyGen (TPM_CC)(0x00000163) #define TPM_CC_EncryptDecrypt (TPM_CC)(0x00000164) #define TPM_CC_FlushContext (TPM_CC)(0x00000165) #define TPM_CC_LoadExternal (TPM_CC)(0x00000167) #define TPM_CC_MakeCredential (TPM_CC)(0x00000168) #define TPM_CC_NV_ReadPublic (TPM_CC)(0x00000169) #define TPM_CC_PolicyAuthorize (TPM_CC)(0x0000016A) #define TPM_CC_PolicyAuthValue (TPM_CC)(0x0000016B) #define TPM_CC_PolicyCommandCode (TPM_CC)(0x0000016C) #define TPM_CC_PolicyCounterTimer (TPM_CC)(0x0000016D) #define TPM_CC_PolicyCpHash (TPM_CC)(0x0000016E) #define TPM_CC_PolicyLocality (TPM_CC)(0x0000016F) #define TPM_CC_PolicyNameHash (TPM_CC)(0x00000170) #define TPM_CC_PolicyOR (TPM_CC)(0x00000171) #define TPM_CC_PolicyTicket (TPM_CC)(0x00000172) #define TPM_CC_ReadPublic (TPM_CC)(0x00000173) #define TPM_CC_RSA_Encrypt (TPM_CC)(0x00000174) #define TPM_CC_StartAuthSession (TPM_CC)(0x00000176) #define TPM_CC_VerifySignature (TPM_CC)(0x00000177) #define TPM_CC_ECC_Parameters (TPM_CC)(0x00000178) #define TPM_CC_FirmwareRead (TPM_CC)(0x00000179) #define TPM_CC_GetCapability (TPM_CC)(0x0000017A) #define TPM_CC_GetRandom (TPM_CC)(0x0000017B) #define TPM_CC_GetTestResult (TPM_CC)(0x0000017C) #define TPM_CC_Hash (TPM_CC)(0x0000017D) #define TPM_CC_PCR_Read (TPM_CC)(0x0000017E) #define TPM_CC_PolicyPCR (TPM_CC)(0x0000017F) #define TPM_CC_PolicyRestart (TPM_CC)(0x00000180) #define TPM_CC_ReadClock (TPM_CC)(0x00000181) #define TPM_CC_PCR_Extend (TPM_CC)(0x00000182) #define TPM_CC_PCR_SetAuthValue (TPM_CC)(0x00000183) #define TPM_CC_NV_Certify (TPM_CC)(0x00000184) #define TPM_CC_EventSequenceComplete (TPM_CC)(0x00000185) #define TPM_CC_HashSequenceStart (TPM_CC)(0x00000186) #define TPM_CC_PolicyPhysicalPresence (TPM_CC)(0x00000187) #define TPM_CC_PolicyDuplicationSelect (TPM_CC)(0x00000188) #define TPM_CC_PolicyGetDigest (TPM_CC)(0x00000189) #define TPM_CC_TestParms (TPM_CC)(0x0000018A) #define TPM_CC_Commit (TPM_CC)(0x0000018B) #define TPM_CC_PolicyPassword (TPM_CC)(0x0000018C) #define TPM_CC_ZGen_2Phase (TPM_CC)(0x0000018D) #define TPM_CC_EC_Ephemeral (TPM_CC)(0x0000018E) #define TPM_CC_PolicyNvWritten (TPM_CC)(0x0000018F) #define TPM_CC_PolicyTemplate (TPM_CC)(0x00000190) #define TPM_CC_CreateLoaded (TPM_CC)(0x00000191) #define TPM_CC_PolicyAuthorizeNV (TPM_CC)(0x00000192) #define TPM_CC_EncryptDecrypt2 (TPM_CC)(0x00000193) #define TPM_CC_AC_GetCapability (TPM_CC)(0x00000194) #define TPM_CC_AC_Send (TPM_CC)(0x00000195) #define TPM_CC_Policy_AC_SendSelect (TPM_CC)(0x00000196) #define TPM_CC_CertifyX509 (TPM_CC)(0x00000197) #define TPM_CC_ACT_SetTimeout (TPM_CC)(0x00000198) #define TPM_CC_ECC_Encrypt (TPM_CC)(0x00000199) #define TPM_CC_ECC_Decrypt (TPM_CC)(0x0000019A) #define CC_VEND 0x20000000 #define TPM_CC_Vendor_TCG_Test (TPM_CC)(0x20000000) /* Table 2:5 - Definition of Types for Documentation Clarity */ typedef UINT32 TPM_ALGORITHM_ID; #define TYPE_OF_TPM_ALGORITHM_ID UINT32 typedef UINT32 TPM_MODIFIER_INDICATOR; #define TYPE_OF_TPM_MODIFIER_INDICATOR UINT32 typedef UINT32 TPM_AUTHORIZATION_SIZE; #define TYPE_OF_TPM_AUTHORIZATION_SIZE UINT32 typedef UINT32 TPM_PARAMETER_SIZE; #define TYPE_OF_TPM_PARAMETER_SIZE UINT32 typedef UINT16 TPM_KEY_SIZE; #define TYPE_OF_TPM_KEY_SIZE UINT16 typedef UINT16 TPM_KEY_BITS; #define TYPE_OF_TPM_KEY_BITS UINT16 /* Table 2:6 - Definition of TPM_SPEC Constants */ typedef UINT32 TPM_SPEC; #define TYPE_OF_TPM_SPEC UINT32 #define SPEC_FAMILY 0x322E3000 #define TPM_SPEC_FAMILY (TPM_SPEC)(SPEC_FAMILY) #define SPEC_LEVEL 00 #define SPEC_LEVEL_NUM 0 // libtpms added: SPEC_LEVEL without leading zeros #define TPM_SPEC_LEVEL (TPM_SPEC)(SPEC_LEVEL) #define SPEC_VERSION 164 #define TPM_SPEC_VERSION (TPM_SPEC)(SPEC_VERSION) #define SPEC_YEAR 2021 #define TPM_SPEC_YEAR (TPM_SPEC)(SPEC_YEAR) #define SPEC_DAY_OF_YEAR 75 #define TPM_SPEC_DAY_OF_YEAR (TPM_SPEC)(SPEC_DAY_OF_YEAR) /* Table 2:7 - Definition of TPM_CONSTANTS32 Constants */ typedef UINT32 TPM_CONSTANTS32; #define TYPE_OF_TPM_CONSTANTS32 UINT32 #define TPM_GENERATED_VALUE (TPM_CONSTANTS32)(0xFF544347) #define TPM_MAX_DERIVATION_BITS (TPM_CONSTANTS32)8192 /* Table 2:16 - Definition of TPM_RC Constants */ typedef UINT32 TPM_RC; #define TYPE_OF_TPM_RC UINT32 #define TPM_RC_SUCCESS (TPM_RC)(0x000) #define TPM_RC_BAD_TAG (TPM_RC)(0x01E) #define RC_VER1 (TPM_RC)(0x100) #define TPM_RC_INITIALIZE (TPM_RC)(RC_VER1+0x000) #define TPM_RC_FAILURE (TPM_RC)(RC_VER1+0x001) #define TPM_RC_SEQUENCE (TPM_RC)(RC_VER1+0x003) #define TPM_RC_PRIVATE (TPM_RC)(RC_VER1+0x00B) #define TPM_RC_HMAC (TPM_RC)(RC_VER1+0x019) #define TPM_RC_DISABLED (TPM_RC)(RC_VER1+0x020) #define TPM_RC_EXCLUSIVE (TPM_RC)(RC_VER1+0x021) #define TPM_RC_AUTH_TYPE (TPM_RC)(RC_VER1+0x024) #define TPM_RC_AUTH_MISSING (TPM_RC)(RC_VER1+0x025) #define TPM_RC_POLICY (TPM_RC)(RC_VER1+0x026) #define TPM_RC_PCR (TPM_RC)(RC_VER1+0x027) #define TPM_RC_PCR_CHANGED (TPM_RC)(RC_VER1+0x028) #define TPM_RC_UPGRADE (TPM_RC)(RC_VER1+0x02D) #define TPM_RC_TOO_MANY_CONTEXTS (TPM_RC)(RC_VER1+0x02E) #define TPM_RC_AUTH_UNAVAILABLE (TPM_RC)(RC_VER1+0x02F) #define TPM_RC_REBOOT (TPM_RC)(RC_VER1+0x030) #define TPM_RC_UNBALANCED (TPM_RC)(RC_VER1+0x031) #define TPM_RC_COMMAND_SIZE (TPM_RC)(RC_VER1+0x042) #define TPM_RC_COMMAND_CODE (TPM_RC)(RC_VER1+0x043) #define TPM_RC_AUTHSIZE (TPM_RC)(RC_VER1+0x044) #define TPM_RC_AUTH_CONTEXT (TPM_RC)(RC_VER1+0x045) #define TPM_RC_NV_RANGE (TPM_RC)(RC_VER1+0x046) #define TPM_RC_NV_SIZE (TPM_RC)(RC_VER1+0x047) #define TPM_RC_NV_LOCKED (TPM_RC)(RC_VER1+0x048) #define TPM_RC_NV_AUTHORIZATION (TPM_RC)(RC_VER1+0x049) #define TPM_RC_NV_UNINITIALIZED (TPM_RC)(RC_VER1+0x04A) #define TPM_RC_NV_SPACE (TPM_RC)(RC_VER1+0x04B) #define TPM_RC_NV_DEFINED (TPM_RC)(RC_VER1+0x04C) #define TPM_RC_BAD_CONTEXT (TPM_RC)(RC_VER1+0x050) #define TPM_RC_CPHASH (TPM_RC)(RC_VER1+0x051) #define TPM_RC_PARENT (TPM_RC)(RC_VER1+0x052) #define TPM_RC_NEEDS_TEST (TPM_RC)(RC_VER1+0x053) #define TPM_RC_NO_RESULT (TPM_RC)(RC_VER1+0x054) #define TPM_RC_SENSITIVE (TPM_RC)(RC_VER1+0x055) #define RC_MAX_FM0 (TPM_RC)(RC_VER1+0x07F) #define RC_FMT1 (TPM_RC)(0x080) #define TPM_RC_ASYMMETRIC (TPM_RC)(RC_FMT1+0x001) #define TPM_RCS_ASYMMETRIC (TPM_RC)(RC_FMT1+0x001) #define TPM_RC_ATTRIBUTES (TPM_RC)(RC_FMT1+0x002) #define TPM_RCS_ATTRIBUTES (TPM_RC)(RC_FMT1+0x002) #define TPM_RC_HASH (TPM_RC)(RC_FMT1+0x003) #define TPM_RCS_HASH (TPM_RC)(RC_FMT1+0x003) #define TPM_RC_VALUE (TPM_RC)(RC_FMT1+0x004) #define TPM_RCS_VALUE (TPM_RC)(RC_FMT1+0x004) #define TPM_RC_HIERARCHY (TPM_RC)(RC_FMT1+0x005) #define TPM_RCS_HIERARCHY (TPM_RC)(RC_FMT1+0x005) #define TPM_RC_KEY_SIZE (TPM_RC)(RC_FMT1+0x007) #define TPM_RCS_KEY_SIZE (TPM_RC)(RC_FMT1+0x007) #define TPM_RC_MGF (TPM_RC)(RC_FMT1+0x008) #define TPM_RCS_MGF (TPM_RC)(RC_FMT1+0x008) #define TPM_RC_MODE (TPM_RC)(RC_FMT1+0x009) #define TPM_RCS_MODE (TPM_RC)(RC_FMT1+0x009) #define TPM_RC_TYPE (TPM_RC)(RC_FMT1+0x00A) #define TPM_RCS_TYPE (TPM_RC)(RC_FMT1+0x00A) #define TPM_RC_HANDLE (TPM_RC)(RC_FMT1+0x00B) #define TPM_RCS_HANDLE (TPM_RC)(RC_FMT1+0x00B) #define TPM_RC_KDF (TPM_RC)(RC_FMT1+0x00C) #define TPM_RCS_KDF (TPM_RC)(RC_FMT1+0x00C) #define TPM_RC_RANGE (TPM_RC)(RC_FMT1+0x00D) #define TPM_RCS_RANGE (TPM_RC)(RC_FMT1+0x00D) #define TPM_RC_AUTH_FAIL (TPM_RC)(RC_FMT1+0x00E) #define TPM_RCS_AUTH_FAIL (TPM_RC)(RC_FMT1+0x00E) #define TPM_RC_NONCE (TPM_RC)(RC_FMT1+0x00F) #define TPM_RCS_NONCE (TPM_RC)(RC_FMT1+0x00F) #define TPM_RC_PP (TPM_RC)(RC_FMT1+0x010) #define TPM_RCS_PP (TPM_RC)(RC_FMT1+0x010) #define TPM_RC_SCHEME (TPM_RC)(RC_FMT1+0x012) #define TPM_RCS_SCHEME (TPM_RC)(RC_FMT1+0x012) #define TPM_RC_SIZE (TPM_RC)(RC_FMT1+0x015) #define TPM_RCS_SIZE (TPM_RC)(RC_FMT1+0x015) #define TPM_RC_SYMMETRIC (TPM_RC)(RC_FMT1+0x016) #define TPM_RCS_SYMMETRIC (TPM_RC)(RC_FMT1+0x016) #define TPM_RC_TAG (TPM_RC)(RC_FMT1+0x017) #define TPM_RCS_TAG (TPM_RC)(RC_FMT1+0x017) #define TPM_RC_SELECTOR (TPM_RC)(RC_FMT1+0x018) #define TPM_RCS_SELECTOR (TPM_RC)(RC_FMT1+0x018) #define TPM_RC_INSUFFICIENT (TPM_RC)(RC_FMT1+0x01A) #define TPM_RCS_INSUFFICIENT (TPM_RC)(RC_FMT1+0x01A) #define TPM_RC_SIGNATURE (TPM_RC)(RC_FMT1+0x01B) #define TPM_RCS_SIGNATURE (TPM_RC)(RC_FMT1+0x01B) #define TPM_RC_KEY (TPM_RC)(RC_FMT1+0x01C) #define TPM_RCS_KEY (TPM_RC)(RC_FMT1+0x01C) #define TPM_RC_POLICY_FAIL (TPM_RC)(RC_FMT1+0x01D) #define TPM_RCS_POLICY_FAIL (TPM_RC)(RC_FMT1+0x01D) #define TPM_RC_INTEGRITY (TPM_RC)(RC_FMT1+0x01F) #define TPM_RCS_INTEGRITY (TPM_RC)(RC_FMT1+0x01F) #define TPM_RC_TICKET (TPM_RC)(RC_FMT1+0x020) #define TPM_RCS_TICKET (TPM_RC)(RC_FMT1+0x020) #define TPM_RC_RESERVED_BITS (TPM_RC)(RC_FMT1+0x021) #define TPM_RCS_RESERVED_BITS (TPM_RC)(RC_FMT1+0x021) #define TPM_RC_BAD_AUTH (TPM_RC)(RC_FMT1+0x022) #define TPM_RCS_BAD_AUTH (TPM_RC)(RC_FMT1+0x022) #define TPM_RC_EXPIRED (TPM_RC)(RC_FMT1+0x023) #define TPM_RCS_EXPIRED (TPM_RC)(RC_FMT1+0x023) #define TPM_RC_POLICY_CC (TPM_RC)(RC_FMT1+0x024) #define TPM_RCS_POLICY_CC (TPM_RC)(RC_FMT1+0x024) #define TPM_RC_BINDING (TPM_RC)(RC_FMT1+0x025) #define TPM_RCS_BINDING (TPM_RC)(RC_FMT1+0x025) #define TPM_RC_CURVE (TPM_RC)(RC_FMT1+0x026) #define TPM_RCS_CURVE (TPM_RC)(RC_FMT1+0x026) #define TPM_RC_ECC_POINT (TPM_RC)(RC_FMT1+0x027) #define TPM_RCS_ECC_POINT (TPM_RC)(RC_FMT1+0x027) #define RC_WARN (TPM_RC)(0x900) #define TPM_RC_CONTEXT_GAP (TPM_RC)(RC_WARN+0x001) #define TPM_RC_OBJECT_MEMORY (TPM_RC)(RC_WARN+0x002) #define TPM_RC_SESSION_MEMORY (TPM_RC)(RC_WARN+0x003) #define TPM_RC_MEMORY (TPM_RC)(RC_WARN+0x004) #define TPM_RC_SESSION_HANDLES (TPM_RC)(RC_WARN+0x005) #define TPM_RC_OBJECT_HANDLES (TPM_RC)(RC_WARN+0x006) #define TPM_RC_LOCALITY (TPM_RC)(RC_WARN+0x007) #define TPM_RC_YIELDED (TPM_RC)(RC_WARN+0x008) #define TPM_RC_CANCELED (TPM_RC)(RC_WARN+0x009) #define TPM_RC_TESTING (TPM_RC)(RC_WARN+0x00A) #define TPM_RC_REFERENCE_H0 (TPM_RC)(RC_WARN+0x010) #define TPM_RC_REFERENCE_H1 (TPM_RC)(RC_WARN+0x011) #define TPM_RC_REFERENCE_H2 (TPM_RC)(RC_WARN+0x012) #define TPM_RC_REFERENCE_H3 (TPM_RC)(RC_WARN+0x013) #define TPM_RC_REFERENCE_H4 (TPM_RC)(RC_WARN+0x014) #define TPM_RC_REFERENCE_H5 (TPM_RC)(RC_WARN+0x015) #define TPM_RC_REFERENCE_H6 (TPM_RC)(RC_WARN+0x016) #define TPM_RC_REFERENCE_S0 (TPM_RC)(RC_WARN+0x018) #define TPM_RC_REFERENCE_S1 (TPM_RC)(RC_WARN+0x019) #define TPM_RC_REFERENCE_S2 (TPM_RC)(RC_WARN+0x01A) #define TPM_RC_REFERENCE_S3 (TPM_RC)(RC_WARN+0x01B) #define TPM_RC_REFERENCE_S4 (TPM_RC)(RC_WARN+0x01C) #define TPM_RC_REFERENCE_S5 (TPM_RC)(RC_WARN+0x01D) #define TPM_RC_REFERENCE_S6 (TPM_RC)(RC_WARN+0x01E) #define TPM_RC_NV_RATE (TPM_RC)(RC_WARN+0x020) #define TPM_RC_LOCKOUT (TPM_RC)(RC_WARN+0x021) #define TPM_RC_RETRY (TPM_RC)(RC_WARN+0x022) #define TPM_RC_NV_UNAVAILABLE (TPM_RC)(RC_WARN+0x023) #define TPM_RC_NOT_USED (TPM_RC)(RC_WARN+0x7F) #define TPM_RC_H (TPM_RC)(0x000) #define TPM_RC_P (TPM_RC)(0x040) #define TPM_RC_S (TPM_RC)(0x800) #define TPM_RC_1 (TPM_RC)(0x100) #define TPM_RC_2 (TPM_RC)(0x200) #define TPM_RC_3 (TPM_RC)(0x300) #define TPM_RC_4 (TPM_RC)(0x400) #define TPM_RC_5 (TPM_RC)(0x500) #define TPM_RC_6 (TPM_RC)(0x600) #define TPM_RC_7 (TPM_RC)(0x700) #define TPM_RC_8 (TPM_RC)(0x800) #define TPM_RC_9 (TPM_RC)(0x900) #define TPM_RC_A (TPM_RC)(0xA00) #define TPM_RC_B (TPM_RC)(0xB00) #define TPM_RC_C (TPM_RC)(0xC00) #define TPM_RC_D (TPM_RC)(0xD00) #define TPM_RC_E (TPM_RC)(0xE00) #define TPM_RC_F (TPM_RC)(0xF00) #define TPM_RC_N_MASK (TPM_RC)(0xF00) /* Table 2:17 - Definition of TPM_CLOCK_ADJUST Constants */ typedef INT8 TPM_CLOCK_ADJUST; #define TYPE_OF_TPM_CLOCK_ADJUST UINT8 #define TPM_CLOCK_COARSE_SLOWER (TPM_CLOCK_ADJUST)(-3) #define TPM_CLOCK_MEDIUM_SLOWER (TPM_CLOCK_ADJUST)(-2) #define TPM_CLOCK_FINE_SLOWER (TPM_CLOCK_ADJUST)(-1) #define TPM_CLOCK_NO_CHANGE (TPM_CLOCK_ADJUST)(0) #define TPM_CLOCK_FINE_FASTER (TPM_CLOCK_ADJUST)(1) #define TPM_CLOCK_MEDIUM_FASTER (TPM_CLOCK_ADJUST)(2) #define TPM_CLOCK_COARSE_FASTER (TPM_CLOCK_ADJUST)(3) /* Table 2:18 - Definition of TPM_EO Constants */ typedef UINT16 TPM_EO; #define TYPE_OF_TPM_EO UINT16 #define TPM_EO_EQ (TPM_EO)(0x0000) #define TPM_EO_NEQ (TPM_EO)(0x0001) #define TPM_EO_SIGNED_GT (TPM_EO)(0x0002) #define TPM_EO_UNSIGNED_GT (TPM_EO)(0x0003) #define TPM_EO_SIGNED_LT (TPM_EO)(0x0004) #define TPM_EO_UNSIGNED_LT (TPM_EO)(0x0005) #define TPM_EO_SIGNED_GE (TPM_EO)(0x0006) #define TPM_EO_UNSIGNED_GE (TPM_EO)(0x0007) #define TPM_EO_SIGNED_LE (TPM_EO)(0x0008) #define TPM_EO_UNSIGNED_LE (TPM_EO)(0x0009) #define TPM_EO_BITSET (TPM_EO)(0x000A) #define TPM_EO_BITCLEAR (TPM_EO)(0x000B) /* Table 2:19 - Definition of TPM_ST Constants */ typedef UINT16 TPM_ST; #define TYPE_OF_TPM_ST UINT16 #define TPM_ST_RSP_COMMAND (TPM_ST)(0x00C4) #define TPM_ST_NULL (TPM_ST)(0x8000) #define TPM_ST_NO_SESSIONS (TPM_ST)(0x8001) #define TPM_ST_SESSIONS (TPM_ST)(0x8002) #define TPM_ST_ATTEST_NV (TPM_ST)(0x8014) #define TPM_ST_ATTEST_COMMAND_AUDIT (TPM_ST)(0x8015) #define TPM_ST_ATTEST_SESSION_AUDIT (TPM_ST)(0x8016) #define TPM_ST_ATTEST_CERTIFY (TPM_ST)(0x8017) #define TPM_ST_ATTEST_QUOTE (TPM_ST)(0x8018) #define TPM_ST_ATTEST_TIME (TPM_ST)(0x8019) #define TPM_ST_ATTEST_CREATION (TPM_ST)(0x801A) #define TPM_ST_ATTEST_NV_DIGEST (TPM_ST)(0x801C) #define TPM_ST_CREATION (TPM_ST)(0x8021) #define TPM_ST_VERIFIED (TPM_ST)(0x8022) #define TPM_ST_AUTH_SECRET (TPM_ST)(0x8023) #define TPM_ST_HASHCHECK (TPM_ST)(0x8024) #define TPM_ST_AUTH_SIGNED (TPM_ST)(0x8025) #define TPM_ST_FU_MANIFEST (TPM_ST)(0x8029) /* Table 2:20 - Definition of TPM_SU Constants */ typedef UINT16 TPM_SU; #define TYPE_OF_TPM_SU UINT16 #define TPM_SU_CLEAR (TPM_SU)(0x0000) #define TPM_SU_STATE (TPM_SU)(0x0001) /* Table 2:21 - Definition of TPM_SE Constants */ typedef UINT8 TPM_SE; #define TYPE_OF_TPM_SE UINT8 #define TPM_SE_HMAC (TPM_SE)(0x00) #define TPM_SE_POLICY (TPM_SE)(0x01) #define TPM_SE_TRIAL (TPM_SE)(0x03) /* Table 2:22 - Definition of TPM_CAP Constants */ typedef UINT32 TPM_CAP; #define TYPE_OF_TPM_CAP UINT32 #define TPM_CAP_FIRST (TPM_CAP)(0x00000000) #define TPM_CAP_ALGS (TPM_CAP)(0x00000000) #define TPM_CAP_HANDLES (TPM_CAP)(0x00000001) #define TPM_CAP_COMMANDS (TPM_CAP)(0x00000002) #define TPM_CAP_PP_COMMANDS (TPM_CAP)(0x00000003) #define TPM_CAP_AUDIT_COMMANDS (TPM_CAP)(0x00000004) #define TPM_CAP_PCRS (TPM_CAP)(0x00000005) #define TPM_CAP_TPM_PROPERTIES (TPM_CAP)(0x00000006) #define TPM_CAP_PCR_PROPERTIES (TPM_CAP)(0x00000007) #define TPM_CAP_ECC_CURVES (TPM_CAP)(0x00000008) #define TPM_CAP_AUTH_POLICIES (TPM_CAP)(0x00000009) #define TPM_CAP_ACT (TPM_CAP)(0x0000000a) #define TPM_CAP_LAST (TPM_CAP)(0x0000000a) #define TPM_CAP_VENDOR_PROPERTY (TPM_CAP)(0x00000100) /* Table 2:23 - Definition of TPM_PT Constants */ typedef UINT32 TPM_PT; #define TYPE_OF_TPM_PT UINT32 #define TPM_PT_NONE (TPM_PT)(0x00000000) #define PT_GROUP (TPM_PT)(0x00000100) #define PT_FIXED (TPM_PT)(PT_GROUP*1) #define TPM_PT_FAMILY_INDICATOR (TPM_PT)(PT_FIXED+0) #define TPM_PT_LEVEL (TPM_PT)(PT_FIXED+1) #define TPM_PT_REVISION (TPM_PT)(PT_FIXED+2) #define TPM_PT_DAY_OF_YEAR (TPM_PT)(PT_FIXED+3) #define TPM_PT_YEAR (TPM_PT)(PT_FIXED+4) #define TPM_PT_MANUFACTURER (TPM_PT)(PT_FIXED+5) #define TPM_PT_VENDOR_STRING_1 (TPM_PT)(PT_FIXED+6) #define TPM_PT_VENDOR_STRING_2 (TPM_PT)(PT_FIXED+7) #define TPM_PT_VENDOR_STRING_3 (TPM_PT)(PT_FIXED+8) #define TPM_PT_VENDOR_STRING_4 (TPM_PT)(PT_FIXED+9) #define TPM_PT_VENDOR_TPM_TYPE (TPM_PT)(PT_FIXED+10) #define TPM_PT_FIRMWARE_VERSION_1 (TPM_PT)(PT_FIXED+11) #define TPM_PT_FIRMWARE_VERSION_2 (TPM_PT)(PT_FIXED+12) #define TPM_PT_INPUT_BUFFER (TPM_PT)(PT_FIXED+13) #define TPM_PT_HR_TRANSIENT_MIN (TPM_PT)(PT_FIXED+14) #define TPM_PT_HR_PERSISTENT_MIN (TPM_PT)(PT_FIXED+15) #define TPM_PT_HR_LOADED_MIN (TPM_PT)(PT_FIXED+16) #define TPM_PT_ACTIVE_SESSIONS_MAX (TPM_PT)(PT_FIXED+17) #define TPM_PT_PCR_COUNT (TPM_PT)(PT_FIXED+18) #define TPM_PT_PCR_SELECT_MIN (TPM_PT)(PT_FIXED+19) #define TPM_PT_CONTEXT_GAP_MAX (TPM_PT)(PT_FIXED+20) #define TPM_PT_NV_COUNTERS_MAX (TPM_PT)(PT_FIXED+22) #define TPM_PT_NV_INDEX_MAX (TPM_PT)(PT_FIXED+23) #define TPM_PT_MEMORY (TPM_PT)(PT_FIXED+24) #define TPM_PT_CLOCK_UPDATE (TPM_PT)(PT_FIXED+25) #define TPM_PT_CONTEXT_HASH (TPM_PT)(PT_FIXED+26) #define TPM_PT_CONTEXT_SYM (TPM_PT)(PT_FIXED+27) #define TPM_PT_CONTEXT_SYM_SIZE (TPM_PT)(PT_FIXED+28) #define TPM_PT_ORDERLY_COUNT (TPM_PT)(PT_FIXED+29) #define TPM_PT_MAX_COMMAND_SIZE (TPM_PT)(PT_FIXED+30) #define TPM_PT_MAX_RESPONSE_SIZE (TPM_PT)(PT_FIXED+31) #define TPM_PT_MAX_DIGEST (TPM_PT)(PT_FIXED+32) #define TPM_PT_MAX_OBJECT_CONTEXT (TPM_PT)(PT_FIXED+33) #define TPM_PT_MAX_SESSION_CONTEXT (TPM_PT)(PT_FIXED+34) #define TPM_PT_PS_FAMILY_INDICATOR (TPM_PT)(PT_FIXED+35) #define TPM_PT_PS_LEVEL (TPM_PT)(PT_FIXED+36) #define TPM_PT_PS_REVISION (TPM_PT)(PT_FIXED+37) #define TPM_PT_PS_DAY_OF_YEAR (TPM_PT)(PT_FIXED+38) #define TPM_PT_PS_YEAR (TPM_PT)(PT_FIXED+39) #define TPM_PT_SPLIT_MAX (TPM_PT)(PT_FIXED+40) #define TPM_PT_TOTAL_COMMANDS (TPM_PT)(PT_FIXED+41) #define TPM_PT_LIBRARY_COMMANDS (TPM_PT)(PT_FIXED+42) #define TPM_PT_VENDOR_COMMANDS (TPM_PT)(PT_FIXED+43) #define TPM_PT_NV_BUFFER_MAX (TPM_PT)(PT_FIXED+44) #define TPM_PT_MODES (TPM_PT)(PT_FIXED+45) #define TPM_PT_MAX_CAP_BUFFER (TPM_PT)(PT_FIXED+46) #define PT_VAR (TPM_PT)(PT_GROUP*2) #define TPM_PT_PERMANENT (TPM_PT)(PT_VAR+0) #define TPM_PT_STARTUP_CLEAR (TPM_PT)(PT_VAR+1) #define TPM_PT_HR_NV_INDEX (TPM_PT)(PT_VAR+2) #define TPM_PT_HR_LOADED (TPM_PT)(PT_VAR+3) #define TPM_PT_HR_LOADED_AVAIL (TPM_PT)(PT_VAR+4) #define TPM_PT_HR_ACTIVE (TPM_PT)(PT_VAR+5) #define TPM_PT_HR_ACTIVE_AVAIL (TPM_PT)(PT_VAR+6) #define TPM_PT_HR_TRANSIENT_AVAIL (TPM_PT)(PT_VAR+7) #define TPM_PT_HR_PERSISTENT (TPM_PT)(PT_VAR+8) #define TPM_PT_HR_PERSISTENT_AVAIL (TPM_PT)(PT_VAR+9) #define TPM_PT_NV_COUNTERS (TPM_PT)(PT_VAR+10) #define TPM_PT_NV_COUNTERS_AVAIL (TPM_PT)(PT_VAR+11) #define TPM_PT_ALGORITHM_SET (TPM_PT)(PT_VAR+12) #define TPM_PT_LOADED_CURVES (TPM_PT)(PT_VAR+13) #define TPM_PT_LOCKOUT_COUNTER (TPM_PT)(PT_VAR+14) #define TPM_PT_MAX_AUTH_FAIL (TPM_PT)(PT_VAR+15) #define TPM_PT_LOCKOUT_INTERVAL (TPM_PT)(PT_VAR+16) #define TPM_PT_LOCKOUT_RECOVERY (TPM_PT)(PT_VAR+17) #define TPM_PT_NV_WRITE_RECOVERY (TPM_PT)(PT_VAR+18) #define TPM_PT_AUDIT_COUNTER_0 (TPM_PT)(PT_VAR+19) #define TPM_PT_AUDIT_COUNTER_1 (TPM_PT)(PT_VAR+20) /* Table 2:24 - Definition of TPM_PT_PCR Constants */ typedef UINT32 TPM_PT_PCR; #define TYPE_OF_TPM_PT_PCR UINT32 #define TPM_PT_PCR_FIRST (TPM_PT_PCR)(0x00000000) #define TPM_PT_PCR_SAVE (TPM_PT_PCR)(0x00000000) #define TPM_PT_PCR_EXTEND_L0 (TPM_PT_PCR)(0x00000001) #define TPM_PT_PCR_RESET_L0 (TPM_PT_PCR)(0x00000002) #define TPM_PT_PCR_EXTEND_L1 (TPM_PT_PCR)(0x00000003) #define TPM_PT_PCR_RESET_L1 (TPM_PT_PCR)(0x00000004) #define TPM_PT_PCR_EXTEND_L2 (TPM_PT_PCR)(0x00000005) #define TPM_PT_PCR_RESET_L2 (TPM_PT_PCR)(0x00000006) #define TPM_PT_PCR_EXTEND_L3 (TPM_PT_PCR)(0x00000007) #define TPM_PT_PCR_RESET_L3 (TPM_PT_PCR)(0x00000008) #define TPM_PT_PCR_EXTEND_L4 (TPM_PT_PCR)(0x00000009) #define TPM_PT_PCR_RESET_L4 (TPM_PT_PCR)(0x0000000A) #define TPM_PT_PCR_NO_INCREMENT (TPM_PT_PCR)(0x00000011) #define TPM_PT_PCR_DRTM_RESET (TPM_PT_PCR)(0x00000012) #define TPM_PT_PCR_POLICY (TPM_PT_PCR)(0x00000013) #define TPM_PT_PCR_AUTH (TPM_PT_PCR)(0x00000014) #define TPM_PT_PCR_LAST (TPM_PT_PCR)(0x00000014) /* Table 2:25 - Definition of TPM_PS Constants */ typedef UINT32 TPM_PS; #define TYPE_OF_TPM_PS UINT32 #define TPM_PS_MAIN (TPM_PS)(0x00000000) #define TPM_PS_PC (TPM_PS)(0x00000001) #define TPM_PS_PDA (TPM_PS)(0x00000002) #define TPM_PS_CELL_PHONE (TPM_PS)(0x00000003) #define TPM_PS_SERVER (TPM_PS)(0x00000004) #define TPM_PS_PERIPHERAL (TPM_PS)(0x00000005) #define TPM_PS_TSS (TPM_PS)(0x00000006) #define TPM_PS_STORAGE (TPM_PS)(0x00000007) #define TPM_PS_AUTHENTICATION (TPM_PS)(0x00000008) #define TPM_PS_EMBEDDED (TPM_PS)(0x00000009) #define TPM_PS_HARDCOPY (TPM_PS)(0x0000000A) #define TPM_PS_INFRASTRUCTURE (TPM_PS)(0x0000000B) #define TPM_PS_VIRTUALIZATION (TPM_PS)(0x0000000C) #define TPM_PS_TNC (TPM_PS)(0x0000000D) #define TPM_PS_MULTI_TENANT (TPM_PS)(0x0000000E) #define TPM_PS_TC (TPM_PS)(0x0000000F) /* Table 2:26 - Definition of Types for Handles */ typedef UINT32 TPM_HANDLE; #define TYPE_OF_TPM_HANDLE UINT32 /* Table 2:27 - Definition of TPM_HT Constants */ typedef UINT8 TPM_HT; #define TYPE_OF_TPM_HT UINT8 #define TPM_HT_PCR (TPM_HT)(0x00) #define TPM_HT_NV_INDEX (TPM_HT)(0x01) #define TPM_HT_HMAC_SESSION (TPM_HT)(0x02) #define TPM_HT_LOADED_SESSION (TPM_HT)(0x02) #define TPM_HT_POLICY_SESSION (TPM_HT)(0x03) #define TPM_HT_SAVED_SESSION (TPM_HT)(0x03) #define TPM_HT_PERMANENT (TPM_HT)(0x40) #define TPM_HT_TRANSIENT (TPM_HT)(0x80) #define TPM_HT_PERSISTENT (TPM_HT)(0x81) #define TPM_HT_AC (TPM_HT)(0x90) /* Table 2:28 - Definition of TPM_RH Constants */ typedef TPM_HANDLE TPM_RH; #define TPM_RH_FIRST (TPM_RH)(0x40000000) #define TPM_RH_SRK (TPM_RH)(0x40000000) #define TPM_RH_OWNER (TPM_RH)(0x40000001) #define TPM_RH_REVOKE (TPM_RH)(0x40000002) #define TPM_RH_TRANSPORT (TPM_RH)(0x40000003) #define TPM_RH_OPERATOR (TPM_RH)(0x40000004) #define TPM_RH_ADMIN (TPM_RH)(0x40000005) #define TPM_RH_EK (TPM_RH)(0x40000006) #define TPM_RH_NULL (TPM_RH)(0x40000007) #define TPM_RH_UNASSIGNED (TPM_RH)(0x40000008) #define TPM_RS_PW (TPM_RH)(0x40000009) #define TPM_RH_LOCKOUT (TPM_RH)(0x4000000A) #define TPM_RH_ENDORSEMENT (TPM_RH)(0x4000000B) #define TPM_RH_PLATFORM (TPM_RH)(0x4000000C) #define TPM_RH_PLATFORM_NV (TPM_RH)(0x4000000D) #define TPM_RH_AUTH_00 (TPM_RH)(0x40000010) #define TPM_RH_AUTH_FF (TPM_RH)(0x4000010F) #define TPM_RH_ACT_0 (TPM_RH)(0x40000110) #define TPM_RH_ACT_F (TPM_RH)(0x4000011F) #define TPM_RH_LAST (TPM_RH)(0x4000011F) /* Table 2:29 - Definition of TPM_HC Constants */ typedef TPM_HANDLE TPM_HC; #define HR_HANDLE_MASK (TPM_HC)(0x00FFFFFF) #define HR_RANGE_MASK (TPM_HC)(0xFF000000) #define HR_SHIFT (TPM_HC)(24) #define HR_PCR (TPM_HC)((TPM_HT_PCR< */ typedef struct { TPM_HANDLE handle; UINT32 timeout; TPMA_ACT attributes; } TPMS_ACT_DATA; /* Table 2:97 - Definition of TPML_CC Structure */ typedef struct { UINT32 count; TPM_CC commandCodes[MAX_CAP_CC]; } TPML_CC; /* Table 2:98 - Definition of TPML_CCA Structure */ typedef struct { UINT32 count; TPMA_CC commandAttributes[MAX_CAP_CC]; } TPML_CCA; /* Table 2:99 - Definition of TPML_ALG Structure */ typedef struct { UINT32 count; TPM_ALG_ID algorithms[MAX_ALG_LIST_SIZE]; } TPML_ALG; /* Table 2:100 - Definition of TPML_HANDLE Structure */ typedef struct { UINT32 count; TPM_HANDLE handle[MAX_CAP_HANDLES]; } TPML_HANDLE; /* Table 2:101 - Definition of TPML_DIGEST Structure */ typedef struct { UINT32 count; TPM2B_DIGEST digests[8]; } TPML_DIGEST; /* Table 2:102 - Definition of TPML_DIGEST_VALUES Structure */ typedef struct { UINT32 count; TPMT_HA digests[HASH_COUNT]; } TPML_DIGEST_VALUES; /* Table 2:104 - Definition of TPML_PCR_SELECTION Structure */ typedef struct { UINT32 count; TPMS_PCR_SELECTION pcrSelections[HASH_COUNT]; } TPML_PCR_SELECTION; /* Table 2:105 - Definition of TPML_ALG_PROPERTY Structure */ typedef struct { UINT32 count; TPMS_ALG_PROPERTY algProperties[MAX_CAP_ALGS]; } TPML_ALG_PROPERTY; /* Table 2:106 - Definition of TPML_TAGGED_TPM_PROPERTY Structure */ typedef struct { UINT32 count; TPMS_TAGGED_PROPERTY tpmProperty[MAX_TPM_PROPERTIES]; } TPML_TAGGED_TPM_PROPERTY; /* Table 2:107 - Definition of TPML_TAGGED_PCR_PROPERTY Structure */ typedef struct { UINT32 count; TPMS_TAGGED_PCR_SELECT pcrProperty[MAX_PCR_PROPERTIES]; } TPML_TAGGED_PCR_PROPERTY; /* Table 2:108 - Definition of TPML_ECC_CURVE Structure */ typedef struct { UINT32 count; TPM_ECC_CURVE eccCurves[MAX_ECC_CURVES]; } TPML_ECC_CURVE; /* Table 2:109 - Definition of TPML_TAGGED_POLICY Structure */ typedef struct { UINT32 count; TPMS_TAGGED_POLICY policies[MAX_TAGGED_POLICIES]; } TPML_TAGGED_POLICY; /* Table 2:118 - Definition of TPML_ACT_DATA Structure */ typedef struct { UINT32 count; TPMS_ACT_DATA actData[MAX_ACT_DATA]; } TPML_ACT_DATA; /* Table 2:110 - Definition of TPMU_CAPABILITIES Union */ typedef union { TPML_ALG_PROPERTY algorithms; TPML_HANDLE handles; TPML_CCA command; TPML_CC ppCommands; TPML_CC auditCommands; TPML_PCR_SELECTION assignedPCR; TPML_TAGGED_TPM_PROPERTY tpmProperties; TPML_TAGGED_PCR_PROPERTY pcrProperties; #if ALG_ECC TPML_ECC_CURVE eccCurves; #endif // ALG_ECC TPML_TAGGED_POLICY authPolicies; TPML_ACT_DATA actData; } TPMU_CAPABILITIES; /* Table 2:111 - Definition of TPMS_CAPABILITY_DATA Structure */ typedef struct { TPM_CAP capability; TPMU_CAPABILITIES data; } TPMS_CAPABILITY_DATA; /* Table 2:112 - Definition of TPMS_CLOCK_INFO Structure */ typedef struct { UINT64 clock; UINT32 resetCount; UINT32 restartCount; TPMI_YES_NO safe; } TPMS_CLOCK_INFO; /* Table 2:113 - Definition of TPMS_TIME_INFO Structure */ typedef struct { UINT64 time; TPMS_CLOCK_INFO clockInfo; } TPMS_TIME_INFO; /* Table 2:114 - Definition of TPMS_TIME_ATTEST_INFO Structure */ typedef struct { TPMS_TIME_INFO time; UINT64 firmwareVersion; } TPMS_TIME_ATTEST_INFO; /* Table 2:115 - Definition of TPMS_CERTIFY_INFO Structure */ typedef struct { TPM2B_NAME name; TPM2B_NAME qualifiedName; } TPMS_CERTIFY_INFO; /* Table 2:116 - Definition of TPMS_QUOTE_INFO Structure */ typedef struct { TPML_PCR_SELECTION pcrSelect; TPM2B_DIGEST pcrDigest; } TPMS_QUOTE_INFO; /* Table 2:117 - Definition of TPMS_COMMAND_AUDIT_INFO Structure */ typedef struct { UINT64 auditCounter; TPM_ALG_ID digestAlg; TPM2B_DIGEST auditDigest; TPM2B_DIGEST commandDigest; } TPMS_COMMAND_AUDIT_INFO; /* Table 2:118 - Definition of TPMS_SESSION_AUDIT_INFO Structure */ typedef struct { TPMI_YES_NO exclusiveSession; TPM2B_DIGEST sessionDigest; } TPMS_SESSION_AUDIT_INFO; /* Table 2:119 - Definition of TPMS_CREATION_INFO Structure */ typedef struct { TPM2B_NAME objectName; TPM2B_DIGEST creationHash; } TPMS_CREATION_INFO; /* Table 2:120 - Definition of TPMS_NV_CERTIFY_INFO Structure */ typedef struct { TPM2B_NAME indexName; UINT16 offset; TPM2B_MAX_NV_BUFFER nvContents; } TPMS_NV_CERTIFY_INFO; /* Table 125 - Definition of TPMS_NV_DIGEST_CERTIFY_INFO Structure */ typedef struct { TPM2B_NAME indexName; TPM2B_DIGEST nvDigest; } TPMS_NV_DIGEST_CERTIFY_INFO; /* Table 2:121 - Definition of TPMI_ST_ATTEST Type */ typedef TPM_ST TPMI_ST_ATTEST; /* Table 2:122 - Definition of TPMU_ATTEST Union */ typedef union { TPMS_CERTIFY_INFO certify; TPMS_CREATION_INFO creation; TPMS_QUOTE_INFO quote; TPMS_COMMAND_AUDIT_INFO commandAudit; TPMS_SESSION_AUDIT_INFO sessionAudit; TPMS_TIME_ATTEST_INFO time; TPMS_NV_CERTIFY_INFO nv; TPMS_NV_DIGEST_CERTIFY_INFO nvDigest; } TPMU_ATTEST; /* Table 2:123 - Definition of TPMS_ATTEST Structure */ typedef struct { TPM_CONSTANTS32 magic; TPMI_ST_ATTEST type; TPM2B_NAME qualifiedSigner; TPM2B_DATA extraData; TPMS_CLOCK_INFO clockInfo; UINT64 firmwareVersion; TPMU_ATTEST attested; } TPMS_ATTEST; /* Table 2:124 - Definition of TPM2B_ATTEST Structure */ typedef union { struct { UINT16 size; BYTE attestationData[sizeof(TPMS_ATTEST)]; } t; TPM2B b; } TPM2B_ATTEST; /* Table 2:125 - Definition of TPMS_AUTH_COMMAND Structure */ typedef struct { TPMI_SH_AUTH_SESSION sessionHandle; TPM2B_NONCE nonce; TPMA_SESSION sessionAttributes; TPM2B_AUTH hmac; } TPMS_AUTH_COMMAND; /* Table 2:126 - Definition of TPMS_AUTH_RESPONSE Structure */ typedef struct { TPM2B_NONCE nonce; TPMA_SESSION sessionAttributes; TPM2B_AUTH hmac; } TPMS_AUTH_RESPONSE; /* Table 2:127 - Definition of TPMI_TDES_KEY_BITS Type */ typedef TPM_KEY_BITS TPMI_TDES_KEY_BITS; /* Table 2:127 - Definition of TPMI_AES_KEY_BITS Type */ typedef TPM_KEY_BITS TPMI_AES_KEY_BITS; /* Table 2:127 - Definition of TPMI_SM4_KEY_BITS Type */ typedef TPM_KEY_BITS TPMI_SM4_KEY_BITS; /* Table 2:127 - Definition of TPMI_CAMELLIA_KEY_BITS Type */ typedef TPM_KEY_BITS TPMI_CAMELLIA_KEY_BITS; /* Table 2:128 - Definition of TPMU_SYM_KEY_BITS Union */ typedef union { #if ALG_TDES TPMI_TDES_KEY_BITS tdes; #endif // ALG_TDES #if ALG_AES TPMI_AES_KEY_BITS aes; #endif // ALG_AES #if ALG_SM4 TPMI_SM4_KEY_BITS sm4; #endif // ALG_SM4 #if ALG_CAMELLIA TPMI_CAMELLIA_KEY_BITS camellia; #endif // ALG_CAMELLIA TPM_KEY_BITS sym; #if ALG_XOR TPMI_ALG_HASH xorr; #endif // ALG_XOR } TPMU_SYM_KEY_BITS; /* Table 2:129 - Definition of TPMU_SYM_MODE Union */ typedef union { #if ALG_TDES TPMI_ALG_SYM_MODE tdes; #endif // ALG_TDES #if ALG_AES TPMI_ALG_SYM_MODE aes; #endif // ALG_AES #if ALG_SM4 TPMI_ALG_SYM_MODE sm4; #endif // ALG_SM4 #if ALG_CAMELLIA TPMI_ALG_SYM_MODE camellia; #endif // ALG_CAMELLIA TPMI_ALG_SYM_MODE sym; } TPMU_SYM_MODE; /* Table 2:131 - Definition of TPMT_SYM_DEF Structure */ typedef struct { TPMI_ALG_SYM algorithm; TPMU_SYM_KEY_BITS keyBits; TPMU_SYM_MODE mode; } TPMT_SYM_DEF; /* Table 2:132 - Definition of TPMT_SYM_DEF_OBJECT Structure */ typedef struct { TPMI_ALG_SYM_OBJECT algorithm; TPMU_SYM_KEY_BITS keyBits; TPMU_SYM_MODE mode; } TPMT_SYM_DEF_OBJECT; /* Table 2:133 - Definition of TPM2B_SYM_KEY Structure */ typedef union { struct { UINT16 size; BYTE buffer[MAX_SYM_KEY_BYTES]; } t; TPM2B b; } TPM2B_SYM_KEY; /* Table 2:134 - Definition of TPMS_SYMCIPHER_PARMS Structure */ typedef struct { TPMT_SYM_DEF_OBJECT sym; } TPMS_SYMCIPHER_PARMS; /* Table 2:135 - Definition of TPM2B_LABEL Structure */ typedef union { struct { UINT16 size; BYTE buffer[LABEL_MAX_BUFFER]; } t; TPM2B b; } TPM2B_LABEL; /* Table 2:136 - Definition of TPMS_DERIVE Structure */ typedef struct { TPM2B_LABEL label; TPM2B_LABEL context; } TPMS_DERIVE; /* Table 2:137 - Definition of TPM2B_DERIVE Structure */ typedef union { struct { UINT16 size; BYTE buffer[sizeof(TPMS_DERIVE)]; } t; TPM2B b; } TPM2B_DERIVE; /* Table 2:138 - Definition of TPMU_SENSITIVE_CREATE Union */ typedef union { BYTE create[MAX_SYM_DATA]; TPMS_DERIVE derive; } TPMU_SENSITIVE_CREATE; /* Table 2:139 - Definition of TPM2B_SENSITIVE_DATA Structure */ typedef union { struct { UINT16 size; BYTE buffer[sizeof(TPMU_SENSITIVE_CREATE)]; } t; TPM2B b; } TPM2B_SENSITIVE_DATA; /* Table 2:140 - Definition of TPMS_SENSITIVE_CREATE Structure */ typedef struct { TPM2B_AUTH userAuth; TPM2B_SENSITIVE_DATA data; } TPMS_SENSITIVE_CREATE; /* Table 2:141 - Definition of TPM2B_SENSITIVE_CREATE Structure */ typedef struct { UINT16 size; TPMS_SENSITIVE_CREATE sensitive; } TPM2B_SENSITIVE_CREATE; /* Table 2:142 - Definition of TPMS_SCHEME_HASH Structure */ typedef struct { TPMI_ALG_HASH hashAlg; } TPMS_SCHEME_HASH; /* Table 2:143 - Definition of TPMS_SCHEME_ECDAA Structure */ typedef struct { TPMI_ALG_HASH hashAlg; UINT16 count; } TPMS_SCHEME_ECDAA; /* Table 2:144 - Definition of TPMI_ALG_KEYEDHASH_SCHEME Type */ typedef TPM_ALG_ID TPMI_ALG_KEYEDHASH_SCHEME; /* Table 2:145 - Definition of Types for HMAC_SIG_SCHEME */ typedef TPMS_SCHEME_HASH TPMS_SCHEME_HMAC; /* Table 2:146 - Definition of TPMS_SCHEME_XOR Structure */ typedef struct { TPMI_ALG_HASH hashAlg; TPMI_ALG_KDF kdf; } TPMS_SCHEME_XOR; /* Table 2:147 - Definition of TPMU_SCHEME_KEYEDHASH Union */ typedef union { #if ALG_HMAC TPMS_SCHEME_HMAC hmac; #endif // ALG_HMAC #if ALG_XOR TPMS_SCHEME_XOR xorr; #endif // ALG_XOR } TPMU_SCHEME_KEYEDHASH; /* Table 2:148 - Definition of TPMT_KEYEDHASH_SCHEME Structure */ typedef struct { TPMI_ALG_KEYEDHASH_SCHEME scheme; TPMU_SCHEME_KEYEDHASH details; } TPMT_KEYEDHASH_SCHEME; /* Table 2:149 - Definition of Types for RSA Signature Schemes */ typedef TPMS_SCHEME_HASH TPMS_SIG_SCHEME_RSASSA; typedef TPMS_SCHEME_HASH TPMS_SIG_SCHEME_RSAPSS; /* Table 2:150 - Definition of Types for ECC Signature Schemes */ typedef TPMS_SCHEME_HASH TPMS_SIG_SCHEME_ECDSA; typedef TPMS_SCHEME_HASH TPMS_SIG_SCHEME_SM2; typedef TPMS_SCHEME_HASH TPMS_SIG_SCHEME_ECSCHNORR; typedef TPMS_SCHEME_ECDAA TPMS_SIG_SCHEME_ECDAA; /* Table 2:151 - Definition of TPMU_SIG_SCHEME Union */ typedef union { #if ALG_ECC TPMS_SIG_SCHEME_ECDAA ecdaa; #endif // ALG_ECC #if ALG_RSASSA TPMS_SIG_SCHEME_RSASSA rsassa; #endif // ALG_RSASSA #if ALG_RSAPSS TPMS_SIG_SCHEME_RSAPSS rsapss; #endif // ALG_RSAPSS #if ALG_ECDSA TPMS_SIG_SCHEME_ECDSA ecdsa; #endif // ALG_ECDSA #if ALG_SM2 TPMS_SIG_SCHEME_SM2 sm2; #endif // ALG_SM2 #if ALG_ECSCHNORR TPMS_SIG_SCHEME_ECSCHNORR ecschnorr; #endif // ALG_ECSCHNORR #if ALG_HMAC TPMS_SCHEME_HMAC hmac; #endif // ALG_HMAC TPMS_SCHEME_HASH any; } TPMU_SIG_SCHEME; /* Table 2:152 - Definition of TPMT_SIG_SCHEME Structure */ typedef struct { TPMI_ALG_SIG_SCHEME scheme; TPMU_SIG_SCHEME details; } TPMT_SIG_SCHEME; /* Table 2:153 - Definition of Types for Encryption Schemes */ typedef TPMS_SCHEME_HASH TPMS_ENC_SCHEME_OAEP; typedef TPMS_EMPTY TPMS_ENC_SCHEME_RSAES; /* Table 2:154 - Definition of Types for ECC Key Exchange */ typedef TPMS_SCHEME_HASH TPMS_KEY_SCHEME_ECDH; typedef TPMS_SCHEME_HASH TPMS_KEY_SCHEME_ECMQV; /* Table 2:155 - Definition of Types for KDF Schemes */ typedef TPMS_SCHEME_HASH TPMS_KDF_SCHEME_MGF1; typedef TPMS_SCHEME_HASH TPMS_KDF_SCHEME_KDF1_SP800_56A; typedef TPMS_SCHEME_HASH TPMS_KDF_SCHEME_KDF2; typedef TPMS_SCHEME_HASH TPMS_KDF_SCHEME_KDF1_SP800_108; /* Table 2:156 - Definition of TPMU_KDF_SCHEME Union */ typedef union { #if ALG_MGF1 TPMS_KDF_SCHEME_MGF1 mgf1; #endif // ALG_MGF1 #if ALG_KDF1_SP800_56A TPMS_KDF_SCHEME_KDF1_SP800_56A kdf1_sp800_56a; #endif // ALG_KDF1_SP800_56A #if ALG_KDF2 TPMS_KDF_SCHEME_KDF2 kdf2; #endif // ALG_KDF2 #if ALG_KDF1_SP800_108 TPMS_KDF_SCHEME_KDF1_SP800_108 kdf1_sp800_108; #endif // ALG_KDF1_SP800_108 TPMS_SCHEME_HASH anyKdf; } TPMU_KDF_SCHEME; /* Table 2:157 - Definition of TPMT_KDF_SCHEME Structure */ typedef struct { TPMI_ALG_KDF scheme; TPMU_KDF_SCHEME details; } TPMT_KDF_SCHEME; /* Table 2:158 - Definition of TPMI_ALG_ASYM_SCHEME Type */ typedef TPM_ALG_ID TPMI_ALG_ASYM_SCHEME; /* Table 2:159 - Definition of TPMU_ASYM_SCHEME Union */ typedef union { #if ALG_ECDH TPMS_KEY_SCHEME_ECDH ecdh; #endif // ALG_ECDH #if ALG_ECMQV TPMS_KEY_SCHEME_ECMQV ecmqv; #endif // ALG_ECMQV #if ALG_ECC TPMS_SIG_SCHEME_ECDAA ecdaa; #endif // ALG_ECC #if ALG_RSASSA TPMS_SIG_SCHEME_RSASSA rsassa; #endif // ALG_RSASSA #if ALG_RSAPSS TPMS_SIG_SCHEME_RSAPSS rsapss; #endif // ALG_RSAPSS #if ALG_ECDSA TPMS_SIG_SCHEME_ECDSA ecdsa; #endif // ALG_ECDSA #if ALG_SM2 TPMS_SIG_SCHEME_SM2 sm2; #endif // ALG_SM2 #if ALG_ECSCHNORR TPMS_SIG_SCHEME_ECSCHNORR ecschnorr; #endif // ALG_ECSCHNORR #if ALG_RSAES TPMS_ENC_SCHEME_RSAES rsaes; #endif // ALG_RSAES #if ALG_OAEP TPMS_ENC_SCHEME_OAEP oaep; #endif // ALG_OAEP TPMS_SCHEME_HASH anySig; } TPMU_ASYM_SCHEME; /* Table 2:160 - Definition of TPMT_ASYM_SCHEME Structure */ typedef struct { TPMI_ALG_ASYM_SCHEME scheme; TPMU_ASYM_SCHEME details; } TPMT_ASYM_SCHEME; /* Table 2:161 - Definition of TPMI_ALG_RSA_SCHEME Type */ typedef TPM_ALG_ID TPMI_ALG_RSA_SCHEME; /* Table 2:162 - Definition of TPMT_RSA_SCHEME Structure */ typedef struct { TPMI_ALG_RSA_SCHEME scheme; TPMU_ASYM_SCHEME details; } TPMT_RSA_SCHEME; /* Table 2:163 - Definition of TPMI_ALG_RSA_DECRYPT Type */ typedef TPM_ALG_ID TPMI_ALG_RSA_DECRYPT; /* Table 2:164 - Definition of TPMT_RSA_DECRYPT Structure */ typedef struct { TPMI_ALG_RSA_DECRYPT scheme; TPMU_ASYM_SCHEME details; } TPMT_RSA_DECRYPT; /* Table 2:165 - Definition of TPM2B_PUBLIC_KEY_RSA Structure */ typedef union { struct { UINT16 size; BYTE buffer[MAX_RSA_KEY_BYTES]; } t; TPM2B b; } TPM2B_PUBLIC_KEY_RSA; /* Table 2:166 - Definition of TPMI_RSA_KEY_BITS Type */ typedef TPM_KEY_BITS TPMI_RSA_KEY_BITS; /* Table 2:167 - Definition of TPM2B_PRIVATE_KEY_RSA Structure */ typedef union { struct { UINT16 size; BYTE buffer[RSA_PRIVATE_SIZE]; } t; TPM2B b; } TPM2B_PRIVATE_KEY_RSA; /* Table 2:168 - Definition of TPM2B_ECC_PARAMETER Structure */ typedef union { struct { UINT16 size; BYTE buffer[MAX_ECC_KEY_BYTES]; } t; TPM2B b; } TPM2B_ECC_PARAMETER; /* Table 2:169 - Definition of TPMS_ECC_POINT Structure */ typedef struct { TPM2B_ECC_PARAMETER x; TPM2B_ECC_PARAMETER y; } TPMS_ECC_POINT; /* Table 2:170 - Definition of TPM2B_ECC_POINT Structure */ typedef struct { UINT16 size; TPMS_ECC_POINT point; } TPM2B_ECC_POINT; /* Table 2:171 - Definition of TPMI_ALG_ECC_SCHEME Type */ typedef TPM_ALG_ID TPMI_ALG_ECC_SCHEME; /* Table 2:172 - Definition of TPMI_ECC_CURVE Type */ typedef TPM_ECC_CURVE TPMI_ECC_CURVE; /* Table 2:173 - Definition of TPMT_ECC_SCHEME Structure */ typedef struct { TPMI_ALG_ECC_SCHEME scheme; TPMU_ASYM_SCHEME details; } TPMT_ECC_SCHEME; /* Table 2:174 - Definition of TPMS_ALGORITHM_DETAIL_ECC Structure */ typedef struct { TPM_ECC_CURVE curveID; UINT16 keySize; TPMT_KDF_SCHEME kdf; TPMT_ECC_SCHEME sign; TPM2B_ECC_PARAMETER p; TPM2B_ECC_PARAMETER a; TPM2B_ECC_PARAMETER b; TPM2B_ECC_PARAMETER gX; TPM2B_ECC_PARAMETER gY; TPM2B_ECC_PARAMETER n; TPM2B_ECC_PARAMETER h; } TPMS_ALGORITHM_DETAIL_ECC; /* Table 2:175 - Definition of TPMS_SIGNATURE_RSA Structure */ typedef struct { TPMI_ALG_HASH hash; TPM2B_PUBLIC_KEY_RSA sig; } TPMS_SIGNATURE_RSA; /* Table 2:176 - Definition of Types for Signature */ typedef TPMS_SIGNATURE_RSA TPMS_SIGNATURE_RSASSA; typedef TPMS_SIGNATURE_RSA TPMS_SIGNATURE_RSAPSS; /* Table 2:177 - Definition of TPMS_SIGNATURE_ECC Structure */ typedef struct { TPMI_ALG_HASH hash; TPM2B_ECC_PARAMETER signatureR; TPM2B_ECC_PARAMETER signatureS; } TPMS_SIGNATURE_ECC; /* Table 2:178 - Definition of Types for TPMS_SIGNATURE_ECC */ typedef TPMS_SIGNATURE_ECC TPMS_SIGNATURE_ECDAA; typedef TPMS_SIGNATURE_ECC TPMS_SIGNATURE_ECDSA; typedef TPMS_SIGNATURE_ECC TPMS_SIGNATURE_SM2; typedef TPMS_SIGNATURE_ECC TPMS_SIGNATURE_ECSCHNORR; /* Table 2:179 - Definition of TPMU_SIGNATURE Union */ typedef union { #if ALG_ECC TPMS_SIGNATURE_ECDAA ecdaa; #endif // ALG_ECC #if ALG_RSA TPMS_SIGNATURE_RSASSA rsassa; #endif // ALG_RSA #if ALG_RSA TPMS_SIGNATURE_RSAPSS rsapss; #endif // ALG_RSA #if ALG_ECC TPMS_SIGNATURE_ECDSA ecdsa; #endif // ALG_ECC #if ALG_ECC TPMS_SIGNATURE_SM2 sm2; #endif // ALG_ECC #if ALG_ECC TPMS_SIGNATURE_ECSCHNORR ecschnorr; #endif // ALG_ECC #if ALG_HMAC TPMT_HA hmac; #endif // ALG_HMAC TPMS_SCHEME_HASH any; } TPMU_SIGNATURE; /* Table 2:180 - Definition of TPMT_SIGNATURE Structure */ typedef struct { TPMI_ALG_SIG_SCHEME sigAlg; TPMU_SIGNATURE signature; } TPMT_SIGNATURE; /* Table 2:181 - Definition of TPMU_ENCRYPTED_SECRET Union */ typedef union { #if ALG_ECC BYTE ecc[sizeof(TPMS_ECC_POINT)]; #endif // ALG_ECC #if ALG_RSA BYTE rsa[MAX_RSA_KEY_BYTES]; #endif // ALG_RSA #if ALG_SYMCIPHER BYTE symmetric[sizeof(TPM2B_DIGEST)]; #endif // ALG_SYMCIPHER #if ALG_KEYEDHASH BYTE keyedHash[sizeof(TPM2B_DIGEST)]; #endif // ALG_KEYEDHASH } TPMU_ENCRYPTED_SECRET; /* Table 2:182 - Definition of TPM2B_ENCRYPTED_SECRET Structure */ typedef union { struct { UINT16 size; BYTE secret[sizeof(TPMU_ENCRYPTED_SECRET)]; } t; TPM2B b; } TPM2B_ENCRYPTED_SECRET; /* Table 2:183 - Definition of TPMI_ALG_PUBLIC Type */ typedef TPM_ALG_ID TPMI_ALG_PUBLIC; /* Table 2:184 - Definition of TPMU_PUBLIC_ID Union */ typedef union { #if ALG_KEYEDHASH TPM2B_DIGEST keyedHash; #endif // ALG_KEYEDHASH #if ALG_SYMCIPHER TPM2B_DIGEST sym; #endif // ALG_SYMCIPHER #if ALG_RSA TPM2B_PUBLIC_KEY_RSA rsa; #endif // ALG_RSA #if ALG_ECC TPMS_ECC_POINT ecc; #endif // ALG_ECC TPMS_DERIVE derive; } TPMU_PUBLIC_ID; /* Table 2:185 - Definition of TPMS_KEYEDHASH_PARMS Structure */ typedef struct { TPMT_KEYEDHASH_SCHEME scheme; } TPMS_KEYEDHASH_PARMS; /* Table 2:186 - Definition of TPMS_ASYM_PARMS Structure */ typedef struct { TPMT_SYM_DEF_OBJECT symmetric; TPMT_ASYM_SCHEME scheme; } TPMS_ASYM_PARMS; /* Table 2:187 - Definition of TPMS_RSA_PARMS Structure */ typedef struct { TPMT_SYM_DEF_OBJECT symmetric; TPMT_RSA_SCHEME scheme; TPMI_RSA_KEY_BITS keyBits; UINT32 exponent; } TPMS_RSA_PARMS; /* Table 2:188 - Definition of TPMS_ECC_PARMS Structure */ typedef struct { TPMT_SYM_DEF_OBJECT symmetric; TPMT_ECC_SCHEME scheme; TPMI_ECC_CURVE curveID; TPMT_KDF_SCHEME kdf; } TPMS_ECC_PARMS; /* Table 2:189 - Definition of TPMU_PUBLIC_PARMS Union */ typedef union { #if ALG_KEYEDHASH TPMS_KEYEDHASH_PARMS keyedHashDetail; #endif // ALG_KEYEDHASH #if ALG_SYMCIPHER TPMS_SYMCIPHER_PARMS symDetail; #endif // ALG_SYMCIPHER #if ALG_RSA TPMS_RSA_PARMS rsaDetail; #endif // ALG_RSA #if ALG_ECC TPMS_ECC_PARMS eccDetail; #endif // ALG_ECC TPMS_ASYM_PARMS asymDetail; } TPMU_PUBLIC_PARMS; /* Table 2:190 - Definition of TPMT_PUBLIC_PARMS Structure */ typedef struct { TPMI_ALG_PUBLIC type; TPMU_PUBLIC_PARMS parameters; } TPMT_PUBLIC_PARMS; /* Table 2:191 - Definition of TPMT_PUBLIC Structure */ typedef struct { TPMI_ALG_PUBLIC type; TPMI_ALG_HASH nameAlg; TPMA_OBJECT objectAttributes; TPM2B_DIGEST authPolicy; TPMU_PUBLIC_PARMS parameters; TPMU_PUBLIC_ID unique; } TPMT_PUBLIC; /* Table 2:192 - Definition of TPM2B_PUBLIC Structure */ typedef struct { UINT16 size; TPMT_PUBLIC publicArea; } TPM2B_PUBLIC; /* Table 2:193 - Definition of TPM2B_TEMPLATE Structure */ typedef union { struct { UINT16 size; BYTE buffer[sizeof(TPMT_PUBLIC)]; } t; TPM2B b; } TPM2B_TEMPLATE; /* Table 2:194 - Definition of TPM2B_PRIVATE_VENDOR_SPECIFIC Structure */ typedef union { struct { UINT16 size; BYTE buffer[PRIVATE_VENDOR_SPECIFIC_BYTES]; } t; TPM2B b; } TPM2B_PRIVATE_VENDOR_SPECIFIC; /* Table 2:195 - Definition of TPMU_SENSITIVE_COMPOSITE Union */ typedef union { #if ALG_RSA TPM2B_PRIVATE_KEY_RSA rsa; #endif // ALG_RSA #if ALG_ECC TPM2B_ECC_PARAMETER ecc; #endif // ALG_ECC #if ALG_KEYEDHASH TPM2B_SENSITIVE_DATA bits; #endif // ALG_KEYEDHASH #if ALG_SYMCIPHER TPM2B_SYM_KEY sym; #endif // ALG_SYMCIPHER TPM2B_PRIVATE_VENDOR_SPECIFIC any; } TPMU_SENSITIVE_COMPOSITE; /* Table 2:196 - Definition of TPMT_SENSITIVE Structure */ typedef struct { TPMI_ALG_PUBLIC sensitiveType; TPM2B_AUTH authValue; TPM2B_DIGEST seedValue; TPMU_SENSITIVE_COMPOSITE sensitive; } TPMT_SENSITIVE; /* Table 2:197 - Definition of TPM2B_SENSITIVE Structure */ typedef struct { UINT16 size; TPMT_SENSITIVE sensitiveArea; } TPM2B_SENSITIVE; /* Table 2:198 - Definition of _PRIVATE Structure */ typedef struct { TPM2B_DIGEST integrityOuter; TPM2B_DIGEST integrityInner; TPM2B_SENSITIVE sensitive; } _PRIVATE; /* Table 2:199 - Definition of TPM2B_PRIVATE Structure */ typedef union { struct { UINT16 size; BYTE buffer[sizeof(_PRIVATE)]; } t; TPM2B b; } TPM2B_PRIVATE; /* Table 2:203 - Definition of TPMS_ID_OBJECT Structure */ typedef struct { TPM2B_DIGEST integrityHMAC; TPM2B_DIGEST encIdentity; } TPMS_ID_OBJECT; /* Table 204 - Definition of TPM2B_ID_OBJECT Structure */ typedef union { struct { UINT16 size; BYTE credential[sizeof(TPMS_ID_OBJECT)]; } t; TPM2B b; } TPM2B_ID_OBJECT; #define TYPE_OF_TPM_NV_INDEX UINT32 #define TPM_NV_INDEX_TO_UINT32(a) (*((UINT32 *)&(a))) #define UINT32_TO_TPM_NV_INDEX(a) (*((TPM_NV_INDEX *)&(a))) #define TPM_NV_INDEX_TO_BYTE_ARRAY(i, a) \ UINT32_TO_BYTE_ARRAY((TPM_NV_INDEX_TO_UINT32(i)), (a)) #define BYTE_ARRAY_TO_TPM_NV_INDEX(i, a) \ { UINT32 x = BYTE_ARRAY_TO_UINT32(a); i = UINT32_TO_TPM_NV_INDEX(x); } #if USE_BIT_FIELD_STRUCTURES typedef struct TPM_NV_INDEX { // Table 2:205 unsigned index : 24; unsigned RH_NV : 8; } TPM_NV_INDEX; // This is the initializer for a TPM_NV_INDEX structure #define TPM_NV_INDEX_INITIALIZER(index, rh_nv) {index, rh_nv} #else // USE_BIT_FIELD_STRUCTURES // This implements Table 2:205 TPM_NV_INDEX using bit masking typedef UINT32 TPM_NV_INDEX; #define TPM_NV_INDEX_index_SHIFT 0 #define TPM_NV_INDEX_index ((TPM_NV_INDEX)0xffffff << 0) #define TPM_NV_INDEX_RH_NV_SHIFT 24 #define TPM_NV_INDEX_RH_NV ((TPM_NV_INDEX)0xff << 24) // This is the initializer for a TPM_NV_INDEX bit array. #define TPM_NV_INDEX_INITIALIZER(index, rh_nv) \ (TPM_NV_INDEX)( \ (index << 0) + (rh_nv << 24)) #endif // USE_BIT_FIELD_STRUCTURES // Table 2:206 - Definition of TPM_NT Constants typedef UINT32 TPM_NT; #define TYPE_OF_TPM_NT UINT32 #define TPM_NT_ORDINARY (TPM_NT)(0x0) #define TPM_NT_COUNTER (TPM_NT)(0x1) #define TPM_NT_BITS (TPM_NT)(0x2) #define TPM_NT_EXTEND (TPM_NT)(0x4) #define TPM_NT_PIN_FAIL (TPM_NT)(0x8) #define TPM_NT_PIN_PASS (TPM_NT)(0x9) // Table 2:207 typedef struct { UINT32 pinCount; UINT32 pinLimit; } TPMS_NV_PIN_COUNTER_PARAMETERS; #define TYPE_OF_TPMA_NV UINT32 #define TPMA_NV_TO_UINT32(a) (*((UINT32 *)&(a))) #define UINT32_TO_TPMA_NV(a) (*((TPMA_NV *)&(a))) #define TPMA_NV_TO_BYTE_ARRAY(i, a) \ UINT32_TO_BYTE_ARRAY((TPMA_NV_TO_UINT32(i)), (a)) #define BYTE_ARRAY_TO_TPMA_NV(i, a) \ { UINT32 x = BYTE_ARRAY_TO_UINT32(a); i = UINT32_TO_TPMA_NV(x); } #if USE_BIT_FIELD_STRUCTURES typedef struct TPMA_NV { // Table 2:208 unsigned PPWRITE : 1; unsigned OWNERWRITE : 1; unsigned AUTHWRITE : 1; unsigned POLICYWRITE : 1; unsigned TPM_NT : 4; unsigned Reserved_bits_at_8 : 2; unsigned POLICY_DELETE : 1; unsigned WRITELOCKED : 1; unsigned WRITEALL : 1; unsigned WRITEDEFINE : 1; unsigned WRITE_STCLEAR : 1; unsigned GLOBALLOCK : 1; unsigned PPREAD : 1; unsigned OWNERREAD : 1; unsigned AUTHREAD : 1; unsigned POLICYREAD : 1; unsigned Reserved_bits_at_20 : 5; unsigned NO_DA : 1; unsigned ORDERLY : 1; unsigned CLEAR_STCLEAR : 1; unsigned READLOCKED : 1; unsigned WRITTEN : 1; unsigned PLATFORMCREATE : 1; unsigned READ_STCLEAR : 1; } TPMA_NV; // This is the initializer for a TPMA_NV structure #define TPMA_NV_INITIALIZER( \ ppwrite, ownerwrite, authwrite, policywrite, \ tpm_nt, bits_at_8, policy_delete, writelocked, \ writeall, writedefine, write_stclear, globallock, \ ppread, ownerread, authread, policyread, \ bits_at_20, no_da, orderly, clear_stclear, \ readlocked, written, platformcreate, read_stclear) \ {ppwrite, ownerwrite, authwrite, policywrite, \ tpm_nt, bits_at_8, policy_delete, writelocked, \ writeall, writedefine, write_stclear, globallock, \ ppread, ownerread, authread, policyread, \ bits_at_20, no_da, orderly, clear_stclear, \ readlocked, written, platformcreate, read_stclear} #else // USE_BIT_FIELD_STRUCTURES // This implements Table 2:208 TPMA_NV using bit masking typedef UINT32 TPMA_NV; #define TYPE_OF_TPMA_NV UINT32 #define TPMA_NV_PPWRITE ((TPMA_NV)1 << 0) #define TPMA_NV_OWNERWRITE ((TPMA_NV)1 << 1) #define TPMA_NV_AUTHWRITE ((TPMA_NV)1 << 2) #define TPMA_NV_POLICYWRITE ((TPMA_NV)1 << 3) #define TPMA_NV_TPM_NT_SHIFT 4 #define TPMA_NV_TPM_NT ((TPMA_NV)0xf << 4) #define TPMA_NV_POLICY_DELETE ((TPMA_NV)1 << 10) #define TPMA_NV_WRITELOCKED ((TPMA_NV)1 << 11) #define TPMA_NV_WRITEALL ((TPMA_NV)1 << 12) #define TPMA_NV_WRITEDEFINE ((TPMA_NV)1 << 13) #define TPMA_NV_WRITE_STCLEAR ((TPMA_NV)1 << 14) #define TPMA_NV_GLOBALLOCK ((TPMA_NV)1 << 15) #define TPMA_NV_PPREAD ((TPMA_NV)1 << 16) #define TPMA_NV_OWNERREAD ((TPMA_NV)1 << 17) #define TPMA_NV_AUTHREAD ((TPMA_NV)1 << 18) #define TPMA_NV_POLICYREAD ((TPMA_NV)1 << 19) #define TPMA_NV_NO_DA ((TPMA_NV)1 << 25) #define TPMA_NV_ORDERLY ((TPMA_NV)1 << 26) #define TPMA_NV_CLEAR_STCLEAR ((TPMA_NV)1 << 27) #define TPMA_NV_READLOCKED ((TPMA_NV)1 << 28) #define TPMA_NV_WRITTEN ((TPMA_NV)1 << 29) #define TPMA_NV_PLATFORMCREATE ((TPMA_NV)1 << 30) #define TPMA_NV_READ_STCLEAR ((TPMA_NV)1 << 31) #define TPMA_NV_RESERVED (0x00000300 | 0x01f00000) // This is the initializer for a TPMA_NV bit array. #define TPMA_NV_INITIALIZER( \ ppwrite, ownerwrite, authwrite, policywrite, \ tpm_nt, bits_at_8, policy_delete, writelocked, \ writeall, writedefine, write_stclear, globallock, \ ppread, ownerread, authread, policyread, \ bits_at_20, no_da, orderly, clear_stclear, \ readlocked, written, platformcreate, read_stclear) \ (TPMA_NV)( \ (ppwrite << 0) + (ownerwrite << 1) + \ (authwrite << 2) + (policywrite << 3) + \ (tpm_nt << 4) + (policy_delete << 10) + \ (writelocked << 11) + (writeall << 12) + \ (writedefine << 13) + (write_stclear << 14) + \ (globallock << 15) + (ppread << 16) + \ (ownerread << 17) + (authread << 18) + \ (policyread << 19) + (no_da << 25) + \ (orderly << 26) + (clear_stclear << 27) + \ (readlocked << 28) + (written << 29) + \ (platformcreate << 30) + (read_stclear << 31)) #endif // USE_BIT_FIELD_STRUCTURES /* Table 2:209 - Definition of TPMS_NV_PUBLIC Structure */ typedef struct { TPMI_RH_NV_INDEX nvIndex; TPMI_ALG_HASH nameAlg; TPMA_NV attributes; TPM2B_DIGEST authPolicy; UINT16 dataSize; } TPMS_NV_PUBLIC; /* Table 2:207 - Definition of TPM2B_NV_PUBLIC Structure */ typedef struct { UINT16 size; TPMS_NV_PUBLIC nvPublic; } TPM2B_NV_PUBLIC; /* Table 2:208 - Definition of TPM2B_CONTEXT_SENSITIVE Structure */ typedef union { struct { UINT16 size; BYTE buffer[MAX_CONTEXT_SIZE]; } t; TPM2B b; } TPM2B_CONTEXT_SENSITIVE; /* Table 2:209 - Definition of TPMS_CONTEXT_DATA Structure */ typedef struct { TPM2B_DIGEST integrity; TPM2B_CONTEXT_SENSITIVE encrypted; } TPMS_CONTEXT_DATA; /* Table 2:210 - Definition of TPM2B_CONTEXT_DATA Structure */ typedef union { struct { UINT16 size; BYTE buffer[sizeof(TPMS_CONTEXT_DATA)]; } t; TPM2B b; } TPM2B_CONTEXT_DATA; /* Table 2:211 - Definition of TPMS_CONTEXT Structure */ typedef struct { UINT64 sequence; TPMI_DH_SAVED savedHandle; TPMI_RH_HIERARCHY hierarchy; TPM2B_CONTEXT_DATA contextBlob; } TPMS_CONTEXT; /* Table 2:213 - Definition of TPMS_CREATION_DATA Structure */ typedef struct { TPML_PCR_SELECTION pcrSelect; TPM2B_DIGEST pcrDigest; TPMA_LOCALITY locality; TPM_ALG_ID parentNameAlg; TPM2B_NAME parentName; TPM2B_NAME parentQualifiedName; TPM2B_DATA outsideInfo; } TPMS_CREATION_DATA; /* Table 2:214 - Definition of TPM2B_CREATION_DATA Structure */ typedef struct { UINT16 size; TPMS_CREATION_DATA creationData; } TPM2B_CREATION_DATA; /* Structure */ // Table 2:220 - Definition of TPM_AT Constants typedef UINT32 TPM_AT; #define TYPE_OF_TPM_AT UINT32 #define TPM_AT_ANY (TPM_AT)(0x00000000) #define TPM_AT_ERROR (TPM_AT)(0x00000001) #define TPM_AT_PV1 (TPM_AT)(0x00000002) #define TPM_AT_VEND (TPM_AT)(0x80000000) // Table 2:221 - Definition of TPM_AE Constants typedef UINT32 TPM_AE; #define TYPE_OF_TPM_AE UINT32 #define TPM_AE_NONE (TPM_AE)(0x00000000) typedef struct { // Table 2:222 TPM_AT tag; UINT32 data; } TPMS_AC_OUTPUT; /* Table 2:218 - Definition of TPML_AC_CAPABILITIES Structure */ typedef struct { UINT32 count; TPMS_AC_OUTPUT acCapabilities[MAX_AC_CAPABILITIES]; } TPML_AC_CAPABILITIES; #endif libtpms-0.9.3/src/tpm2/Unique.c000066400000000000000000000117721421143571500162730ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Secret Value to the TPM */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Unique.c 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ /* C.12 Unique.c */ /* C.12.1. Introduction */ /* In some implementations of the TPM, the hardware can provide a secret value to the TPM. This secret value is statistically unique to the instance of the TPM. Typical uses of this value are to provide personalization to the random number generation and as a shared secret between the TPM and the manufacturer. */ /* C.12.2. Includes */ #include "Platform.h" const char notReallyUnique[] = "This is not really a unique value. A real unique value should" " be generated by the platform."; /* C.12.3. _plat__GetUnique() */ /* This function is used to access the platform-specific unique value. This function places the unique value in the provided buffer (b) and returns the number of bytes transferred. The function will not copy more data than bSize. */ /* NOTE: If a platform unique value has unequal distribution of uniqueness and bSize is smaller than the size of the unique value, the bSize portion with the most uniqueness should be returned. */ LIB_EXPORT uint32_t _plat__GetUnique( uint32_t which, // authorities (0) or details uint32_t bSize, // size of the buffer unsigned char *b // output buffer ) { const char *from = notReallyUnique; uint32_t retVal = 0; if(which == 0) // the authorities value { for(retVal = 0; *from != 0 && retVal < bSize; retVal++) { *b++ = *from++; } } else { #define uSize sizeof(notReallyUnique) b = &b[((bSize < uSize) ? bSize : uSize) - 1]; for(retVal = 0; *from != 0 && retVal < bSize; retVal++) { *b-- = *from++; } } return retVal; } libtpms-0.9.3/src/tpm2/Unmarshal.c000066400000000000000000003361541421143571500167630ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Parameter Unmarshaling */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Unmarshal.c 1635 2020-06-12 21:48:27Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2015 - 2018 */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ /* rev 136 */ #include #include "Unmarshal_fp.h" #include "CryptEccMain_fp.h" // libtpms added TPM_RC UINT8_Unmarshal(UINT8 *target, BYTE **buffer, INT32 *size) { if ((UINT32)*size < sizeof(UINT8)) { return TPM_RC_INSUFFICIENT; } *target = (*buffer)[0]; *buffer += sizeof(UINT8); *size -= sizeof(UINT8); return TPM_RC_SUCCESS; } TPM_RC INT8_Unmarshal(INT8 *target, BYTE **buffer, INT32 *size) { return UINT8_Unmarshal((UINT8 *)target, buffer, size); } TPM_RC UINT16_Unmarshal(UINT16 *target, BYTE **buffer, INT32 *size) { if ((UINT32)*size < sizeof(UINT16)) { return TPM_RC_INSUFFICIENT; } *target = ((UINT16)((*buffer)[0]) << 8) | ((UINT16)((*buffer)[1]) << 0); *buffer += sizeof(UINT16); *size -= sizeof(UINT16); return TPM_RC_SUCCESS; } TPM_RC UINT32_Unmarshal(UINT32 *target, BYTE **buffer, INT32 *size) { if ((UINT32)*size < sizeof(UINT32)) { return TPM_RC_INSUFFICIENT; } *target = ((UINT32)((*buffer)[0]) << 24) | ((UINT32)((*buffer)[1]) << 16) | ((UINT32)((*buffer)[2]) << 8) | ((UINT32)((*buffer)[3]) << 0); *buffer += sizeof(UINT32); *size -= sizeof(UINT32); return TPM_RC_SUCCESS; } TPM_RC UINT64_Unmarshal(UINT64 *target, BYTE **buffer, INT32 *size) { if ((UINT32)*size < sizeof(UINT64)) { return TPM_RC_INSUFFICIENT; } *target = ((UINT64)((*buffer)[0]) << 56) | ((UINT64)((*buffer)[1]) << 48) | ((UINT64)((*buffer)[2]) << 40) | ((UINT64)((*buffer)[3]) << 32) | ((UINT64)((*buffer)[4]) << 24) | ((UINT64)((*buffer)[5]) << 16) | ((UINT64)((*buffer)[6]) << 8) | ((UINT64)((*buffer)[7]) << 0); *buffer += sizeof(UINT64); *size -= sizeof(UINT64); return TPM_RC_SUCCESS; } TPM_RC Array_Unmarshal(BYTE *targetBuffer, UINT16 targetSize, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (targetSize > *size) { rc = TPM_RC_INSUFFICIENT; } else { memcpy(targetBuffer, *buffer, targetSize); *buffer += targetSize; *size -= targetSize; } return rc; } TPM_RC TPM2B_Unmarshal(TPM2B *target, UINT16 targetSize, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(&target->size, buffer, size); } if (rc == TPM_RC_SUCCESS) { if (target->size > targetSize) { rc = TPM_RC_SIZE; target->size = 0; // libtpms added } } if (rc == TPM_RC_SUCCESS) { rc = Array_Unmarshal(target->buffer, target->size, buffer, size); } return rc; } /* Table 5 - Definition of Types for Documentation Clarity */ TPM_RC TPM_KEY_BITS_Unmarshal(TPM_KEY_BITS *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(target, buffer, size); } return rc; } /* Table 7 - Definition of (UINT32) TPM_GENERATED Constants */ #if 0 TPM_RC TPM_GENERATED_Unmarshal(TPM_GENERATED *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; TPM_GENERATED orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { if (*target != TPM_GENERATED_VALUE) { rc = TPM_RC_VALUE; *target = orig_target; // libtpms added } } return rc; } #endif /* Table 9 - Definition of (UINT16) TPM_ALG_ID Constants */ TPM_RC TPM_ALG_ID_Unmarshal(TPM_ALG_ID *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(target, buffer, size); } return rc; } /* Table 10 - Definition of (UINT16) {ECC} TPM_ECC_CURVE Constants */ #if ALG_ECC TPM_RC TPM_ECC_CURVE_Unmarshal(TPM_ECC_CURVE *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; TPM_ECC_CURVE orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (*target) { case TPM_ECC_NONE: case TPM_ECC_NIST_P192: case TPM_ECC_NIST_P224: case TPM_ECC_NIST_P256: case TPM_ECC_NIST_P384: case TPM_ECC_NIST_P521: case TPM_ECC_BN_P256: case TPM_ECC_BN_P638: case TPM_ECC_SM2_P256: break; default: rc = TPM_RC_CURVE; *target = orig_target; // libtpms added } } return rc; } #endif /* Table 13 - Definition of (UINT32) TPM_CC Constants (Numeric Order) */ TPM_RC TPM_CC_Unmarshal(TPM_RC *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(target, buffer, size); } return rc; } /* Table 18 - Definition of (INT8) TPM_CLOCK_ADJUST Constants */ TPM_RC TPM_CLOCK_ADJUST_Unmarshal(TPM_CLOCK_ADJUST *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; TPM_CLOCK_ADJUST orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = INT8_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (*target) { case TPM_CLOCK_COARSE_SLOWER: case TPM_CLOCK_MEDIUM_SLOWER: case TPM_CLOCK_FINE_SLOWER: case TPM_CLOCK_NO_CHANGE: case TPM_CLOCK_FINE_FASTER: case TPM_CLOCK_MEDIUM_FASTER: case TPM_CLOCK_COARSE_FASTER: break; default: rc = TPM_RC_VALUE; *target = orig_target; // libtpms added } } return rc; } /* Table 19 - Definition of (UINT16) TPM_EO Constants */ TPM_RC TPM_EO_Unmarshal(TPM_EO *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; TPM_EO orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (*target) { case TPM_EO_EQ: case TPM_EO_NEQ: case TPM_EO_SIGNED_GT: case TPM_EO_UNSIGNED_GT: case TPM_EO_SIGNED_LT: case TPM_EO_UNSIGNED_LT: case TPM_EO_SIGNED_GE: case TPM_EO_UNSIGNED_GE: case TPM_EO_SIGNED_LE: case TPM_EO_UNSIGNED_LE: case TPM_EO_BITSET: case TPM_EO_BITCLEAR: break; default: rc = TPM_RC_VALUE; *target = orig_target; // libtpms added } } return rc; } /* Table 20 - Definition of (UINT16) TPM_ST Constants */ TPM_RC TPM_ST_Unmarshal(TPM_ST *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; TPM_ST orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (*target) { case TPM_ST_RSP_COMMAND: case TPM_ST_NULL: case TPM_ST_NO_SESSIONS: case TPM_ST_SESSIONS: case TPM_ST_ATTEST_NV: case TPM_ST_ATTEST_COMMAND_AUDIT: case TPM_ST_ATTEST_SESSION_AUDIT: case TPM_ST_ATTEST_CERTIFY: case TPM_ST_ATTEST_QUOTE: case TPM_ST_ATTEST_TIME: case TPM_ST_ATTEST_CREATION: case TPM_ST_CREATION: case TPM_ST_VERIFIED: case TPM_ST_AUTH_SECRET: case TPM_ST_HASHCHECK: case TPM_ST_AUTH_SIGNED: break; default: rc = TPM_RC_VALUE; *target = orig_target; // libtpms added } } return rc; } /* Table 20 - Definition of (UINT16) TPM_SU Constants */ TPM_RC TPM_SU_Unmarshal(TPM_SU *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; TPM_SU orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (*target) { case TPM_SU_CLEAR: case TPM_SU_STATE: break; default: rc = TPM_RC_VALUE; *target = orig_target; // libtpms added } } return rc; } /* Table 21 - Definition of (UINT8) TPM_SE Constants */ TPM_RC TPM_SE_Unmarshal(TPM_SE *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; TPM_SE orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = UINT8_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (*target) { case TPM_SE_HMAC: case TPM_SE_POLICY: case TPM_SE_TRIAL: break; default: rc = TPM_RC_VALUE; *target = orig_target; // libtpms added } } return rc; } /* Table 22 - Definition of (UINT32) TPM_CAP Constants */ TPM_RC TPM_CAP_Unmarshal(TPM_CAP *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; TPM_CAP orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (*target) { case TPM_CAP_ALGS: case TPM_CAP_HANDLES: case TPM_CAP_COMMANDS: case TPM_CAP_PP_COMMANDS: case TPM_CAP_AUDIT_COMMANDS: case TPM_CAP_PCRS: case TPM_CAP_TPM_PROPERTIES: case TPM_CAP_PCR_PROPERTIES: case TPM_CAP_ECC_CURVES: case TPM_CAP_AUTH_POLICIES: case TPM_CAP_ACT: case TPM_CAP_VENDOR_PROPERTY: break; default: rc = TPM_RC_VALUE; *target = orig_target; // libtpms added } } return rc; } /* Table 24 - Definition of (UINT32) TPM_PT Constants */ TPM_RC TPM_PT_Unmarshal(TPM_HANDLE *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(target, buffer, size); } return rc; } /* Table 25 - Definition of (UINT32) TPM_PT_PCR Constants */ TPM_RC TPM_PT_PCR_Unmarshal(TPM_PT_PCR *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(target, buffer, size); } return rc; } /* Table 27 - Definition of Types for Handles */ TPM_RC TPM_HANDLE_Unmarshal(TPM_HANDLE *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(target, buffer, size); } return rc; } /* Table 31 - Definition of (UINT32) TPMA_ALGORITHM Bits */ TPM_RC TPMA_ALGORITHM_Unmarshal(TPMA_ALGORITHM *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; TPMA_ALGORITHM orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal((UINT32 *)target, buffer, size); /* libtpms changed */ } if (rc == TPM_RC_SUCCESS) { if (*target & TPMA_ALGORITHM_reserved) { rc = TPM_RC_RESERVED_BITS; *target = orig_target; // libtpms added } } return rc; } /* Table 32 - Definition of (UINT32) TPMA_OBJECT Bits */ TPM_RC TPMA_OBJECT_Unmarshal(TPMA_OBJECT *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; TPMA_OBJECT orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal((UINT32 *)target, buffer, size); /* libtpms changed */ } if (rc == TPM_RC_SUCCESS) { if (*target & TPMA_OBJECT_reserved) { rc = TPM_RC_RESERVED_BITS; *target = orig_target; // libtpms added } } return rc; } /* Table 33 - Definition of (UINT8) TPMA_SESSION Bits */ TPM_RC TPMA_SESSION_Unmarshal(TPMA_SESSION *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; TPMA_SESSION orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = UINT8_Unmarshal((UINT8 *)target, buffer, size); /* libtpms changed */ } if (rc == TPM_RC_SUCCESS) { if (*target & TPMA_SESSION_reserved) { rc = TPM_RC_RESERVED_BITS; *target = orig_target; // libtpms added } } return rc; } /* Table 34 - Definition of (UINT8) TPMA_LOCALITY Bits */ TPM_RC TPMA_LOCALITY_Unmarshal(TPMA_LOCALITY *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = UINT8_Unmarshal((UINT8 *)target, buffer, size); /* libtpms changed */ } return rc; } /* Table 38 - Definition of (TPM_CC) TPMA_CC Bits */ TPM_RC TPMA_CC_Unmarshal(TPMA_CC *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; TPMA_CC orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal((UINT32 *)target, buffer, size); /* libtpms changed */ } if (rc == TPM_RC_SUCCESS) { if (*target & TPMA_CC_reserved) { rc = TPM_RC_RESERVED_BITS; *target = orig_target; // libtpms added } } return rc; } /* Table 39 - Definition of (BYTE) TPMI_YES_NO Type */ TPM_RC TPMI_YES_NO_Unmarshal(TPMI_YES_NO *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_YES_NO orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = UINT8_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (*target) { case NO: case YES: break; default: rc = TPM_RC_VALUE; *target = orig_target; // libtpms added } } return rc; } /* Table 40 - Definition of (TPM_HANDLE) TPMI_DH_OBJECT Type */ TPM_RC TPMI_DH_OBJECT_Unmarshal(TPMI_DH_OBJECT *target, BYTE **buffer, INT32 *size, BOOL allowNull) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_DH_OBJECT orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_HANDLE_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { BOOL isNotTransient = (*target < TRANSIENT_FIRST) || (*target > TRANSIENT_LAST); BOOL isNotPersistent = (*target < PERSISTENT_FIRST) || (*target > PERSISTENT_LAST); BOOL isNotLegalNull = (*target != TPM_RH_NULL) || !allowNull; if (isNotTransient && isNotPersistent && isNotLegalNull) { rc = TPM_RC_VALUE; *target = orig_target; // libtpms added } } return rc; } /* Table 2:41 - Definition of TPMI_DH_PARENT Type (InterfaceTable()) */ TPM_RC TPMI_DH_PARENT_Unmarshal(TPMI_DH_PARENT *target, BYTE **buffer, INT32 *size, BOOL allowNull) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_DH_PARENT orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_HANDLE_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { BOOL isNotTransient = (*target < TRANSIENT_FIRST) || (*target > TRANSIENT_LAST); BOOL isNotPersistent = (*target < PERSISTENT_FIRST) || (*target > PERSISTENT_LAST); BOOL isNotOwner = *target != TPM_RH_OWNER; BOOL isNotPlatform = *target != TPM_RH_PLATFORM; BOOL isNotEndorsement = *target != TPM_RH_ENDORSEMENT; BOOL isNotLegalNull = (*target != TPM_RH_NULL) || !allowNull; if (isNotTransient && isNotPersistent && isNotOwner && isNotPlatform && isNotEndorsement && isNotLegalNull) { rc = TPM_RC_VALUE; *target = orig_target; // libtpms added } } return rc; } /* Table 41 - Definition of (TPM_HANDLE) TPMI_DH_PERSISTENT Type */ TPM_RC TPMI_DH_PERSISTENT_Unmarshal(TPMI_DH_PERSISTENT *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_DH_PERSISTENT orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_HANDLE_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { BOOL isNotPersistent = (*target < PERSISTENT_FIRST) || (*target > PERSISTENT_LAST); if (isNotPersistent) { rc = TPM_RC_VALUE; *target = orig_target; // libtpms added } } return rc; } /* Table 42 - Definition of (TPM_HANDLE) TPMI_DH_ENTITY Type */ TPM_RC TPMI_DH_ENTITY_Unmarshal(TPMI_DH_ENTITY *target, BYTE **buffer, INT32 *size, BOOL allowNull) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_DH_ENTITY orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_HANDLE_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { BOOL isNotOwner = *target != TPM_RH_OWNER; BOOL isNotEndorsement = *target != TPM_RH_ENDORSEMENT; BOOL isNotPlatform = *target != TPM_RH_PLATFORM; BOOL isNotLockout = *target != TPM_RH_LOCKOUT; BOOL isNotTransient = (*target < TRANSIENT_FIRST) || (*target > TRANSIENT_LAST); BOOL isNotPersistent = (*target < PERSISTENT_FIRST) || (*target > PERSISTENT_LAST); BOOL isNotNv = (*target < NV_INDEX_FIRST) || (*target > NV_INDEX_LAST); BOOL isNotPcr = (*target > PCR_LAST); BOOL isNotAuth = (*target < TPM_RH_AUTH_00) || (*target > TPM_RH_AUTH_FF); BOOL isNotLegalNull = (*target != TPM_RH_NULL) || !allowNull; if (isNotOwner && isNotEndorsement && isNotPlatform && isNotLockout && isNotTransient && isNotPersistent && isNotNv && isNotPcr && isNotAuth && isNotLegalNull) { rc = TPM_RC_VALUE; *target = orig_target; // libtpms added } } return rc; } /* Table 43 - Definition of (TPM_HANDLE) TPMI_DH_PCR Type */ TPM_RC TPMI_DH_PCR_Unmarshal(TPMI_DH_PCR *target, BYTE **buffer, INT32 *size, BOOL allowNull) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_DH_PCR orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_HANDLE_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { BOOL isNotPcr = (*target > PCR_LAST); BOOL isNotLegalNull = (*target != TPM_RH_NULL) || !allowNull; if (isNotPcr && isNotLegalNull) { rc = TPM_RC_VALUE; *target = orig_target; // libtpms added } } return rc; } /* Table 44 - Definition of (TPM_HANDLE) TPMI_SH_AUTH_SESSION Type */ TPM_RC TPMI_SH_AUTH_SESSION_Unmarshal(TPMI_SH_AUTH_SESSION *target, BYTE **buffer, INT32 *size, BOOL allowPwd) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_SH_AUTH_SESSION orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_HANDLE_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { BOOL isNotHmacSession = (*target < HMAC_SESSION_FIRST ) || (*target > HMAC_SESSION_LAST); BOOL isNotPolicySession = (*target < POLICY_SESSION_FIRST) || (*target > POLICY_SESSION_LAST); BOOL isNotLegalPwd = (*target != TPM_RS_PW) || !allowPwd; if (isNotHmacSession && isNotPolicySession && isNotLegalPwd) { rc = TPM_RC_VALUE; *target = orig_target; // libtpms added } } return rc; } /* Table 45 - Definition of (TPM_HANDLE) TPMI_SH_HMAC Type */ TPM_RC TPMI_SH_HMAC_Unmarshal(TPMI_SH_HMAC *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_SH_HMAC orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_HANDLE_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { BOOL isNotHmacSession = (*target < HMAC_SESSION_FIRST ) || (*target > HMAC_SESSION_LAST); if (isNotHmacSession) { rc = TPM_RC_VALUE; *target = orig_target; // libtpms added } } return rc; } /* Table 46 - Definition of (TPM_HANDLE) TPMI_SH_POLICY Type */ TPM_RC TPMI_SH_POLICY_Unmarshal(TPMI_SH_POLICY *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_SH_POLICY orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_HANDLE_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { BOOL isNotPolicySession = (*target < POLICY_SESSION_FIRST) || (*target > POLICY_SESSION_LAST); if (isNotPolicySession) { rc = TPM_RC_VALUE; *target = orig_target; // libtpms added } } return rc; } /* Table 47 - Definition of (TPM_HANDLE) TPMI_DH_CONTEXT Type */ TPM_RC TPMI_DH_CONTEXT_Unmarshal(TPMI_DH_CONTEXT *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_DH_CONTEXT orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_HANDLE_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { BOOL isNotHmacSession = (*target < HMAC_SESSION_FIRST ) || (*target > HMAC_SESSION_LAST); BOOL isNotPolicySession = (*target < POLICY_SESSION_FIRST) || (*target > POLICY_SESSION_LAST); BOOL isNotTransient = (*target < TRANSIENT_FIRST) || (*target > TRANSIENT_LAST); if (isNotHmacSession && isNotPolicySession && isNotTransient) { rc = TPM_RC_VALUE; *target = orig_target; // libtpms added } } return rc; } /* Table 49 - Definition of (TPM_HANDLE) TPMI_DH_SAVED Type */ TPM_RC TPMI_DH_SAVED_Unmarshal(TPMI_DH_SAVED *target, BYTE **buffer, INT32 *size, BOOL allowNull) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_DH_SAVED orig_target = *target; // libtpms added allowNull = allowNull; if (rc == TPM_RC_SUCCESS) { rc = TPM_HANDLE_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { BOOL isNotHmacSession = (*target < HMAC_SESSION_FIRST ) || (*target > HMAC_SESSION_LAST); BOOL isNotPolicySession = (*target < POLICY_SESSION_FIRST) || (*target > POLICY_SESSION_LAST); BOOL isNotTransientObject = (*target != 0x80000000); BOOL isNotSequenceObject = (*target != 0x80000001); BOOL isNotTransientStClear = (*target != 0x80000002); if (isNotHmacSession && isNotPolicySession && isNotTransientObject && isNotSequenceObject && isNotTransientStClear) { rc = TPM_RC_VALUE; *target = orig_target; // libtpms added } } return rc; } /* Table 48 - Definition of (TPM_HANDLE) TPMI_RH_HIERARCHY Type */ TPM_RC TPMI_RH_HIERARCHY_Unmarshal(TPMI_RH_HIERARCHY *target, BYTE **buffer, INT32 *size, BOOL allowNull) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_RH_HIERARCHY orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_HANDLE_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (*target) { case TPM_RH_OWNER: case TPM_RH_PLATFORM: case TPM_RH_ENDORSEMENT: break; case TPM_RH_NULL: if (allowNull) { break; } default: rc = TPM_RC_VALUE; *target = orig_target; // libtpms added } } return rc; } /* Table 49 - Definition of (TPM_HANDLE) TPMI_RH_ENABLES Type */ TPM_RC TPMI_RH_ENABLES_Unmarshal(TPMI_RH_ENABLES *target, BYTE **buffer, INT32 *size, BOOL allowNull) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_RH_ENABLES orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_HANDLE_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (*target) { case TPM_RH_OWNER: case TPM_RH_PLATFORM: case TPM_RH_ENDORSEMENT: case TPM_RH_PLATFORM_NV: break; case TPM_RH_NULL: if (allowNull) { break; } default: rc = TPM_RC_VALUE; *target = orig_target; // libtpms added } } return rc; } /* Table 50 - Definition of (TPM_HANDLE) TPMI_RH_HIERARCHY_AUTH Type */ TPM_RC TPMI_RH_HIERARCHY_AUTH_Unmarshal(TPMI_RH_HIERARCHY_AUTH *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_RH_HIERARCHY_AUTH orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_HANDLE_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (*target) { case TPM_RH_OWNER: case TPM_RH_PLATFORM: case TPM_RH_ENDORSEMENT: case TPM_RH_LOCKOUT: break; default: rc = TPM_RC_VALUE; *target = orig_target; // libtpms added } } return rc; } /* Table 50 - Definition of (TPM_HANDLE) TPMI_RH_HIERARCHY_POLICY Type */ TPM_RC TPMI_RH_HIERARCHY_POLICY_Unmarshal(TPMI_RH_HIERARCHY_POLICY *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_RH_HIERARCHY_POLICY orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_HANDLE_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (*target) { case TPM_RH_OWNER: case TPM_RH_PLATFORM: case TPM_RH_ENDORSEMENT: case TPM_RH_LOCKOUT: break; default: { BOOL isNotHP = (*target < TPM_RH_ACT_0) || (*target > TPM_RH_ACT_F); if (isNotHP) { rc = TPM_RC_VALUE; *target = orig_target; // libtpms added } } } } return rc; } /* Table 51 - Definition of (TPM_HANDLE) TPMI_RH_PLATFORM Type */ TPM_RC TPMI_RH_PLATFORM_Unmarshal(TPMI_RH_PLATFORM *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_RH_PLATFORM orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_HANDLE_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (*target) { case TPM_RH_PLATFORM: break; default: rc = TPM_RC_VALUE; *target = orig_target; // libtpms added } } return rc; } /* Table 53 - Definition of (TPM_HANDLE) TPMI_RH_ENDORSEMENT Type */ TPM_RC TPMI_RH_ENDORSEMENT_Unmarshal(TPMI_RH_ENDORSEMENT *target, BYTE **buffer, INT32 *size, BOOL allowNull) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_RH_ENDORSEMENT orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_HANDLE_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (*target) { case TPM_RH_ENDORSEMENT: break; case TPM_RH_NULL: if (allowNull) { break; } default: rc = TPM_RC_VALUE; *target = orig_target; // libtpms added } } return rc; } /* Table 54 - Definition of (TPM_HANDLE) TPMI_RH_PROVISION Type */ TPM_RC TPMI_RH_PROVISION_Unmarshal(TPMI_RH_PROVISION *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_RH_PROVISION orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_HANDLE_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (*target) { case TPM_RH_OWNER: case TPM_RH_PLATFORM: break; default: rc = TPM_RC_VALUE; *target = orig_target; // libtpms added } } return rc; } /* Table 55 - Definition of (TPM_HANDLE) TPMI_RH_CLEAR Type */ TPM_RC TPMI_RH_CLEAR_Unmarshal(TPMI_RH_CLEAR *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_RH_CLEAR orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_HANDLE_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (*target) { case TPM_RH_LOCKOUT: case TPM_RH_PLATFORM: break; default: rc = TPM_RC_VALUE; *target = orig_target; // libtpms added } } return rc; } /* Table 56 - Definition of (TPM_HANDLE) TPMI_RH_NV_AUTH Type */ TPM_RC TPMI_RH_NV_AUTH_Unmarshal(TPMI_RH_NV_AUTH *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_RH_NV_AUTH orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_HANDLE_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (*target) { case TPM_RH_OWNER: case TPM_RH_PLATFORM: break; default: { BOOL isNotNv = (*target < NV_INDEX_FIRST) || (*target > NV_INDEX_LAST); if (isNotNv) { rc = TPM_RC_VALUE; *target = orig_target; // libtpms added } } } } return rc; } /* Table 57 - Definition of (TPM_HANDLE) TPMI_RH_LOCKOUT Type */ TPM_RC TPMI_RH_LOCKOUT_Unmarshal(TPMI_RH_LOCKOUT *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_RH_LOCKOUT orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_HANDLE_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (*target) { case TPM_RH_LOCKOUT: break; default: rc = TPM_RC_VALUE; *target = orig_target; // libtpms added } } return rc; } /* Table 58 - Definition of (TPM_HANDLE) TPMI_RH_NV_INDEX Type */ TPM_RC TPMI_RH_NV_INDEX_Unmarshal(TPMI_RH_NV_INDEX *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_RH_NV_INDEX orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_HANDLE_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { BOOL isNotNv = (*target < NV_INDEX_FIRST) || (*target > NV_INDEX_LAST); if (isNotNv) { rc = TPM_RC_VALUE; *target = orig_target; // libtpms added } } return rc; } /* Table 64 - Definition of (TPM_HANDLE) TPMI_RH_AC Type */ TPM_RC TPMI_RH_AC_Unmarshal(TPMI_RH_AC *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_RH_AC orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_HANDLE_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { BOOL isNotAC = (*target < AC_FIRST) || (*target > AC_LAST); if (isNotAC) { rc = TPM_RC_VALUE; *target = orig_target; // libtpms added } } return rc; } /* Table 65 - Definition of (TPM_HANDLE) TPMI_RH_ACT Type */ TPM_RC TPMI_RH_ACT_Unmarshal( TPMI_RH_ACT *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_RH_ACT orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_HANDLE_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { BOOL isNotACT = (*target < TPM_RH_ACT_0) || (*target > TPM_RH_ACT_F); if (isNotACT) { rc = TPM_RC_VALUE; *target = orig_target; // libtpms added } } return rc; } /* Table 59 - Definition of (TPM_ALG_ID) TPMI_ALG_HASH Type */ TPM_RC TPMI_ALG_HASH_Unmarshal(TPMI_ALG_HASH *target, BYTE **buffer, INT32 *size, BOOL allowNull) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_ALG_HASH orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_ALG_ID_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (*target) { #if ALG_SHA1 case TPM_ALG_SHA1: #endif #if ALG_SHA256 case TPM_ALG_SHA256: #endif #if ALG_SHA384 case TPM_ALG_SHA384: #endif #if ALG_SHA512 case TPM_ALG_SHA512: #endif #if ALG_SM3_256 case TPM_ALG_SM3_256: #endif break; case TPM_ALG_NULL: if (allowNull) { break; } default: rc = TPM_RC_HASH; *target = orig_target; // libtpms added } } return rc; } /* Table 61 - Definition of (TPM_ALG_ID) TPMI_ALG_SYM Type */ TPM_RC TPMI_ALG_SYM_Unmarshal(TPMI_ALG_SYM *target, BYTE **buffer, INT32 *size, BOOL allowNull) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_ALG_SYM orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_ALG_ID_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (*target) { #if ALG_AES case TPM_ALG_AES: #endif #if ALG_SM4 case TPM_ALG_SM4: #endif #if ALG_CAMELLIA case TPM_ALG_CAMELLIA: #endif #if ALG_TDES // libtpms added begin case TPM_ALG_TDES: #endif // libtpms added end #if ALG_XOR case TPM_ALG_XOR: #endif break; case TPM_ALG_NULL: if (allowNull) { break; } default: rc = TPM_RC_SYMMETRIC; *target = orig_target; // libtpms added } } return rc; } /* Table 62 - Definition of (TPM_ALG_ID) TPMI_ALG_SYM_OBJECT Type */ TPM_RC TPMI_ALG_SYM_OBJECT_Unmarshal(TPMI_ALG_SYM_OBJECT *target, BYTE **buffer, INT32 *size, BOOL allowNull) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_ALG_SYM_OBJECT orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_ALG_ID_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (*target) { #if ALG_AES case TPM_ALG_AES: #endif #if ALG_SM4 case TPM_ALG_SM4: #endif #if ALG_CAMELLIA case TPM_ALG_CAMELLIA: #endif #if ALG_TDES // libtpms added begin case TPM_ALG_TDES: #endif // iibtpms added end break; case TPM_ALG_NULL: if (allowNull) { break; } default: rc = TPM_RC_SYMMETRIC; *target = orig_target; // libtpms added } } return rc; } /* Table 63 - Definition of (TPM_ALG_ID) TPMI_ALG_SYM_MODE Type */ TPM_RC TPMI_ALG_SYM_MODE_Unmarshal(TPMI_ALG_SYM_MODE *target, BYTE **buffer, INT32 *size, BOOL allowNull) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_ALG_SYM_MODE orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_ALG_ID_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (*target) { #if ALG_CTR case TPM_ALG_CTR: #endif #if ALG_OFB case TPM_ALG_OFB: #endif #if ALG_CBC case TPM_ALG_CBC: #endif #if ALG_CFB case TPM_ALG_CFB: #endif #if ALG_ECB case TPM_ALG_ECB: #endif #if ALG_CMAC case TPM_ALG_CMAC: #endif break; case TPM_ALG_NULL: if (allowNull) { break; } default: rc = TPM_RC_MODE; *target = orig_target; // libtpms added } } return rc; } /* Table 64 - Definition of (TPM_ALG_ID) TPMI_ALG_KDF Type */ TPM_RC TPMI_ALG_KDF_Unmarshal(TPMI_ALG_KDF *target, BYTE **buffer, INT32 *size, BOOL allowNull) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_ALG_KDF orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_ALG_ID_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (*target) { #if ALG_MGF1 case TPM_ALG_MGF1: #endif #if ALG_KDF1_SP800_56A case TPM_ALG_KDF1_SP800_56A: #endif #if ALG_KDF2 case TPM_ALG_KDF2: #endif #if ALG_KDF1_SP800_108 case TPM_ALG_KDF1_SP800_108: #endif break; case TPM_ALG_NULL: if (allowNull) { break; } default: rc = TPM_RC_KDF; *target = orig_target; // libtpms added } } return rc; } /* Table 65 - Definition of (TPM_ALG_ID) TPMI_ALG_SIG_SCHEME Type */ TPM_RC TPMI_ALG_SIG_SCHEME_Unmarshal(TPMI_ALG_SIG_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_ALG_SIG_SCHEME orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_ALG_ID_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (*target) { #if ALG_HMAC case TPM_ALG_HMAC: #endif #if ALG_RSASSA case TPM_ALG_RSASSA: #endif #if ALG_RSAPSS case TPM_ALG_RSAPSS: #endif #if ALG_ECDSA case TPM_ALG_ECDSA: #endif #if ALG_ECDAA case TPM_ALG_ECDAA: #endif #if ALG_SM2 case TPM_ALG_SM2: #endif #if ALG_ECSCHNORR case TPM_ALG_ECSCHNORR: #endif break; case TPM_ALG_NULL: if (allowNull) { break; } default: rc = TPM_RC_SCHEME; *target = orig_target; // libtpms added } } return rc; } /* Table 66 - Definition of (TPM_ALG_ID) TPMI_ECC_KEY_EXCHANGE Type */ TPM_RC TPMI_ECC_KEY_EXCHANGE_Unmarshal(TPMI_ECC_KEY_EXCHANGE *target, BYTE **buffer, INT32 *size, BOOL allowNull) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_ECC_KEY_EXCHANGE orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_ALG_ID_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (*target) { #if ALG_ECDH case TPM_ALG_ECDH: #endif #if ALG_ECMQV case TPM_ALG_ECMQV: #endif #if ALG_SM2 case TPM_ALG_SM2: #endif break; case TPM_ALG_NULL: if (allowNull) { break; } default: rc = TPM_RC_SCHEME; *target = orig_target; // libtpms added } } return rc; } /* Table 67 - Definition of (TPM_ST) TPMI_ST_COMMAND_TAG Type */ TPM_RC TPMI_ST_COMMAND_TAG_Unmarshal(TPMI_ST_COMMAND_TAG *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_ST_COMMAND_TAG orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_ST_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (*target) { case TPM_ST_NO_SESSIONS: case TPM_ST_SESSIONS: break; default: rc = TPM_RC_BAD_TAG; *target = orig_target; // libtpms added } } return rc; } /* Table 70 TPMI_ALG_MAC_SCHEME */ TPM_RC TPMI_ALG_MAC_SCHEME_Unmarshal(TPMI_ALG_MAC_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_ALG_MAC_SCHEME orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_ALG_ID_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (*target) { #if ALG_SHA1 case TPM_ALG_SHA1: #endif #if ALG_SHA256 case TPM_ALG_SHA256: #endif #if ALG_SHA384 case TPM_ALG_SHA384: #endif #if ALG_SHA512 case TPM_ALG_SHA512: #endif #if ALG_SM3_256 case TPM_ALG_SM3_256: #endif #if ALG_CMAC case TPM_ALG_CMAC: #endif break; case TPM_ALG_NULL: if (allowNull) { break; } default: rc = TPM_RC_SYMMETRIC; *target = orig_target; // libtpms added } } return rc; } /* Table 70 TPMI_ALG_CIPHER_MODE */ TPM_RC TPMI_ALG_CIPHER_MODE_Unmarshal(TPMI_ALG_CIPHER_MODE*target, BYTE **buffer, INT32 *size, BOOL allowNull) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_ALG_CIPHER_MODE orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_ALG_ID_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (*target) { #if ALG_CTR case TPM_ALG_CTR: #endif #if ALG_OFB case TPM_ALG_OFB: #endif #if ALG_CBC case TPM_ALG_CBC: #endif #if ALG_CFB case TPM_ALG_CFB: #endif #if ALG_ECB case TPM_ALG_ECB: #endif break; case TPM_ALG_NULL: if (allowNull) { break; } default: rc = TPM_RC_MODE; *target = orig_target; // libtpms added } } return rc; } /* Table 68 - Definition of TPMS_EMPTY Structure */ TPM_RC TPMS_EMPTY_Unmarshal(TPMS_EMPTY *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; target = target; buffer = buffer; size = size; return rc; } /* Table 70 - Definition of TPMU_HA Union */ TPM_RC TPMU_HA_Unmarshal(TPMU_HA *target, BYTE **buffer, INT32 *size, UINT32 selector) { TPM_RC rc = TPM_RC_SUCCESS; switch (selector) { #if ALG_SHA1 case TPM_ALG_SHA1: rc = Array_Unmarshal(target->sha1, SHA1_DIGEST_SIZE, buffer, size); break; #endif #if ALG_SHA256 case TPM_ALG_SHA256: rc = Array_Unmarshal(target->sha256, SHA256_DIGEST_SIZE, buffer, size); break; #endif #if ALG_SHA384 case TPM_ALG_SHA384: rc = Array_Unmarshal(target->sha384, SHA384_DIGEST_SIZE, buffer, size); break; #endif #if ALG_SHA512 case TPM_ALG_SHA512: rc = Array_Unmarshal(target->sha512, SHA512_DIGEST_SIZE, buffer, size); break; #endif #if ALG_SM3_256 case TPM_ALG_SM3_256: rc = Array_Unmarshal(target->sm3_256, SM3_256_DIGEST_SIZE, buffer, size); break; #endif case TPM_ALG_NULL: break; default: rc = TPM_RC_SELECTOR; } return rc; } /* Table 71 - Definition of TPMT_HA Structure */ TPM_RC TPMT_HA_Unmarshal(TPMT_HA *target, BYTE **buffer, INT32 *size, BOOL allowNull) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMI_ALG_HASH_Unmarshal(&target->hashAlg, buffer, size, allowNull); } if (rc == TPM_RC_SUCCESS) { rc = TPMU_HA_Unmarshal(&target->digest, buffer, size, target->hashAlg); } return rc; } /* Table 72 - Definition of TPM2B_DIGEST Structure */ TPM_RC TPM2B_DIGEST_Unmarshal(TPM2B_DIGEST *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPM2B_Unmarshal(&target->b, sizeof(TPMU_HA), buffer, size); } return rc; } /* Table 73 - Definition of TPM2B_DATA Structure */ TPM_RC TPM2B_DATA_Unmarshal(TPM2B_DATA *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPM2B_Unmarshal(&target->b, sizeof(TPMT_HA), buffer, size); } return rc; } /* Table 74 - Definition of Types for TPM2B_NONCE */ TPM_RC TPM2B_NONCE_Unmarshal(TPM2B_NONCE *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPM2B_DIGEST_Unmarshal(target, buffer, size); } return rc; } /* Table 75 - Definition of Types for TPM2B_AUTH */ TPM_RC TPM2B_AUTH_Unmarshal(TPM2B_AUTH *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPM2B_DIGEST_Unmarshal(target, buffer, size); } return rc; } /* Table 77 - Definition of TPM2B_EVENT Structure */ TPM_RC TPM2B_EVENT_Unmarshal(TPM2B_EVENT *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPM2B_Unmarshal(&target->b, sizeof(TPM2B_EVENT) - sizeof(UINT16), buffer, size); } return rc; } /* Table 78 - Definition of TPM2B_MAX_BUFFER Structure */ TPM_RC TPM2B_MAX_BUFFER_Unmarshal(TPM2B_MAX_BUFFER *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPM2B_Unmarshal(&target->b, MAX_DIGEST_BUFFER, buffer, size); } return rc; } /* Table 79 - Definition of TPM2B_MAX_NV_BUFFER Structure */ TPM_RC TPM2B_MAX_NV_BUFFER_Unmarshal(TPM2B_MAX_NV_BUFFER *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPM2B_Unmarshal(&target->b, MAX_NV_BUFFER_SIZE, buffer, size); } return rc; } /* Table 80 - Definition of TPM2B_TIMEOUT Structure */ TPM_RC TPM2B_TIMEOUT_Unmarshal(TPM2B_TIMEOUT *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPM2B_Unmarshal(&target->b, sizeof(target->t.buffer), buffer, size); } return rc; } /* Table 81 - Definition of TPM2B_IV Structure */ TPM_RC TPM2B_IV_Unmarshal(TPM2B_IV *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPM2B_Unmarshal(&target->b, MAX_SYM_BLOCK_SIZE, buffer, size); } return rc; } /* Table 83 - Definition of TPM2B_NAME Structure */ TPM_RC TPM2B_NAME_Unmarshal(TPM2B_NAME *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPM2B_Unmarshal(&target->b, sizeof(TPMU_NAME), buffer, size); } return rc; } /* Table 85 - Definition of TPMS_PCR_SELECTION Structure */ TPM_RC TPMS_PCR_SELECTION_Unmarshal(TPMS_PCR_SELECTION *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMI_ALG_HASH_Unmarshal(&target->hash, buffer, size, NO); } if (rc == TPM_RC_SUCCESS) { rc = UINT8_Unmarshal(&target->sizeofSelect, buffer, size); } if (rc == TPM_RC_SUCCESS) { if ((target->sizeofSelect < PCR_SELECT_MIN) || (target->sizeofSelect > PCR_SELECT_MAX)) { rc = TPM_RC_VALUE; target->sizeofSelect = 0; // libtpms added } } if (rc == TPM_RC_SUCCESS) { rc = Array_Unmarshal(target->pcrSelect, target->sizeofSelect, buffer, size); } return rc; } /* Table 88 - Definition of TPMT_TK_CREATION Structure */ TPM_RC TPMT_TK_CREATION_Unmarshal(TPMT_TK_CREATION *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; TPM_ST orig_tag = target->tag; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_ST_Unmarshal(&target->tag, buffer, size); } if (rc == TPM_RC_SUCCESS) { if (target->tag != TPM_ST_CREATION) { rc = TPM_RC_TAG; target->tag = orig_tag; // libtpms added } } if (rc == TPM_RC_SUCCESS) { rc = TPMI_RH_HIERARCHY_Unmarshal(&target->hierarchy, buffer, size, YES); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_DIGEST_Unmarshal(&target->digest, buffer, size); } return rc; } /* Table 89 - Definition of TPMT_TK_VERIFIED Structure */ TPM_RC TPMT_TK_VERIFIED_Unmarshal(TPMT_TK_VERIFIED *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; TPM_ST orig_tag = target->tag; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_ST_Unmarshal(&target->tag, buffer, size); } if (rc == TPM_RC_SUCCESS) { if (target->tag != TPM_ST_VERIFIED) { rc = TPM_RC_TAG; target->tag = orig_tag; // libtpms added } } if (rc == TPM_RC_SUCCESS) { rc = TPMI_RH_HIERARCHY_Unmarshal(&target->hierarchy, buffer, size, YES); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_DIGEST_Unmarshal(&target->digest, buffer, size); } return rc; } /* Table 90 - Definition of TPMT_TK_AUTH Structure */ TPM_RC TPMT_TK_AUTH_Unmarshal(TPMT_TK_AUTH *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; TPM_ST orig_tag = target->tag; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_ST_Unmarshal(&target->tag, buffer, size); } if (rc == TPM_RC_SUCCESS) { if ((target->tag != TPM_ST_AUTH_SIGNED) && (target->tag != TPM_ST_AUTH_SECRET)) { rc = TPM_RC_TAG; target->tag = orig_tag; // libtpms added } } if (rc == TPM_RC_SUCCESS) { rc = TPMI_RH_HIERARCHY_Unmarshal(&target->hierarchy, buffer, size, YES); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_DIGEST_Unmarshal(&target->digest, buffer, size); } return rc; } /* Table 91 - Definition of TPMT_TK_HASHCHECK Structure */ TPM_RC TPMT_TK_HASHCHECK_Unmarshal(TPMT_TK_HASHCHECK *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; TPM_ST orig_tag = target->tag; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_ST_Unmarshal(&target->tag, buffer, size); } if (rc == TPM_RC_SUCCESS) { if (target->tag != TPM_ST_HASHCHECK) { rc = TPM_RC_TAG; target->tag = orig_tag; // libtpms added } } if (rc == TPM_RC_SUCCESS) { rc = TPMI_RH_HIERARCHY_Unmarshal(&target->hierarchy, buffer, size, YES); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_DIGEST_Unmarshal(&target->digest, buffer, size); } return rc; } /* Table 92 - Definition of TPMS_ALG_PROPERTY Structure */ #if 0 // libtpms added TPM_RC TPMS_ALG_PROPERTY_Unmarshal(TPMS_ALG_PROPERTY *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPM_ALG_ID_Unmarshal(&target->alg, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPMA_ALGORITHM_Unmarshal(&target->algProperties, buffer, size); } return rc; } #endif // libtpms added /* Table 93 - Definition of TPMS_TAGGED_PROPERTY Structure */ #if 0 // libtpms added TPM_RC TPMS_TAGGED_PROPERTY_Unmarshal(TPMS_TAGGED_PROPERTY *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPM_PT_Unmarshal(&target->property, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&target->value, buffer, size); } return rc; } #endif // libtpms added /* Table 94 - Definition of TPMS_TAGGED_PCR_SELECT Structure */ #if 0 // libtpms added TPM_RC TPMS_TAGGED_PCR_SELECT_Unmarshal(TPMS_TAGGED_PCR_SELECT *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPM_PT_PCR_Unmarshal(&target->tag, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT8_Unmarshal(&target->sizeofSelect, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = Array_Unmarshal(target->pcrSelect, target->sizeofSelect, buffer, size); } return rc; } #endif // libtpms added /* Table 95 - Definition of TPML_CC Structure */ TPM_RC TPML_CC_Unmarshal(TPML_CC *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; UINT32 i; if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&target->count, buffer, size); } if (rc == TPM_RC_SUCCESS) { if (target->count > MAX_CAP_CC) { rc = TPM_RC_SIZE; target->count = 0; // libtpms added } } for (i = 0 ; (rc == TPM_RC_SUCCESS) && (i < target->count) ; i++) { rc = TPM_CC_Unmarshal(&target->commandCodes[i], buffer, size); } return rc; } /* Table 2:96 - Definition of TPMS_TAGGED_POLICY Structure (StructuresTable()) */ #if 0 // libtpms added TPM_RC TPMS_TAGGED_POLICY_Unmarshal(TPMS_TAGGED_POLICY *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPM_HANDLE_Unmarshal(&target->handle, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPMT_HA_Unmarshal(&target->policyHash, buffer, size, NO); } return rc; } #endif // libtpms added /* Table 96 - Definition of TPML_CCA Structure */ #if 0 // libtpms added TPM_RC TPML_CCA_Unmarshal(TPML_CCA *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; UINT32 i; if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&target->count, buffer, size); } if (rc == TPM_RC_SUCCESS) { if (target->count > MAX_CAP_CC) { rc = TPM_RC_SIZE; target->count = 0; // libtpms added } } for (i = 0 ; (rc == TPM_RC_SUCCESS) && (i < target->count) ; i++) { rc = TPMA_CC_Unmarshal(&target->commandAttributes[i], buffer, size); } return rc; } #endif // libtpms added /* Table 97 - Definition of TPML_ALG Structure */ TPM_RC TPML_ALG_Unmarshal(TPML_ALG *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; UINT32 i; if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&target->count, buffer, size); } if (rc == TPM_RC_SUCCESS) { if (target->count > MAX_ALG_LIST_SIZE) { rc = TPM_RC_SIZE; target->count = 0; // libtpms added } } for (i = 0 ; (rc == TPM_RC_SUCCESS) && (i < target->count) ; i++) { rc = TPM_ALG_ID_Unmarshal(&target->algorithms[i], buffer, size); } return rc; } /* Table 98 - Definition of TPML_HANDLE Structure */ #if 0 // libtpms added TPM_RC TPML_HANDLE_Unmarshal(TPML_HANDLE *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; UINT32 i; if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&target->count, buffer, size); } if (rc == TPM_RC_SUCCESS) { if (target->count > MAX_CAP_HANDLES) { rc = TPM_RC_SIZE; target->count = 0; // libtpms added } } for (i = 0 ; (rc == TPM_RC_SUCCESS) && (i < target->count) ; i++) { rc = TPM_HANDLE_Unmarshal(&target->handle[i], buffer, size); } return rc; } #endif // libtpms added /* Table 99 - Definition of TPML_DIGEST Structure */ /* PolicyOr has a restriction of at least a count of two. This function is also used to unmarshal PCR_Read, where a count of one is permitted. */ TPM_RC TPML_DIGEST_Unmarshal(TPML_DIGEST *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; UINT32 i; if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&target->count, buffer, size); } if (rc == TPM_RC_SUCCESS) { /* TPM side is hard coded to 2 minimum */ if (target->count < 2) { rc = TPM_RC_SIZE; target->count = 0; // libtpms added } } if (rc == TPM_RC_SUCCESS) { if (target->count > 8) { rc = TPM_RC_SIZE; target->count = 0; // libtpms added } } for (i = 0 ; (rc == TPM_RC_SUCCESS) && (i < target->count) ; i++) { rc = TPM2B_DIGEST_Unmarshal(&target->digests[i], buffer, size); } return rc; } /* Table 100 - Definition of TPML_DIGEST_VALUES Structure */ TPM_RC TPML_DIGEST_VALUES_Unmarshal(TPML_DIGEST_VALUES *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; UINT32 i; if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&target->count, buffer, size); } if (rc == TPM_RC_SUCCESS) { if (target->count > HASH_COUNT) { rc = TPM_RC_SIZE; target->count = 0; // libtpms added } } for (i = 0 ; (rc == TPM_RC_SUCCESS) && (i < target->count) ; i++) { rc = TPMT_HA_Unmarshal(&target->digests[i], buffer, size, NO); } return rc; } /* Table 102 - Definition of TPML_PCR_SELECTION Structure */ TPM_RC TPML_PCR_SELECTION_Unmarshal(TPML_PCR_SELECTION *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; UINT32 i; if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&target->count, buffer, size); } if (rc == TPM_RC_SUCCESS) { if (target->count > HASH_COUNT) { rc = TPM_RC_SIZE; target->count = 0; // libtpms added } } for (i = 0 ; (rc == TPM_RC_SUCCESS) && (i < target->count) ; i++) { rc = TPMS_PCR_SELECTION_Unmarshal(&target->pcrSelections[i], buffer, size); } return rc; } #if 0 /* Table 103 - Definition of TPML_ALG_PROPERTY Structure */ TPM_RC TPML_ALG_PROPERTY_Unmarshal(TPML_ALG_PROPERTY *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; UINT32 i; if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&target->count, buffer, size); } if (rc == TPM_RC_SUCCESS) { if (target->count > MAX_CAP_ALGS) { rc = TPM_RC_SIZE; target->count = 0; // libtpms added } } for (i = 0 ; (rc == TPM_RC_SUCCESS) && (i < target->count) ; i++) { rc = TPMS_ALG_PROPERTY_Unmarshal(&target->algProperties[i], buffer, size); } return rc; } /* Table 104 - Definition of TPML_TAGGED_TPM_PROPERTY Structure */ TPM_RC TPML_TAGGED_TPM_PROPERTY_Unmarshal(TPML_TAGGED_TPM_PROPERTY *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; UINT32 i; if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&target->count, buffer, size); } if (rc == TPM_RC_SUCCESS) { if (target->count > MAX_TPM_PROPERTIES) { rc = TPM_RC_SIZE; target->count = 0; // libtpms added } } for (i = 0 ; (rc == TPM_RC_SUCCESS) && (i < target->count) ; i++) { rc = TPMS_TAGGED_PROPERTY_Unmarshal(&target->tpmProperty[i], buffer, size); } return rc; } /* Table 105 - Definition of TPML_TAGGED_PCR_PROPERTY Structure */ TPM_RC TPML_TAGGED_PCR_PROPERTY_Unmarshal(TPML_TAGGED_PCR_PROPERTY *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; UINT32 i; if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&target->count, buffer, size); } if (rc == TPM_RC_SUCCESS) { if (target->count > MAX_PCR_PROPERTIES) { rc = TPM_RC_SIZE; target->count = 0; // libtpms added } } for (i = 0 ; (rc == TPM_RC_SUCCESS) && (i < target->count) ; i++) { rc = TPMS_TAGGED_PCR_SELECT_Unmarshal(&target->pcrProperty[i], buffer, size); } return rc; } /* Table 106 - Definition of {ECC} TPML_ECC_CURVE Structure */ TPM_RC TPML_ECC_CURVE_Unmarshal(TPML_ECC_CURVE *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; UINT32 i; if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&target->count, buffer, size); } if (rc == TPM_RC_SUCCESS) { if (target->count > MAX_ECC_CURVES) { rc = TPM_RC_SIZE; target->count = 0; // libtpms added } } for (i = 0 ; (rc == TPM_RC_SUCCESS) && (i < target->count) ; i++) { rc = TPM_ECC_CURVE_Unmarshal(&target->eccCurves[i], buffer, size); } return rc; } /* Table 2:109 - Definition of TPML_TAGGED_POLICY Structure (StructuresTable()) */ TPM_RC TPML_TAGGED_POLICY_Unmarshal(TPML_TAGGED_POLICY *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; UINT32 i; if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&target->count, buffer, size); } if (rc == TPM_RC_SUCCESS) { if (target->count > MAX_TAGGED_POLICIES) { rc = TPM_RC_SIZE; target->count = 0; // libtpms added } } for (i = 0 ; (rc == TPM_RC_SUCCESS) && (i < target->count) ; i++) { rc = TPMS_TAGGED_POLICY_Unmarshal(&target->policies[i], buffer, size); } return rc; } /* Table 2:110 - Definition of TPMU_CAPABILITIES Union (StructuresTable()) */ TPM_RC TPMU_CAPABILITIES_Unmarshal(TPMU_CAPABILITIES *target, BYTE **buffer, INT32 *size, UINT32 selector) { TPM_RC rc = TPM_RC_SUCCESS; switch (selector) { case TPM_CAP_ALGS: rc = TPML_ALG_PROPERTY_Unmarshal(&target->algorithms, buffer, size); break; case TPM_CAP_HANDLES: rc = TPML_HANDLE_Unmarshal(&target->handles, buffer, size); break; case TPM_CAP_COMMANDS: rc = TPML_CCA_Unmarshal(&target->command, buffer, size); break; case TPM_CAP_PP_COMMANDS: rc = TPML_CC_Unmarshal(&target->ppCommands, buffer, size); break; case TPM_CAP_AUDIT_COMMANDS: rc = TPML_CC_Unmarshal(&target->auditCommands, buffer, size); break; case TPM_CAP_PCRS: rc = TPML_PCR_SELECTION_Unmarshal(&target->assignedPCR, buffer, size); break; case TPM_CAP_TPM_PROPERTIES: rc = TPML_TAGGED_TPM_PROPERTY_Unmarshal(&target->tpmProperties, buffer, size); break; case TPM_CAP_PCR_PROPERTIES: rc = TPML_TAGGED_PCR_PROPERTY_Unmarshal(&target->pcrProperties, buffer, size); break; case TPM_CAP_ECC_CURVES: rc = TPML_ECC_CURVE_Unmarshal(&target->eccCurves, buffer, size); break; case TPM_CAP_AUTH_POLICIES: rc = TPML_TAGGED_POLICY_Unmarshal(&target->authPolicies, buffer, size); break; default: rc = TPM_RC_SELECTOR; } return rc; } /* Table 2:111 - Definition of TPMS_CAPABILITY_DATA Structure (StructuresTable()) */ TPM_RC TPMS_CAPABILITY_DATA_Unmarshal(TPMS_CAPABILITY_DATA *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPM_CAP_Unmarshal(&target->capability, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPMU_CAPABILITIES_Unmarshal(&target->data, buffer, size, target->capability); } return rc; } /* Table 109 - Definition of TPMS_CLOCK_INFO Structure */ TPM_RC TPMS_CLOCK_INFO_Unmarshal(TPMS_CLOCK_INFO *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = UINT64_Unmarshal(&target->clock, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&target->resetCount, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&target->restartCount, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPMI_YES_NO_Unmarshal(&target->safe, buffer, size); } return rc; } /* Table 110 - Definition of TPMS_TIME_INFO Structure */ TPM_RC TPMS_TIME_INFO_Unmarshal(TPMS_TIME_INFO *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = UINT64_Unmarshal(&target->time, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPMS_CLOCK_INFO_Unmarshal(&target->clockInfo, buffer, size); } return rc; } /* Table 111 - Definition of TPMS_TIME_ATTEST_INFO Structure */ TPM_RC TPMS_TIME_ATTEST_INFO_Unmarshal(TPMS_TIME_ATTEST_INFO *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMS_TIME_INFO_Unmarshal(&target->time, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT64_Unmarshal(&target->firmwareVersion, buffer, size); } return rc; } /* Table 112 - Definition of TPMS_CERTIFY_INFO Structure */ TPM_RC TPMS_CERTIFY_INFO_Unmarshal(TPMS_CERTIFY_INFO *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPM2B_NAME_Unmarshal(&target->name, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_NAME_Unmarshal(&target->qualifiedName, buffer, size); } return rc; } /* Table 113 - Definition of TPMS_QUOTE_INFO Structure */ TPM_RC TPMS_QUOTE_INFO_Unmarshal(TPMS_QUOTE_INFO *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPML_PCR_SELECTION_Unmarshal(&target->pcrSelect, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_DIGEST_Unmarshal(&target->pcrDigest, buffer, size); } return rc; } /* Table 114 - Definition of TPMS_COMMAND_AUDIT_INFO Structure */ TPM_RC TPMS_COMMAND_AUDIT_INFO_Unmarshal(TPMS_COMMAND_AUDIT_INFO *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = UINT64_Unmarshal(&target->auditCounter, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM_ALG_ID_Unmarshal(&target->digestAlg, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_DIGEST_Unmarshal(&target->auditDigest, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_DIGEST_Unmarshal(&target->commandDigest, buffer, size); } return rc; } /* Table 115 - Definition of TPMS_SESSION_AUDIT_INFO Structure */ TPM_RC TPMS_SESSION_AUDIT_INFO_Unmarshal(TPMS_SESSION_AUDIT_INFO *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMI_YES_NO_Unmarshal(&target->exclusiveSession, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_DIGEST_Unmarshal(&target->sessionDigest, buffer, size); } return rc; } /* Table 116 - Definition of TPMS_CREATION_INFO Structure */ TPM_RC TPMS_CREATION_INFO_Unmarshal(TPMS_CREATION_INFO *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPM2B_NAME_Unmarshal(&target->objectName, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_DIGEST_Unmarshal(&target->creationHash, buffer, size); } return rc; } /* Table 117 - Definition of TPMS_NV_CERTIFY_INFO Structure */ TPM_RC TPMS_NV_CERTIFY_INFO_Unmarshal(TPMS_NV_CERTIFY_INFO *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPM2B_NAME_Unmarshal(&target->indexName, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(&target->offset, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_MAX_NV_BUFFER_Unmarshal(&target->nvContents, buffer, size); } return rc; } /* Table 118 - Definition of (TPM_ST) TPMI_ST_ATTEST Type */ TPM_RC TPMI_ST_ATTEST_Unmarshal(TPMI_ST_ATTEST *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_ST_ATTEST orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_ST_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (*target) { case TPM_ST_ATTEST_CERTIFY: case TPM_ST_ATTEST_CREATION: case TPM_ST_ATTEST_QUOTE: case TPM_ST_ATTEST_COMMAND_AUDIT: case TPM_ST_ATTEST_SESSION_AUDIT: case TPM_ST_ATTEST_TIME: case TPM_ST_ATTEST_NV: break; default: rc = TPM_RC_SELECTOR; *target = orig_target; // libtpms added } } return rc; } /* Table 119 - Definition of TPMU_ATTEST Union */ TPM_RC TPMU_ATTEST_Unmarshal(TPMU_ATTEST *target, BYTE **buffer, INT32 *size, UINT32 selector) { TPM_RC rc = TPM_RC_SUCCESS; switch (selector) { case TPM_ST_ATTEST_CERTIFY: rc = TPMS_CERTIFY_INFO_Unmarshal(&target->certify, buffer, size); break; case TPM_ST_ATTEST_CREATION: rc = TPMS_CREATION_INFO_Unmarshal(&target->creation, buffer, size); break; case TPM_ST_ATTEST_QUOTE: rc = TPMS_QUOTE_INFO_Unmarshal(&target->quote, buffer, size); break; case TPM_ST_ATTEST_COMMAND_AUDIT: rc = TPMS_COMMAND_AUDIT_INFO_Unmarshal(&target->commandAudit, buffer, size); break; case TPM_ST_ATTEST_SESSION_AUDIT: rc = TPMS_SESSION_AUDIT_INFO_Unmarshal(&target->sessionAudit, buffer, size); break; case TPM_ST_ATTEST_TIME: rc = TPMS_TIME_ATTEST_INFO_Unmarshal(&target->time, buffer, size); break; case TPM_ST_ATTEST_NV: rc = TPMS_NV_CERTIFY_INFO_Unmarshal(&target->nv, buffer, size); break; default: rc = TPM_RC_SELECTOR; } return rc; } /* Table 120 - Definition of TPMS_ATTEST Structure */ TPM_RC TPMS_ATTEST_Unmarshal(TPMS_ATTEST *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPM_GENERATED_Unmarshal(&target->magic, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPMI_ST_ATTEST_Unmarshal(&target->type, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_NAME_Unmarshal(&target->qualifiedSigner, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_DATA_Unmarshal(&target->extraData, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPMS_CLOCK_INFO_Unmarshal(&target->clockInfo, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT64_Unmarshal(&target->firmwareVersion, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPMU_ATTEST_Unmarshal(&target->attested, buffer, size, target->type); } return rc; } /* Table 121 - Definition of TPM2B_ATTEST Structure */ TPM_RC TPM2B_ATTEST_Unmarshal(TPM2B_ATTEST *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPM2B_Unmarshal(&target->b, sizeof(TPMS_ATTEST), buffer, size); } return rc; } #endif /* Table 124 - Definition of {!ALG.S} (TPM_KEY_BITS) TPMI_!ALG.S_KEY_BITS Type */ #if ALG_AES TPM_RC TPMI_AES_KEY_BITS_Unmarshal(TPMI_AES_KEY_BITS *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_AES_KEY_BITS orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_KEY_BITS_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (*target) { #if AES_128 // libtpms added case 128: #endif // libtpms added begin #if AES_192 case 192: #endif #if AES_256 // libtpms added end case 256: #endif // libtpms added break; default: rc = TPM_RC_VALUE; *target = orig_target; // libtpms added } } return rc; } #endif #if ALG_CAMELLIA TPM_RC TPMI_CAMELLIA_KEY_BITS_Unmarshal(TPMI_CAMELLIA_KEY_BITS *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_CAMELLIA_KEY_BITS orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_KEY_BITS_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (*target) { #if CAMELLIA_128 // libtpms added case 128: #endif // libtpms added begin #if CAMELLIA_192 case 192: #endif #if CAMELLIA_256 case 256: #endif // libtpms added end break; default: rc = TPM_RC_VALUE; *target = orig_target; // libtpms added } } return rc; } #endif #if ALG_SM4 TPM_RC TPMI_SM4_KEY_BITS_Unmarshal(TPMI_SM4_KEY_BITS *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_SM4_KEY_BITS orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_KEY_BITS_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (*target) { case 128: break; default: rc = TPM_RC_VALUE; *target = orig_target; // libtpms added } } return rc; } #endif #if ALG_TDES // libtpms added begin TPM_RC TPMI_TDES_KEY_BITS_Unmarshal(TPMI_SM4_KEY_BITS *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_SM4_KEY_BITS orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_KEY_BITS_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (*target) { case 128: case 192: break; default: rc = TPM_RC_VALUE; *target = orig_target; // libtpms added } } return rc; } #endif // libtpms added end /* Table 125 - Definition of TPMU_SYM_KEY_BITS Union */ TPM_RC TPMU_SYM_KEY_BITS_Unmarshal(TPMU_SYM_KEY_BITS *target, BYTE **buffer, INT32 *size, UINT32 selector) { TPM_RC rc = TPM_RC_SUCCESS; switch (selector) { #if ALG_AES case TPM_ALG_AES: rc = TPMI_AES_KEY_BITS_Unmarshal(&target->aes, buffer, size); break; #endif #if ALG_SM4 case TPM_ALG_SM4: rc = TPMI_SM4_KEY_BITS_Unmarshal(&target->sm4, buffer, size); break; #endif #if ALG_CAMELLIA case TPM_ALG_CAMELLIA: rc = TPMI_CAMELLIA_KEY_BITS_Unmarshal(&target->camellia, buffer, size); break; #endif #if ALG_TDES // libtpms added beging case TPM_ALG_TDES: rc = TPMI_TDES_KEY_BITS_Unmarshal(&target->tdes, buffer, size); break; #endif // libtpms added end #if ALG_XOR case TPM_ALG_XOR: rc = TPMI_ALG_HASH_Unmarshal(&target->xorr, buffer, size, NO); break; #endif case TPM_ALG_NULL: break; default: rc = TPM_RC_SELECTOR; } return rc; } /* Table 126 - Definition of TPMU_SYM_MODE Union */ TPM_RC TPMU_SYM_MODE_Unmarshal(TPMU_SYM_MODE *target, BYTE **buffer, INT32 *size, UINT32 selector) { TPM_RC rc = TPM_RC_SUCCESS; switch (selector) { #if ALG_AES case TPM_ALG_AES: rc = TPMI_ALG_SYM_MODE_Unmarshal(&target->aes, buffer, size, YES); break; #endif #if ALG_SM4 case TPM_ALG_SM4: rc = TPMI_ALG_SYM_MODE_Unmarshal(&target->sm4, buffer, size, YES); break; #endif #if ALG_CAMELLIA case TPM_ALG_CAMELLIA: rc = TPMI_ALG_SYM_MODE_Unmarshal(&target->camellia, buffer, size, YES); break; #endif #if ALG_TDES // libtpms added begin case TPM_ALG_TDES: rc = TPMI_ALG_SYM_MODE_Unmarshal(&target->tdes, buffer, size, YES); break; #endif // libtpms added end case TPM_ALG_XOR: case TPM_ALG_NULL: break; default: rc = TPM_RC_SELECTOR; } return rc; } /* Table 131 - Definition of TPMT_SYM_DEF Structure */ TPM_RC TPMT_SYM_DEF_Unmarshal(TPMT_SYM_DEF *target, BYTE **buffer, INT32 *size, BOOL allowNull) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMI_ALG_SYM_Unmarshal(&target->algorithm, buffer, size, allowNull); } if (rc == TPM_RC_SUCCESS) { rc = TPMU_SYM_KEY_BITS_Unmarshal(&target->keyBits, buffer, size, target->algorithm); } if (rc == TPM_RC_SUCCESS) { rc = TPMU_SYM_MODE_Unmarshal(&target->mode, buffer, size, target->algorithm); } return rc; } /* Table 132 - Definition of TPMT_SYM_DEF_OBJECT Structure */ TPM_RC TPMT_SYM_DEF_OBJECT_Unmarshal(TPMT_SYM_DEF_OBJECT *target, BYTE **buffer, INT32 *size, BOOL allowNull) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMI_ALG_SYM_OBJECT_Unmarshal(&target->algorithm, buffer, size, allowNull); } if (rc == TPM_RC_SUCCESS) { rc = TPMU_SYM_KEY_BITS_Unmarshal(&target->keyBits, buffer, size, target->algorithm); } if (rc == TPM_RC_SUCCESS) { rc = TPMU_SYM_MODE_Unmarshal(&target->mode, buffer, size, target->algorithm); } return rc; } /* Table 133 - Definition of TPM2B_SYM_KEY Structure */ TPM_RC TPM2B_SYM_KEY_Unmarshal(TPM2B_SYM_KEY *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPM2B_Unmarshal(&target->b, MAX_SYM_KEY_BYTES, buffer, size); } return rc; } /* Table 134 - Definition of TPMS_SYMCIPHER_PARMS Structure */ TPM_RC TPMS_SYMCIPHER_PARMS_Unmarshal(TPMS_SYMCIPHER_PARMS *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMT_SYM_DEF_OBJECT_Unmarshal(&target->sym, buffer, size, NO); } return rc; } /* Table 2:135 - Definition of TPM2B_LABEL Structure (StructuresTable()) */ TPM_RC TPM2B_LABEL_Unmarshal(TPM2B_LABEL *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPM2B_Unmarshal(&target->b, LABEL_MAX_BUFFER, buffer, size); } return rc; } /* Table 2:136 - Definition of TPMS_DERIVE Structure (StructuresTable()) */ TPM_RC TPMS_DERIVE_Unmarshal(TPMS_DERIVE *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPM2B_LABEL_Unmarshal(&target->label, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_LABEL_Unmarshal(&target->context, buffer, size); } return rc; } /* Table 139 - Definition of TPM2B_SENSITIVE_DATA Structure */ TPM_RC TPM2B_SENSITIVE_DATA_Unmarshal(TPM2B_SENSITIVE_DATA *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPM2B_Unmarshal(&target->b, MAX_SYM_DATA, buffer, size); } return rc; } /* Table 133 - Definition of TPMS_SENSITIVE_CREATE Structure */ TPM_RC TPMS_SENSITIVE_CREATE_Unmarshal(TPMS_SENSITIVE_CREATE *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPM2B_AUTH_Unmarshal(&target->userAuth, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_SENSITIVE_DATA_Unmarshal(&target->data, buffer, size); } return rc; } /* Table 134 - Definition of TPM2B_SENSITIVE_CREATE Structure */ TPM_RC TPM2B_SENSITIVE_CREATE_Unmarshal(TPM2B_SENSITIVE_CREATE *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; INT32 startSize; if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(&target->size, buffer, size); } if (rc == TPM_RC_SUCCESS) { if (target->size == 0) { rc = TPM_RC_SIZE; } } if (rc == TPM_RC_SUCCESS) { startSize = *size; } if (rc == TPM_RC_SUCCESS) { rc = TPMS_SENSITIVE_CREATE_Unmarshal(&target->sensitive, buffer, size); } if (rc == TPM_RC_SUCCESS) { if (target->size != startSize - *size) { rc = TPM_RC_SIZE; target->size = 0; // libtpms added } } return rc; } /* Table 135 - Definition of TPMS_SCHEME_HASH Structure */ TPM_RC TPMS_SCHEME_HASH_Unmarshal(TPMS_SCHEME_HASH *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMI_ALG_HASH_Unmarshal(&target->hashAlg, buffer, size, NO); } return rc; } /* Table 136 - Definition of {ECC} TPMS_SCHEME_ECDAA Structure */ TPM_RC TPMS_SCHEME_ECDAA_Unmarshal(TPMS_SCHEME_ECDAA *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMI_ALG_HASH_Unmarshal(&target->hashAlg, buffer, size, NO); } if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(&target->count, buffer, size); } return rc; } /* Table 137 - Definition of (TPM_ALG_ID) TPMI_ALG_KEYEDHASH_SCHEME Type */ TPM_RC TPMI_ALG_KEYEDHASH_SCHEME_Unmarshal(TPMI_ALG_KEYEDHASH_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_ALG_KEYEDHASH_SCHEME orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_ALG_ID_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (*target) { #if ALG_HMAC case TPM_ALG_HMAC: #endif #if ALG_XOR case TPM_ALG_XOR: #endif break; case TPM_ALG_NULL: if (allowNull) { break; } default: rc = TPM_RC_VALUE; *target = orig_target; // libtpms added } } return rc; } /* Table 138 - Definition of Types for HMAC_SIG_SCHEME */ TPM_RC TPMS_SCHEME_HMAC_Unmarshal(TPMS_SCHEME_HMAC *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMS_SCHEME_HASH_Unmarshal(target, buffer, size); } return rc; } /* Table 139 - Definition of TPMS_SCHEME_XOR Structure */ TPM_RC TPMS_SCHEME_XOR_Unmarshal(TPMS_SCHEME_XOR *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMI_ALG_HASH_Unmarshal(&target->hashAlg, buffer, size, NO); /* as of rev 147 */ } if (rc == TPM_RC_SUCCESS) { rc = TPMI_ALG_KDF_Unmarshal(&target->kdf, buffer, size, YES); } return rc; } /* Table 140 - Definition of TPMU_SCHEME_KEYEDHASH Union */ TPM_RC TPMU_SCHEME_KEYEDHASH_Unmarshal(TPMU_SCHEME_KEYEDHASH *target, BYTE **buffer, INT32 *size, UINT32 selector) { TPM_RC rc = TPM_RC_SUCCESS; switch (selector) { #if ALG_HMAC case TPM_ALG_HMAC: rc = TPMS_SCHEME_HMAC_Unmarshal(&target->hmac, buffer, size); break; #endif #if ALG_XOR case TPM_ALG_XOR: rc = TPMS_SCHEME_XOR_Unmarshal(&target->xorr, buffer, size); break; #endif case TPM_ALG_NULL: break; default: rc = TPM_RC_SELECTOR; } return rc; } /* Table 141 - Definition of TPMT_KEYEDHASH_SCHEME Structure */ TPM_RC TPMT_KEYEDHASH_SCHEME_Unmarshal(TPMT_KEYEDHASH_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMI_ALG_KEYEDHASH_SCHEME_Unmarshal(&target->scheme, buffer, size, allowNull); } if (rc == TPM_RC_SUCCESS) { rc = TPMU_SCHEME_KEYEDHASH_Unmarshal(&target->details, buffer, size, target->scheme); } return rc; } /* Table 142 - Definition of {RSA} Types for RSA Signature Schemes */ TPM_RC TPMS_SIG_SCHEME_RSAPSS_Unmarshal(TPMS_SIG_SCHEME_RSAPSS *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMS_SCHEME_HASH_Unmarshal(target, buffer, size); } return rc; } /* Table 142 - Definition of {RSA} Types for RSA Signature Schemes */ TPM_RC TPMS_SIG_SCHEME_RSASSA_Unmarshal(TPMS_SIG_SCHEME_RSASSA *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMS_SCHEME_HASH_Unmarshal(target, buffer, size); } return rc; } /* Table 143 - Definition of {ECC} Types for ECC Signature Schemes */ TPM_RC TPMS_SIG_SCHEME_ECDAA_Unmarshal(TPMS_SIG_SCHEME_ECDAA *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMS_SCHEME_ECDAA_Unmarshal(target, buffer, size); } return rc; } /* Table 143 - Definition of {ECC} Types for ECC Signature Schemes */ TPM_RC TPMS_SIG_SCHEME_ECDSA_Unmarshal(TPMS_SIG_SCHEME_ECDSA *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMS_SCHEME_HASH_Unmarshal(target, buffer, size); } return rc; } /* Table 143 - Definition of {ECC} Types for ECC Signature Schemes */ TPM_RC TPMS_SIG_SCHEME_ECSCHNORR_Unmarshal(TPMS_SIG_SCHEME_ECSCHNORR *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMS_SCHEME_HASH_Unmarshal(target, buffer, size); } return rc; } /* Table 143 - Definition of {ECC} Types for ECC Signature Schemes */ TPM_RC TPMS_SIG_SCHEME_SM2_Unmarshal(TPMS_SIG_SCHEME_SM2 *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMS_SCHEME_HASH_Unmarshal(target, buffer, size); } return rc; } /* Table 144 - Definition of TPMU_SIG_SCHEME Union */ TPM_RC TPMU_SIG_SCHEME_Unmarshal(TPMU_SIG_SCHEME *target, BYTE **buffer, INT32 *size, UINT32 selector) { TPM_RC rc = TPM_RC_SUCCESS; switch (selector) { #if ALG_RSASSA case TPM_ALG_RSASSA: rc = TPMS_SIG_SCHEME_RSASSA_Unmarshal(&target->rsassa, buffer, size); break; #endif #if ALG_RSAPSS case TPM_ALG_RSAPSS: rc = TPMS_SIG_SCHEME_RSAPSS_Unmarshal(&target->rsapss, buffer, size); break; #endif #if ALG_ECDSA case TPM_ALG_ECDSA: rc = TPMS_SIG_SCHEME_ECDSA_Unmarshal(&target->ecdsa, buffer, size); break; #endif #if ALG_ECDAA case TPM_ALG_ECDAA: rc = TPMS_SIG_SCHEME_ECDAA_Unmarshal(&target->ecdaa, buffer, size); break; #endif #if ALG_SM2 case TPM_ALG_SM2: rc = TPMS_SIG_SCHEME_SM2_Unmarshal(&target->sm2, buffer, size); break; #endif #if ALG_ECSCHNORR case TPM_ALG_ECSCHNORR: rc = TPMS_SIG_SCHEME_ECSCHNORR_Unmarshal(&target->ecschnorr, buffer, size); break; #endif #if ALG_HMAC case TPM_ALG_HMAC: rc = TPMS_SCHEME_HMAC_Unmarshal(&target->hmac, buffer, size); break; #endif case TPM_ALG_NULL: break; default: rc = TPM_RC_SELECTOR; } return rc; } /* Table 145 - Definition of TPMT_SIG_SCHEME Structure */ TPM_RC TPMT_SIG_SCHEME_Unmarshal(TPMT_SIG_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMI_ALG_SIG_SCHEME_Unmarshal(&target->scheme, buffer, size, allowNull); } if (rc == TPM_RC_SUCCESS) { rc = TPMU_SIG_SCHEME_Unmarshal(&target->details, buffer, size, target->scheme); } return rc; } /* Table 146 - Definition of Types for {RSA} Encryption Schemes */ TPM_RC TPMS_ENC_SCHEME_OAEP_Unmarshal(TPMS_ENC_SCHEME_OAEP *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMS_SCHEME_HASH_Unmarshal(target, buffer, size); } return rc; } /* Table 146 - Definition of Types for {RSA} Encryption Schemes */ TPM_RC TPMS_ENC_SCHEME_RSAES_Unmarshal(TPMS_ENC_SCHEME_RSAES *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMS_EMPTY_Unmarshal(target, buffer, size); } return rc; } /* Table 147 - Definition of Types for {ECC} ECC Key Exchange */ TPM_RC TPMS_KEY_SCHEME_ECDH_Unmarshal(TPMS_KEY_SCHEME_ECDH *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMS_SCHEME_HASH_Unmarshal(target, buffer, size); } return rc; } /* Table 147 - Definition of Types for {ECC} ECC Key Exchange */ TPM_RC TPMS_KEY_SCHEME_ECMQV_Unmarshal(TPMS_KEY_SCHEME_ECMQV *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMS_SCHEME_HASH_Unmarshal(target, buffer, size); } return rc; } /* Table 148 - Definition of Types for KDF Schemes, hash-based key- or mask-generation functions */ TPM_RC TPMS_KDF_SCHEME_KDF1_SP800_108_Unmarshal(TPMS_KDF_SCHEME_KDF1_SP800_108 *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMS_SCHEME_HASH_Unmarshal(target, buffer, size); } return rc; } /* Table 148 - Definition of Types for KDF Schemes, hash-based key- or mask-generation functions */ TPM_RC TPMS_KDF_SCHEME_KDF1_SP800_56A_Unmarshal(TPMS_KDF_SCHEME_KDF1_SP800_56A *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMS_SCHEME_HASH_Unmarshal(target, buffer, size); } return rc; } /* Table 148 - Definition of Types for KDF Schemes, hash-based key- or mask-generation functions */ TPM_RC TPMS_KDF_SCHEME_KDF2_Unmarshal(TPMS_KDF_SCHEME_KDF2 *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMS_SCHEME_HASH_Unmarshal(target, buffer, size); } return rc; } /* Table 148 - Definition of Types for KDF Schemes, hash-based key- or mask-generation functions */ TPM_RC TPMS_KDF_SCHEME_MGF1_Unmarshal(TPMS_KDF_SCHEME_MGF1 *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMS_SCHEME_HASH_Unmarshal(target, buffer, size); } return rc; } /* Table 149 - Definition of TPMU_KDF_SCHEME Union */ TPM_RC TPMU_KDF_SCHEME_Unmarshal(TPMU_KDF_SCHEME *target, BYTE **buffer, INT32 *size, UINT32 selector) { TPM_RC rc = TPM_RC_SUCCESS; switch (selector) { #if ALG_MGF1 case TPM_ALG_MGF1: rc = TPMS_KDF_SCHEME_MGF1_Unmarshal(&target->mgf1, buffer, size); break; #endif #if ALG_KDF1_SP800_56A case TPM_ALG_KDF1_SP800_56A: rc = TPMS_KDF_SCHEME_KDF1_SP800_56A_Unmarshal(&target->kdf1_sp800_56a, buffer, size); break; #endif #if ALG_KDF2 case TPM_ALG_KDF2: rc = TPMS_KDF_SCHEME_KDF2_Unmarshal(&target->kdf2, buffer, size); break; #endif #if ALG_KDF1_SP800_108 case TPM_ALG_KDF1_SP800_108: rc = TPMS_KDF_SCHEME_KDF1_SP800_108_Unmarshal(&target->kdf1_sp800_108, buffer, size); break; #endif case TPM_ALG_NULL: break; default: rc = TPM_RC_SELECTOR; } return rc; } /* Table 150 - Definition of TPMT_KDF_SCHEME Structure */ TPM_RC TPMT_KDF_SCHEME_Unmarshal(TPMT_KDF_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMI_ALG_KDF_Unmarshal(&target->scheme, buffer, size, allowNull); } if (rc == TPM_RC_SUCCESS) { rc = TPMU_KDF_SCHEME_Unmarshal(&target->details, buffer, size, target->scheme); } return rc; } /* Table 151 - Definition of (TPM_ALG_ID) TPMI_ALG_ASYM_SCHEME Type <> */ #if 0 TPM_RC TPMI_ALG_ASYM_SCHEME_Unmarshal(TPMI_ALG_ASYM_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_ALG_ASYM_SCHEME orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_ALG_ID_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (*target) { #if ALG_ECDH case TPM_ALG_ECDH: #endif #if ALG_ECMQV case TPM_ALG_ECMQV: #endif #if ALG_RSASSA case TPM_ALG_RSASSA: #endif #if ALG_RSAPSS case TPM_ALG_RSAPSS: #endif #if ALG_ECDSA case TPM_ALG_ECDSA: #endif #if ALG_ECDAA case TPM_ALG_ECDAA: #endif #if ALG_SM2 case TPM_ALG_SM2: #endif #if ALG_ECSCHNORR case TPM_ALG_ECSCHNORR: #endif #if ALG_RSAES case TPM_ALG_RSAES: #endif #if ALG_OAEP case TPM_ALG_OAEP: #endif break; case TPM_ALG_NULL: if (allowNull) { break; } default: rc = TPM_RC_VALUE; *target = orig_target; // libtpms added } } return rc; } #endif /* Table 152 - Definition of TPMU_ASYM_SCHEME Union */ TPM_RC TPMU_ASYM_SCHEME_Unmarshal(TPMU_ASYM_SCHEME *target, BYTE **buffer, INT32 *size, UINT32 selector) { TPM_RC rc = TPM_RC_SUCCESS; switch (selector) { #if ALG_ECDH case TPM_ALG_ECDH: rc = TPMS_KEY_SCHEME_ECDH_Unmarshal(&target->ecdh, buffer, size); break; #endif #if ALG_ECMQV case TPM_ALG_ECMQV: rc = TPMS_KEY_SCHEME_ECMQV_Unmarshal(&target->ecmqv, buffer, size); break; #endif #if ALG_RSASSA case TPM_ALG_RSASSA: rc = TPMS_SIG_SCHEME_RSASSA_Unmarshal(&target->rsassa, buffer, size); break; #endif #if ALG_RSAPSS case TPM_ALG_RSAPSS: rc = TPMS_SIG_SCHEME_RSAPSS_Unmarshal(&target->rsapss, buffer, size); break; #endif #if ALG_ECDSA case TPM_ALG_ECDSA: rc = TPMS_SIG_SCHEME_ECDSA_Unmarshal(&target->ecdsa, buffer, size); break; #endif #if ALG_ECDAA case TPM_ALG_ECDAA: rc = TPMS_SIG_SCHEME_ECDAA_Unmarshal(&target->ecdaa, buffer, size); break; #endif #if ALG_SM2 case TPM_ALG_SM2: rc = TPMS_SIG_SCHEME_SM2_Unmarshal(&target->sm2, buffer, size); break; #endif #if ALG_ECSCHNORR case TPM_ALG_ECSCHNORR: rc = TPMS_SIG_SCHEME_ECSCHNORR_Unmarshal(&target->ecschnorr, buffer, size); break; #endif #if ALG_RSAES case TPM_ALG_RSAES: rc = TPMS_ENC_SCHEME_RSAES_Unmarshal(&target->rsaes, buffer, size); break; #endif #if ALG_OAEP case TPM_ALG_OAEP: rc = TPMS_ENC_SCHEME_OAEP_Unmarshal(&target->oaep, buffer, size); break; #endif case TPM_ALG_NULL: break; default: rc = TPM_RC_SELECTOR; } return rc; } /* Table 154 - Definition of (TPM_ALG_ID) {RSA} TPMI_ALG_RSA_SCHEME Type */ TPM_RC TPMI_ALG_RSA_SCHEME_Unmarshal(TPMI_ALG_RSA_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_ALG_RSA_SCHEME orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_ALG_ID_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (*target) { #if ALG_RSASSA case TPM_ALG_RSASSA: #endif #if ALG_RSAPSS case TPM_ALG_RSAPSS: #endif #if ALG_RSAES case TPM_ALG_RSAES: #endif #if ALG_OAEP case TPM_ALG_OAEP: #endif break; case TPM_ALG_NULL: if (allowNull) { break; } default: rc = TPM_RC_VALUE; *target = orig_target; // libtpms added } } return rc; } /* Table 155 - Definition of {RSA} TPMT_RSA_SCHEME Structure */ TPM_RC TPMT_RSA_SCHEME_Unmarshal(TPMT_RSA_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMI_ALG_RSA_SCHEME_Unmarshal(&target->scheme, buffer, size, allowNull); } if (rc == TPM_RC_SUCCESS) { rc = TPMU_ASYM_SCHEME_Unmarshal(&target->details, buffer, size, target->scheme); } return rc; } /* Table 156 - Definition of (TPM_ALG_ID) {RSA} TPMI_ALG_RSA_DECRYPT Type */ TPM_RC TPMI_ALG_RSA_DECRYPT_Unmarshal(TPMI_ALG_RSA_DECRYPT *target, BYTE **buffer, INT32 *size, BOOL allowNull) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_ALG_RSA_DECRYPT orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_ALG_ID_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (*target) { #if ALG_RSAES case TPM_ALG_RSAES: #endif #if ALG_OAEP case TPM_ALG_OAEP: #endif break; case TPM_ALG_NULL: if (allowNull) { break; } default: rc = TPM_RC_VALUE; *target = orig_target; // libtpms added } } return rc; } /* Table 157 - Definition of {RSA} TPMT_RSA_DECRYPT Structure */ TPM_RC TPMT_RSA_DECRYPT_Unmarshal(TPMT_RSA_DECRYPT *target, BYTE **buffer, INT32 *size, BOOL allowNull) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMI_ALG_RSA_DECRYPT_Unmarshal(&target->scheme, buffer, size, allowNull); } if (rc == TPM_RC_SUCCESS) { rc = TPMU_ASYM_SCHEME_Unmarshal(&target->details, buffer, size, target->scheme); } return rc; } /* Table 158 - Definition of {RSA} TPM2B_PUBLIC_KEY_RSA Structure */ TPM_RC TPM2B_PUBLIC_KEY_RSA_Unmarshal(TPM2B_PUBLIC_KEY_RSA *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPM2B_Unmarshal(&target->b, MAX_RSA_KEY_BYTES, buffer, size); } return rc; } /* Table 159 - Definition of {RSA} (TPM_KEY_BITS) TPMI_RSA_KEY_BITS Type */ TPM_RC TPMI_RSA_KEY_BITS_Unmarshal(TPMI_RSA_KEY_BITS *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_RSA_KEY_BITS orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_KEY_BITS_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (*target) { case 1024: case 2048: case 3072: break; default: rc = TPM_RC_VALUE; *target = orig_target; // libtpms added } } return rc; } /* Table 160 - Definition of {RSA} TPM2B_PRIVATE_KEY_RSA Structure */ TPM_RC TPM2B_PRIVATE_KEY_RSA_Unmarshal(TPM2B_PRIVATE_KEY_RSA *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPM2B_Unmarshal(&target->b, MAX_RSA_KEY_BYTES/2, buffer, size); } return rc; } /* Table 161 - Definition of {ECC} TPM2B_ECC_PARAMETER Structure */ TPM_RC TPM2B_ECC_PARAMETER_Unmarshal(TPM2B_ECC_PARAMETER *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPM2B_Unmarshal(&target->b, MAX_ECC_KEY_BYTES, buffer, size); } return rc; } /* Table 162 - Definition of {ECC} TPMS_ECC_POINT Structure */ TPM_RC TPMS_ECC_POINT_Unmarshal(TPMS_ECC_POINT *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPM2B_ECC_PARAMETER_Unmarshal(&target->x, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_ECC_PARAMETER_Unmarshal(&target->y, buffer, size); } return rc; } /* Table 163 - Definition of {ECC} TPM2B_ECC_POINT Structure */ TPM_RC TPM2B_ECC_POINT_Unmarshal(TPM2B_ECC_POINT *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; INT32 startSize; if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(&target->size, buffer, size); } if (rc == TPM_RC_SUCCESS) { if (target->size == 0) { rc = TPM_RC_SIZE; } } if (rc == TPM_RC_SUCCESS) { startSize = *size; } if (rc == TPM_RC_SUCCESS) { rc = TPMS_ECC_POINT_Unmarshal(&target->point, buffer, size); } if (rc == TPM_RC_SUCCESS) { if (target->size != startSize - *size) { rc = TPM_RC_SIZE; target->size = 0; // libtpms added } } return rc; } /* Table 164 - Definition of (TPM_ALG_ID) {ECC} TPMI_ALG_ECC_SCHEME Type */ TPM_RC TPMI_ALG_ECC_SCHEME_Unmarshal(TPMI_ALG_ECC_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_ALG_ECC_SCHEME orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_ALG_ID_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (*target) { #if ALG_ECDSA case TPM_ALG_ECDSA: #endif #if ALG_SM2 case TPM_ALG_SM2: #endif #if ALG_ECDAA case TPM_ALG_ECDAA: #endif #if ALG_ECSCHNORR case TPM_ALG_ECSCHNORR: #endif #if ALG_ECDH case TPM_ALG_ECDH: #endif #if ALG_ECMQV case TPM_ALG_ECMQV: #endif break; case TPM_ALG_NULL: if (allowNull) { break; } default: rc = TPM_RC_SCHEME; *target = orig_target; // libtpms added } } return rc; } /* Table 165 - Definition of {ECC} (TPM_ECC_CURVE) TPMI_ECC_CURVE Type */ TPM_RC TPMI_ECC_CURVE_Unmarshal(TPMI_ECC_CURVE *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_ECC_CURVE orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_ECC_CURVE_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (*target) { #if ECC_BN_P256 case TPM_ECC_BN_P256: #endif #if ECC_BN_P638 // libtpms added begin case TPM_ECC_BN_P638: #endif #if ECC_NIST_P192 case TPM_ECC_NIST_P192: #endif #if ECC_NIST_P224 case TPM_ECC_NIST_P224: #endif // libtpms added end #if ECC_NIST_P256 case TPM_ECC_NIST_P256: #endif #if ECC_NIST_P384 case TPM_ECC_NIST_P384: #endif #if ECC_NIST_P521 // libtpms added begin case TPM_ECC_NIST_P521: #endif #if ECC_SM2_P256 case TPM_ECC_SM2_P256: #endif if (!CryptEccIsCurveRuntimeUsable(*target)) rc = TPM_RC_CURVE; // libtpms added end break; default: rc = TPM_RC_CURVE; *target = orig_target; // libtpms added } } return rc; } /* Table 166 - Definition of (TPMT_SIG_SCHEME) {ECC} TPMT_ECC_SCHEME Structure */ TPM_RC TPMT_ECC_SCHEME_Unmarshal(TPMT_ECC_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMI_ALG_ECC_SCHEME_Unmarshal(&target->scheme, buffer, size, allowNull); } if (rc == TPM_RC_SUCCESS) { rc = TPMU_ASYM_SCHEME_Unmarshal(&target->details, buffer, size, target->scheme); } return rc; } /* Table 168 - Definition of {RSA} TPMS_SIGNATURE_RSA Structure */ TPM_RC TPMS_SIGNATURE_RSA_Unmarshal(TPMS_SIGNATURE_RSA *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMI_ALG_HASH_Unmarshal(&target->hash, buffer, size, NO); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_PUBLIC_KEY_RSA_Unmarshal(&target->sig, buffer, size); } return rc; } /* Table 169 - Definition of Types for {RSA} Signature */ TPM_RC TPMS_SIGNATURE_RSASSA_Unmarshal(TPMS_SIGNATURE_RSASSA *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMS_SIGNATURE_RSA_Unmarshal(target, buffer, size); } return rc; } /* Table 169 - Definition of Types for {RSA} Signature */ TPM_RC TPMS_SIGNATURE_RSAPSS_Unmarshal(TPMS_SIGNATURE_RSAPSS *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMS_SIGNATURE_RSA_Unmarshal(target, buffer, size); } return rc; } /* Table 170 - Definition of {ECC} TPMS_SIGNATURE_ECC Structure */ TPM_RC TPMS_SIGNATURE_ECC_Unmarshal(TPMS_SIGNATURE_ECC *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMI_ALG_HASH_Unmarshal(&target->hash, buffer, size, NO); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_ECC_PARAMETER_Unmarshal(&target->signatureR, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_ECC_PARAMETER_Unmarshal(&target->signatureS, buffer, size); } return rc; } /* Table 171 - Definition of Types for {ECC} TPMS_SIGNATURE_ECC */ TPM_RC TPMS_SIGNATURE_ECDSA_Unmarshal(TPMS_SIGNATURE_ECDSA *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMS_SIGNATURE_ECC_Unmarshal(target, buffer, size); } return rc; } TPM_RC TPMS_SIGNATURE_ECDAA_Unmarshal(TPMS_SIGNATURE_ECDAA *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMS_SIGNATURE_ECC_Unmarshal(target, buffer, size); } return rc; } TPM_RC TPMS_SIGNATURE_SM2_Unmarshal(TPMS_SIGNATURE_SM2 *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMS_SIGNATURE_ECC_Unmarshal(target, buffer, size); } return rc; } TPM_RC TPMS_SIGNATURE_ECSCHNORR_Unmarshal(TPMS_SIGNATURE_ECSCHNORR *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMS_SIGNATURE_ECC_Unmarshal(target, buffer, size); } return rc; } /* Table 172 - Definition of TPMU_SIGNATURE Union */ TPM_RC TPMU_SIGNATURE_Unmarshal(TPMU_SIGNATURE *target, BYTE **buffer, INT32 *size, UINT32 selector) { TPM_RC rc = TPM_RC_SUCCESS; switch (selector) { #if ALG_RSASSA case TPM_ALG_RSASSA: rc = TPMS_SIGNATURE_RSASSA_Unmarshal(&target->rsassa, buffer, size); break; #endif #if ALG_RSAPSS case TPM_ALG_RSAPSS: rc = TPMS_SIGNATURE_RSAPSS_Unmarshal(&target->rsapss, buffer, size); break; #endif #if ALG_ECDSA case TPM_ALG_ECDSA: rc = TPMS_SIGNATURE_ECDSA_Unmarshal(&target->ecdsa, buffer, size); break; #endif #if ALG_ECDAA case TPM_ALG_ECDAA: rc = TPMS_SIGNATURE_ECDAA_Unmarshal(&target->ecdaa, buffer, size); break; #endif #if ALG_SM2 case TPM_ALG_SM2: rc = TPMS_SIGNATURE_SM2_Unmarshal(&target->sm2, buffer, size); break; #endif #if ALG_ECSCHNORR case TPM_ALG_ECSCHNORR: rc = TPMS_SIGNATURE_ECSCHNORR_Unmarshal(&target->ecschnorr, buffer, size); break; #endif #if ALG_HMAC case TPM_ALG_HMAC: rc = TPMT_HA_Unmarshal(&target->hmac, buffer, size, NO); break; #endif case TPM_ALG_NULL: break; default: rc = TPM_RC_SELECTOR; } return rc; } /* Table 173 - Definition of TPMT_SIGNATURE Structure */ TPM_RC TPMT_SIGNATURE_Unmarshal(TPMT_SIGNATURE *target, BYTE **buffer, INT32 *size, BOOL allowNull) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMI_ALG_SIG_SCHEME_Unmarshal(&target->sigAlg, buffer, size, allowNull); } if (rc == TPM_RC_SUCCESS) { rc = TPMU_SIGNATURE_Unmarshal(&target->signature, buffer, size, target->sigAlg); } return rc; } /* Table 175 - Definition of TPM2B_ENCRYPTED_SECRET Structure */ TPM_RC TPM2B_ENCRYPTED_SECRET_Unmarshal(TPM2B_ENCRYPTED_SECRET *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPM2B_Unmarshal(&target->b, sizeof(TPMU_ENCRYPTED_SECRET), buffer, size); } return rc; } /* Table 176 - Definition of (TPM_ALG_ID) TPMI_ALG_PUBLIC Type */ TPM_RC TPMI_ALG_PUBLIC_Unmarshal(TPMI_ALG_PUBLIC *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; TPMI_ALG_PUBLIC orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = TPM_ALG_ID_Unmarshal(target, buffer, size); } if (rc == TPM_RC_SUCCESS) { switch (*target) { #if ALG_KEYEDHASH case TPM_ALG_KEYEDHASH: #endif #if ALG_RSA case TPM_ALG_RSA: #endif #if ALG_ECC case TPM_ALG_ECC: #endif #if ALG_SYMCIPHER case TPM_ALG_SYMCIPHER: #endif break; default: rc = TPM_RC_TYPE; *target = orig_target; // libtpms added } } return rc; } /* Table 177 - Definition of TPMU_PUBLIC_ID Union */ TPM_RC TPMU_PUBLIC_ID_Unmarshal(TPMU_PUBLIC_ID *target, BYTE **buffer, INT32 *size, UINT32 selector) { TPM_RC rc = TPM_RC_SUCCESS; switch (selector) { #if ALG_KEYEDHASH case TPM_ALG_KEYEDHASH: rc = TPM2B_DIGEST_Unmarshal(&target->keyedHash, buffer, size); break; #endif #if ALG_SYMCIPHER case TPM_ALG_SYMCIPHER: rc = TPM2B_DIGEST_Unmarshal(&target->sym, buffer, size); break; #endif #if ALG_RSA case TPM_ALG_RSA: rc = TPM2B_PUBLIC_KEY_RSA_Unmarshal(&target->rsa, buffer, size); break; #endif #if ALG_ECC case TPM_ALG_ECC: rc = TPMS_ECC_POINT_Unmarshal(&target->ecc, buffer, size); break; #endif default: rc = TPM_RC_SELECTOR; } return rc; } /* Table 178 - Definition of TPMS_KEYEDHASH_PARMS Structure */ TPM_RC TPMS_KEYEDHASH_PARMS_Unmarshal(TPMS_KEYEDHASH_PARMS *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMT_KEYEDHASH_SCHEME_Unmarshal(&target->scheme, buffer, size, YES); } return rc; } /* Table 180 - Definition of {RSA} TPMS_RSA_PARMS Structure */ TPM_RC TPMS_RSA_PARMS_Unmarshal(TPMS_RSA_PARMS *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMT_SYM_DEF_OBJECT_Unmarshal(&target->symmetric, buffer, size, YES); } if (rc == TPM_RC_SUCCESS) { rc = TPMT_RSA_SCHEME_Unmarshal(&target->scheme, buffer, size, YES); } if (rc == TPM_RC_SUCCESS) { rc = TPMI_RSA_KEY_BITS_Unmarshal(&target->keyBits, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(&target->exponent, buffer, size); } return rc; } /* Table 181 - Definition of {ECC} TPMS_ECC_PARMS Structure */ TPM_RC TPMS_ECC_PARMS_Unmarshal(TPMS_ECC_PARMS *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMT_SYM_DEF_OBJECT_Unmarshal(&target->symmetric, buffer, size, YES); } if (rc == TPM_RC_SUCCESS) { rc = TPMT_ECC_SCHEME_Unmarshal(&target->scheme, buffer, size, YES); } if (rc == TPM_RC_SUCCESS) { rc = TPMI_ECC_CURVE_Unmarshal(&target->curveID, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPMT_KDF_SCHEME_Unmarshal(&target->kdf, buffer, size, YES); } return rc; } /* Table 182 - Definition of TPMU_PUBLIC_PARMS Union */ TPM_RC TPMU_PUBLIC_PARMS_Unmarshal(TPMU_PUBLIC_PARMS *target, BYTE **buffer, INT32 *size, UINT32 selector) { TPM_RC rc = TPM_RC_SUCCESS; switch (selector) { #if ALG_KEYEDHASH case TPM_ALG_KEYEDHASH: rc = TPMS_KEYEDHASH_PARMS_Unmarshal(&target->keyedHashDetail, buffer, size); break; #endif #if ALG_SYMCIPHER case TPM_ALG_SYMCIPHER: rc = TPMS_SYMCIPHER_PARMS_Unmarshal(&target->symDetail, buffer, size); break; #endif #if ALG_RSA case TPM_ALG_RSA: rc = TPMS_RSA_PARMS_Unmarshal(&target->rsaDetail, buffer, size); break; #endif #if ALG_ECC case TPM_ALG_ECC: rc = TPMS_ECC_PARMS_Unmarshal(&target->eccDetail, buffer, size); break; #endif default: rc = TPM_RC_SELECTOR; } return rc; } /* Table 183 - Definition of TPMT_PUBLIC_PARMS Structure */ TPM_RC TPMT_PUBLIC_PARMS_Unmarshal(TPMT_PUBLIC_PARMS *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMI_ALG_PUBLIC_Unmarshal(&target->type, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPMU_PUBLIC_PARMS_Unmarshal(&target->parameters, buffer, size, target->type); } return rc; } /* Table 191 - Definition of TPMT_PUBLIC Structure */ TPM_RC TPMT_PUBLIC_Unmarshal(TPMT_PUBLIC *target, BYTE **buffer, INT32 *size, BOOL allowNull) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMI_ALG_PUBLIC_Unmarshal(&target->type, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPMI_ALG_HASH_Unmarshal(&target->nameAlg, buffer, size, allowNull); } if (rc == TPM_RC_SUCCESS) { rc = TPMA_OBJECT_Unmarshal(&target->objectAttributes, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_DIGEST_Unmarshal(&target->authPolicy, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPMU_PUBLIC_PARMS_Unmarshal(&target->parameters, buffer, size, target->type); } if (rc == TPM_RC_SUCCESS) { rc = TPMU_PUBLIC_ID_Unmarshal(&target->unique, buffer, size, target->type); } return rc; } /* Table 192 - Definition of TPM2B_PUBLIC Structure */ TPM_RC TPM2B_PUBLIC_Unmarshal(TPM2B_PUBLIC *target, BYTE **buffer, INT32 *size, BOOL allowNull) { TPM_RC rc = TPM_RC_SUCCESS; INT32 startSize; if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(&target->size, buffer, size); } if (rc == TPM_RC_SUCCESS) { if (target->size == 0) { rc = TPM_RC_SIZE; } } if (rc == TPM_RC_SUCCESS) { startSize = *size; } if (rc == TPM_RC_SUCCESS) { rc = TPMT_PUBLIC_Unmarshal(&target->publicArea, buffer, size, allowNull); } if (rc == TPM_RC_SUCCESS) { if (target->size != startSize - *size) { rc = TPM_RC_SIZE; target->size = 0; // libtpms added } } return rc; } /* Table 2:193 - Definition of TPM2B_TEMPLATE Structure (StructuresTable()) */ TPM_RC TPM2B_TEMPLATE_Unmarshal(TPM2B_TEMPLATE *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPM2B_Unmarshal(&target->b, sizeof(TPMT_PUBLIC), buffer, size); } return rc; } /* Table 187 - Definition of TPMU_SENSITIVE_COMPOSITE Union */ TPM_RC TPMU_SENSITIVE_COMPOSITE_Unmarshal(TPMU_SENSITIVE_COMPOSITE *target, BYTE **buffer, INT32 *size, UINT32 selector) { TPM_RC rc = TPM_RC_SUCCESS; switch (selector) { #if ALG_RSA case TPM_ALG_RSA: rc = TPM2B_PRIVATE_KEY_RSA_Unmarshal(&target->rsa, buffer, size); break; #endif #if ALG_ECC case TPM_ALG_ECC: rc = TPM2B_ECC_PARAMETER_Unmarshal(&target->ecc, buffer, size); break; #endif #if ALG_KEYEDHASH case TPM_ALG_KEYEDHASH: rc = TPM2B_SENSITIVE_DATA_Unmarshal(&target->bits, buffer, size); break; #endif #if ALG_SYMCIPHER case TPM_ALG_SYMCIPHER: rc = TPM2B_SYM_KEY_Unmarshal(&target->sym, buffer, size); break; #endif default: rc = TPM_RC_SELECTOR; } return rc; } /* Table 188 - Definition of TPMT_SENSITIVE Structure */ TPM_RC TPMT_SENSITIVE_Unmarshal(TPMT_SENSITIVE *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMI_ALG_PUBLIC_Unmarshal(&target->sensitiveType, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_AUTH_Unmarshal(&target->authValue, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_DIGEST_Unmarshal(&target->seedValue, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPMU_SENSITIVE_COMPOSITE_Unmarshal(&target->sensitive, buffer, size, target->sensitiveType); } return rc; } /* Table 189 - Definition of TPM2B_SENSITIVE Structure */ TPM_RC TPM2B_SENSITIVE_Unmarshal(TPM2B_SENSITIVE *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; INT32 startSize; if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(&target->size, buffer, size); } if (target->size != 0) { if (rc == TPM_RC_SUCCESS) { startSize = *size; } if (rc == TPM_RC_SUCCESS) { rc = TPMT_SENSITIVE_Unmarshal(&target->sensitiveArea, buffer, size); } if (rc == TPM_RC_SUCCESS) { if (target->size != startSize - *size) { rc = TPM_RC_SIZE; target->size = 0; // libtpms added } } } return rc; } /* Table 191 - Definition of TPM2B_PRIVATE Structure */ TPM_RC TPM2B_PRIVATE_Unmarshal(TPM2B_PRIVATE *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPM2B_Unmarshal(&target->b, sizeof(_PRIVATE), buffer, size); } return rc; } /* Table 193 - Definition of TPM2B_ID_OBJECT Structure */ TPM_RC TPM2B_ID_OBJECT_Unmarshal(TPM2B_ID_OBJECT *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPM2B_Unmarshal(&target->b, sizeof(TPMS_ID_OBJECT), buffer, size); } return rc; } /* Table 196 - Definition of (UINT32) TPMA_NV Bits */ TPM_RC TPMA_NV_Unmarshal(TPMA_NV *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; TPMA_NV orig_target = *target; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal((UINT32 *)target, buffer, size); /* libtpms changed */ } if (rc == TPM_RC_SUCCESS) { if (*target & TPMA_NV_RESERVED) { rc = TPM_RC_RESERVED_BITS; *target = orig_target; // libtpms added } } return rc; } /* Table 197 - Definition of TPMS_NV_PUBLIC Structure */ TPM_RC TPMS_NV_PUBLIC_Unmarshal(TPMS_NV_PUBLIC *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPMI_RH_NV_INDEX_Unmarshal(&target->nvIndex, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPMI_ALG_HASH_Unmarshal(&target->nameAlg, buffer, size, NO); } if (rc == TPM_RC_SUCCESS) { rc = TPMA_NV_Unmarshal(&target->attributes, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_DIGEST_Unmarshal(&target->authPolicy, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(&target->dataSize, buffer, size); } if (rc == TPM_RC_SUCCESS) { if (target->dataSize > MAX_NV_INDEX_SIZE) { rc = TPM_RC_SIZE; target->dataSize = 0; // libtpms added } } return rc; } /* Table 198 - Definition of TPM2B_NV_PUBLIC Structure */ TPM_RC TPM2B_NV_PUBLIC_Unmarshal(TPM2B_NV_PUBLIC *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; INT32 startSize; if (rc == TPM_RC_SUCCESS) { rc = UINT16_Unmarshal(&target->size, buffer, size); } if (rc == TPM_RC_SUCCESS) { if (target->size == 0) { rc = TPM_RC_SIZE; } } if (rc == TPM_RC_SUCCESS) { startSize = *size; } if (rc == TPM_RC_SUCCESS) { rc = TPMS_NV_PUBLIC_Unmarshal(&target->nvPublic, buffer, size); } if (rc == TPM_RC_SUCCESS) { if (target->size != startSize - *size) { rc = TPM_RC_SIZE; target->size = 0; // libtpms added } } return rc; } /* Table 199 - Definition of TPM2B_CONTEXT_SENSITIVE Structure */ #if 0 // libtpms added TPM_RC TPM2B_CONTEXT_SENSITIVE_Unmarshal(TPM2B_CONTEXT_SENSITIVE *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPM2B_Unmarshal(&target->b, MAX_CONTEXT_SIZE, buffer, size); } return rc; } #endif // libtpms added /* Table 201 - Definition of TPM2B_CONTEXT_DATA Structure */ TPM_RC TPM2B_CONTEXT_DATA_Unmarshal(TPM2B_CONTEXT_DATA *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = TPM2B_Unmarshal(&target->b, sizeof(TPMS_CONTEXT_DATA), buffer, size); } return rc; } /* Table 202 - Definition of TPMS_CONTEXT Structure */ TPM_RC TPMS_CONTEXT_Unmarshal(TPMS_CONTEXT *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; INT32 orig_size = *size; // libtpms added if (rc == TPM_RC_SUCCESS) { rc = UINT64_Unmarshal(&target->sequence, buffer, size); } if (rc == TPM_RC_SUCCESS) { rc = TPMI_DH_SAVED_Unmarshal(&target->savedHandle, buffer, size, NO); } if (rc == TPM_RC_SUCCESS) { rc = TPMI_RH_HIERARCHY_Unmarshal(&target->hierarchy, buffer, size, YES); } if (rc == TPM_RC_SUCCESS) { rc = TPM2B_CONTEXT_DATA_Unmarshal(&target->contextBlob, buffer, size); } // libtpms added begin if (rc == TPM_RC_SUCCESS) { if (*size > 0) { /* Windows 2019 server pads the command TPM_ContextLoad up to the value of * TPM_PT_MAX_OBJECT_CONTENT for the TPMS_CONTEXT part and we end up with * left-over padding bytes here that will make the TPM2_ContextLoad command * fail. This is because we don't just write an OBJECT as the context but use * ANY_OBJECT_Marshal to write it, which consumes less bytes. We had to do * this due to a Linux TPM resource manager bug that couldn't deal with the * larger context sizes once RSA 3072 was enabled and it ran out of memory * when receiving contexts. * Luckily only one command needs TPMS_CONTEXT unmarshalled, so we can adjust * for the left-over padding here but also ONLY do this if * 'orig_size' == value(TPM_PT_MAX_OBJECT_CONTENT). */ static UINT32 tpm_pt_max_object_context; if (tpm_pt_max_object_context == 0) { TPML_TAGGED_TPM_PROPERTY tttp; TPMCapGetProperties(TPM_PT_MAX_OBJECT_CONTEXT, 1, &tttp); if (tttp.count == 1) tpm_pt_max_object_context = tttp.tpmProperty[0].value; } if ((UINT32)orig_size == tpm_pt_max_object_context) *size = 0; /* consume the padding bytes */ } } // libtpms added end return rc; } /* Table 225 - Definition of (UINT32) TPM_AT Constants */ TPM_RC TPM_AT_Unmarshal(TPM_AT *target, BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; if (rc == TPM_RC_SUCCESS) { rc = UINT32_Unmarshal(target, buffer, size); } return rc; } libtpms-0.9.3/src/tpm2/Unmarshal_fp.h000066400000000000000000000616241421143571500174520ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Unmarshal Prototypes */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Unmarshal_fp.h 1603 2020-04-03 17:48:43Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012 - 2019 */ /* */ /********************************************************************************/ /* rev 136 */ #ifndef UNMARSHAL_FP_H #define UNMARSHAL_FP_H #include "Tpm.h" #include "TpmTypes.h" #ifdef __cplusplus extern "C" { #endif LIB_EXPORT TPM_RC UINT8_Unmarshal(UINT8 *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC INT8_Unmarshal(INT8 *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC UINT16_Unmarshal(UINT16 *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC UINT32_Unmarshal(UINT32 *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC UINT64_Unmarshal(UINT64 *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC Array_Unmarshal(BYTE *targetBuffer, UINT16 targetSize, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPM2B_Unmarshal(TPM2B *target, UINT16 targetSize, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPM_KEY_BITS_Unmarshal(TPM_KEY_BITS *target, BYTE **buffer, INT32 *size); #if 0 LIB_EXPORT TPM_RC TPM_GENERATED_Unmarshal(TPM_GENERATED *target, BYTE **buffer, INT32 *size); #endif LIB_EXPORT TPM_RC TPM_ALG_ID_Unmarshal(TPM_ALG_ID *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPM_ECC_CURVE_Unmarshal(TPM_ECC_CURVE *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPM_CC_Unmarshal(TPM_RC *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPM_CLOCK_ADJUST_Unmarshal(TPM_CLOCK_ADJUST *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPM_EO_Unmarshal(TPM_EO *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPM_ST_Unmarshal(TPM_ST *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPM_SU_Unmarshal(TPM_SU *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPM_SE_Unmarshal(TPM_SE *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPM_CAP_Unmarshal(TPM_CAP *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPM_PT_Unmarshal(TPM_HANDLE *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPM_PT_PCR_Unmarshal(TPM_PT_PCR *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPM_HANDLE_Unmarshal(TPM_HANDLE *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMA_ALGORITHM_Unmarshal(TPMA_ALGORITHM *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMA_OBJECT_Unmarshal(TPMA_OBJECT *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMA_SESSION_Unmarshal(TPMA_SESSION *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMA_LOCALITY_Unmarshal(TPMA_LOCALITY *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMA_CC_Unmarshal(TPMA_CC *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMI_YES_NO_Unmarshal(TPMI_YES_NO *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMI_DH_OBJECT_Unmarshal(TPMI_DH_OBJECT *target, BYTE **buffer, INT32 *size, BOOL allowNull); LIB_EXPORT TPM_RC TPMI_DH_PARENT_Unmarshal(TPMI_DH_PARENT *target, BYTE **buffer, INT32 *size, BOOL allowNull); LIB_EXPORT TPM_RC TPMI_DH_PERSISTENT_Unmarshal(TPMI_DH_PERSISTENT *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMI_DH_ENTITY_Unmarshal(TPMI_DH_ENTITY *target, BYTE **buffer, INT32 *size, BOOL allowNull); LIB_EXPORT TPM_RC TPMI_DH_PCR_Unmarshal(TPMI_DH_PCR *target, BYTE **buffer, INT32 *size, BOOL allowNull); LIB_EXPORT TPM_RC TPMI_SH_AUTH_SESSION_Unmarshal(TPMI_SH_AUTH_SESSION *target, BYTE **buffer, INT32 *size, BOOL allowPwd); LIB_EXPORT TPM_RC TPMI_SH_HMAC_Unmarshal(TPMI_SH_HMAC *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMI_SH_POLICY_Unmarshal(TPMI_SH_POLICY *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMI_DH_CONTEXT_Unmarshal(TPMI_DH_CONTEXT *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMI_DH_SAVED_Unmarshal(TPMI_DH_SAVED *target, BYTE **buffer, INT32 *size, BOOL allowNull); LIB_EXPORT TPM_RC TPMI_RH_HIERARCHY_Unmarshal(TPMI_RH_HIERARCHY *target, BYTE **buffer, INT32 *size, BOOL allowNull); LIB_EXPORT TPM_RC TPMI_RH_ENABLES_Unmarshal(TPMI_RH_ENABLES *target, BYTE **buffer, INT32 *size, BOOL allowNull); LIB_EXPORT TPM_RC TPMI_RH_HIERARCHY_AUTH_Unmarshal(TPMI_RH_HIERARCHY_AUTH *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMI_RH_HIERARCHY_POLICY_Unmarshal(TPMI_RH_HIERARCHY_POLICY *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMI_RH_PLATFORM_Unmarshal(TPMI_RH_PLATFORM *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMI_RH_ENDORSEMENT_Unmarshal(TPMI_RH_ENDORSEMENT *target, BYTE **buffer, INT32 *size, BOOL allowNull); LIB_EXPORT TPM_RC TPMI_RH_PROVISION_Unmarshal(TPMI_RH_PROVISION *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMI_RH_CLEAR_Unmarshal(TPMI_RH_CLEAR *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMI_RH_NV_AUTH_Unmarshal(TPMI_RH_NV_AUTH *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMI_RH_LOCKOUT_Unmarshal(TPMI_RH_LOCKOUT *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMI_RH_NV_INDEX_Unmarshal(TPMI_RH_NV_INDEX *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMI_RH_AC_Unmarshal(TPMI_RH_AC *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMI_RH_ACT_Unmarshal(TPMI_RH_ACT *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMI_ALG_HASH_Unmarshal(TPMI_ALG_HASH *target, BYTE **buffer, INT32 *size, BOOL allowNull); LIB_EXPORT TPM_RC TPMI_ALG_SYM_Unmarshal(TPMI_ALG_SYM *target, BYTE **buffer, INT32 *size, BOOL allowNull); LIB_EXPORT TPM_RC TPMI_ALG_SYM_OBJECT_Unmarshal(TPMI_ALG_SYM_OBJECT *target, BYTE **buffer, INT32 *size, BOOL allowNull); LIB_EXPORT TPM_RC TPMI_ALG_SYM_MODE_Unmarshal(TPMI_ALG_SYM_MODE *target, BYTE **buffer, INT32 *size, BOOL allowNull); LIB_EXPORT TPM_RC TPMI_ALG_KDF_Unmarshal(TPMI_ALG_KDF *target, BYTE **buffer, INT32 *size, BOOL allowNull); LIB_EXPORT TPM_RC TPMI_ALG_SIG_SCHEME_Unmarshal(TPMI_ALG_SIG_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull); LIB_EXPORT TPM_RC TPMI_ECC_KEY_EXCHANGE_Unmarshal(TPMI_ECC_KEY_EXCHANGE *target, BYTE **buffer, INT32 *size, BOOL allowNull); LIB_EXPORT TPM_RC TPMI_ST_COMMAND_TAG_Unmarshal(TPMI_ST_COMMAND_TAG *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMI_ALG_MAC_SCHEME_Unmarshal(TPMI_ALG_MAC_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull); LIB_EXPORT TPM_RC TPMI_ALG_CIPHER_MODE_Unmarshal(TPMI_ALG_CIPHER_MODE*target, BYTE **buffer, INT32 *size, BOOL allowNull); LIB_EXPORT TPM_RC TPMS_EMPTY_Unmarshal(TPMS_EMPTY *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMU_HA_Unmarshal(TPMU_HA *target, BYTE **buffer, INT32 *size, UINT32 selector); LIB_EXPORT TPM_RC TPMT_HA_Unmarshal(TPMT_HA *target, BYTE **buffer, INT32 *size, BOOL allowNull); LIB_EXPORT TPM_RC TPM2B_DIGEST_Unmarshal(TPM2B_DIGEST *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPM2B_DATA_Unmarshal(TPM2B_DATA *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPM2B_NONCE_Unmarshal(TPM2B_NONCE *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPM2B_AUTH_Unmarshal(TPM2B_AUTH *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPM2B_EVENT_Unmarshal(TPM2B_EVENT *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPM2B_MAX_BUFFER_Unmarshal(TPM2B_MAX_BUFFER *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPM2B_MAX_NV_BUFFER_Unmarshal(TPM2B_MAX_NV_BUFFER *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPM2B_TIMEOUT_Unmarshal(TPM2B_TIMEOUT *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPM2B_IV_Unmarshal(TPM2B_IV *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPM2B_NAME_Unmarshal(TPM2B_NAME *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMS_PCR_SELECTION_Unmarshal(TPMS_PCR_SELECTION *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMT_TK_CREATION_Unmarshal(TPMT_TK_CREATION *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMT_TK_VERIFIED_Unmarshal(TPMT_TK_VERIFIED *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMT_TK_AUTH_Unmarshal(TPMT_TK_AUTH *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMT_TK_HASHCHECK_Unmarshal(TPMT_TK_HASHCHECK *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMS_ALG_PROPERTY_Unmarshal(TPMS_ALG_PROPERTY *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMS_TAGGED_PROPERTY_Unmarshal(TPMS_TAGGED_PROPERTY *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMS_TAGGED_PCR_SELECT_Unmarshal(TPMS_TAGGED_PCR_SELECT *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPML_CC_Unmarshal(TPML_CC *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMS_TAGGED_POLICY_Unmarshal(TPMS_TAGGED_POLICY *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPML_CCA_Unmarshal(TPML_CCA *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPML_ALG_Unmarshal(TPML_ALG *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPML_HANDLE_Unmarshal(TPML_HANDLE *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPML_DIGEST_Unmarshal(TPML_DIGEST *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPML_DIGEST_VALUES_Unmarshal(TPML_DIGEST_VALUES *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPML_PCR_SELECTION_Unmarshal(TPML_PCR_SELECTION *target, BYTE **buffer, INT32 *size); #if 0 /* libtpms added */ LIB_EXPORT TPM_RC TPML_ALG_PROPERTY_Unmarshal(TPML_ALG_PROPERTY *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPML_TAGGED_TPM_PROPERTY_Unmarshal(TPML_TAGGED_TPM_PROPERTY *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPML_TAGGED_PCR_PROPERTY_Unmarshal(TPML_TAGGED_PCR_PROPERTY *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPML_ECC_CURVE_Unmarshal(TPML_ECC_CURVE *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPML_TAGGED_POLICY_Unmarshal(TPML_TAGGED_POLICY *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMU_CAPABILITIES_Unmarshal(TPMU_CAPABILITIES *target, BYTE **buffer, INT32 *size, UINT32 selector); LIB_EXPORT TPM_RC TPMS_CLOCK_INFO_Unmarshal(TPMS_CLOCK_INFO *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMS_TIME_INFO_Unmarshal(TPMS_TIME_INFO *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMS_TIME_ATTEST_INFO_Unmarshal(TPMS_TIME_ATTEST_INFO *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMS_CERTIFY_INFO_Unmarshal(TPMS_CERTIFY_INFO *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMS_QUOTE_INFO_Unmarshal(TPMS_QUOTE_INFO *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMS_COMMAND_AUDIT_INFO_Unmarshal(TPMS_COMMAND_AUDIT_INFO *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMS_SESSION_AUDIT_INFO_Unmarshal(TPMS_SESSION_AUDIT_INFO *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMS_CREATION_INFO_Unmarshal(TPMS_CREATION_INFO *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMS_NV_CERTIFY_INFO_Unmarshal(TPMS_NV_CERTIFY_INFO *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMI_ST_ATTEST_Unmarshal(TPMI_ST_ATTEST *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMU_ATTEST_Unmarshal(TPMU_ATTEST *target, BYTE **buffer, INT32 *size, UINT32 selector); LIB_EXPORT TPM_RC TPMS_ATTEST_Unmarshal(TPMS_ATTEST *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPM2B_ATTEST_Unmarshal(TPM2B_ATTEST *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMS_CAPABILITY_DATA_Unmarshal(TPMS_CAPABILITY_DATA *target, BYTE **buffer, INT32 *size); #endif /* libtpms added */ LIB_EXPORT TPM_RC TPMI_AES_KEY_BITS_Unmarshal(TPMI_AES_KEY_BITS *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMI_CAMELLIA_KEY_BITS_Unmarshal(TPMI_CAMELLIA_KEY_BITS *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC /* libtpms added */ TPMI_TDES_KEY_BITS_Unmarshal(TPMI_SM4_KEY_BITS *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMU_SYM_KEY_BITS_Unmarshal(TPMU_SYM_KEY_BITS *target, BYTE **buffer, INT32 *size, UINT32 selector); LIB_EXPORT TPM_RC TPMU_SYM_MODE_Unmarshal(TPMU_SYM_MODE *target, BYTE **buffer, INT32 *size, UINT32 selector); LIB_EXPORT TPM_RC TPMT_SYM_DEF_Unmarshal(TPMT_SYM_DEF *target, BYTE **buffer, INT32 *size, BOOL allowNull); LIB_EXPORT TPM_RC TPMT_SYM_DEF_OBJECT_Unmarshal(TPMT_SYM_DEF_OBJECT *target, BYTE **buffer, INT32 *size, BOOL allowNull); LIB_EXPORT TPM_RC TPM2B_SYM_KEY_Unmarshal(TPM2B_SYM_KEY *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMS_SYMCIPHER_PARMS_Unmarshal(TPMS_SYMCIPHER_PARMS *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPM2B_LABEL_Unmarshal(TPM2B_LABEL *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMS_DERIVE_Unmarshal(TPMS_DERIVE *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPM2B_SENSITIVE_DATA_Unmarshal(TPM2B_SENSITIVE_DATA *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMS_SENSITIVE_CREATE_Unmarshal(TPMS_SENSITIVE_CREATE *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPM2B_SENSITIVE_CREATE_Unmarshal(TPM2B_SENSITIVE_CREATE *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMS_SCHEME_HASH_Unmarshal(TPMS_SCHEME_HASH *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMS_SCHEME_ECDAA_Unmarshal(TPMS_SCHEME_ECDAA *target, BYTE **buffer, INT32 *size) ; LIB_EXPORT TPM_RC TPMI_ALG_KEYEDHASH_SCHEME_Unmarshal(TPMI_ALG_KEYEDHASH_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull); LIB_EXPORT TPM_RC TPMS_SCHEME_HMAC_Unmarshal(TPMS_SCHEME_HMAC *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMS_SCHEME_XOR_Unmarshal(TPMS_SCHEME_XOR *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMU_SCHEME_KEYEDHASH_Unmarshal(TPMU_SCHEME_KEYEDHASH *target, BYTE **buffer, INT32 *size, UINT32 selector); LIB_EXPORT TPM_RC TPMT_KEYEDHASH_SCHEME_Unmarshal(TPMT_KEYEDHASH_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull); LIB_EXPORT TPM_RC TPMS_SIG_SCHEME_ECDAA_Unmarshal(TPMS_SIG_SCHEME_ECDAA *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMS_SIG_SCHEME_ECDSA_Unmarshal(TPMS_SIG_SCHEME_ECDSA *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMS_SIG_SCHEME_ECSCHNORR_Unmarshal(TPMS_SIG_SCHEME_ECSCHNORR *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMS_SIG_SCHEME_RSAPSS_Unmarshal(TPMS_SIG_SCHEME_RSAPSS *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMS_SIG_SCHEME_RSASSA_Unmarshal(TPMS_SIG_SCHEME_RSASSA *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMS_SIG_SCHEME_SM2_Unmarshal(TPMS_SIG_SCHEME_SM2 *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMU_SIG_SCHEME_Unmarshal(TPMU_SIG_SCHEME *target, BYTE **buffer, INT32 *size, UINT32 selector); LIB_EXPORT TPM_RC TPMT_SIG_SCHEME_Unmarshal(TPMT_SIG_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull); LIB_EXPORT TPM_RC TPMS_ENC_SCHEME_OAEP_Unmarshal(TPMS_ENC_SCHEME_OAEP *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMS_ENC_SCHEME_RSAES_Unmarshal(TPMS_ENC_SCHEME_RSAES *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMS_KEY_SCHEME_ECDH_Unmarshal(TPMS_KEY_SCHEME_ECDH *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMS_KEY_SCHEME_ECMQV_Unmarshal(TPMS_KEY_SCHEME_ECMQV *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMS_KDF_SCHEME_KDF1_SP800_108_Unmarshal(TPMS_KDF_SCHEME_KDF1_SP800_108 *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMS_KDF_SCHEME_KDF1_SP800_56A_Unmarshal(TPMS_KDF_SCHEME_KDF1_SP800_56A *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMS_KDF_SCHEME_KDF2_Unmarshal(TPMS_KDF_SCHEME_KDF2 *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMS_KDF_SCHEME_MGF1_Unmarshal(TPMS_KDF_SCHEME_MGF1 *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMU_KDF_SCHEME_Unmarshal(TPMU_KDF_SCHEME *target, BYTE **buffer, INT32 *size, UINT32 selector); LIB_EXPORT TPM_RC TPMT_KDF_SCHEME_Unmarshal(TPMT_KDF_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull); #if 0 /* libtpms added */ LIB_EXPORT TPM_RC TPMI_ALG_ASYM_SCHEME_Unmarshal(TPMI_ALG_ASYM_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull); #endif /* libtpms added */ LIB_EXPORT TPM_RC TPMU_ASYM_SCHEME_Unmarshal(TPMU_ASYM_SCHEME *target, BYTE **buffer, INT32 *size, UINT32 selector); LIB_EXPORT TPM_RC TPMI_ALG_RSA_SCHEME_Unmarshal(TPMI_ALG_RSA_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull); LIB_EXPORT TPM_RC TPMT_RSA_SCHEME_Unmarshal(TPMT_RSA_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull); LIB_EXPORT TPM_RC TPMI_ALG_RSA_DECRYPT_Unmarshal(TPMI_ALG_RSA_DECRYPT *target, BYTE **buffer, INT32 *size, BOOL allowNull); LIB_EXPORT TPM_RC TPMT_RSA_DECRYPT_Unmarshal(TPMT_RSA_DECRYPT *target, BYTE **buffer, INT32 *size, BOOL allowNull); LIB_EXPORT TPM_RC TPM2B_PUBLIC_KEY_RSA_Unmarshal(TPM2B_PUBLIC_KEY_RSA *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMI_RSA_KEY_BITS_Unmarshal(TPMI_RSA_KEY_BITS *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPM2B_PRIVATE_KEY_RSA_Unmarshal(TPM2B_PRIVATE_KEY_RSA *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPM2B_ECC_PARAMETER_Unmarshal(TPM2B_ECC_PARAMETER *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMS_ECC_POINT_Unmarshal(TPMS_ECC_POINT *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPM2B_ECC_POINT_Unmarshal(TPM2B_ECC_POINT *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMI_ALG_ECC_SCHEME_Unmarshal(TPMI_ALG_ECC_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull); LIB_EXPORT TPM_RC TPMI_ECC_CURVE_Unmarshal(TPMI_ECC_CURVE *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMT_ECC_SCHEME_Unmarshal(TPMT_ECC_SCHEME *target, BYTE **buffer, INT32 *size, BOOL allowNull); LIB_EXPORT TPM_RC TPMS_SIGNATURE_RSA_Unmarshal(TPMS_SIGNATURE_RSA *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMS_SIGNATURE_RSASSA_Unmarshal(TPMS_SIGNATURE_RSASSA *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMS_SIGNATURE_RSAPSS_Unmarshal(TPMS_SIGNATURE_RSAPSS *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMS_SIGNATURE_ECC_Unmarshal(TPMS_SIGNATURE_ECC *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMS_SIGNATURE_ECDSA_Unmarshal(TPMS_SIGNATURE_ECDSA *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMS_SIGNATURE_ECDAA_Unmarshal(TPMS_SIGNATURE_ECDAA *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMS_SIGNATURE_SM2_Unmarshal(TPMS_SIGNATURE_SM2 *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMS_SIGNATURE_ECSCHNORR_Unmarshal(TPMS_SIGNATURE_ECSCHNORR *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMU_SIGNATURE_Unmarshal(TPMU_SIGNATURE *target, BYTE **buffer, INT32 *size, UINT32 selector); LIB_EXPORT TPM_RC TPMT_SIGNATURE_Unmarshal(TPMT_SIGNATURE *target, BYTE **buffer, INT32 *size, BOOL allowNull); LIB_EXPORT TPM_RC TPM2B_ENCRYPTED_SECRET_Unmarshal(TPM2B_ENCRYPTED_SECRET *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMI_ALG_PUBLIC_Unmarshal(TPMI_ALG_PUBLIC *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMU_PUBLIC_ID_Unmarshal(TPMU_PUBLIC_ID *target, BYTE **buffer, INT32 *size, UINT32 selector); LIB_EXPORT TPM_RC TPMS_KEYEDHASH_PARMS_Unmarshal(TPMS_KEYEDHASH_PARMS *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMS_RSA_PARMS_Unmarshal(TPMS_RSA_PARMS *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMS_ECC_PARMS_Unmarshal(TPMS_ECC_PARMS *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMU_PUBLIC_PARMS_Unmarshal(TPMU_PUBLIC_PARMS *target, BYTE **buffer, INT32 *size, UINT32 selector); LIB_EXPORT TPM_RC TPMT_PUBLIC_PARMS_Unmarshal(TPMT_PUBLIC_PARMS *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMT_PUBLIC_Unmarshal(TPMT_PUBLIC *target, BYTE **buffer, INT32 *size, BOOL allowNull); LIB_EXPORT TPM_RC TPM2B_PUBLIC_Unmarshal(TPM2B_PUBLIC *target, BYTE **buffer, INT32 *size, BOOL allowNull); LIB_EXPORT TPM_RC TPM2B_TEMPLATE_Unmarshal(TPM2B_TEMPLATE *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMU_SENSITIVE_COMPOSITE_Unmarshal(TPMU_SENSITIVE_COMPOSITE *target, BYTE **buffer, INT32 *size, UINT32 selector); LIB_EXPORT TPM_RC TPMT_SENSITIVE_Unmarshal(TPMT_SENSITIVE *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPM2B_SENSITIVE_Unmarshal(TPM2B_SENSITIVE *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPM2B_PRIVATE_Unmarshal(TPM2B_PRIVATE *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPM2B_ID_OBJECT_Unmarshal(TPM2B_ID_OBJECT *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMA_NV_Unmarshal(TPMA_NV *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMS_NV_PUBLIC_Unmarshal(TPMS_NV_PUBLIC *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPM2B_NV_PUBLIC_Unmarshal(TPM2B_NV_PUBLIC *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPM2B_CONTEXT_SENSITIVE_Unmarshal(TPM2B_CONTEXT_SENSITIVE *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPM2B_CONTEXT_DATA_Unmarshal(TPM2B_CONTEXT_DATA *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPMS_CONTEXT_Unmarshal(TPMS_CONTEXT *target, BYTE **buffer, INT32 *size); LIB_EXPORT TPM_RC TPM_AT_Unmarshal(TPM_AT *target, BYTE **buffer, INT32 *size); #ifdef __cplusplus } #endif #endif libtpms-0.9.3/src/tpm2/Unseal_fp.h000066400000000000000000000071721421143571500167450ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Unseal_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef UNSEAL_FP_H #define UNSEAL_FP_H typedef struct { TPMI_DH_OBJECT itemHandle; } Unseal_In; #define RC_Unseal_itemHandle (TPM_RC_H + TPM_RC_1) typedef struct { TPM2B_SENSITIVE_DATA outData; } Unseal_Out; TPM_RC TPM2_Unseal( Unseal_In *in, Unseal_Out *out ); #endif libtpms-0.9.3/src/tpm2/Utils.h000066400000000000000000000045371421143571500161330ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Utility functions */ /* Written by Stefan Berger */ /* IBM Thomas J. Watson Research Center */ /* */ /* (c) Copyright IBM Corporation 2017,2018. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef UTILS_H #define UTILS_H #include "Memory_fp.h" #define TPM2_ROUNDUP(VAL, SIZE) \ ( ( (VAL) + (SIZE) - 1) / (SIZE) ) * (SIZE) __attribute__((unused)) static inline void clear_and_free(void *ptr, size_t size) { if (ptr) { MemorySet(ptr, 0, size); free(ptr); } } #endif /* UTILS_H */ libtpms-0.9.3/src/tpm2/VendorString.h000066400000000000000000000124751421143571500174570ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Vendor String */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: VendorString.h 1519 2019-11-15 20:43:51Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ #ifndef VENDORSTRING_H #define VENDORSTRING_H /* Define up to 4-byte values for MANUFACTURER. This value defines the response for TPM_PT_MANUFACTURER in TPM2_GetCapability(). The following line should be un-commented and a vendor specific string should be provided here. */ #define MANUFACTURER "IBM" /* The following #if macro may be deleted after a proper MANUFACTURER is provided. */ #ifndef MANUFACTURER #error MANUFACTURER is not provided. \ Please modify VendorString.h to provide a specific \ manufacturer name. #endif /* Define up to 4, 4-byte, vendor-specific values. The values must each be 4 bytes long and the last value used may contain trailing zeros. These values define the response for TPM_PT_VENDOR_STRING_(1-4) in TPM2_GetCapability(). The following line should be un-commented and a vendor specific string. The vendor strings 2-4 may also be defined as appropriate. */ #define VENDOR_STRING_1 "SW " #define VENDOR_STRING_2 " TPM" //#define VENDOR_STRING_3 //#define VENDOR_STRING_4 /* The following #if macro may be deleted after a proper VENDOR_STRING_1 is provided. */ #ifndef VENDOR_STRING_1 #error VENDOR_STRING_1 is not provided. \ Please modify VendorString.h to provide a vendor specific string. #endif /* the more significant 32-bits of a vendor-specific value indicating the version of the firmware The following line should be un-commented and a vendor specific firmware V1 should be provided here. The FIRMWARE_V2 may also be defined as appropriate. */ #define FIRMWARE_V1 (0x20191023) // the less significant 32-bits of a vendor-specific value indicating the version of the firmware #define FIRMWARE_V2 (0x00163636) // The following #if macro may be deleted after a proper FIRMWARE_V1 is provided. #ifndef FIRMWARE_V1 #error FIRMWARE_V1 is not provided. \ Please modify VendorString.h to provide a vendor specific firmware \ version #endif #endif libtpms-0.9.3/src/tpm2/Vendor_TCG_Test.c000066400000000000000000000073401421143571500177520ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Vendor_TCG_Test.c 1548 2019-12-13 23:15:40Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 */ /* */ /********************************************************************************/ #include "Tpm.h" #include "Vendor_TCG_Test_fp.h" #include "Marshal_fp.h" #if CC_Vendor_TCG_Test /* A dummy function for testing. */ TPM_RC TPM2_Vendor_TCG_Test( Vendor_TCG_Test_In *in, // IN: input parameter list Vendor_TCG_Test_Out *out // OUT: output parameter list ) { out->outputData = in->inputData; return TPM_RC_SUCCESS; } #endif // CC_Vendor_TCG_Test libtpms-0.9.3/src/tpm2/Vendor_TCG_Test_fp.h000066400000000000000000000073461421143571500204520ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Sample Vendor Specific Command */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: Vendor_TCG_Test_fp.h 1635 2020-06-12 21:48:27Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2020 */ /* */ /********************************************************************************/ #ifndef VENDOR_TCG_TEST_FP_H #define VENDOR_TCG_TEST_FP_H typedef struct { TPM2B_DATA inputData; } Vendor_TCG_Test_In; typedef struct { TPM2B_DATA outputData; } Vendor_TCG_Test_Out; TPM_RC TPM2_Vendor_TCG_Test( Vendor_TCG_Test_In *in, // IN: input parameter list Vendor_TCG_Test_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/VerifySignature_fp.h000066400000000000000000000077071421143571500206500ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: VerifySignature_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef VERIFYSIGNATURE_FP_H #define VERIFYSIGNATURE_FP_H typedef struct { TPMI_DH_OBJECT keyHandle; TPM2B_DIGEST digest; TPMT_SIGNATURE signature; } VerifySignature_In; #define RC_VerifySignature_keyHandle (TPM_RC_H + TPM_RC_1) #define RC_VerifySignature_digest (TPM_RC_P + TPM_RC_1) #define RC_VerifySignature_signature (TPM_RC_P + TPM_RC_2) typedef struct { TPMT_TK_VERIFIED validation; } VerifySignature_Out; TPM_RC TPM2_VerifySignature( VerifySignature_In *in, // IN: input parameter list VerifySignature_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/Volatile.c000066400000000000000000000102541421143571500165760ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Marshalling and unmarshalling of state */ /* Written by Stefan Berger */ /* IBM Thomas J. Watson Research Center */ /* */ /* (c) Copyright IBM Corporation 2017,2018. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #if defined __FreeBSD__ || defined __DragonFly__ # include #elif defined __APPLE__ # include #else # include #endif #include #include "config.h" #include "assert.h" #include "NVMarshal.h" #include "Volatile.h" #define TPM_HAVE_TPM2_DECLARATIONS #include "tpm_library_intern.h" TPM_RC VolatileState_Load(BYTE **buffer, INT32 *size) { TPM_RC rc = TPM_RC_SUCCESS; BYTE hash[SHA1_DIGEST_SIZE], acthash[SHA1_DIGEST_SIZE]; UINT16 hashAlg = TPM_ALG_SHA1; if (rc == TPM_RC_SUCCESS) { if ((UINT32)*size < sizeof(hash)) return TPM_RC_INSUFFICIENT; CryptHashBlock(hashAlg, *size - sizeof(hash), *buffer, sizeof(acthash), acthash); rc = VolatileState_Unmarshal(buffer, size); /* specific error has already been reported */ } if (rc == TPM_RC_SUCCESS) { /* * advance pointer towards hash if we have a later version of * the state that has extra data we didn't read */ if (*size > 0 && (UINT32)*size > sizeof(hash)) { *buffer += *size - sizeof(hash); *size = sizeof(hash); } rc = Array_Unmarshal(hash, sizeof(hash), buffer, size); if (rc != TPM_RC_SUCCESS) TPMLIB_LogTPM2Error("Error unmarshalling volatile state hash: " "0x%02x\n", rc); } if (rc == TPM_RC_SUCCESS) { if (memcmp(acthash, hash, sizeof(hash))) { rc = TPM_RC_HASH; TPMLIB_LogTPM2Error("Volatile state checksum error: 0x%02x\n", rc); } } if (rc != TPM_RC_SUCCESS) g_inFailureMode = TRUE; return rc; } UINT16 VolatileState_Save(BYTE **buffer, INT32 *size) { UINT16 written; const BYTE *start; BYTE hash[SHA1_DIGEST_SIZE]; TPM_ALG_ID hashAlg = TPM_ALG_SHA1; start = *buffer; written = VolatileState_Marshal(buffer, size); /* append the checksum */ CryptHashBlock(hashAlg, written, start, sizeof(hash), hash); written += Array_Marshal(hash, sizeof(hash), buffer, size); return written; } libtpms-0.9.3/src/tpm2/Volatile.h000066400000000000000000000043631421143571500166070ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Marshalling and unmarshalling of state */ /* Written by Stefan Berger */ /* IBM Thomas J. Watson Research Center */ /* */ /* (c) Copyright IBM Corporation 2017,2018. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef VOLATILE_H #define VOLATILE_H #include "BaseTypes.h" TPM_RC VolatileState_Load(BYTE **buffer, INT32 *size); UINT16 VolatileState_Save(BYTE **buffer, INT32 *size); #endif /* VOLATILE_H */ libtpms-0.9.3/src/tpm2/X509.h000066400000000000000000000150321421143571500154700ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Macro and Structure Definitions for the X509 Commands and Functions. */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: X509.h 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2019 - 2021 */ /* */ /********************************************************************************/ // 10.1.16 X509.h // 10.1.16.1 Introduction // This file contains the macro and structure definitions for the X509 commands and functions. #ifndef _X509_H_ #define _X509_H_ // 10.1.16.2 Includes #include "Tpm.h" #include "TpmAsn1.h" // 10.1.16.3 Defined Constants // 10.1.16.3.1 X509 Application-specific types #define X509_SELECTION 0xA0 #define X509_ISSUER_UNIQUE_ID 0xA1 #define X509_SUBJECT_UNIQUE_ID 0xA2 #define X509_EXTENSIONS 0xA3 // These defines give the order in which values appear in the TBScertificate of an x.509 // certificate. These values are used to index into an array of #define ENCODED_SIZE_REF 0 #define VERSION_REF (ENCODED_SIZE_REF + 1) #define SERIAL_NUMBER_REF (VERSION_REF + 1) #define SIGNATURE_REF (SERIAL_NUMBER_REF + 1) #define ISSUER_REF (SIGNATURE_REF + 1) #define VALIDITY_REF (ISSUER_REF + 1) #define SUBJECT_KEY_REF (VALIDITY_REF + 1) #define SUBJECT_PUBLIC_KEY_REF (SUBJECT_KEY_REF + 1) #define EXTENSIONS_REF (SUBJECT_PUBLIC_KEY_REF + 1) #define REF_COUNT (EXTENSIONS_REF + 1) // 10.1.16.4 Structures Used to access the fields of a TBSsignature some of which are in the // in_CertifyX509 structure and some of which are in the out_CertifyX509 structure. typedef struct stringRef { BYTE *buf; INT16 len; } stringRef; // This is defined to avoid bit by bit comparisons within a UINT32 typedef union x509KeyUsageUnion { TPMA_X509_KEY_USAGE x509; UINT32 integer; } x509KeyUsageUnion; // 10.1.16.5 Global X509 Constants // These values are instanced by X509_spt.c and referenced by other X509-related files. This is the // DER-encoded value for the Key Usage OID (2.5.29.15). This is the full OID, not just the numeric // value #define OID_KEY_USAGE_EXTENSION_VALUE 0x06, 0x03, 0x55, 0x1D, 0x0F MAKE_OID(_KEY_USAGE_EXTENSION); // This is the DER-encoded value for the TCG-defined TPMA_OBJECT OID (2.23.133.10.1.1.1) #define OID_TCG_TPMA_OBJECT_VALUE 0x06, 0x07, 0x67, 0x81, 0x05, 0x0a, 0x01, \ 0x01, 0x01 MAKE_OID(_TCG_TPMA_OBJECT); #ifdef _X509_SPT_ // If a bit is SET in KEY_USAGE_SIGN is also SET in keyUsage then the associated key has to have // sign SET. const x509KeyUsageUnion KEY_USAGE_SIGN = {TPMA_X509_KEY_USAGE_INITIALIZER( /* bits_at_0 */ 0, /* decipheronly */ 0, /* encipheronly */ 0, /* crlsign */ 1, /* keycertsign */ 1, /* keyagreement */ 0, /* dataencipherment */ 0, /* keyencipherment */ 0, /* nonrepudiation */ 0, /* digitalsignature */ 1)}; // If a bit is SET in KEY_USAGE_DECRYPT is also SET in keyUsage then the associated key has to have decrypt SET. const x509KeyUsageUnion KEY_USAGE_DECRYPT = {TPMA_X509_KEY_USAGE_INITIALIZER( /* bits_at_0 */ 0, /* decipheronly */ 1, /* encipheronly */ 1, /* crlsign */ 0, /* keycertsign */ 0, /* keyagreement */ 1, /* dataencipherment */ 1, /* keyencipherment */ 1, /* nonrepudiation */ 0, /* digitalsignature */ 0)}; #else extern x509KeyUsageUnion KEY_USAGE_SIGN; extern x509KeyUsageUnion KEY_USAGE_DECRYPT; #endif #endif // _X509_H_ libtpms-0.9.3/src/tpm2/X509_ECC.c000066400000000000000000000154421421143571500161420ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM X509 ECC */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: X509_ECC.c 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2019 - 2021 */ /* */ /********************************************************************************/ /* 10.2.24 X509_ECC.c */ /* 10.2.24.1 Includes */ #include "Tpm.h" #include "X509.h" #include "OIDs.h" #include "TpmAsn1_fp.h" #include "X509_ECC_fp.h" #include "X509_spt_fp.h" #include "CryptHash_fp.h" /* 10.2.24.2 Functions */ /* 10.2.24.2.1 X509PushPoint() */ /* This seems like it might be used more than once so... */ /* Return Value Meaning */ /* > 0 number of bytes added */ /* == 0 failure */ INT16 X509PushPoint( ASN1MarshalContext *ctx, TPMS_ECC_POINT *p ) { // Push a bit string containing the public key. For now, push the x, and y // coordinates of the public point, bottom up ASN1StartMarshalContext(ctx); // BIT STRING { ASN1PushBytes(ctx, p->y.t.size, p->y.t.buffer); ASN1PushBytes(ctx, p->x.t.size, p->x.t.buffer); ASN1PushByte(ctx, 0x04); } return ASN1EndEncapsulation(ctx, ASN1_BITSTRING); // Ends BIT STRING } /* 10.2.24.2.2 X509AddSigningAlgorithmECC() */ /* This creates the singing algorithm data. */ /* Return Value Meaning */ /* > 0 number of bytes added */ /* == 0 failure */ INT16 X509AddSigningAlgorithmECC( OBJECT *signKey, TPMT_SIG_SCHEME *scheme, ASN1MarshalContext *ctx ) { PHASH_DEF hashDef = CryptGetHashDef(scheme->details.any.hashAlg); // NOT_REFERENCED(signKey); // If the desired hashAlg definition wasn't found... if(hashDef->hashAlg != scheme->details.any.hashAlg) return 0; switch(scheme->scheme) { #if ALG_ECDSA case TPM_ALG_ECDSA: // Make sure that we have an OID for this hash and ECC if((hashDef->ECDSA)[0] != ASN1_OBJECT_IDENTIFIER) break; // if this is just an implementation check, indicate that this // combination is supported if(!ctx) return 1; ASN1StartMarshalContext(ctx); ASN1PushOID(ctx, hashDef->ECDSA); return ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE); #endif // ALG_ECDSA default: break; } return 0; } /* 10.2.24.2.3 X509AddPublicECC() */ /* This function will add the publicKey description to the DER data. If ctx is NULL, then no data is transferred and this function will indicate if the TPM has the values for DER-encoding of the public key. */ /* Return Value Meaning */ /* > 0 number of bytes added */ /* == 0 failure */ INT16 X509AddPublicECC( OBJECT *object, ASN1MarshalContext *ctx ) { const BYTE *curveOid = CryptEccGetOID(object->publicArea.parameters.eccDetail.curveID); if((curveOid == NULL) || (*curveOid != ASN1_OBJECT_IDENTIFIER)) return 0; // // // SEQUENCE (2 elem) 1st // SEQUENCE (2 elem) 2nd // OBJECT IDENTIFIER 1.2.840.10045.2.1 ecPublicKey (ANSI X9.62 public key type) // OBJECT IDENTIFIER 1.2.840.10045.3.1.7 prime256v1 (ANSI X9.62 named curve) // BIT STRING (520 bit) 000001001010000111010101010111001001101101000100000010... // // If this is a check to see if the key can be encoded, it can. // Need to mark the end sequence if(ctx == NULL) return 1; ASN1StartMarshalContext(ctx); // SEQUENCE (2 elem) 1st { X509PushPoint(ctx, &object->publicArea.unique.ecc); // BIT STRING ASN1StartMarshalContext(ctx); // SEQUENCE (2 elem) 2nd { ASN1PushOID(ctx, curveOid); // curve dependent ASN1PushOID(ctx, OID_ECC_PUBLIC); // (1.2.840.10045.2.1) } ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE); // Ends SEQUENCE 2nd } return ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE); // Ends SEQUENCE 1st } libtpms-0.9.3/src/tpm2/X509_ECC_fp.h000066400000000000000000000073141421143571500166330ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM X509 ECC */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: X509_ECC_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2019 */ /* */ /********************************************************************************/ #ifndef X509_ECC_FP_H #define X509_ECC_FP_H INT16 X509PushPoint( ASN1MarshalContext *ctx, TPMS_ECC_POINT *p ); INT16 X509AddSigningAlgorithmECC( OBJECT *signKey, TPMT_SIG_SCHEME *scheme, ASN1MarshalContext *ctx ); INT16 X509AddPublicECC( OBJECT *object, ASN1MarshalContext *ctx ); #endif libtpms-0.9.3/src/tpm2/X509_RSA.c000066400000000000000000000256441421143571500162020ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM X509 RSA */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: X509_RSA.c 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2019 - 2021 */ /* */ /********************************************************************************/ /* 10.2.25 X509_RSA.c */ /* 10.2.25.1 Includes */ #include "Tpm.h" #include "X509.h" #include "TpmAsn1_fp.h" #include "X509_RSA_fp.h" #include "X509_spt_fp.h" #include "CryptHash_fp.h" #include "CryptRsa_fp.h" /* 10.2.25.2 Functions */ #if ALG_RSA /* 10.2.25.2.1 X509AddSigningAlgorithmRSA() */ /* This creates the singing algorithm data. */ /* Return Value Meaning */ /* > 0 number of bytes added */ /* == 0 failure */ INT16 X509AddSigningAlgorithmRSA( OBJECT *signKey, TPMT_SIG_SCHEME *scheme, ASN1MarshalContext *ctx ) { TPM_ALG_ID hashAlg = scheme->details.any.hashAlg; PHASH_DEF hashDef = CryptGetHashDef(hashAlg); // NOT_REFERENCED(signKey); // return failure if hash isn't implemented if(hashDef->hashAlg != hashAlg) return 0; switch(scheme->scheme) { case TPM_ALG_RSASSA: { // if the hash is implemented but there is no PKCS1 OID defined // then this is not a valid signing combination. if(hashDef->PKCS1[0] != ASN1_OBJECT_IDENTIFIER) break; if(ctx == NULL) return 1; return X509PushAlgorithmIdentifierSequence(ctx, hashDef->PKCS1); } case TPM_ALG_RSAPSS: // leave if this is just an implementation check if(ctx == NULL) return 1; // In the case of SHA1, everything is default and RFC4055 says that // implementations that do signature generation MUST omit the parameter // when defaults are used. )-: if(hashDef->hashAlg == TPM_ALG_SHA1) { return X509PushAlgorithmIdentifierSequence(ctx, OID_RSAPSS); } else { // Going to build something that looks like: // SEQUENCE (2 elem) // OBJECT IDENTIFIER 1.2.840.113549.1.1.10 rsaPSS (PKCS #1) // SEQUENCE (3 elem) // [0] (1 elem) // SEQUENCE (2 elem) // OBJECT IDENTIFIER 2.16.840.1.101.3.4.2.1 sha-256 // NULL // [1] (1 elem) // SEQUENCE (2 elem) // OBJECT IDENTIFIER 1.2.840.113549.1.1.8 pkcs1-MGF // SEQUENCE (2 elem) // OBJECT IDENTIFIER 2.16.840.1.101.3.4.2.1 sha-256 // NULL // [2] (1 elem) salt length // INTEGER 32 // The indentation is just to keep track of where we are in the // structure ASN1StartMarshalContext(ctx); // SEQUENCE (2 elements) { ASN1StartMarshalContext(ctx); // SEQUENCE (3 elements) { // [2] (1 elem) salt length // INTEGER 32 ASN1StartMarshalContext(ctx); { INT16 saltSize = CryptRsaPssSaltSize((INT16)hashDef->digestSize, (INT16)signKey->publicArea.unique.rsa.t.size); ASN1PushUINT(ctx, saltSize); } ASN1EndEncapsulation(ctx, ASN1_APPLICAIION_SPECIFIC + 2); // Add the mask generation algorithm // [1] (1 elem) // SEQUENCE (2 elem) 1st // OBJECT IDENTIFIER 1.2.840.113549.1.1.8 pkcs1-MGF // SEQUENCE (2 elem) 2nd // OBJECT IDENTIFIER 2.16.840.1.101.3.4.2.1 sha-256 // NULL ASN1StartMarshalContext(ctx); // mask context [1] (1 elem) { ASN1StartMarshalContext(ctx); // SEQUENCE (2 elem) 1st // Handle the 2nd Sequence (sequence (object, null)) { // This adds a NULL, then an OID and a SEQUENCE // wrapper. X509PushAlgorithmIdentifierSequence(ctx, hashDef->OID); // add the pkcs1-MGF OID ASN1PushOID(ctx, OID_MGF1); } // End outer sequence ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE); } // End the [1] ASN1EndEncapsulation(ctx, ASN1_APPLICAIION_SPECIFIC + 1); // Add the hash algorithm // [0] (1 elem) // SEQUENCE (2 elem) (done by // X509PushAlgorithmIdentifierSequence) // OBJECT IDENTIFIER 2.16.840.1.101.3.4.2.1 sha-256 (NIST) // NULL ASN1StartMarshalContext(ctx); // [0] (1 elem) { X509PushAlgorithmIdentifierSequence(ctx, hashDef->OID); } ASN1EndEncapsulation(ctx, (ASN1_APPLICAIION_SPECIFIC + 0)); } // SEQUENCE (3 elements) end ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE); // RSA PSS OID // OBJECT IDENTIFIER 1.2.840.113549.1.1.10 rsaPSS (PKCS #1) ASN1PushOID(ctx, OID_RSAPSS); } // End Sequence (2 elements) return ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE); } default: break; } return 0; } /* 10.2.25.2.2 X509AddPublicRSA() */ /* This function will add the publicKey description to the DER data. If fillPtr is NULL, then no data is transferred and this function will indicate if the TPM has the values for DER-encoding of the public key. */ /* Return Value Meaning */ /* > 0 number of bytes added */ /* == 0 failure */ INT16 X509AddPublicRSA( OBJECT *object, ASN1MarshalContext *ctx ) { UINT32 exp = object->publicArea.parameters.rsaDetail.exponent; // // If this is a check to see if the key can be encoded, it can. // Need to mark the end sequence if(ctx == NULL) return 1; ASN1StartMarshalContext(ctx); // SEQUENCE (2 elem) 1st ASN1StartMarshalContext(ctx); // BIT STRING ASN1StartMarshalContext(ctx); // SEQUENCE *(2 elem) 3rd // Get public exponent in big-endian byte order. if(exp == 0) exp = RSA_DEFAULT_PUBLIC_EXPONENT; // Push a 4 byte integer. This might get reduced if there are leading zeros or // extended if the high order byte is negative. ASN1PushUINT(ctx, exp); // Push the public key as an integer ASN1PushInteger(ctx, object->publicArea.unique.rsa.t.size, object->publicArea.unique.rsa.t.buffer); // Embed this in a SEQUENCE tag and length in for the key, exponent sequence ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE); // SEQUENCE (3rd) // Embed this in a BIT STRING ASN1EndEncapsulation(ctx, ASN1_BITSTRING); // Now add the formatted SEQUENCE for the RSA public key OID. This is a // fully constructed value so it doesn't need to have a context started X509PushAlgorithmIdentifierSequence(ctx, OID_PKCS1_PUB); return ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE); } #endif // ALG_RSA libtpms-0.9.3/src/tpm2/X509_RSA_fp.h000066400000000000000000000071501421143571500166640ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM X509 RSA */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: X509_RSA_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2019 */ /* */ /********************************************************************************/ #ifndef X509_RSA_FP_H #define X509_RSA_FP_H INT16 X509AddSigningAlgorithmRSA( OBJECT *signKey, TPMT_SIG_SCHEME *scheme, ASN1MarshalContext *ctx ); INT16 X509AddPublicRSA( OBJECT *object, ASN1MarshalContext *ctx ); #endif libtpms-0.9.3/src/tpm2/X509_spt.c000066400000000000000000000267711421143571500163650ustar00rootroot00000000000000/********************************************************************************/ /* */ /* X509 Support */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: X509_spt.c 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG rants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2019 - 2021 */ /* */ /********************************************************************************/ /* 10.2.26 X509_spt.c */ /* 10.2.26.1 Includes */ #include "Tpm.h" #include "TpmAsn1.h" #include "TpmAsn1_fp.h" #define _X509_SPT_ #include "X509.h" #include "X509_spt_fp.h" #if ALG_RSA # include "X509_RSA_fp.h" #endif // ALG_RSA #if ALG_ECC # include "X509_ECC_fp.h" #endif // ALG_ECC #if ALG_SM2 //# include "X509_SM2_fp.h" #endif // ALG_RSA /* 10.2.26.2 Unmarshaling Functions */ /* 10.2.26.2.1 X509FindExtensionByOID() */ /* This will search a list of X509 extensions to find an extension with the requested OID. If the extension is found, the output context (ctx) is set up to point to the OID in the extension. */ /* Return Value Meaning */ /* TRUE(1) success */ /* FALSE(0) failure (could be catastrophic) */ BOOL X509FindExtensionByOID( ASN1UnmarshalContext *ctxIn, // IN: the context to search ASN1UnmarshalContext *ctx, // OUT: the extension context const BYTE *OID // IN: oid to search for ) { INT16 length; // pAssert(ctxIn != NULL); // Make the search non-destructive of the input if ctx provided. Otherwise, use // the provided context. if (ctx == NULL) ctx = ctxIn; // if the provided search context is different from the context of the extension, // then copy the search context to the search context. else if(ctx != ctxIn) *ctx = *ctxIn; // Now, search in the extension context for(;ctx->size > ctx->offset; ctx->offset += length) { VERIFY((length = ASN1NextTag(ctx)) >= 0); // If this is not a constructed sequence, then it doesn't belong // in the extensions. VERIFY(ctx->tag == ASN1_CONSTRUCTED_SEQUENCE); // Make sure that this entry could hold the OID if (length >= OID_SIZE(OID)) { // See if this is a match for the provided object identifier. if (MemoryEqual(OID, &(ctx->buffer[ctx->offset]), OID_SIZE(OID))) { // Return with ' ctx' set to point to the start of the OID with the size // set to be the size of the SEQUENCE ctx->buffer += ctx->offset; ctx->offset = 0; ctx->size = length; return TRUE; } } } VERIFY(ctx->offset == ctx->size); return FALSE; Error: ctxIn->size = -1; ctx->size = -1; return FALSE; } /* 10.2.26.2.2 X509GetExtensionBits() */ /* This function will extract a bit field from an extension. If the extension doesn't contain a bit string, it will fail. */ /* Return Value Meaning */ /* TRUE(1) success */ /* FALSE(0) failure */ UINT32 X509GetExtensionBits( ASN1UnmarshalContext *ctx, UINT32 *value ) { INT16 length; // while (((length = ASN1NextTag(ctx)) > 0) && (ctx->size > ctx->offset)) { // Since this is an extension, the extension value will be in an OCTET STRING if (ctx->tag == ASN1_OCTET_STRING) { return ASN1GetBitStringValue(ctx, value); } ctx->offset += length; } ctx->size = -1; return FALSE; } /* 10.2.26.2.3 X509ProcessExtensions() */ /* This function is used to process the TPMA_OBJECT and KeyUsage() extensions. It is not in the CertifyX509.c code because it makes the code harder to follow. */ /* Error Returns Meaning */ /* TPM_RCS_ATTRIBUTES the attributes of object are not consistent with the extension setting */ /* TPM_RC_VALUE problem parsing the extensions */ TPM_RC X509ProcessExtensions( OBJECT *object, // IN: The object with the attributes to // check stringRef *extension // IN: The start and length of the extensions ) { ASN1UnmarshalContext ctx; ASN1UnmarshalContext extensionCtx; INT16 length; UINT32 value; TPMA_OBJECT attributes = object->publicArea.objectAttributes; // if(!ASN1UnmarshalContextInitialize(&ctx, extension->len, extension->buf) || ((length = ASN1NextTag(&ctx)) < 0) || (ctx.tag != X509_EXTENSIONS)) return TPM_RCS_VALUE; if( ((length = ASN1NextTag(&ctx)) < 0) || (ctx.tag != (ASN1_CONSTRUCTED_SEQUENCE))) return TPM_RCS_VALUE; // Get the extension for the TPMA_OBJECT if there is one if(X509FindExtensionByOID(&ctx, &extensionCtx, OID_TCG_TPMA_OBJECT) && X509GetExtensionBits(&extensionCtx, &value)) { // If an keyAttributes extension was found, it must be exactly the same as the // attributes of the object. // NOTE: MemoryEqual() is used rather than a simple UINT32 compare to avoid // type-punned pointer warning/error. if(!MemoryEqual(&value, &attributes, sizeof(value))) return TPM_RCS_ATTRIBUTES; } // Make sure the failure to find the value wasn't because of a fatal error else if(extensionCtx.size < 0) return TPM_RCS_VALUE; // Get the keyUsage extension. This one is required if(X509FindExtensionByOID(&ctx, &extensionCtx, OID_KEY_USAGE_EXTENSION) && X509GetExtensionBits(&extensionCtx, &value)) { x509KeyUsageUnion keyUsage; BOOL badSign; BOOL badDecrypt; BOOL badFixedTPM; BOOL badRestricted; keyUsage.integer = value; // For KeyUsage: // 1) 'sign' is SET if Key Usage includes signing badSign = ((KEY_USAGE_SIGN.integer & keyUsage.integer) != 0) && !IS_ATTRIBUTE(attributes, TPMA_OBJECT, sign); // 2) 'decrypt' is SET if Key Usage includes decryption uses badDecrypt = ((KEY_USAGE_DECRYPT.integer & keyUsage.integer) != 0) && !IS_ATTRIBUTE(attributes, TPMA_OBJECT, decrypt); // 3) 'fixedTPM' is SET if Key Usage is non-repudiation badFixedTPM = IS_ATTRIBUTE(keyUsage.x509, TPMA_X509_KEY_USAGE, nonrepudiation) && !IS_ATTRIBUTE(attributes, TPMA_OBJECT, fixedTPM); // 4)'restricted' is SET if Key Usage is for key agreement. badRestricted = IS_ATTRIBUTE(keyUsage.x509, TPMA_X509_KEY_USAGE, keyAgreement) && !IS_ATTRIBUTE(attributes, TPMA_OBJECT, restricted); if(badSign || badDecrypt || badFixedTPM || badRestricted) return TPM_RCS_VALUE; } else // The KeyUsage extension is required return TPM_RCS_VALUE; return TPM_RC_SUCCESS; } /* 10.2.26.3 Marshaling Functions */ /* 10.2.26.3.1 X509AddSigningAlgorithm() */ /* This creates the singing algorithm data. */ /* Return Value Meaning */ /* > 0 number of octets added */ /* <= 0 failure */ INT16 X509AddSigningAlgorithm( ASN1MarshalContext *ctx, OBJECT *signKey, TPMT_SIG_SCHEME *scheme ) { switch(signKey->publicArea.type) { #if ALG_RSA case TPM_ALG_RSA: return X509AddSigningAlgorithmRSA(signKey, scheme, ctx); #endif // ALG_RSA #if ALG_ECC case TPM_ALG_ECC: return X509AddSigningAlgorithmECC(signKey, scheme, ctx); #endif // ALG_ECC #if ALG_SM2 case TPM_ALG_SM2: break; // no signing algorithm for SM2 yet // return X509AddSigningAlgorithmSM2(signKey, scheme, ctx); #endif // ALG_SM2 default: break; } return 0; } /* 10.2.26.3.2 X509AddPublicKey() */ /* This function will add the publicKey description to the DER data. If fillPtr is NULL, then no data is transferred and this function will indicate if the TPM has the values for DER-encoding of the public key. */ /* Return Value Meaning */ /* > 0 number of octets added */ /* == 0 failure */ INT16 X509AddPublicKey( ASN1MarshalContext *ctx, OBJECT *object ) { switch(object->publicArea.type) { #if ALG_RSA case TPM_ALG_RSA: return X509AddPublicRSA(object, ctx); #endif #if ALG_ECC case TPM_ALG_ECC: return X509AddPublicECC(object, ctx); #endif #if ALG_SM2 case TPM_ALG_SM2: break; #endif default: break; } return FALSE; } /* 10.2.26.3.3 X509PushAlgorithmIdentifierSequence() */ /* The function adds the algorithm identifier sequence. */ /* Return Value Meaning */ /* > 0 number of bytes added */ /* == 0 failure */ INT16 X509PushAlgorithmIdentifierSequence( ASN1MarshalContext *ctx, const BYTE *OID ) { ASN1StartMarshalContext(ctx); // hash algorithm ASN1PushNull(ctx); ASN1PushOID(ctx, OID); return ASN1EndEncapsulation(ctx, ASN1_CONSTRUCTED_SEQUENCE); } libtpms-0.9.3/src/tpm2/X509_spt_fp.h000066400000000000000000000106731421143571500170510ustar00rootroot00000000000000/********************************************************************************/ /* */ /* X509 Support */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: X509_spt_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2019. */ /* */ /********************************************************************************/ #ifndef X509_SPT_FP_H #define X509_SPT_FP_H BOOL X509FindExtensionByOID( ASN1UnmarshalContext *ctxIn, // IN: the context to search ASN1UnmarshalContext *ctx, // OUT: the extension context const BYTE *OID // IN: oid to search for ); UINT32 X509GetExtensionBits( ASN1UnmarshalContext *ctx, UINT32 *value ); TPM_RC X509ProcessExtensions( OBJECT *object, // IN: The object with the attributes to // check stringRef *extension // IN: The start and length of the extensions ); INT16 X509AddSigningAlgorithm( ASN1MarshalContext *ctx, OBJECT *signKey, TPMT_SIG_SCHEME *scheme ); INT16 X509AddPublicKey( ASN1MarshalContext *ctx, OBJECT *object ); INT16 X509PushAlgorithmIdentifierSequence( ASN1MarshalContext *ctx, const BYTE *OID ); #endif libtpms-0.9.3/src/tpm2/ZGen_2Phase_fp.h000066400000000000000000000100731421143571500175550ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: ZGen_2Phase_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2012-2015 */ /* */ /********************************************************************************/ /* rev 119 */ #ifndef ZGEN_2PHASE_FP_H #define ZGEN_2PHASE_FP_H typedef struct { TPMI_DH_OBJECT keyA; TPM2B_ECC_POINT inQsB; TPM2B_ECC_POINT inQeB; TPMI_ECC_KEY_EXCHANGE inScheme; UINT16 counter; } ZGen_2Phase_In; #define RC_ZGen_2Phase_keyA (TPM_RC_H + TPM_RC_1) #define RC_ZGen_2Phase_inQsB (TPM_RC_P + TPM_RC_1) #define RC_ZGen_2Phase_inQeB (TPM_RC_P + TPM_RC_2) #define RC_ZGen_2Phase_inScheme (TPM_RC_P + TPM_RC_3) #define RC_ZGen_2Phase_counter (TPM_RC_P + TPM_RC_4) typedef struct { TPM2B_ECC_POINT outZ1; TPM2B_ECC_POINT outZ2; } ZGen_2Phase_Out; TPM_RC TPM2_ZGen_2Phase( ZGen_2Phase_In *in, // IN: input parameter list ZGen_2Phase_Out *out // OUT: output parameter list ); #endif libtpms-0.9.3/src/tpm2/_TPM_Hash_Data_fp.h000066400000000000000000000070541421143571500202100ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: _TPM_Hash_Data_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 */ /* */ /********************************************************************************/ #ifndef _TPM_HASH_DATA_FP_H #define _TPM_HASH_DATA_FP_H LIB_EXPORT void _TPM_Hash_Data( uint32_t dataSize, // IN: size of data to be extend unsigned char *data // IN: data buffer ); #endif libtpms-0.9.3/src/tpm2/_TPM_Hash_End_fp.h000066400000000000000000000066571421143571500200550ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: _TPM_Hash_End_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 */ /* */ /********************************************************************************/ #ifndef _TPM_HASH_END_FP_H #define _TPM_HASH_END_FP_H LIB_EXPORT void _TPM_Hash_End( void ); #endif libtpms-0.9.3/src/tpm2/_TPM_Hash_Start_fp.h000066400000000000000000000066551421143571500204420ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: _TPM_Hash_Start_fp.h 1521 2019-11-15 21:00:47Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 */ /* */ /********************************************************************************/ #ifndef _TPM_HASH_START_FP_H #define _TPM_HASH_START_FP_H LIB_EXPORT void _TPM_Hash_Start( void ); #endif libtpms-0.9.3/src/tpm2/_TPM_Init_fp.h000066400000000000000000000066311421143571500172770ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: _TPM_Init_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 */ /* */ /********************************************************************************/ #ifndef _TPM_INIT_FP_H #define _TPM_INIT_FP_H LIB_EXPORT void _TPM_Init( void ); #endif libtpms-0.9.3/src/tpm2/crypto/000077500000000000000000000000001421143571500161715ustar00rootroot00000000000000libtpms-0.9.3/src/tpm2/crypto/CryptCmac_fp.h000066400000000000000000000076601421143571500207250ustar00rootroot00000000000000/********************************************************************************/ /* Message Authentication Codes Based on a Symmetric Block Cipher */ /* Implementation of cryptographic functions for hashing. */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CryptCmac_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2018 */ /* */ /********************************************************************************/ #ifndef CRYPTCMAC_FP_H #define CRYPTCMAC_FP_H #include "Tpm.h" UINT16 CryptCmacStart( SMAC_STATE *state, TPMU_PUBLIC_PARMS *keyParms, TPM_ALG_ID macAlg, TPM2B *key ); void CryptCmacData( SMAC_STATES *state, UINT32 size, const BYTE *buffer ); UINT16 CryptCmacEnd( SMAC_STATES *state, UINT32 outSize, BYTE *outBuffer ); #endif libtpms-0.9.3/src/tpm2/crypto/CryptDes_fp.h000066400000000000000000000075011421143571500205670ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CryptDes_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 */ /* */ /********************************************************************************/ #ifndef CRYPTDES_FP_H #define CRYPTDES_FP_H UINT64 CryptSetOddByteParity( UINT64 k ); BOOL CryptDesValidateKey( TPM2B_SYM_KEY *desKey // IN: key to validate ); TPM_RC CryptGenerateKeyDes( TPMT_PUBLIC *publicArea, // IN/OUT: The public area template // for the new key. TPMT_SENSITIVE *sensitive, // OUT: sensitive area RAND_STATE *rand // IN: the "entropy" source for ); #endif libtpms-0.9.3/src/tpm2/crypto/CryptEcc.h000066400000000000000000000113001421143571500200510ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Structure definitions used for ECC */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CryptEcc.h 1594 2020-03-26 22:15:48Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2020 */ /* */ /********************************************************************************/ /* 10.1.2 CryptEcc.h */ /* 10.1.2.1 Introduction */ /* This file contains structure definitions used for ECC. The structures in this file are only used internally. The ECC-related structures that cross the TPM interface are defined in TpmTypes.h */ #ifndef _CRYPT_ECC_H #define _CRYPT_ECC_H /* 10.1.2.2 Structures */ typedef struct ECC_CURVE { const TPM_ECC_CURVE curveId; const UINT16 keySizeBits; const TPMT_KDF_SCHEME kdf; const TPMT_ECC_SCHEME sign; const ECC_CURVE_DATA *curveData; // the address of the curve data const BYTE *OID; } ECC_CURVE; /* 10.1.2.2.1 Macros */ /* This macro is used to instance an ECC_CURVE_DATA structure for the curve. This structure is referenced by the ECC_CURVE structure */ #define CURVE_DATA_DEF(CURVE) \ const ECC_CURVE_DATA CURVE = { \ (bigNum)&CURVE##_p_DATA, (bigNum)&CURVE##_n_DATA, (bigNum)&CURVE##_h_DATA, \ (bigNum)&CURVE##_a_DATA, (bigNum)&CURVE##_b_DATA, \ {(bigNum)&CURVE##_gX_DATA, (bigNum)&CURVE##_gY_DATA, (bigNum)&BN_ONE} }; extern const ECC_CURVE eccCurves[ECC_CURVE_COUNT]; #define CURVE_DEF(CURVE) \ { \ TPM_ECC_##CURVE, \ CURVE##_KEY_SIZE, \ CURVE##_KDF, \ CURVE##_SIGN, \ &##CURVE, \ OID_ECC_##CURVE \ } #define CURVE_NAME(N) #endif libtpms-0.9.3/src/tpm2/crypto/CryptEccCrypt_fp.h000066400000000000000000000066271421143571500216000ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Include Headers for Internal Routines */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CryptEccCrypt_fp.h 1594 2020-03-26 22:15:48Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2020 */ /* */ /********************************************************************************/ #ifndef CRYPTECCCRYPT_FP_H #define CRYPTECCCRYPT_FP_H #endif libtpms-0.9.3/src/tpm2/crypto/CryptEccKeyExchange_fp.h000066400000000000000000000100541421143571500226570ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CryptEccKeyExchange_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 */ /* */ /********************************************************************************/ #ifndef CRYPTECCKEYEXCHANGE_FP_H #define CRYPTECCKEYEXCHANGE_FP_H LIB_EXPORT TPM_RC CryptEcc2PhaseKeyExchange( TPMS_ECC_POINT *outZ1, // OUT: a computed point TPMS_ECC_POINT *outZ2, // OUT: and optional second point TPM_ECC_CURVE curveId, // IN: the curve for the computations TPM_ALG_ID scheme, // IN: the key exchange scheme TPM2B_ECC_PARAMETER *dsA, // IN: static private TPM key TPM2B_ECC_PARAMETER *deA, // IN: ephemeral private TPM key TPMS_ECC_POINT *QsB, // IN: static public party B key TPMS_ECC_POINT *QeB // IN: ephemeral public party B key ); #endif libtpms-0.9.3/src/tpm2/crypto/CryptEccMain_fp.h000066400000000000000000000215571421143571500213620ustar00rootroot00000000000000/********************************************************************************/ /* */ /* ECC Main */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CryptEccMain_fp.h 1476 2019-06-10 19:32:03Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ #ifndef CRYPTECCMAIN_FP_H #define CRYPTECCMAIN_FP_H void EccSimulationEnd( void ); BOOL CryptEccInit( void ); BOOL CryptEccStartup( void ); void ClearPoint2B( TPMS_ECC_POINT *p // IN: the point ); LIB_EXPORT const ECC_CURVE * CryptEccGetParametersByCurveId( TPM_ECC_CURVE curveId // IN: the curveID ); LIB_EXPORT UINT16 CryptEccGetKeySizeForCurve( TPM_ECC_CURVE curveId // IN: the curve ); const ECC_CURVE_DATA * GetCurveData( TPM_ECC_CURVE curveId // IN: the curveID ); const BYTE * CryptEccGetOID( TPM_ECC_CURVE curveId ); LIB_EXPORT TPM_ECC_CURVE CryptEccGetCurveByIndex( UINT16 i ); LIB_EXPORT BOOL CryptEccGetParameter( TPM2B_ECC_PARAMETER *out, // OUT: place to put parameter char p, // IN: the parameter selector TPM_ECC_CURVE curveId // IN: the curve id ); TPMI_YES_NO CryptCapGetECCCurve( TPM_ECC_CURVE curveID, // IN: the starting ECC curve UINT32 maxCount, // IN: count of returned curves TPML_ECC_CURVE *curveList // OUT: ECC curve list ); const TPMT_ECC_SCHEME * CryptGetCurveSignScheme( TPM_ECC_CURVE curveId // IN: The curve selector ); BOOL CryptGenerateR( TPM2B_ECC_PARAMETER *r, // OUT: the generated random value UINT16 *c, // IN/OUT: count value. TPMI_ECC_CURVE curveID, // IN: the curve for the value TPM2B_NAME *name // IN: optional name of a key to // associate with 'r' ); UINT16 CryptCommit( void ); void CryptEndCommit( UINT16 c // IN: the counter value of the commitment ); BOOL CryptEccGetParameters( TPM_ECC_CURVE curveId, // IN: ECC curve ID TPMS_ALGORITHM_DETAIL_ECC *parameters // OUT: ECC parameters ); const bignum_t * BnGetCurvePrime( TPM_ECC_CURVE curveId ); const bignum_t * BnGetCurveOrder( TPM_ECC_CURVE curveId ); BOOL BnIsOnCurve( pointConst Q, const ECC_CURVE_DATA *C ); BOOL BnIsValidPrivateEcc( bigConst x, // IN: private key to check bigCurve E // IN: the curve to check ); LIB_EXPORT BOOL CryptEccIsValidPrivateKey( TPM2B_ECC_PARAMETER *d, TPM_ECC_CURVE curveId ); TPM_RC BnPointMult( bigPoint R, // OUT: computed point pointConst S, // IN: optional point to multiply by 'd' bigConst d, // IN: scalar for [d]S or [d]G pointConst Q, // IN: optional second point bigConst u, // IN: optional second scalar bigCurve E // IN: curve parameters ); BOOL BnEccGetPrivate( bigNum dOut, // OUT: the qualified random value const ECC_CURVE_DATA *C, // IN: curve for which the private key #if USE_OPENSSL_FUNCTIONS_EC const EC_GROUP *G, // IN: the EC_GROUP to use; must be != NULL for rand == NULL BOOL noLeadingZeros, // IN: require that all bytes in the private key be set // result may not have leading zero bytes #endif // needs to be appropriate RAND_STATE *rand // IN: state for DRBG ); BOOL BnEccGenerateKeyPair( bigNum bnD, // OUT: private scalar bn_point_t *ecQ, // OUT: public point bigCurve E, // IN: curve for the point RAND_STATE *rand // IN: DRBG state to use ); LIB_EXPORT TPM_RC CryptEccNewKeyPair( TPMS_ECC_POINT *Qout, // OUT: the public point TPM2B_ECC_PARAMETER *dOut, // OUT: the private scalar TPM_ECC_CURVE curveId // IN: the curve for the key ); LIB_EXPORT TPM_RC CryptEccPointMultiply( TPMS_ECC_POINT *Rout, // OUT: the product point R TPM_ECC_CURVE curveId, // IN: the curve to use TPMS_ECC_POINT *Pin, // IN: first point (can be null) TPM2B_ECC_PARAMETER *dIn, // IN: scalar value for [dIn]Qin // the Pin TPMS_ECC_POINT *Qin, // IN: point Q TPM2B_ECC_PARAMETER *uIn // IN: scalar value for the multiplier // of Q ); LIB_EXPORT BOOL CryptEccIsPointOnCurve( TPM_ECC_CURVE curveId, // IN: the curve selector TPMS_ECC_POINT *Qin // IN: the point. ); LIB_EXPORT TPM_RC CryptEccGenerateKey( TPMT_PUBLIC *publicArea, // IN/OUT: The public area template for // the new key. The public key // area will be replaced computed // ECC public key TPMT_SENSITIVE *sensitive, // OUT: the sensitive area will be // updated to contain the private // ECC key and the symmetric // encryption key RAND_STATE *rand // IN: if not NULL, the deterministic // RNG state ); // libtpms added begin LIB_EXPORT BOOL CryptEccIsCurveRuntimeUsable( TPMI_ECC_CURVE curveId ); // libtpms added end #endif libtpms-0.9.3/src/tpm2/crypto/CryptEccSignature_fp.h000066400000000000000000000130741421143571500224320ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CryptEccSignature_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 */ /* */ /********************************************************************************/ #ifndef CRYPTECCSIGNATURE_FP_H #define CRYPTECCSIGNATURE_FP_H TPM_RC BnSignEcdsa( bigNum bnR, // OUT: r component of the signature bigNum bnS, // OUT: s component of the signature bigCurve E, // IN: the curve used in the signature // process bigNum bnD, // IN: private signing key const TPM2B_DIGEST *digest, // IN: the digest to sign RAND_STATE *rand // IN: used in debug of signing ); LIB_EXPORT TPM_RC CryptEccSign( TPMT_SIGNATURE *signature, // OUT: signature OBJECT *signKey, // IN: ECC key to sign the hash const TPM2B_DIGEST *digest, // IN: digest to sign TPMT_ECC_SCHEME *scheme, // IN: signing scheme RAND_STATE *rand ); TPM_RC BnValidateSignatureEcdsa( bigNum bnR, // IN: r component of the signature bigNum bnS, // IN: s component of the signature bigCurve E, // IN: the curve used in the signature // process bn_point_t *ecQ, // IN: the public point of the key const TPM2B_DIGEST *digest // IN: the digest that was signed ); LIB_EXPORT TPM_RC CryptEccValidateSignature( TPMT_SIGNATURE *signature, // IN: signature to be verified OBJECT *signKey, // IN: ECC key signed the hash const TPM2B_DIGEST *digest // IN: digest that was signed ); LIB_EXPORT TPM_RC CryptEccCommitCompute( TPMS_ECC_POINT *K, // OUT: [d]B or [r]Q TPMS_ECC_POINT *L, // OUT: [r]B TPMS_ECC_POINT *E, // OUT: [r]M TPM_ECC_CURVE curveId, // IN: the curve for the computations TPMS_ECC_POINT *M, // IN: M (optional) TPMS_ECC_POINT *B, // IN: B (optional) TPM2B_ECC_PARAMETER *d, // IN: d (optional) TPM2B_ECC_PARAMETER *r // IN: the computed r value (required) ); #endif libtpms-0.9.3/src/tpm2/crypto/CryptHash.h000066400000000000000000000337771421143571500202700ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Hash structure definitions */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CryptHash.h 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2021 */ /* */ /********************************************************************************/ #ifndef CRYPTHASH_H #define CRYPTHASH_H /* 10.1.3.1 Introduction */ /* This header contains the hash structure definitions used in the TPM code to define the amount of space to be reserved for the hash state. This allows the TPM code to not have to import all of the symbols used by the hash computations. This lets the build environment of the TPM code not to have include the header files associated with the CryptoEngine() code. */ /* 10.1.3.2 Hash-related Structures */ union SMAC_STATES; /* These definitions add the high-level methods for processing state that may be an SMAC */ typedef void(* SMAC_DATA_METHOD)( union SMAC_STATES *state, UINT32 size, const BYTE *buffer ); typedef UINT16(* SMAC_END_METHOD)( union SMAC_STATES *state, UINT32 size, BYTE *buffer ); typedef struct sequenceMethods { SMAC_DATA_METHOD data; SMAC_END_METHOD end; } SMAC_METHODS; #define SMAC_IMPLEMENTED (CC_MAC || CC_MAC_Start) /* These definitions are here because the SMAC state is in the union of hash states. */ typedef struct tpmCmacState { TPM_ALG_ID symAlg; UINT16 keySizeBits; INT16 bcount; // current count of bytes accumulated in IV TPM2B_IV iv; // IV buffer TPM2B_SYM_KEY symKey; } tpmCmacState_t; typedef union SMAC_STATES { #if ALG_CMAC tpmCmacState_t cmac; #endif UINT64 pad; } SMAC_STATES; typedef struct SMAC_STATE { SMAC_METHODS smacMethods; SMAC_STATES state; } SMAC_STATE; #if ALG_SHA1 # define IF_IMPLEMENTED_SHA1(op) op(SHA1, Sha1) #else # define IF_IMPLEMENTED_SHA1(op) #endif #if ALG_SHA256 # define IF_IMPLEMENTED_SHA256(op) op(SHA256, Sha256) #else # define IF_IMPLEMENTED_SHA256(op) #endif #if ALG_SHA384 # define IF_IMPLEMENTED_SHA384(op) op(SHA384, Sha384) #else # define IF_IMPLEMENTED_SHA384(op) #endif #if ALG_SHA512 # define IF_IMPLEMENTED_SHA512(op) op(SHA512, Sha512) #else # define IF_IMPLEMENTED_SHA512(op) #endif #if ALG_SM3_256 # define IF_IMPLEMENTED_SM3_256(op) op(SM3_256, Sm3_256) #else # define IF_IMPLEMENTED_SM3_256(op) #endif #if ALG_SHA3_256 # define IF_IMPLEMENTED_SHA3_256(op) op(SHA3_256, Sha3_256) #else # define IF_IMPLEMENTED_SHA3_256(op) #endif #if ALG_SHA3_384 # define IF_IMPLEMENTED_SHA3_384(op) op(SHA3_384, Sha3_384) #else # define IF_IMPLEMENTED_SHA3_384(op) #endif #if ALG_SHA3_512 # define IF_IMPLEMENTED_SHA3_512(op) op(SHA3_512, Sha3_512) #else # define IF_IMPLEMENTED_SHA3_512(op) #endif /* SHA512 added kgold */ #define FOR_EACH_HASH(op) \ IF_IMPLEMENTED_SHA1(op) \ IF_IMPLEMENTED_SHA256(op) \ IF_IMPLEMENTED_SHA384(op) \ IF_IMPLEMENTED_SHA512(op) \ IF_IMPLEMENTED_SM3_256(op) \ IF_IMPLEMENTED_SHA3_256(op) \ IF_IMPLEMENTED_SHA3_384(op) \ IF_IMPLEMENTED_SHA3_512(op) #define HASH_TYPE(HASH, Hash) tpmHashState##HASH##_t Hash; typedef union { FOR_EACH_HASH(HASH_TYPE) // Additions for symmetric block cipher MAC #if SMAC_IMPLEMENTED SMAC_STATE smac; #endif // to force structure alignment to be no worse than HASH_ALIGNMENT #if HASH_ALIGNMENT == 8 uint64_t align; #else uint32_t align; #endif } ANY_HASH_STATE; typedef ANY_HASH_STATE *PANY_HASH_STATE; typedef const ANY_HASH_STATE *PCANY_HASH_STATE; #define ALIGNED_SIZE(x, b) ((((x) + (b) - 1) / (b)) * (b)) /* MAX_HASH_STATE_SIZE will change with each implementation. It is assumed that a hash state will not be larger than twice the block size plus some overhead (in this case, 16 bytes). The overall size needs to be as large as any of the hash contexts. The structure needs to start on an alignment boundary and be an even multiple of the alignment */ #define MAX_HASH_STATE_SIZE ((2 * MAX_HASH_BLOCK_SIZE) + 16) #define MAX_HASH_STATE_SIZE_ALIGNED \ ALIGNED_SIZE(MAX_HASH_STATE_SIZE, HASH_ALIGNMENT) /* This is an aligned byte array that will hold any of the hash contexts. */ typedef ANY_HASH_STATE ALIGNED_HASH_STATE; /* The header associated with the hash library is expected to define the methods which include the calling sequence. When not compiling CryptHash.c, the methods are not defined so we need placeholder functions for the structures */ #ifndef HASH_START_METHOD_DEF # define HASH_START_METHOD_DEF void (HASH_START_METHOD)(void) #endif #ifndef HASH_DATA_METHOD_DEF # define HASH_DATA_METHOD_DEF void (HASH_DATA_METHOD)(void) #endif #ifndef HASH_END_METHOD_DEF # define HASH_END_METHOD_DEF void (HASH_END_METHOD)(void) #endif #ifndef HASH_STATE_COPY_METHOD_DEF # define HASH_STATE_COPY_METHOD_DEF void (HASH_STATE_COPY_METHOD)(void) #endif #ifndef HASH_STATE_EXPORT_METHOD_DEF # define HASH_STATE_EXPORT_METHOD_DEF void (HASH_STATE_EXPORT_METHOD)(void) #endif #ifndef HASH_STATE_IMPORT_METHOD_DEF # define HASH_STATE_IMPORT_METHOD_DEF void (HASH_STATE_IMPORT_METHOD)(void) #endif /* Define the prototypical function call for each of the methods. This defines the order in which the parameters are passed to the underlying function. */ typedef HASH_START_METHOD_DEF; typedef HASH_DATA_METHOD_DEF; typedef HASH_END_METHOD_DEF; typedef HASH_STATE_COPY_METHOD_DEF; typedef HASH_STATE_EXPORT_METHOD_DEF; typedef HASH_STATE_IMPORT_METHOD_DEF; typedef struct _HASH_METHODS { HASH_START_METHOD *start; HASH_DATA_METHOD *data; HASH_END_METHOD *end; HASH_STATE_COPY_METHOD *copy; // Copy a hash block HASH_STATE_EXPORT_METHOD *copyOut; // Copy a hash block from a hash // context HASH_STATE_IMPORT_METHOD *copyIn; // Copy a hash block to a proper hash // context } HASH_METHODS, *PHASH_METHODS; #define HASH_TPM2B(HASH, Hash) TPM2B_TYPE(HASH##_DIGEST, HASH##_DIGEST_SIZE); FOR_EACH_HASH(HASH_TPM2B) /* When the TPM implements RSA, the hash-dependent OID pointers are part of the HASH_DEF. These macros conditionally add the OID reference to the HASH_DEF and the HASH_DEF_TEMPLATE. */ #if ALG_RSA #define PKCS1_HASH_REF const BYTE *PKCS1; #define PKCS1_OID(NAME) , OID_PKCS1_##NAME #else #define PKCS1_HASH_REF #define PKCS1_OID(NAME) #endif /* When the TPM implements ECC, the hash-dependent OID pointers are part of the HASH_DEF. These macros conditionally add the OID reference to the HASH_DEF and the HASH_DEF_TEMPLATE. */ #if ALG_ECDSA #define ECDSA_HASH_REF const BYTE *ECDSA; #define ECDSA_OID(NAME) , OID_ECDSA_##NAME #else #define ECDSA_HASH_REF #define ECDSA_OID(NAME) #endif typedef const struct { HASH_METHODS method; uint16_t blockSize; uint16_t digestSize; uint16_t contextSize; uint16_t hashAlg; const BYTE *OID; PKCS1_HASH_REF // PKCS1 OID ECDSA_HASH_REF // ECDSA OID } HASH_DEF, *PHASH_DEF; /* Macro to fill in the HASH_DEF for an algorithm. For SHA1, the instance would be: HASH_DEF_TEMPLATE(Sha1, SHA1) This handles the difference in capitalization for the various pieces. */ #define HASH_DEF_TEMPLATE(HASH, Hash) \ HASH_DEF Hash##_Def= { \ {(HASH_START_METHOD *)&tpmHashStart_##HASH, \ (HASH_DATA_METHOD *)&tpmHashData_##HASH, \ (HASH_END_METHOD *)&tpmHashEnd_##HASH, \ (HASH_STATE_COPY_METHOD *)&tpmHashStateCopy_##HASH, \ (HASH_STATE_EXPORT_METHOD *)&tpmHashStateExport_##HASH, \ (HASH_STATE_IMPORT_METHOD *)&tpmHashStateImport_##HASH, \ }, \ HASH##_BLOCK_SIZE, /*block size */ \ HASH##_DIGEST_SIZE, /*data size */ \ sizeof(tpmHashState##HASH##_t), \ TPM_ALG_##HASH, OID_##HASH \ PKCS1_OID(HASH) ECDSA_OID(HASH)}; /* These definitions are for the types that can be in a hash state structure. These types are used in the cryptographic utilities. This is a define rather than an enum so that the size of this field can be explicit. */ typedef BYTE HASH_STATE_TYPE; #define HASH_STATE_EMPTY ((HASH_STATE_TYPE) 0) #define HASH_STATE_HASH ((HASH_STATE_TYPE) 1) #define HASH_STATE_HMAC ((HASH_STATE_TYPE) 2) #if CC_MAC || CC_MAC_Start #define HASH_STATE_SMAC ((HASH_STATE_TYPE) 3) #endif /* This is the structure that is used for passing a context into the hashing functions. It should be the same size as the function context used within the hashing functions. This is checked when the hash function is initialized. This version uses a new layout for the contexts and a different definition. The state buffer is an array of HASH_UNIT values so that a decent compiler will put the structure on a HASH_UNIT boundary. If the structure is not properly aligned, the code that manipulates the structure will copy to a properly aligned structure before it is used and copy the result back. This just makes things slower. */ /* NOTE: This version of the state had the pointer to the update method in the state. This is to allow the SMAC functions to use the same structure without having to replicate the entire HASH_DEF structure. */ typedef struct _HASH_STATE { HASH_STATE_TYPE type; // type of the context TPM_ALG_ID hashAlg; PHASH_DEF def; ANY_HASH_STATE state; } HASH_STATE, *PHASH_STATE; typedef const HASH_STATE *PCHASH_STATE; /* 10.1.3.3 HMAC State Structures */ /* This header contains the hash structure definitions used in the TPM code to define the amount of space to be reserved for the hash state. This allows the TPM code to not have to import all of the symbols used by the hash computations. This lets the build environment of the TPM code not to have include the header files associated with the CryptoEngine() code. */ /* An HMAC_STATE structure contains an opaque HMAC stack state. A caller would use this structure when performing incremental HMAC operations. This structure contains a hash state and an HMAC key and allows slightly better stack optimization than adding an HMAC key to each hash state. */ typedef struct hmacState { HASH_STATE hashState; // the hash state TPM2B_HASH_BLOCK hmacKey; // the HMAC key } HMAC_STATE, *PHMAC_STATE; /* This is for the external hash state. This implementation assumes that the size of the exported hash state is no larger than the internal hash state. */ typedef struct { BYTE buffer[sizeof(HASH_STATE)]; } EXPORT_HASH_STATE, *PEXPORT_HASH_STATE; typedef const EXPORT_HASH_STATE *PCEXPORT_HASH_STATE; #endif // _CRYPT_HASH_H libtpms-0.9.3/src/tpm2/crypto/CryptHash_fp.h000066400000000000000000000215671421143571500207470ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Implementation of cryptographic functions for hashing. */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CryptHash_fp.h 1594 2020-03-26 22:15:48Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2020 */ /* */ /********************************************************************************/ #ifndef CRYPTHASH_FP_H #define CRYPTHASH_FP_H BOOL CryptHashInit( void ); BOOL CryptHashStartup( void ); PHASH_DEF CryptGetHashDef( TPM_ALG_ID hashAlg ); BOOL CryptHashIsValidAlg( TPM_ALG_ID hashAlg, BOOL flag ); LIB_EXPORT TPM_ALG_ID CryptHashGetAlgByIndex( UINT32 index // IN: the index ); LIB_EXPORT UINT16 CryptHashGetDigestSize( TPM_ALG_ID hashAlg // IN: hash algorithm to look up ); LIB_EXPORT UINT16 CryptHashGetBlockSize( TPM_ALG_ID hashAlg // IN: hash algorithm to look up ); LIB_EXPORT const BYTE * CryptHashGetOid( TPM_ALG_ID hashAlg ); TPM_ALG_ID CryptHashGetContextAlg( PHASH_STATE state // IN: the context to check ); LIB_EXPORT void CryptHashCopyState( HASH_STATE *out, // OUT: destination of the state const HASH_STATE *in // IN: source of the state ); void CryptHashExportState( PCHASH_STATE internalFmt, // IN: the hash state formatted for use by // library PEXPORT_HASH_STATE externalFmt // OUT: the exported hash state ); void CryptHashImportState( PHASH_STATE internalFmt, // OUT: the hash state formatted for use by // the library PCEXPORT_HASH_STATE externalFmt // IN: the exported hash state ); LIB_EXPORT UINT16 CryptHashStart( PHASH_STATE hashState, // OUT: the running hash state TPM_ALG_ID hashAlg // IN: hash algorithm ); LIB_EXPORT void CryptDigestUpdate( PHASH_STATE hashState, // IN: the hash context information UINT32 dataSize, // IN: the size of data to be added const BYTE *data // IN: data to be hashed ); LIB_EXPORT UINT16 CryptHashEnd( PHASH_STATE hashState, // IN: the state of hash stack UINT32 dOutSize, // IN: size of digest buffer BYTE *dOut // OUT: hash digest ); LIB_EXPORT UINT16 CryptHashBlock( TPM_ALG_ID hashAlg, // IN: The hash algorithm UINT32 dataSize, // IN: size of buffer to hash const BYTE *data, // IN: the buffer to hash UINT32 dOutSize, // IN: size of the digest buffer BYTE *dOut // OUT: digest buffer ); LIB_EXPORT void CryptDigestUpdate2B( PHASH_STATE state, // IN: the digest state const TPM2B *bIn // IN: 2B containing the data ); LIB_EXPORT UINT16 CryptHashEnd2B( PHASH_STATE state, // IN: the hash state P2B digest // IN: the size of the buffer Out: requested // number of bytes ); LIB_EXPORT void CryptDigestUpdateInt( void *state, // IN: the state of hash stack UINT32 intSize, // IN: the size of 'intValue' in bytes UINT64 intValue // IN: integer value to be hashed ); LIB_EXPORT UINT16 CryptHmacStart( PHMAC_STATE state, // IN/OUT: the state buffer TPM_ALG_ID hashAlg, // IN: the algorithm to use UINT16 keySize, // IN: the size of the HMAC key const BYTE *key // IN: the HMAC key ); LIB_EXPORT UINT16 CryptHmacEnd( PHMAC_STATE state, // IN: the hash state buffer UINT32 dOutSize, // IN: size of digest buffer BYTE *dOut // OUT: hash digest ); LIB_EXPORT UINT16 CryptHmacStart2B( PHMAC_STATE hmacState, // OUT: the state of HMAC stack. It will be used // in HMAC update and completion TPMI_ALG_HASH hashAlg, // IN: hash algorithm P2B key // IN: HMAC key ); LIB_EXPORT UINT16 CryptHmacEnd2B( PHMAC_STATE hmacState, // IN: the state of HMAC stack P2B digest // OUT: HMAC ); LIB_EXPORT UINT16 CryptMGF_KDF( UINT32 mSize, // IN: length of the mask to be produced BYTE *mask, // OUT: buffer to receive the mask TPM_ALG_ID hashAlg, // IN: hash to use UINT32 seedSize, // IN: size of the seed BYTE *seed, // IN: seed size UINT32 counter // IN: counter initial value ); LIB_EXPORT UINT16 CryptKDFa( TPM_ALG_ID hashAlg, // IN: hash algorithm used in HMAC const TPM2B *key, // IN: HMAC key const TPM2B *label, // IN: a label for the KDF const TPM2B *contextU, // IN: context U const TPM2B *contextV, // IN: context V UINT32 sizeInBits, // IN: size of generated key in bits BYTE *keyStream, // OUT: key buffer UINT32 *counterInOut, // IN/OUT: caller may provide the iteration UINT16 blocks // IN: If non-zero, this is the maximum number ); LIB_EXPORT UINT16 CryptKDFe( TPM_ALG_ID hashAlg, // IN: hash algorithm used in HMAC TPM2B *Z, // IN: Z const TPM2B *label, // IN: a label value for the KDF TPM2B *partyUInfo, // IN: PartyUInfo TPM2B *partyVInfo, // IN: PartyVInfo UINT32 sizeInBits, // IN: size of generated key in bits BYTE *keyStream // OUT: key buffer ); #endif libtpms-0.9.3/src/tpm2/crypto/CryptPrimeSieve_fp.h000066400000000000000000000105631421143571500221260ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CryptPrimeSieve_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 */ /* */ /********************************************************************************/ #ifndef CRYPTPRIMESIEVE_FP_H #define CRYPTPRIMESIEVE_FP_H LIB_EXPORT void RsaAdjustPrimeLimit( uint32_t requestedPrimes ); LIB_EXPORT uint32_t RsaNextPrime( uint32_t lastPrime ); LIB_EXPORT int FindNthSetBit( const UINT16 aSize, // IN: the size of the array to check const BYTE *a, // IN: the array to check const UINT32 n // IN, the number of the SET bit ); LIB_EXPORT UINT32 PrimeSieve( bigNum bnN, // IN/OUT: number to sieve UINT32 fieldSize, // IN: size of the field area in bytes BYTE *field // IN: field ); LIB_EXPORT uint32_t SetFieldSize( uint32_t newFieldSize ); LIB_EXPORT TPM_RC PrimeSelectWithSieve( bigNum candidate, // IN/OUT: The candidate to filter UINT32 e, // IN: the exponent RAND_STATE *rand // IN: the random number generator state ); void RsaSimulationEnd( void ); #endif libtpms-0.9.3/src/tpm2/crypto/CryptPrime_fp.h000066400000000000000000000103641421143571500211310ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Code for prime validation */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CryptPrime_fp.h 1476 2019-06-10 19:32:03Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ #ifndef CRYPTPRIME_FP_H #define CRYPTPRIME_FP_H BOOL IsPrimeInt( uint32_t n ); BOOL BnIsProbablyPrime( bigNum prime, // IN: RAND_STATE *rand // IN: the random state just // in case Miller-Rabin is required ); UINT32 MillerRabinRounds( UINT32 bits // IN: Number of bits in the RSA prime ); BOOL MillerRabin( bigNum bnW, RAND_STATE *rand ); TPM_RC RsaCheckPrime( bigNum prime, UINT32 exponent, RAND_STATE *rand ); LIB_EXPORT void RsaAdjustPrimeCandidate( bigNum prime, SEED_COMPAT_LEVEL seedCompatLevel // IN: compatibility level; libtpms added ); TPM_RC BnGeneratePrimeForRSA( bigNum prime, UINT32 bits, UINT32 exponent, RAND_STATE *rand ); #endif libtpms-0.9.3/src/tpm2/crypto/CryptRand.h000066400000000000000000000217471421143571500202630ustar00rootroot00000000000000/********************************************************************************/ /* */ /* DRBG with a behavior according to SP800-90A */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CryptRand.h 1594 2020-03-26 22:15:48Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2020 */ /* */ /********************************************************************************/ /* 10.1.4 CryptRand.h */ /* 10.1.4.1 Introduction */ /* This file contains constant definition shared by CryptUtil() and the parts of the Crypto Engine. */ #ifndef _CRYPT_RAND_H #define _CRYPT_RAND_H /* DRBG Structures and Defines Values and structures for the random number generator. These values are defined in this header file so that the size of the RNG state can be known to TPM.lib. This allows the allocation of some space in NV memory for the state to be stored on an orderly shutdown. The DRBG based on a symmetric block cipher is defined by three values, */ /* a) the key size */ /* b) the block size (the IV size) */ /* c) the symmetric algorithm */ #define DRBG_KEY_SIZE_BITS AES_MAX_KEY_SIZE_BITS #define DRBG_IV_SIZE_BITS (AES_MAX_BLOCK_SIZE * 8) #define DRBG_ALGORITHM TPM_ALG_AES typedef tpmKeyScheduleAES DRBG_KEY_SCHEDULE; #define DRBG_ENCRYPT_SETUP(key, keySizeInBits, schedule) \ TpmCryptSetEncryptKeyAES(key, keySizeInBits, schedule) #define DRBG_ENCRYPT(keySchedule, in, out) \ TpmCryptEncryptAES(SWIZZLE(keySchedule, in, out)) #if ((DRBG_KEY_SIZE_BITS % RADIX_BITS) != 0) \ || ((DRBG_IV_SIZE_BITS % RADIX_BITS) != 0) #error "Key size and IV for DRBG must be even multiples of the radix" #endif #if (DRBG_KEY_SIZE_BITS % DRBG_IV_SIZE_BITS) != 0 #error "Key size for DRBG must be even multiple of the cypher block size" #endif /* Derived values */ #define DRBG_MAX_REQUESTS_PER_RESEED (1 << 48) #define DRBG_MAX_REQEST_SIZE (1 << 32) #define pDRBG_KEY(seed) ((DRBG_KEY *)&(((BYTE *)(seed))[0])) #define pDRBG_IV(seed) ((DRBG_IV *)&(((BYTE *)(seed))[DRBG_KEY_SIZE_BYTES])) #define DRBG_KEY_SIZE_WORDS (BITS_TO_CRYPT_WORDS(DRBG_KEY_SIZE_BITS)) #define DRBG_KEY_SIZE_BYTES (DRBG_KEY_SIZE_WORDS * RADIX_BYTES) #define DRBG_IV_SIZE_WORDS (BITS_TO_CRYPT_WORDS(DRBG_IV_SIZE_BITS)) #define DRBG_IV_SIZE_BYTES (DRBG_IV_SIZE_WORDS * RADIX_BYTES) #define DRBG_SEED_SIZE_WORDS (DRBG_KEY_SIZE_WORDS + DRBG_IV_SIZE_WORDS) #define DRBG_SEED_SIZE_BYTES (DRBG_KEY_SIZE_BYTES + DRBG_IV_SIZE_BYTES) typedef union { BYTE bytes[DRBG_KEY_SIZE_BYTES]; crypt_uword_t words[DRBG_KEY_SIZE_WORDS]; } DRBG_KEY; typedef union { BYTE bytes[DRBG_IV_SIZE_BYTES]; crypt_uword_t words[DRBG_IV_SIZE_WORDS]; } DRBG_IV; typedef union { BYTE bytes[DRBG_SEED_SIZE_BYTES]; crypt_uword_t words[DRBG_SEED_SIZE_WORDS]; } DRBG_SEED; #define CTR_DRBG_MAX_REQUESTS_PER_RESEED ((UINT64)1 << 20) #define CTR_DRBG_MAX_BYTES_PER_REQUEST (1 << 16) # define CTR_DRBG_MIN_ENTROPY_INPUT_LENGTH DRBG_SEED_SIZE_BYTES # define CTR_DRBG_MAX_ENTROPY_INPUT_LENGTH DRBG_SEED_SIZE_BYTES # define CTR_DRBG_MAX_ADDITIONAL_INPUT_LENGTH DRBG_SEED_SIZE_BYTES #define TESTING (1 << 0) #define ENTROPY (1 << 1) #define TESTED (1 << 2) #define IsTestStateSet(BIT) ((g_cryptoSelfTestState.rng & BIT) != 0) #define SetTestStateBit(BIT) (g_cryptoSelfTestState.rng |= BIT) #define ClearTestStateBit(BIT) (g_cryptoSelfTestState.rng &= ~BIT) #define IsSelfTest() IsTestStateSet(TESTING) #define SetSelfTest() SetTestStateBit(TESTING) #define ClearSelfTest() ClearTestStateBit(TESTING) #define IsEntropyBad() IsTestStateSet(ENTROPY) #define SetEntropyBad() SetTestStateBit(ENTROPY) #define ClearEntropyBad() ClearTestStateBit(ENTROPY) #define IsDrbgTested() IsTestStateSet(TESTED) #define SetDrbgTested() SetTestStateBit(TESTED) #define ClearDrbgTested() ClearTestStateBit(TESTED) typedef struct { UINT64 reseedCounter; UINT32 magic; DRBG_SEED seed; // contains the key and IV for the counter mode DRBG SEED_COMPAT_LEVEL seedCompatLevel; // libtpms added: the compatibility level for keeping backwards compatibility UINT32 lastValue[4]; // used when the TPM does continuous self-test // for FIPS compliance of DRBG } DRBG_STATE, *pDRBG_STATE; #define DRBG_MAGIC ((UINT32) 0x47425244) // "DRBG" backwards so that it displays typedef struct KDF_STATE { UINT64 counter; UINT32 magic; UINT32 limit; TPM2B *seed; const TPM2B *label; TPM2B *context; TPM_ALG_ID hash; TPM_ALG_ID kdf; UINT16 digestSize; TPM2B_DIGEST residual; } KDF_STATE, *pKDR_STATE; #define KDF_MAGIC ((UINT32) 0x4048444a) // "KDF " backwards /* Make sure that any other structures added to this union start with a 64-bit counter and a 32-bit magic number */ typedef union { DRBG_STATE drbg; KDF_STATE kdf; } RAND_STATE; /* This is the state used when the library uses a random number generator. A special function is installed for the library to call. That function picks up the state from this location and uses it for the generation of the random number. */ extern RAND_STATE *s_random; /* When instrumenting RSA key sieve */ #if RSA_INSTRUMENT #define PRIME_INDEX(x) ((x) == 512 ? 0 : (x) == 1024 ? 1 : 2) # define INSTRUMENT_SET(a, b) ((a) = (b)) # define INSTRUMENT_ADD(a, b) (a) = (a) + (b) # define INSTRUMENT_INC(a) (a) = (a) + 1 extern UINT32 PrimeIndex; extern UINT32 failedAtIteration[10]; extern UINT32 PrimeCounts[3]; extern UINT32 MillerRabinTrials[3]; extern UINT32 totalFieldsSieved[3]; extern UINT32 bitsInFieldAfterSieve[3]; extern UINT32 emptyFieldsSieved[3]; extern UINT32 noPrimeFields[3]; extern UINT32 primesChecked[3]; extern UINT16 lastSievePrime; #else # define INSTRUMENT_SET(a, b) # define INSTRUMENT_ADD(a, b) # define INSTRUMENT_INC(a) #endif #endif // _CRYPT_RAND_H libtpms-0.9.3/src/tpm2/crypto/CryptRand_fp.h000066400000000000000000000144471421143571500207470ustar00rootroot00000000000000/********************************************************************************/ /* */ /* DRBG with a behavior according to SP800-90A */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CryptRand_fp.h 1476 2019-06-10 19:32:03Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ #ifndef CRYPTRAND_FP_H #define CRYPTRAND_FP_H BOOL DRBG_GetEntropy( UINT32 requiredEntropy, // IN: requested number of bytes of full // entropy BYTE *entropy // OUT: buffer to return collected entropy ); void IncrementIv( DRBG_IV *iv ); BOOL DRBG_Reseed( DRBG_STATE *drbgState, // IN: the state to update DRBG_SEED *providedEntropy, // IN: entropy DRBG_SEED *additionalData // IN: ); BOOL DRBG_SelfTest( void ); LIB_EXPORT TPM_RC CryptRandomStir( UINT16 additionalDataSize, BYTE *additionalData ); LIB_EXPORT UINT16 CryptRandomGenerate( UINT16 randomSize, BYTE *buffer ); LIB_EXPORT BOOL DRBG_InstantiateSeededKdf( KDF_STATE *state, // IN: buffer to hold the state TPM_ALG_ID hashAlg, // IN: hash algorithm TPM_ALG_ID kdf, // IN: the KDF to use TPM2B *seed, // IN: the seed to use const TPM2B *label, // IN: a label for the generation process. TPM2B *context, // IN: the context value UINT32 limit // IN: Maximum number of bits from the KDF ); LIB_EXPORT void DRBG_AdditionalData( DRBG_STATE *drbgState, // IN:OUT state to update TPM2B *additionalData // IN: value to incorporate ); LIB_EXPORT TPM_RC DRBG_InstantiateSeeded( DRBG_STATE *drbgState, // IN: buffer to hold the state const TPM2B *seed, // IN: the seed to use const TPM2B *purpose, // IN: a label for the generation process. const TPM2B *name, // IN: name of the object const TPM2B *additional, // IN: additional data SEED_COMPAT_LEVEL seedCompatLevel// IN: compatibility level (associated with seed); libtpms added ); LIB_EXPORT BOOL CryptRandStartup( void ); LIB_EXPORT BOOL CryptRandInit( void ); LIB_EXPORT UINT16 DRBG_Generate( RAND_STATE *state, BYTE *random, // OUT: buffer to receive the random values UINT16 randomSize // IN: the number of bytes to generate ); // libtpms added begin LIB_EXPORT SEED_COMPAT_LEVEL DRBG_GetSeedCompatLevel( RAND_STATE *state // IN ); // libtpms added end LIB_EXPORT BOOL DRBG_Instantiate( DRBG_STATE *drbgState, // OUT: the instantiated value UINT16 pSize, // IN: Size of personalization string BYTE *personalization // IN: The personalization string ); LIB_EXPORT TPM_RC DRBG_Uninstantiate( DRBG_STATE *drbgState // IN/OUT: working state to erase ); LIB_EXPORT NUMBYTES CryptRandMinMax( BYTE *out, UINT32 max, UINT32 min, RAND_STATE *rand ); #endif libtpms-0.9.3/src/tpm2/crypto/CryptRsa.h000066400000000000000000000110541421143571500201120ustar00rootroot00000000000000/********************************************************************************/ /* */ /* RSA-related structures and defines */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CryptRsa.h 1476 2019-06-10 19:32:03Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ // 10.1.5 CryptRsa.h // This file contains the RSA-related structures and defines. #ifndef _CRYPT_RSA_H #define _CRYPT_RSA_H /* This structure is a succinct representation of the cryptographic components of an RSA key. It is used in testing */ typedef struct { UINT32 exponent; // The public exponent pointer TPM2B *publicKey; // Pointer to the public modulus TPM2B *privateKey; // The private prime } RSA_KEY; /* These values are used in the bigNum representation of various RSA values. */ #define RSA_BITS (MAX_RSA_KEY_BYTES * 8) BN_TYPE(rsa, RSA_BITS); #define BN_RSA(name) BN_VAR(name, RSA_BITS) #define BN_RSA_INITIALIZED(name, initializer) \ BN_INITIALIZED(name, RSA_BITS, initializer) #define BN_PRIME(name) BN_VAR(name, (RSA_BITS / 2)) BN_TYPE(prime, (RSA_BITS / 2)); #define BN_PRIME_INITIALIZED(name, initializer) \ BN_INITIALIZED(name, RSA_BITS / 2, initializer) typedef struct privateExponent { #if CRT_FORMAT_RSA == NO bn_rsa_t D; #else bn_prime_t Q; bn_prime_t dP; bn_prime_t dQ; bn_prime_t qInv; #endif // CRT_FORMAT_RSA } privateExponent_t; #endif // _CRYPT_RSA_H libtpms-0.9.3/src/tpm2/crypto/CryptRsa_fp.h000066400000000000000000000134551421143571500206060ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Implementation of cryptographic primitives for RSA */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CryptRsa_fp.h 1476 2019-06-10 19:32:03Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ #ifndef CRYPTRSA_FP_H #define CRYPTRSA_FP_H BOOL CryptRsaInit( void ); BOOL CryptRsaStartup( void ); void RsaInitializeExponent( privateExponent_t *pExp ); INT16 CryptRsaPssSaltSize( INT16 hashSize, INT16 outSize ); TPMT_RSA_DECRYPT* CryptRsaSelectScheme( TPMI_DH_OBJECT rsaHandle, // IN: handle of an RSA key TPMT_RSA_DECRYPT *scheme // IN: a sign or decrypt scheme ); TPM_RC CryptRsaLoadPrivateExponent( OBJECT *rsaKey // IN: the RSA key object ); LIB_EXPORT TPM_RC CryptRsaEncrypt( TPM2B_PUBLIC_KEY_RSA *cOut, // OUT: the encrypted data TPM2B *dIn, // IN: the data to encrypt OBJECT *key, // IN: the key used for encryption TPMT_RSA_DECRYPT *scheme, // IN: the type of padding and hash // if needed const TPM2B *label, // IN: in case it is needed RAND_STATE *rand // IN: random number generator // state (mostly for testing) ); LIB_EXPORT TPM_RC CryptRsaDecrypt( TPM2B *dOut, // OUT: the decrypted data TPM2B *cIn, // IN: the data to decrypt OBJECT *key, // IN: the key to use for decryption TPMT_RSA_DECRYPT *scheme, // IN: the padding scheme const TPM2B *label // IN: in case it is needed for the scheme ); LIB_EXPORT TPM_RC CryptRsaSign( TPMT_SIGNATURE *sigOut, OBJECT *key, // IN: key to use TPM2B_DIGEST *hIn, // IN: the digest to sign RAND_STATE *rand // IN: the random number generator // to use (mostly for testing) ); LIB_EXPORT TPM_RC CryptRsaValidateSignature( TPMT_SIGNATURE *sig, // IN: signature OBJECT *key, // IN: public modulus TPM2B_DIGEST *digest // IN: The digest being validated ); LIB_EXPORT TPM_RC CryptRsaGenerateKey( OBJECT *rsaKey, // IN/OUT: The object structure in which // the key is created. RAND_STATE *rand // IN: if not NULL, the deterministic // RNG state ); INT16 MakeDerTag( TPM_ALG_ID hashAlg, INT16 sizeOfBuffer, BYTE *buffer ); #endif libtpms-0.9.3/src/tpm2/crypto/CryptSelfTest_fp.h000066400000000000000000000075251421143571500216130ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CryptSelfTest_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 */ /* */ /********************************************************************************/ #ifndef CRYPTSELFTEST_FP_H #define CRYPTSELFTEST_FP_H LIB_EXPORT TPM_RC CryptSelfTest( TPMI_YES_NO fullTest // IN: if full test is required ); TPM_RC CryptIncrementalSelfTest( TPML_ALG *toTest, // IN: list of algorithms to be tested TPML_ALG *toDoList // OUT: list of algorithms needing test ); void CryptInitializeToTest( void ); LIB_EXPORT TPM_RC CryptTestAlgorithm( TPM_ALG_ID alg, ALGORITHM_VECTOR *toTest ); #endif libtpms-0.9.3/src/tpm2/crypto/CryptSmac_fp.h000066400000000000000000000103221421143571500207320ustar00rootroot00000000000000/********************************************************************************/ /* Message Authentication Codes Based on a Symmetric Block Cipher */ /* Implementation of cryptographic functions for hashing. */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CryptSmac_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2018 */ /* */ /********************************************************************************/ #ifndef CRYPTSMAC_FP_H #define CRYPTSMAC_FP_H #include "Tpm.h" UINT16 CryptSmacStart( HASH_STATE *state, TPMU_PUBLIC_PARMS *keyParameters, TPM_ALG_ID macAlg, TPM2B *key ); UINT16 CryptMacStart( HMAC_STATE *state, TPMU_PUBLIC_PARMS *keyParameters, TPM_ALG_ID macAlg, TPM2B *key ); UINT16 CryptMacEnd( HMAC_STATE *state, UINT32 size, BYTE *buffer ); UINT16 CryptMacEnd( HMAC_STATE *state, UINT32 size, BYTE *buffer ); UINT16 CryptMacEnd2B ( HMAC_STATE *state, TPM2B *data ); #endif libtpms-0.9.3/src/tpm2/crypto/CryptSym.h000066400000000000000000000142411421143571500201360ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Implementation of the symmetric block cipher modes */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CryptSym.h 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2017 - 2021 */ /* */ /********************************************************************************/ #ifndef CRYPTSYM_H #define CRYPTSYM_H #if ALG_AES # define IF_IMPLEMENTED_AES(op) op(AES, aes) #else # define IF_IMPLEMENTED_AES(op) #endif #if ALG_SM4 # define IF_IMPLEMENTED_SM4(op) op(SM4, sm4) #else # define IF_IMPLEMENTED_SM4(op) #endif #if ALG_CAMELLIA # define IF_IMPLEMENTED_CAMELLIA(op) op(CAMELLIA, camellia) #else # define IF_IMPLEMENTED_CAMELLIA(op) #endif #if ALG_TDES # define IF_IMPLEMENTED_TDES(op) op(TDES, tdes) #else # define IF_IMPLEMENTED_TDES(op) #endif #define FOR_EACH_SYM(op) \ IF_IMPLEMENTED_AES(op) \ IF_IMPLEMENTED_SM4(op) \ IF_IMPLEMENTED_CAMELLIA(op) \ IF_IMPLEMENTED_TDES(op) /* libtpms added begin */ #define FOR_EACH_SYM_WITHOUT_TDES(op) \ IF_IMPLEMENTED_AES(op) \ IF_IMPLEMENTED_SM4(op) \ IF_IMPLEMENTED_CAMELLIA(op) /* libtpms added end */ /* Macros for creating the key schedule union */ #define KEY_SCHEDULE(SYM, sym) tpmKeySchedule##SYM sym; //#define TDES DES[3] /* libtpms commented */ typedef union tpmCryptKeySchedule_t { FOR_EACH_SYM_WITHOUT_TDES(KEY_SCHEDULE) /* libtpms changed from FOR_EACH_SYM */ tpmKeyScheduleTDES tdes[3]; /* libtpms added */ #if SYMMETRIC_ALIGNMENT == 8 uint64_t alignment; #else uint32_t alignment; #endif } tpmCryptKeySchedule_t; /* Each block cipher within a library is expected to conform to the same calling conventions with three parameters (keySchedule, in, and out) in the same order. That means that all algorithms would use the same order of the same parameters. The code is written assuming the (keySchedule, in, and out) order. However, if the library uses a different order, the order can be changed with a SWIZZLE macro that puts the parameters in the correct order. Note that all algorithms have to use the same order and number of parameters because the code to build the calling list is common for each call to encrypt or decrypt with the algorithm chosen by setting a function pointer to select the algorithm that is used. */ # define ENCRYPT(keySchedule, in, out) \ encrypt(SWIZZLE(keySchedule, in, out)) # define DECRYPT(keySchedule, in, out) \ decrypt(SWIZZLE(keySchedule, in, out)) /* Note that the macros rely on encrypt as local values in the functions that use these macros. Those parameters are set by the macro that set the key schedule to be used for the call. */ #define ENCRYPT_CASE(ALG, alg) \ case TPM_ALG_##ALG: \ TpmCryptSetEncryptKey##ALG(key, keySizeInBits, &keySchedule.alg); \ encrypt = (TpmCryptSetSymKeyCall_t)TpmCryptEncrypt##ALG; \ break; #define DECRYPT_CASE(ALG, alg) \ case TPM_ALG_##ALG: \ TpmCryptSetDecryptKey##ALG(key, keySizeInBits, &keySchedule.alg); \ decrypt = (TpmCryptSetSymKeyCall_t)TpmCryptDecrypt##ALG; \ break; #endif libtpms-0.9.3/src/tpm2/crypto/CryptSym_fp.h000066400000000000000000000121421421143571500206210ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CryptSym_fp.h 1047 2017-07-20 18:27:34Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 */ /* */ /********************************************************************************/ #ifndef CRYPTSYM_FP_H #define CRYPTSYM_FP_H BOOL CryptSymInit( void ); BOOL CryptSymStartup( void ); LIB_EXPORT INT16 CryptGetSymmetricBlockSize( TPM_ALG_ID symmetricAlg, // IN: the symmetric algorithm UINT16 keySizeInBits // IN: the key size ); LIB_EXPORT TPM_RC CryptSymmetricEncrypt( BYTE *dOut, // OUT: TPM_ALG_ID algorithm, // IN: the symmetric algorithm UINT16 keySizeInBits, // IN: key size in bits const BYTE *key, // IN: key buffer. The size of this buffer // in bytes is (keySizeInBits + 7) / 8 TPM2B_IV *ivInOut, // IN/OUT: IV for decryption. TPM_ALG_ID mode, // IN: Mode to use INT32 dSize, // IN: data size (may need to be a // multiple of the blockSize) const BYTE *dIn // IN: data buffer ); LIB_EXPORT TPM_RC CryptSymmetricDecrypt( BYTE *dOut, // OUT: decrypted data TPM_ALG_ID algorithm, // IN: the symmetric algorithm UINT16 keySizeInBits, // IN: key size in bits const BYTE *key, // IN: key buffer. The size of this buffer // in bytes is (keySizeInBits + 7) / 8 TPM2B_IV *ivInOut, // IN/OUT: IV for decryption. TPM_ALG_ID mode, // IN: Mode to use INT32 dSize, // IN: data size (may need to be a // multiple of the blockSize) const BYTE *dIn // IN: data buffer ); TPM_RC CryptSymKeyValidate( TPMT_SYM_DEF_OBJECT *symDef, TPM2B_SYM_KEY *key ); #endif libtpms-0.9.3/src/tpm2/crypto/CryptTest.h000066400000000000000000000110061421143571500203010ustar00rootroot00000000000000/********************************************************************************/ /* */ /* constant definitions used for self-test. */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CryptTest.h 1594 2020-03-26 22:15:48Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2020 */ /* */ /********************************************************************************/ #ifndef CRYPTTEST_H #define CRYPTTEST_H /* 10.1.7 CryptTest.h */ /* This file contains constant definitions used for self test */ /* This is the definition of a bit array with one bit per algorithm */ /* NOTE: Since bit numbering starts at zero, when TPM_ALG_LAST is a multiple of 8, ALGORITHM_VECTOR will need to have byte for the single bit in the last byte. So, for example, when TPM_ALG_LAST is 8, ALGORITHM_VECTOR will need 2 bytes. */ #define ALGORITHM_VECTOR_BYTES ((TPM_ALG_LAST + 8) / 8) typedef BYTE ALGORITHM_VECTOR[ALGORITHM_VECTOR_BYTES]; #ifdef TEST_SELF_TEST LIB_EXPORT extern ALGORITHM_VECTOR LibToTest; #endif /* This structure is used to contain self-test tracking information for the cryptographic modules. Each of the major modules is given a 32-bit value in which it may maintain its own self test information. The convention for this state is that when all of the bits in this structure are 0, all functions need to be tested. */ typedef struct { UINT32 rng; UINT32 hash; UINT32 sym; #if ALG_RSA UINT32 rsa; #endif #if ALG_ECC UINT32 ecc; #endif } CRYPTO_SELF_TEST_STATE; #endif // _CRYPT_TEST_H libtpms-0.9.3/src/tpm2/crypto/CryptUtil_fp.h000066400000000000000000000226751421143571500210020ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Interfaces to the CryptoEngine */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CryptUtil_fp.h 1519 2019-11-15 20:43:51Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ #ifndef CRYPTUTIL_FP_H #define CRYPTUTIL_FP_H BOOL CryptIsSchemeAnonymous( TPM_ALG_ID scheme // IN: the scheme algorithm to test ); void ParmDecryptSym( TPM_ALG_ID symAlg, // IN: the symmetric algorithm TPM_ALG_ID hash, // IN: hash algorithm for KDFa UINT16 keySizeInBits, // IN: the key size in bits TPM2B *key, // IN: KDF HMAC key TPM2B *nonceCaller, // IN: nonce caller TPM2B *nonceTpm, // IN: nonce TPM UINT32 dataSize, // IN: size of parameter buffer BYTE *data // OUT: buffer to be decrypted ); void ParmEncryptSym( TPM_ALG_ID symAlg, // IN: symmetric algorithm TPM_ALG_ID hash, // IN: hash algorithm for KDFa UINT16 keySizeInBits, // IN: AES key size in bits TPM2B *key, // IN: KDF HMAC key TPM2B *nonceCaller, // IN: nonce caller TPM2B *nonceTpm, // IN: nonce TPM UINT32 dataSize, // IN: size of parameter buffer BYTE *data // OUT: buffer to be encrypted ); void CryptXORObfuscation( TPM_ALG_ID hash, // IN: hash algorithm for KDF TPM2B *key, // IN: KDF key TPM2B *contextU, // IN: contextU TPM2B *contextV, // IN: contextV UINT32 dataSize, // IN: size of data buffer BYTE *data // IN/OUT: data to be XORed in place ); BOOL CryptInit( void ); BOOL CryptStartup( STARTUP_TYPE type // IN: the startup type ); BOOL CryptIsAsymAlgorithm( TPM_ALG_ID algID // IN: algorithm ID ); TPM_RC CryptSecretEncrypt( OBJECT *encryptKey, // IN: encryption key object const TPM2B *label, // IN: a null-terminated string as L TPM2B_DATA *data, // OUT: secret value TPM2B_ENCRYPTED_SECRET *secret // OUT: secret structure ); TPM_RC CryptSecretDecrypt( OBJECT *decryptKey, // IN: decrypt key TPM2B_NONCE *nonceCaller, // IN: nonceCaller. It is needed for // symmetric decryption. For // asymmetric decryption, this // parameter is NULL const TPM2B *label, // IN: a value for L TPM2B_ENCRYPTED_SECRET *secret, // IN: input secret TPM2B_DATA *data // OUT: decrypted secret value ); void CryptParameterEncryption( TPM_HANDLE handle, // IN: encrypt session handle TPM2B *nonceCaller, // IN: nonce caller UINT16 leadingSizeInByte, // IN: the size of the leading size field in // bytes TPM2B_AUTH *extraKey, // IN: additional key material other than // sessionAuth BYTE *buffer // IN/OUT: parameter buffer to be encrypted ); TPM_RC CryptParameterDecryption( TPM_HANDLE handle, // IN: encrypted session handle TPM2B *nonceCaller, // IN: nonce caller UINT32 bufferSize, // IN: size of parameter buffer UINT16 leadingSizeInByte, // IN: the size of the leading size field in // byte TPM2B_AUTH *extraKey, // IN: the authValue BYTE *buffer // IN/OUT: parameter buffer to be decrypted ); void CryptComputeSymmetricUnique( TPMT_PUBLIC *publicArea, // IN: the object's public area TPMT_SENSITIVE *sensitive, // IN: the associated sensitive area TPM2B_DIGEST *unique // OUT: unique buffer ); TPM_RC CryptCreateObject( OBJECT *object, // IN: new object structure pointer TPMS_SENSITIVE_CREATE *sensitiveCreate, // IN: sensitive creation RAND_STATE *rand // IN: the random number generator // to use ); TPMI_ALG_HASH CryptGetSignHashAlg( TPMT_SIGNATURE *auth // IN: signature ); BOOL CryptIsSplitSign( TPM_ALG_ID scheme // IN: the algorithm selector ); BOOL CryptIsAsymSignScheme( TPMI_ALG_PUBLIC publicType, // IN: Type of the object TPMI_ALG_ASYM_SCHEME scheme // IN: the scheme ); BOOL CryptIsAsymDecryptScheme( TPMI_ALG_PUBLIC publicType, // IN: Type of the object TPMI_ALG_ASYM_SCHEME scheme // IN: the scheme ); BOOL CryptSelectSignScheme( OBJECT *signObject, // IN: signing key TPMT_SIG_SCHEME *scheme // IN/OUT: signing scheme ); TPM_RC CryptSign( OBJECT *signKey, // IN: signing key TPMT_SIG_SCHEME *signScheme, // IN: sign scheme. TPM2B_DIGEST *digest, // IN: The digest being signed TPMT_SIGNATURE *signature // OUT: signature ); TPM_RC CryptValidateSignature( TPMI_DH_OBJECT keyHandle, // IN: The handle of sign key TPM2B_DIGEST *digest, // IN: The digest being validated TPMT_SIGNATURE *signature // IN: signature ); TPM_RC CryptGetTestResult( TPM2B_MAX_BUFFER *outData // OUT: test result data ); TPM_RC CryptValidateKeys( TPMT_PUBLIC *publicArea, TPMT_SENSITIVE *sensitive, TPM_RC blamePublic, TPM_RC blameSensitive ); TPM_RC CryptSelectMac( TPMT_PUBLIC *publicArea, TPMI_ALG_MAC_SCHEME *inMac ); BOOL CryptMacIsValidForKey( TPM_ALG_ID keyType, TPM_ALG_ID macAlg, BOOL flag ); BOOL CryptSmacIsValidAlg( TPM_ALG_ID alg, BOOL FLAG // IN: Indicates if TPM_ALG_NULL is valid ); BOOL CryptSymModeIsValid( TPM_ALG_ID mode, BOOL flag ); #endif libtpms-0.9.3/src/tpm2/crypto/openssl/000077500000000000000000000000001421143571500176545ustar00rootroot00000000000000libtpms-0.9.3/src/tpm2/crypto/openssl/BnConvert_fp.h000066400000000000000000000111311421143571500224070ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: BnConvert_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 */ /* */ /********************************************************************************/ #ifndef BNCONVERT_FP_H #define BNCONVERT_FP_H LIB_EXPORT bigNum BnFromBytes( bigNum bn, const BYTE *bytes, NUMBYTES nBytes ); LIB_EXPORT bigNum BnFrom2B( bigNum bn, // OUT: const TPM2B *a2B // IN: number to convert ); LIB_EXPORT bigNum BnFromHex( bigNum bn, // OUT: const char *hex // IN: ); LIB_EXPORT BOOL BnToBytes( bigConst bn, BYTE *buffer, NUMBYTES *size // This the number of bytes that are // available in the buffer. The result // should be this big. ); LIB_EXPORT BOOL BnTo2B( bigConst bn, // IN: TPM2B *a2B, // OUT: NUMBYTES size // IN: the desired size ); LIB_EXPORT bn_point_t * BnPointFrom2B( bigPoint ecP, // OUT: the preallocated point structure TPMS_ECC_POINT *p // IN: the number to convert ); LIB_EXPORT BOOL BnPointTo2B( TPMS_ECC_POINT *p, // OUT: the converted 2B structure bigPoint ecP, // IN: the values to be converted bigCurve E // IN: curve descriptor for the point ); #endif libtpms-0.9.3/src/tpm2/crypto/openssl/BnMath_fp.h000066400000000000000000000125431421143571500216700ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: BnMath_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 */ /* */ /********************************************************************************/ #ifndef BNMATH_FP_H #define BNMATH_FP_H LIB_EXPORT BOOL BnAdd( bigNum result, bigConst op1, bigConst op2 ); LIB_EXPORT BOOL BnAddWord( bigNum result, bigConst op, crypt_uword_t word ); LIB_EXPORT BOOL BnSub( bigNum result, bigConst op1, bigConst op2 ); LIB_EXPORT BOOL BnSubWord( bigNum result, bigConst op, crypt_uword_t word ); LIB_EXPORT int BnUnsignedCmp( bigConst op1, bigConst op2 ); LIB_EXPORT int BnUnsignedCmpWord( bigConst op1, crypt_uword_t word ); LIB_EXPORT crypt_word_t BnModWord( bigConst numerator, crypt_word_t modulus ); LIB_EXPORT int Msb( crypt_uword_t word ); LIB_EXPORT int BnMsb( bigConst bn ); LIB_EXPORT unsigned BnSizeInBits( bigConst n ); LIB_EXPORT bigNum BnSetWord( bigNum n, crypt_uword_t w ); LIB_EXPORT BOOL BnSetBit( bigNum bn, // IN/OUT: big number to modify unsigned int bitNum // IN: Bit number to SET ); LIB_EXPORT BOOL BnTestBit( bigNum bn, // IN: number to check unsigned int bitNum // IN: bit to test ); LIB_EXPORT BOOL BnMaskBits( bigNum bn, // IN/OUT: number to mask crypt_uword_t maskBit // IN: the bit number for the mask. ); LIB_EXPORT BOOL BnShiftRight( bigNum result, bigConst toShift, uint32_t shiftAmount ); LIB_EXPORT BOOL BnGetRandomBits( bigNum n, size_t bits, RAND_STATE *rand ); LIB_EXPORT BOOL BnGenerateRandomInRange( bigNum dest, bigConst limit, RAND_STATE *rand ); // libtpms added begin LIB_EXPORT BOOL BnGenerateRandomInRangeAllBytes( bigNum dest, bigConst limit, RAND_STATE *rand ); // libtpms added end #endif libtpms-0.9.3/src/tpm2/crypto/openssl/BnMemory_fp.h000066400000000000000000000105761421143571500222530ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: BnMemory_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 */ /* */ /********************************************************************************/ #ifndef BNMEMORY_FP_H #define BNMEMORY_FP_H LIB_EXPORT bigNum BnSetTop( bigNum bn, // IN/OUT: number to clean crypt_uword_t top // IN: the new top ); #if 0 /* libtpms added */ LIB_EXPORT bigNum BnClearTop( bigNum bn ); #endif /* libtpms added */ LIB_EXPORT bigNum BnInitializeWord( bigNum bn, // IN: crypt_uword_t allocated, // IN: crypt_uword_t word // IN: ); LIB_EXPORT bigNum BnInit( bigNum bn, crypt_uword_t allocated ); LIB_EXPORT BOOL BnCopy( bigNum out, bigConst in ); #if 0 /* libtpms added */ LIB_EXPORT BOOL BnPointCopy( bigPoint pOut, pointConst pIn ); #endif /* libtpms added */ LIB_EXPORT bn_point_t * BnInitializePoint( bigPoint p, // OUT: structure to receive pointers bigNum x, // IN: x coordinate bigNum y, // IN: y coordinate bigNum z // IN: x coordinate ); #endif libtpms-0.9.3/src/tpm2/crypto/openssl/BnValues.h000066400000000000000000000400421421143571500215440ustar00rootroot00000000000000/********************************************************************************/ /* */ /* For defining the internal BIGNUM structure */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: BnValues.h 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2021 */ /* */ /********************************************************************************/ /* 10.1.1 BnValues.h */ /* This file contains the definitions needed for defining the internal BIGNUM structure. A BIGNUM is a pointer to a structure. The structure has three fields. The last field is and array (d) of crypt_uword_t. Each word is in machine format (big- or little-endian) with the words in ascending significance (i.e. words in little-endian order). This is the order that seems to be used in every big number library in the worlds, so... */ /* The first field in the structure (allocated) is the number of words in d. This is the upper limit on the size of the number that can be held in the structure. This differs from libraries like OpenSSL() as this is not intended to deal with numbers of arbitrary size; just numbers that are needed to deal with the algorithms that are defined in the TPM implementation. */ /* The second field in the structure (size) is the number of significant words in n. When this number is zero, the number is zero. The word at used-1 should never be zero. All words between d[size] and d[allocated-1] should be zero. */ #ifndef _BN_NUMBERS_H #define _BN_NUMBERS_H #if RADIX_BITS == 64 # define RADIX_LOG2 6 #elif RADIX_BITS == 32 #define RADIX_LOG2 5 #else # error "Unsupported radix" #endif #define RADIX_MOD(x) ((x) & ((1 << RADIX_LOG2) - 1)) #define RADIX_DIV(x) ((x) >> RADIX_LOG2) #define RADIX_MASK ((((crypt_uword_t)1) << RADIX_LOG2) - 1) #define BITS_TO_CRYPT_WORDS(bits) RADIX_DIV((bits) + (RADIX_BITS - 1)) #define BYTES_TO_CRYPT_WORDS(bytes) BITS_TO_CRYPT_WORDS(bytes * 8) #define SIZE_IN_CRYPT_WORDS(thing) BYTES_TO_CRYPT_WORDS(sizeof(thing)) #if RADIX_BITS == 64 #define SWAP_CRYPT_WORD(x) REVERSE_ENDIAN_64(x) typedef uint64_t crypt_uword_t; typedef int64_t crypt_word_t; # define TO_CRYPT_WORD_64 BIG_ENDIAN_BYTES_TO_UINT64 # define TO_CRYPT_WORD_32(a, b, c, d) TO_CRYPT_WORD_64(0, 0, 0, 0, a, b, c, d) #define BN_PAD 0 /* libtpms added */ #elif RADIX_BITS == 32 #define SWAP_CRYPT_WORD(x) REVERSE_ENDIAN_32((x)) typedef uint32_t crypt_uword_t; typedef int32_t crypt_word_t; # define TO_CRYPT_WORD_64(a, b, c, d, e, f, g, h) \ BIG_ENDIAN_BYTES_TO_UINT32(e, f, g, h), \ BIG_ENDIAN_BYTES_TO_UINT32(a, b, c, d) # define TO_CRYPT_WORD_32 BIG_ENDIAN_BYTES_TO_UINT32 #define BN_PAD 1 /* libtpms added */ #endif #define MAX_CRYPT_UWORD (~((crypt_uword_t)0)) #define MAX_CRYPT_WORD ((crypt_word_t)(MAX_CRYPT_UWORD >> 1)) #define MIN_CRYPT_WORD (~MAX_CRYPT_WORD) #define LARGEST_NUMBER (MAX((ALG_RSA * MAX_RSA_KEY_BYTES), \ MAX((ALG_ECC * MAX_ECC_KEY_BYTES), MAX_DIGEST_SIZE))) #define LARGEST_NUMBER_BITS (LARGEST_NUMBER * 8) #define MAX_ECC_PARAMETER_BYTES (MAX_ECC_KEY_BYTES * ALG_ECC) /* These are the basic big number formats. This is convertible to the library- specific format without too much difficulty. For the math performed using these numbers, the value is always positive. */ #define BN_STRUCT_DEF(count) struct { \ crypt_uword_t allocated; \ crypt_uword_t size; \ crypt_uword_t d[count + BN_PAD + BN_PAD + BN_PAD]; /* libtpms changed */ \ } typedef BN_STRUCT_DEF(1) bignum_t; #ifndef bigNum typedef bignum_t *bigNum; typedef const bignum_t *bigConst; #endif extern const bignum_t BnConstZero; /* The Functions to access the properties of a big number. Get number of allocated words */ #define BnGetAllocated(x) (unsigned)((x)->allocated) /* Get number of words used */ #define BnGetSize(x) ((x)->size) /* Get a pointer to the data array */ #define BnGetArray(x) ((crypt_uword_t *)&((x)->d[0])) /* Get the nth word of a BIGNUM (zero-based) */ #define BnGetWord(x, i) (crypt_uword_t)((x)->d[i]) /* Some things that are done often. Test to see if a bignum_t is equal to zero */ #define BnEqualZero(bn) (BnGetSize(bn) == 0) /* Test to see if a bignum_t is equal to a word type */ #define BnEqualWord(bn, word) \ ((BnGetSize(bn) == 1) && (BnGetWord(bn, 0) == (crypt_uword_t)word)) /* Determine if a BIGNUM is even. A zero is even. Although the indication that a number is zero is that its size is zero, all words of the number are 0 so this test works on zero. */ #define BnIsEven(n) ((BnGetWord(n, 0) & 1) == 0) /* The macros below are used to define BIGNUM values of the required size. The values are allocated on the stack so they can be treated like simple local values. This will call the initialization function for a defined bignum_t. This sets the allocated and used fields and clears the words of n. */ #define BN_INIT(name) \ (bigNum)BnInit((bigNum)&(name), \ BYTES_TO_CRYPT_WORDS(sizeof(name.d))) /* In some cases, a function will need the address of the structure associated with a variable. The structure for a BIGNUM variable of name is name_. Generally, when the structure is created, it is initialized and a parameter is created with a pointer to the structure. The pointer has the name and the structure it points to is name_ */ #define BN_ADDRESS(name) (bigNum)&name##_ #define BN_CONST(name, words, initializer) \ typedef const struct name##_type { \ crypt_uword_t allocated; \ crypt_uword_t size; \ crypt_uword_t d[words < 1 ? 1 : words]; \ } name##_type; \ name##_type name = {(words < 1 ? 1 : words), words, {initializer}}; #define BN_STRUCT_ALLOCATION(bits) (BITS_TO_CRYPT_WORDS(bits) + 1) /* Create a structure of the correct size. */ #define BN_STRUCT(bits) \ BN_STRUCT_DEF(BN_STRUCT_ALLOCATION(bits)) /* Define a BIGNUM type with a specific allocation */ #define BN_TYPE(name, bits) \ typedef BN_STRUCT(bits) bn_##name##_t /* This creates a local BIGNUM variable of a specific size and initializes it from a TPM2B input parameter. */ #define BN_INITIALIZED(name, bits, initializer) \ BN_STRUCT(bits) name##_; \ bigNum name = BnFrom2B(BN_INIT(name##_), \ (const TPM2B *)initializer) /* Create a local variable that can hold a number with bits */ #define BN_VAR(name, bits) \ BN_STRUCT(bits) _##name; \ bigNum name = BN_INIT(_##name) /* Create a type that can hold the largest number defined by the implementation. */ #define BN_MAX(name) BN_VAR(name, LARGEST_NUMBER_BITS) #define BN_MAX_INITIALIZED(name, initializer) \ BN_INITIALIZED(name, LARGEST_NUMBER_BITS, initializer) /* A word size value is useful */ #define BN_WORD(name) BN_VAR(name, RADIX_BITS) /* This is used to create a word-size BIGNUM and initialize it with an input parameter to a function. */ #define BN_WORD_INITIALIZED(name, initial) \ BN_STRUCT(RADIX_BITS) name##_; \ bigNum name = BnInitializeWord((bigNum)&name##_, \ BN_STRUCT_ALLOCATION(RADIX_BITS), initial) /* ECC-Specific Values This is the format for a point. It is always in affine format. The Z value is carried as part of the point, primarily to simplify the interface to the support library. Rather than have the interface layer have to create space for the point each time it is used... The x, y, and z values are pointers to bigNum values and not in-line versions of the numbers. This is a relic of the days when there was no standard TPM format for the numbers */ typedef struct _bn_point_t { bigNum x; bigNum y; bigNum z; } bn_point_t; typedef bn_point_t *bigPoint; typedef const bn_point_t *pointConst; typedef struct constant_point_t { bigConst x; bigConst y; bigConst z; } constant_point_t; #define ECC_BITS (MAX_ECC_KEY_BYTES * 8) BN_TYPE(ecc, ECC_BITS); #define ECC_NUM(name) BN_VAR(name, ECC_BITS) #define ECC_INITIALIZED(name, initializer) \ BN_INITIALIZED(name, ECC_BITS, initializer) #define POINT_INSTANCE(name, bits) \ BN_STRUCT (bits) name##_x = \ {BITS_TO_CRYPT_WORDS ( bits ), 0,{0}}; \ BN_STRUCT ( bits ) name##_y = \ {BITS_TO_CRYPT_WORDS ( bits ), 0,{0}}; \ BN_STRUCT ( bits ) name##_z = \ {BITS_TO_CRYPT_WORDS ( bits ), 0,{0}}; \ bn_point_t name##_ #define POINT_INITIALIZER(name) \ BnInitializePoint(&name##_, (bigNum)&name##_x, \ (bigNum)&name##_y, (bigNum)&name##_z) #define POINT_INITIALIZED(name, initValue) \ POINT_INSTANCE(name, MAX_ECC_KEY_BITS); \ bigPoint name = BnPointFrom2B( \ POINT_INITIALIZER(name), \ initValue) #define POINT_VAR(name, bits) \ POINT_INSTANCE (name, bits); \ bigPoint name = POINT_INITIALIZER(name) #define POINT(name) POINT_VAR(name, MAX_ECC_KEY_BITS) /* Structure for the curve parameters. This is an analog to the TPMS_ALGORITHM_DETAIL_ECC */ typedef struct { bigConst prime; // a prime number bigConst order; // the order of the curve bigConst h; // cofactor bigConst a; // linear coefficient bigConst b; // constant term constant_point_t base; // base point } ECC_CURVE_DATA; /* Access macros for the ECC_CURVE structure. The parameter C is a pointer to an ECC_CURVE_DATA structure. In some libraries, the curve structure contains a pointer to an ECC_CURVE_DATA structure as well as some other bits. For those cases, the AccessCurveData() macro is used in the code to first get the pointer to the ECC_CURVE_DATA for access. In some cases, the macro does nothing. */ #define CurveGetPrime(C) ((C)->prime) #define CurveGetOrder(C) ((C)->order) #define CurveGetCofactor(C) ((C)->h) #define CurveGet_a(C) ((C)->a) #define CurveGet_b(C) ((C)->b) #define CurveGetG(C) ((pointConst)&((C)->base)) #define CurveGetGx(C) ((C)->base.x) #define CurveGetGy(C) ((C)->base.y) /* Convert bytes in initializers according to the endianness of the system. This is used for CryptEccData.c. */ #define BIG_ENDIAN_BYTES_TO_UINT32(a, b, c, d) \ ( ((UINT32)(a) << 24) \ + ((UINT32)(b) << 16) \ + ((UINT32)(c) << 8) \ + ((UINT32)(d)) \ ) #define BIG_ENDIAN_BYTES_TO_UINT64(a, b, c, d, e, f, g, h) \ ( ((UINT64)(a) << 56) \ + ((UINT64)(b) << 48) \ + ((UINT64)(c) << 40) \ + ((UINT64)(d) << 32) \ + ((UINT64)(e) << 24) \ + ((UINT64)(f) << 16) \ + ((UINT64)(g) << 8) \ + ((UINT64)(h)) \ ) #ifndef RADIX_BYTES # if RADIX_BITS == 32 # define RADIX_BYTES 4 # elif RADIX_BITS == 64 # define RADIX_BYTES 8 # else # error "RADIX_BITS must either be 32 or 64" # endif #endif /* These macros are used for data initialization of big number ECC constants These two macros combine a macro for data definition with a macro for structure initialization. The a parameter is a macro that gives numbers to each of the bytes of the initializer and defines where each of the numberd bytes will show up in the final structure. The b value is a structure that contains the requisite number of bytes in big endian order. S, the MJOIN and JOIND macros will combine a macro defining a data layout with a macro defining the data to be places. Generally, these macros will only need expansion when CryptEccData().c gets compiled. */ #define JOINED(a,b) a b #define MJOIN(a,b) a b #define B4_TO_BN(a, b, c, d) (((((a << 8) + b) << 8) + c) + d) #if RADIX_BYTES == 64 #define B8_TO_BN(a, b, c, d, e, f, g, h) \ (UINT64)(((((((((((((((a) << 8) | b) << 8) | c) << 8) | d) << 8) \ e) << 8) | f) << 8) | g) << 8) | h) #define B1_TO_BN(a) B8_TO_BN(0, 0, 0, 0, 0, 0, 0, a) #define B2_TO_BN(a, b) B8_TO_BN(0, 0, 0, 0, 0, 0, a, b) #define B3_TO_BN(a, b, c) B8_TO_BN(0, 0, 0, 0, 0, a, b, c) #define B4_TO_BN(a, b, c, d) B8_TO_BN(0, 0, 0, 0, a, b, c, d) #define B5_TO_BN(a, b, c, d, e) B8_TO_BN(0, 0, 0, a, b, c, d, e) #define B6_TO_BN(a, b, c, d, e, f) B8_TO_BN(0, 0, a, b, c, d, e, f) #define B7_TO_BN(a, b, c, d, e, f, g) B8_TO_BN(0, a, b, c, d, e, f, g) #else #define B1_TO_BN(a) B4_TO_BN(0, 0, 0, a) #define B2_TO_BN(a, b) B4_TO_BN(0, 0, a, b) #define B3_TO_BN(a, b, c) B4_TO_BN(0, a, b, c) #define B4_TO_BN(a, b, c, d) (((((a << 8) + b) << 8) + c) + d) #define B5_TO_BN(a, b, c, d, e) B4_TO_BN(b, c, d, e), B1_TO_BN(a) #define B6_TO_BN(a, b, c, d, e, f) B4_TO_BN(c, d, e, f), B2_TO_BN(a, b) #define B7_TO_BN(a, b, c, d, e, f, g) B4_TO_BN(d, e, f, g), B3_TO_BN(a, b, c) #define B8_TO_BN(a, b, c, d, e, f, g, h) B4_TO_BN(e, f, g, h), B4_TO_BN(a, b, c, d) #endif /* Add implementation dependent definitions for other ECC Values and for linkages */ #include LIB_INCLUDE(MATH_LIB, Math) #endif // _BN_NUMBERS_H libtpms-0.9.3/src/tpm2/crypto/openssl/ConsttimeUtils.h000066400000000000000000000117471421143571500230250ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Constant time debugging helper functions */ /* Written by Stefan Berger */ /* IBM Thomas J. Watson Research Center */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2020 */ /* */ /********************************************************************************/ #ifndef CONSTTIME_UTILS_H #define CONSTTIME_UTILS_H #include #include #include "BnValues.h" #include static __inline__ unsigned long long rdtsc() { unsigned long h, l; __asm__ __volatile__ ("rdtsc" : "=a"(l), "=d"(h)); return (unsigned long long)l | ((unsigned long long)h << 32 ); } // Make sure that the given BIGNUM has the given number of expected bytes. // Skip over any leading zeros the BIGNUM may have. static inline void assert_ossl_num_bytes(const BIGNUM *a, unsigned int num_bytes, int verbose, const char *caller) { unsigned char buffer[LARGEST_NUMBER] = { 0, }; int len, i; len = BN_bn2bin(a, buffer); for (i = 0; i < len; i++) { if (buffer[i]) break; } len -= i; if (num_bytes != (unsigned int)len) { printf("%s: Expected %u bytes but found %d (caller: %s)\n", __func__, num_bytes, len, caller); } else { if (verbose) printf("%s: check passed; num_bytes = %d (caller: %s)\n",__func__, num_bytes, caller); } assert(num_bytes == (unsigned int)len); } // Make sure that the bigNum has the expected number of bytes after it was // converted to an OpenSSL BIGNUM. static inline void assert_bn_ossl_num_bytes(bigNum tpmb, unsigned int num_bytes, int verbose, const char *caller) { BIG_INITIALIZED(osslb, tpmb); assert_ossl_num_bytes(osslb, num_bytes, verbose, caller); BN_free(osslb); } #endif /* CONSTTIME_UTILS_H */ libtpms-0.9.3/src/tpm2/crypto/openssl/CryptCmac.c000066400000000000000000000217731421143571500217170ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Message Authentication Codes Based on a Symmetric Block Cipher */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CryptCmac.c 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2018 - 2021 */ /* */ /********************************************************************************/ /* 10.2.6 CryptCmac.c */ /* 10.2.6.1 Introduction */ /* This file contains the implementation of the message authentication codes based on a symmetric block cipher. These functions only use the single block encryption functions of the selected symmetric cryptographic library. */ /* 10.2.6.2 Includes, Defines, and Typedefs */ #define _CRYPT_HASH_C_ #include "Tpm.h" #include "CryptSym.h" #if ALG_CMAC /* 10.2.6.3 Functions */ /* 10.2.6.3.1 CryptCmacStart() */ /* This is the function to start the CMAC sequence operation. It initializes the dispatch functions for the data and end operations for CMAC and initializes the parameters that are used for the processing of data, including the key, key size and block cipher algorithm. */ UINT16 CryptCmacStart( SMAC_STATE *state, TPMU_PUBLIC_PARMS *keyParms, TPM_ALG_ID macAlg, TPM2B *key ) { tpmCmacState_t *cState = &state->state.cmac; TPMT_SYM_DEF_OBJECT *def = &keyParms->symDetail.sym; // if(macAlg != TPM_ALG_CMAC) return 0; MemorySet(cState, 0, sizeof(*cState)); // libtpms bugfix // set up the encryption algorithm and parameters cState->symAlg = def->algorithm; cState->keySizeBits = def->keyBits.sym; cState->iv.t.size = CryptGetSymmetricBlockSize(def->algorithm, def->keyBits.sym); MemoryCopy2B(&cState->symKey.b, key, sizeof(cState->symKey.t.buffer)); // Set up the dispatch methods for the CMAC state->smacMethods.data = CryptCmacData; state->smacMethods.end = CryptCmacEnd; return cState->iv.t.size; } /* 10.2.5.3.2 CryptCmacData() */ /* This function is used to add data to the CMAC sequence computation. The function will XOR new data into the IV. If the buffer is full, and there is additional input data, the data is encrypted into the IV buffer, the new data is then XOR into the IV. When the data runs out, the function returns without encrypting even if the buffer is full. The last data block of a sequence will not be encrypted until the call to CryptCmacEnd(). This is to allow the proper subkey to be computed and applied before the last block is encrypted. */ void CryptCmacData( SMAC_STATES *state, UINT32 size, const BYTE *buffer ) { tpmCmacState_t *cmacState = &state->cmac; TPM_ALG_ID algorithm = cmacState->symAlg; BYTE *key = cmacState->symKey.t.buffer; UINT16 keySizeInBits = cmacState->keySizeBits; tpmCryptKeySchedule_t keySchedule; TpmCryptSetSymKeyCall_t encrypt; // memset(&keySchedule, 0, sizeof(keySchedule)); /* libtpms added: coverity */ // Set up the encryption values based on the algorithm switch (algorithm) { FOR_EACH_SYM(ENCRYPT_CASE) default: FAIL(FATAL_ERROR_INTERNAL); } while(size > 0) { if(cmacState->bcount == cmacState->iv.t.size) { ENCRYPT(&keySchedule, cmacState->iv.t.buffer, cmacState->iv.t.buffer); cmacState->bcount = 0; } for(;(size > 0) && (cmacState->bcount < cmacState->iv.t.size); size--, cmacState->bcount++) { cmacState->iv.t.buffer[cmacState->bcount] ^= *buffer++; } } } /* 10.2.6.3.3 CryptCmacEnd() */ /* This is the completion function for the CMAC. It does padding, if needed, and selects the subkey to be applied before the last block is encrypted. */ UINT16 CryptCmacEnd( SMAC_STATES *state, UINT32 outSize, BYTE *outBuffer ) { tpmCmacState_t *cState = &state->cmac; // Need to set algorithm, key, and keySizeInBits in the local context so that // the SELECT and ENCRYPT macros will work here TPM_ALG_ID algorithm = cState->symAlg; BYTE *key = cState->symKey.t.buffer; UINT16 keySizeInBits = cState->keySizeBits; tpmCryptKeySchedule_t keySchedule; TpmCryptSetSymKeyCall_t encrypt; TPM2B_IV subkey = {{0, {0}}}; BOOL xorVal; UINT16 i; memset(&keySchedule, 0, sizeof(keySchedule)); /* libtpms added: coverity */ subkey.t.size = cState->iv.t.size; // Encrypt a block of zero // Set up the encryption values based on the algorithm switch (algorithm) { FOR_EACH_SYM(ENCRYPT_CASE) default: return 0; } ENCRYPT(&keySchedule, subkey.t.buffer, subkey.t.buffer); // shift left by 1 and XOR with 0x0...87 if the MSb was 0 xorVal = ((subkey.t.buffer[0] & 0x80) == 0) ? 0 : 0x87; ShiftLeft(&subkey.b); subkey.t.buffer[subkey.t.size - 1] ^= xorVal; // this is a sanity check to make sure that the algorithm is working properly. // remove this check when debug is done pAssert(cState->bcount <= cState->iv.t.size); // If the buffer is full then no need to compute subkey 2. if(cState->bcount < cState->iv.t.size) { //Pad the data cState->iv.t.buffer[cState->bcount++] ^= 0x80; // The rest of the data is a pad of zero which would simply be XORed // with the iv value so nothing to do... // Now compute K2 xorVal = ((subkey.t.buffer[0] & 0x80) == 0) ? 0 : 0x87; ShiftLeft(&subkey.b); subkey.t.buffer[subkey.t.size - 1] ^= xorVal; } // XOR the subkey into the IV for(i = 0; i < subkey.t.size; i++) cState->iv.t.buffer[i] ^= subkey.t.buffer[i]; ENCRYPT(&keySchedule, cState->iv.t.buffer, cState->iv.t.buffer); i = (UINT16)MIN(cState->iv.t.size, outSize); MemoryCopy(outBuffer, cState->iv.t.buffer, i); return i; } #endif libtpms-0.9.3/src/tpm2/crypto/openssl/CryptDes.c000066400000000000000000000211561421143571500215620ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Functions Required for TDES */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CryptDes.c 1398 2018-12-17 22:37:57Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2018 */ /* */ /********************************************************************************/ /* 10.2.9 CryptDes.c */ /* 10.2.9.1 Introduction */ /* This file contains the extra functions required for TDES. */ /* 10.2.9.2 Includes, Defines, and Typedefs */ #include "Tpm.h" #include "Helpers_fp.h" // libtpms added #if ALG_TDES #define DES_NUM_WEAK 64 const UINT64 DesWeakKeys[DES_NUM_WEAK] = { 0x0101010101010101ULL, 0xFEFEFEFEFEFEFEFEULL, 0xE0E0E0E0F1F1F1F1ULL, 0x1F1F1F1F0E0E0E0EULL, 0x011F011F010E010EULL, 0x1F011F010E010E01ULL, 0x01E001E001F101F1ULL, 0xE001E001F101F101ULL, 0x01FE01FE01FE01FEULL, 0xFE01FE01FE01FE01ULL, 0x1FE01FE00EF10EF1ULL, 0xE01FE01FF10EF10EULL, 0x1FFE1FFE0EFE0EFEULL, 0xFE1FFE1FFE0EFE0EULL, 0xE0FEE0FEF1FEF1FEULL, 0xFEE0FEE0FEF1FEF1ULL, 0x01011F1F01010E0EULL, 0x1F1F01010E0E0101ULL, 0xE0E01F1FF1F10E0EULL, 0x0101E0E00101F1F1ULL, 0x1F1FE0E00E0EF1F1ULL, 0xE0E0FEFEF1F1FEFEULL, 0x0101FEFE0101FEFEULL, 0x1F1FFEFE0E0EFEFEULL, 0xE0FE011FF1FE010EULL, 0x011F1F01010E0E01ULL, 0x1FE001FE0EF101FEULL, 0xE0FE1F01F1FE0E01ULL, 0x011FE0FE010EF1FEULL, 0x1FE0E01F0EF1F10EULL, 0xE0FEFEE0F1FEFEF1ULL, 0x011FFEE0010EFEF1ULL, 0x1FE0FE010EF1FE01ULL, 0xFE0101FEFE0101FEULL, 0x01E01FFE01F10EFEULL, 0x1FFE01E00EFE01F1ULL, 0xFE011FE0FE010EF1ULL, 0xFE01E01FFE01F10EULL, 0x1FFEE0010EFEF101ULL, 0xFE1F01E0FE0E01F1ULL, 0x01E0E00101F1F101ULL, 0x1FFEFE1F0EFEFE0EULL, 0xFE1FE001FE0EF101ULL, 0x01E0FE1F01F1FE0EULL, 0xE00101E0F10101F1ULL, 0xFE1F1FFEFE0E0EFEULL, 0x01FE1FE001FE0EF1ULL, 0xE0011FFEF1010EFEULL, 0xFEE0011FFEF1010EULL, 0x01FEE01F01FEF10EULL, 0xE001FE1FF101FE0EULL, 0xFEE01F01FEF10E01ULL, 0x01FEFE0101FEFE01ULL, 0xE01F01FEF10E01FEULL, 0xFEE0E0FEFEF1F1FEULL, 0x1F01011F0E01010EULL, 0xE01F1FE0F10E0EF1ULL, 0xFEFE0101FEFE0101ULL, 0x1F01E0FE0E01F1FEULL, 0xE01FFE01F10EFE01ULL, 0xFEFE1F1FFEFE0E0EULL, 0x1F01FEE00E01FEF1ULL, 0xE0E00101F1F10101ULL, 0xFEFEE0E0FEFEF1F1ULL}; /* 10.2.9.2.1 CryptSetOddByteParity() */ /* This function sets the per byte parity of a 64-bit value. The least-significant bit is of each byte is replaced with the odd parity of the other 7 bits in the byte. With odd parity, no byte will ever be 0x00. */ UINT64 CryptSetOddByteParity( UINT64 k ) { #define PMASK 0x0101010101010101ULL UINT64 out; k |= PMASK; // set the parity bit out = k; k ^= k >> 4; k ^= k >> 2; k ^= k >> 1; k &= PMASK; // odd parity extracted out ^= k; // out is now even parity because parity bit was already set out ^= PMASK; // out is now even parity return out; } /* 10.2.9.2.2 CryptDesIsWeakKey() */ /* Check to see if a DES key is on the list of weak, semi-weak, or possibly weak keys. */ /* Return Value Meaning */ /* TRUE(1) DES key is weak */ /* FALSE(0) DES key is not weak */ static BOOL CryptDesIsWeakKey( UINT64 k ) { int i; // for(i = 0; i < DES_NUM_WEAK; i++) { if(k == DesWeakKeys[i]) return TRUE; } return FALSE; } /* 10.2.9.2.3 CryptDesValidateKey() */ /* Function to check to see if the input key is a valid DES key where the definition of valid is that none of the elements are on the list of weak, semi-weak, or possibly weak keys; and that for two keys, K1!=K2, and for three keys that K1!=K2 and K2!=K3. */ BOOL CryptDesValidateKey( TPM2B_SYM_KEY *desKey // IN: key to validate ) { UINT64 k[3]; int i; int keys = (desKey->t.size + 7) / 8; BYTE *pk = desKey->t.buffer; BOOL ok; // // Note: 'keys' is the number of keys, not the maximum index for 'k' ok = ((keys == 2) || (keys == 3)) && ((desKey->t.size % 8) == 0); for(i = 0; ok && i < keys; pk += 8, i++) { k[i] = CryptSetOddByteParity(BYTE_ARRAY_TO_UINT64(pk)); ok = !CryptDesIsWeakKey(k[i]); } ok = ok && k[0] != k[1]; if(keys == 3) ok = ok && k[1] != k[2]; return ok; } /* 10.2.9.2.4 CryptGenerateKeyDes() */ /* This function is used to create a DES key of the appropriate size. The key will have odd parity in the bytes. */ TPM_RC CryptGenerateKeyDes( TPMT_PUBLIC *publicArea, // IN/OUT: The public area template // for the new key. TPMT_SENSITIVE *sensitive, // OUT: sensitive area RAND_STATE *rand // IN: the "entropy" source for ) { // Assume that the publicArea key size has been validated and is a supported // number of bits. sensitive->sensitive.sym.t.size = BITS_TO_BYTES(publicArea->parameters.symDetail.sym.keyBits.sym); #if USE_OPENSSL_FUNCTIONS_SYMMETRIC // libtpms added begin if (rand == NULL) return OpenSSLCryptGenerateKeyDes(sensitive); #endif // libtpms added end do { BYTE *pK = sensitive->sensitive.sym.t.buffer; int i = (sensitive->sensitive.sym.t.size + 7) / 8; // Use the random number generator to generate the required number of bits if(DRBG_Generate(rand, pK, sensitive->sensitive.sym.t.size) == 0) return TPM_RC_NO_RESULT; for(; i > 0; pK += 8, i--) { UINT64 k = BYTE_ARRAY_TO_UINT64(pK); k = CryptSetOddByteParity(k); UINT64_TO_BYTE_ARRAY(k, pK); } } while(!CryptDesValidateKey(&sensitive->sensitive.sym)); return TPM_RC_SUCCESS; } #endif libtpms-0.9.3/src/tpm2/crypto/openssl/CryptEccKeyExchange.c000066400000000000000000000363431421143571500236610ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Functions that are used for the two-phase, ECC, key-exchange protocols */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CryptEccKeyExchange.c 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2021 */ /* */ /********************************************************************************/ /* 10.2.11 CryptEccKeyExchange.c */ #include "Tpm.h" LIB_EXPORT TPM_RC SM2KeyExchange( TPMS_ECC_POINT *outZ, // OUT: the computed point TPM_ECC_CURVE curveId, // IN: the curve for the computations TPM2B_ECC_PARAMETER *dsAIn, // IN: static private TPM key TPM2B_ECC_PARAMETER *deAIn, // IN: ephemeral private TPM key TPMS_ECC_POINT *QsBIn, // IN: static public party B key TPMS_ECC_POINT *QeBIn // IN: ephemeral public party B key ); #if CC_ZGen_2Phase == YES #if ALG_ECMQV /* 10.2.11.1.1 avf1() */ /* This function does the associated value computation required by MQV key exchange. Process: */ /* a) Convert xQ to an integer xqi using the convention specified in Appendix C.3. */ /* b) Calculate xqm = xqi mod 2^ceil(f/2) (where f = ceil(log2(n)). */ /* c) Calculate the associate value function avf(Q) = xqm + 2ceil(f / 2) */ /* Always returns TRUE(1). */ static BOOL avf1( bigNum bnX, // IN/OUT: the reduced value bigNum bnN // IN: the order of the curve ) { // compute f = 2^(ceil(ceil(log2(n)) / 2)) int f = (BnSizeInBits(bnN) + 1) / 2; // x' = 2^f + (x mod 2^f) BnMaskBits(bnX, f); // This is mod 2*2^f but it doesn't matter because // the next operation will SET the extra bit anyway BnSetBit(bnX, f); return TRUE; } /* 10.2.11.1.2 C_2_2_MQV() */ /* This function performs the key exchange defined in SP800-56A 6.1.1.4 Full MQV, C(2, 2, ECC MQV). */ /* CAUTION: Implementation of this function may require use of essential claims in patents not owned by TCG members. */ /* Points QsB() and QeB() are required to be on the curve of inQsA. The function will fail, possibly catastrophically, if this is not the case. */ /* Error Returns Meaning */ /* TPM_RC_NO_RESULT the value for dsA does not give a valid point on the curve */ static TPM_RC C_2_2_MQV( TPMS_ECC_POINT *outZ, // OUT: the computed point TPM_ECC_CURVE curveId, // IN: the curve for the computations TPM2B_ECC_PARAMETER *dsA, // IN: static private TPM key TPM2B_ECC_PARAMETER *deA, // IN: ephemeral private TPM key TPMS_ECC_POINT *QsB, // IN: static public party B key TPMS_ECC_POINT *QeB // IN: ephemeral public party B key ) { CURVE_INITIALIZED(E, curveId); const ECC_CURVE_DATA *C; POINT(pQeA); POINT_INITIALIZED(pQeB, QeB); POINT_INITIALIZED(pQsB, QsB); ECC_NUM(bnTa); ECC_INITIALIZED(bnDeA, deA); ECC_INITIALIZED(bnDsA, dsA); ECC_NUM(bnN); ECC_NUM(bnXeB); TPM_RC retVal; // // Parameter checks if(E == NULL) ERROR_RETURN(TPM_RC_VALUE); pAssert(outZ != NULL && pQeB != NULL && pQsB != NULL && deA != NULL && dsA != NULL); C = AccessCurveData(E); // Process: // 1. implicitsigA = (de,A + avf(Qe,A)ds,A ) mod n. // 2. P = h(implicitsigA)(Qe,B + avf(Qe,B)Qs,B). // 3. If P = O, output an error indicator. // 4. Z=xP, where xP is the x-coordinate of P. // Compute the public ephemeral key pQeA = [de,A]G if((retVal = BnPointMult(pQeA, CurveGetG(C), bnDeA, NULL, NULL, E)) != TPM_RC_SUCCESS) goto Exit; // 1. implicitsigA = (de,A + avf(Qe,A)ds,A ) mod n. // tA := (ds,A + de,A avf(Xe,A)) mod n (3) // Compute 'tA' = ('deA' + 'dsA' avf('XeA')) mod n // Ta = avf(XeA); BnCopy(bnTa, pQeA->x); avf1(bnTa, bnN); // do Ta = ds,A * Ta mod n = dsA * avf(XeA) mod n BnModMult(bnTa, bnDsA, bnTa, bnN); // now Ta = deA + Ta mod n = deA + dsA * avf(XeA) mod n BnAdd(bnTa, bnTa, bnDeA); BnMod(bnTa, bnN); // 2. P = h(implicitsigA)(Qe,B + avf(Qe,B)Qs,B). // Put this in because almost every case of h is == 1 so skip the call when // not necessary. if(!BnEqualWord(CurveGetCofactor(C), 1)) // Cofactor is not 1 so compute Ta := Ta * h mod n BnModMult(bnTa, bnTa, CurveGetCofactor(C), CurveGetOrder(C)); // Now that 'tA' is (h * 'tA' mod n) // 'outZ' = (tA)(Qe,B + avf(Qe,B)Qs,B). // first, compute XeB = avf(XeB) avf1(bnXeB, bnN); // QsB := [XeB]QsB BnPointMult(pQsB, pQsB, bnXeB, NULL, NULL, E); BnEccAdd(pQeB, pQeB, pQsB, E); // QeB := [tA]QeB = [tA](QsB + [Xe,B]QeB) and check for at infinity // If the result is not the point at infinity, return QeB BnPointMult(pQeB, pQeB, bnTa, NULL, NULL, E); if(BnEqualZero(pQeB->z)) ERROR_RETURN(TPM_RC_NO_RESULT); // Convert BIGNUM E to TPM2B E BnPointTo2B(outZ, pQeB, E); Exit: CURVE_FREE(E); return retVal; } #endif // ALG_ECMQV /* 10.2.11.1.3 C_2_2_ECDH() */ /* This function performs the two phase key exchange defined in SP800-56A, 6.1.1.2 Full Unified Model, C(2, 2, ECC CDH). */ static TPM_RC C_2_2_ECDH( TPMS_ECC_POINT *outZs, // OUT: Zs TPMS_ECC_POINT *outZe, // OUT: Ze TPM_ECC_CURVE curveId, // IN: the curve for the computations TPM2B_ECC_PARAMETER *dsA, // IN: static private TPM key TPM2B_ECC_PARAMETER *deA, // IN: ephemeral private TPM key TPMS_ECC_POINT *QsB, // IN: static public party B key TPMS_ECC_POINT *QeB // IN: ephemeral public party B key ) { CURVE_INITIALIZED(E, curveId); ECC_INITIALIZED(bnAs, dsA); ECC_INITIALIZED(bnAe, deA); POINT_INITIALIZED(ecBs, QsB); POINT_INITIALIZED(ecBe, QeB); POINT(ecZ); TPM_RC retVal; // // Parameter checks if(E == NULL) ERROR_RETURN(TPM_RC_CURVE); pAssert(outZs != NULL && dsA != NULL && deA != NULL && QsB != NULL && QeB != NULL); // Do the point multiply for the Zs value ([dsA]QsB) retVal = BnPointMult(ecZ, ecBs, bnAs, NULL, NULL, E); if(retVal == TPM_RC_SUCCESS) { // Convert the Zs value. BnPointTo2B(outZs, ecZ, E); // Do the point multiply for the Ze value ([deA]QeB) retVal = BnPointMult(ecZ, ecBe, bnAe, NULL, NULL, E); if(retVal == TPM_RC_SUCCESS) BnPointTo2B(outZe, ecZ, E); } Exit: CURVE_FREE(E); return retVal; } /* 10.2.11.1.4 CryptEcc2PhaseKeyExchange() */ /* This function is the dispatch routine for the EC key exchange functions that use two ephemeral and two static keys. */ /* Error Returns Meaning */ /* TPM_RC_SCHEME scheme is not defined */ LIB_EXPORT TPM_RC CryptEcc2PhaseKeyExchange( TPMS_ECC_POINT *outZ1, // OUT: a computed point TPMS_ECC_POINT *outZ2, // OUT: and optional second point TPM_ECC_CURVE curveId, // IN: the curve for the computations TPM_ALG_ID scheme, // IN: the key exchange scheme TPM2B_ECC_PARAMETER *dsA, // IN: static private TPM key TPM2B_ECC_PARAMETER *deA, // IN: ephemeral private TPM key TPMS_ECC_POINT *QsB, // IN: static public party B key TPMS_ECC_POINT *QeB // IN: ephemeral public party B key ) { pAssert(outZ1 != NULL && dsA != NULL && deA != NULL && QsB != NULL && QeB != NULL); // Initialize the output points so that they are empty until one of the // functions decides otherwise outZ1->x.b.size = 0; outZ1->y.b.size = 0; if(outZ2 != NULL) { outZ2->x.b.size = 0; outZ2->y.b.size = 0; } switch(scheme) { case TPM_ALG_ECDH: return C_2_2_ECDH(outZ1, outZ2, curveId, dsA, deA, QsB, QeB); break; #if ALG_ECMQV case TPM_ALG_ECMQV: return C_2_2_MQV(outZ1, curveId, dsA, deA, QsB, QeB); break; #endif #if ALG_SM2 case TPM_ALG_SM2: return SM2KeyExchange(outZ1, curveId, dsA, deA, QsB, QeB); break; #endif default: return TPM_RC_SCHEME; } } #if ALG_SM2 /* 10.2.11.1.5 ComputeWForSM2() */ /* Compute the value for w used by SM2 */ static UINT32 ComputeWForSM2( bigCurve E ) { // w := ceil(ceil(log2(n)) / 2) - 1 return (BnMsb(CurveGetOrder(AccessCurveData(E))) / 2 - 1); } /* 10.2.11.1.6 avfSm2() */ /* This function does the associated value computation required by SM2 key exchange. This is different form the avf() in the international standards because it returns a value that is half the size of the value returned by the standard avf. For example, if n is 15, Ws (w in the standard) is 2 but the W here is 1. This means that an input value of 14 (1110b) would return a value of 110b with the standard but 10b with the scheme in SM2. */ static bigNum avfSm2( bigNum bn, // IN/OUT: the reduced value UINT32 w // IN: the value of w ) { // a) set w := ceil(ceil(log2(n)) / 2) - 1 // b) set x' := 2^w + ( x & (2^w - 1)) // This is just like the avf for MQV where x' = 2^w + (x mod 2^w) BnMaskBits(bn, w); // as with avf1, this is too big by a factor of 2 but // it doesn't matter because we SET the extra bit // anyway BnSetBit(bn, w); return bn; } /* SM2KeyExchange() This function performs the key exchange defined in SM2. The first step is to compute tA = (dsA + deA avf(Xe,A)) mod n Then, compute the Z value from outZ = (h tA mod n) (QsA + [avf(QeB().x)](QeB())). The function will compute the ephemeral public key from the ephemeral private key. All points are required to be on the curve of inQsA. The function will fail catastrophically if this is not the case */ /* Error Returns Meaning */ /* TPM_RC_NO_RESULT the value for dsA does not give a valid point on the curve */ LIB_EXPORT TPM_RC SM2KeyExchange( TPMS_ECC_POINT *outZ, // OUT: the computed point TPM_ECC_CURVE curveId, // IN: the curve for the computations TPM2B_ECC_PARAMETER *dsAIn, // IN: static private TPM key TPM2B_ECC_PARAMETER *deAIn, // IN: ephemeral private TPM key TPMS_ECC_POINT *QsBIn, // IN: static public party B key TPMS_ECC_POINT *QeBIn // IN: ephemeral public party B key ) { CURVE_INITIALIZED(E, curveId); const ECC_CURVE_DATA *C; ECC_INITIALIZED(dsA, dsAIn); ECC_INITIALIZED(deA, deAIn); POINT_INITIALIZED(QsB, QsBIn); POINT_INITIALIZED(QeB, QeBIn); BN_WORD_INITIALIZED(One, 1); POINT(QeA); ECC_NUM(XeB); POINT(Z); ECC_NUM(Ta); UINT32 w; TPM_RC retVal = TPM_RC_NO_RESULT; // // Parameter checks if(E == NULL) ERROR_RETURN(TPM_RC_CURVE); C = AccessCurveData(E); pAssert(outZ != NULL && dsA != NULL && deA != NULL && QsB != NULL && QeB != NULL); // Compute the value for w w = ComputeWForSM2(E); // Compute the public ephemeral key pQeA = [de,A]G if(!BnEccModMult(QeA, CurveGetG(C), deA, E)) goto Exit; // tA := (ds,A + de,A avf(Xe,A)) mod n (3) // Compute 'tA' = ('dsA' + 'deA' avf('XeA')) mod n // Ta = avf(XeA); // do Ta = de,A * Ta = deA * avf(XeA) BnMult(Ta, deA, avfSm2(QeA->x, w)); // now Ta = dsA + Ta = dsA + deA * avf(XeA) BnAdd(Ta, dsA, Ta); BnMod(Ta, CurveGetOrder(C)); // outZ = [h tA mod n] (Qs,B + [avf(Xe,B)](Qe,B)) (4) // Put this in because almost every case of h is == 1 so skip the call when // not necessary. if(!BnEqualWord(CurveGetCofactor(C), 1)) // Cofactor is not 1 so compute Ta := Ta * h mod n BnModMult(Ta, Ta, CurveGetCofactor(C), CurveGetOrder(C)); // Now that 'tA' is (h * 'tA' mod n) // 'outZ' = ['tA'](QsB + [avf(QeB.x)](QeB)). BnCopy(XeB, QeB->x); if(!BnEccModMult2(Z, QsB, One, QeB, avfSm2(XeB, w), E)) goto Exit; // QeB := [tA]QeB = [tA](QsB + [Xe,B]QeB) and check for at infinity if(!BnEccModMult(Z, Z, Ta, E)) goto Exit; // Convert BIGNUM E to TPM2B E BnPointTo2B(outZ, Z, E); retVal = TPM_RC_SUCCESS; Exit: CURVE_FREE(E); return retVal; } #endif #endif // CC_ZGen_2Phase libtpms-0.9.3/src/tpm2/crypto/openssl/CryptEccMain.c000066400000000000000000000767721421143571500223640ustar00rootroot00000000000000/********************************************************************************/ /* */ /* ECC Main */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CryptEccMain.c 1519 2019-11-15 20:43:51Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ /* 10.2.11 CryptEccMain.c */ /* 10.2.11.1 Includes and Defines */ #include "Tpm.h" #include "Helpers_fp.h" // libtpms added #include "TpmToOsslMath_fp.h" // libtpms added #if ALG_ECC /* This version requires that the new format for ECC data be used */ #if !USE_BN_ECC_DATA #error "Need to SET USE_BN_ECC_DATA to YES in TpmBuildSwitches.h" #endif /* 10.2.11.2 Functions */ #if SIMULATION void EccSimulationEnd( void ) { #if SIMULATION // put things to be printed at the end of the simulation here #endif } #endif // SIMULATION /* 10.2.11.2.1 CryptEccInit() */ /* This function is called at _TPM_Init() */ BOOL CryptEccInit( void ) { return TRUE; } /* 10.2.11.2.2 CryptEccStartup() */ /* This function is called at TPM2_Startup(). */ BOOL CryptEccStartup( void ) { return TRUE; } /* 10.2.11.2.3 ClearPoint2B(generic */ /* Initialize the size values of a TPMS_ECC_POINT structure. */ void ClearPoint2B( TPMS_ECC_POINT *p // IN: the point ) { if(p != NULL) { p->x.t.size = 0; p->y.t.size = 0; } } /* 10.2.11.2.4 CryptEccGetParametersByCurveId() */ /* This function returns a pointer to the curve data that is associated with the indicated curveId. If there is no curve with the indicated ID, the function returns NULL. This function is in this module so that it can be called by GetCurve() data. */ /* Return Values Meaning */ /* NULL curve with the indicated TPM_ECC_CURVE is not implemented */ /* non-NULL pointer to the curve data */ LIB_EXPORT const ECC_CURVE * CryptEccGetParametersByCurveId( TPM_ECC_CURVE curveId // IN: the curveID ) { int i; for(i = 0; i < ECC_CURVE_COUNT; i++) { if(eccCurves[i].curveId == curveId) return &eccCurves[i]; } return NULL; } /* 10.2.11.2.5 CryptEccGetKeySizeForCurve() */ /* This function returns the key size in bits of the indicated curve */ LIB_EXPORT UINT16 CryptEccGetKeySizeForCurve( TPM_ECC_CURVE curveId // IN: the curve ) { const ECC_CURVE *curve = CryptEccGetParametersByCurveId(curveId); UINT16 keySizeInBits; // keySizeInBits = (curve != NULL) ? curve->keySizeBits : 0; return keySizeInBits; } /* 10.2.11.2.6 GetCurveData() */ /* This function returns the a pointer for the parameter data associated with a curve. */ const ECC_CURVE_DATA * GetCurveData( TPM_ECC_CURVE curveId // IN: the curveID ) { const ECC_CURVE *curve = CryptEccGetParametersByCurveId(curveId); return (curve != NULL) ? curve->curveData : NULL; } /* 10.2.11.2.7 CryptEccGetOID() */ const BYTE * CryptEccGetOID( TPM_ECC_CURVE curveId ) { const ECC_CURVE *curve = CryptEccGetParametersByCurveId(curveId); return (curve != NULL) ? curve->OID : NULL; } /* 10.2.11.2.7 CryptEccGetCurveByIndex() */ /* This function returns the number of the i-th implemented curve. The normal use would be to call this function with i starting at 0. When the i is greater than or equal to the number of implemented curves, TPM_ECC_NONE is returned. */ LIB_EXPORT TPM_ECC_CURVE CryptEccGetCurveByIndex( UINT16 i ) { if(i >= ECC_CURVE_COUNT) return TPM_ECC_NONE; return eccCurves[i].curveId; } /* 10.2.11.2.8 CryptEccGetParameter() */ /* This function returns an ECC curve parameter. The parameter is selected by a single character designator from the set of {PNABXYH}. */ /* Return Values Meaning */ /* TRUE curve exists and parameter returned */ /* FALSE curve does not exist or parameter selector */ LIB_EXPORT BOOL CryptEccGetParameter( TPM2B_ECC_PARAMETER *out, // OUT: place to put parameter char p, // IN: the parameter selector TPM_ECC_CURVE curveId // IN: the curve id ) { const ECC_CURVE_DATA *curve = GetCurveData(curveId); bigConst parameter = NULL; if(curve != NULL) { switch(p) { case 'p': parameter = CurveGetPrime(curve); break; case 'n': parameter = CurveGetOrder(curve); break; case 'a': parameter = CurveGet_a(curve); break; case 'b': parameter = CurveGet_b(curve); break; case 'x': parameter = CurveGetGx(curve); break; case 'y': parameter = CurveGetGy(curve); break; case 'h': parameter = CurveGetCofactor(curve); break; default: FAIL(FATAL_ERROR_INTERNAL); break; } } // If not debugging and we get here with parameter still NULL, had better // not try to convert so just return FALSE instead. return (parameter != NULL) ? BnTo2B(parameter, &out->b, 0) : 0; } /* 10.2.11.2.9 CryptCapGetECCCurve() */ /* This function returns the list of implemented ECC curves. */ /* Return Values Meaning */ /* YES if no more ECC curve is available */ /* NO if there are more ECC curves not reported */ TPMI_YES_NO CryptCapGetECCCurve( TPM_ECC_CURVE curveID, // IN: the starting ECC curve UINT32 maxCount, // IN: count of returned curves TPML_ECC_CURVE *curveList // OUT: ECC curve list ) { TPMI_YES_NO more = NO; UINT16 i; UINT32 count = ECC_CURVE_COUNT; TPM_ECC_CURVE curve; // Initialize output property list curveList->count = 0; // The maximum count of curves we may return is MAX_ECC_CURVES if(maxCount > MAX_ECC_CURVES) maxCount = MAX_ECC_CURVES; // Scan the eccCurveValues array for(i = 0; i < count; i++) { curve = CryptEccGetCurveByIndex(i); // If curveID is less than the starting curveID, skip it if(curve < curveID) continue; if (!CryptEccIsCurveRuntimeUsable(curve)) // libtpms added: runtime filter supported curves continue; if(curveList->count < maxCount) { // If we have not filled up the return list, add more curves to // it curveList->eccCurves[curveList->count] = curve; curveList->count++; } else { // If the return list is full but we still have curves // available, report this and stop iterating more = YES; break; } } return more; } /* 10.2.11.2.10 CryptGetCurveSignScheme() */ /* This function will return a pointer to the scheme of the curve. */ const TPMT_ECC_SCHEME * CryptGetCurveSignScheme( TPM_ECC_CURVE curveId // IN: The curve selector ) { const ECC_CURVE *curve = CryptEccGetParametersByCurveId(curveId); if(curve != NULL) return &(curve->sign); else return NULL; } /* 10.2.11.2.11 CryptGenerateR() */ /* This function computes the commit random value for a split signing scheme. */ /* If c is NULL, it indicates that r is being generated for TPM2_Commit(). If c is not NULL, the TPM will validate that the gr.commitArray bit associated with the input value of c is SET. If not, the TPM returns FALSE and no r value is generated. */ /* Return Values Meaning */ /* TRUE r value computed */ /* FALSE no r value computed */ BOOL CryptGenerateR( TPM2B_ECC_PARAMETER *r, // OUT: the generated random value UINT16 *c, // IN/OUT: count value. TPMI_ECC_CURVE curveID, // IN: the curve for the value TPM2B_NAME *name // IN: optional name of a key to // associate with 'r' ) { // This holds the marshaled g_commitCounter. TPM2B_TYPE(8B, 8); TPM2B_8B cntr = {{8,{0}}}; UINT32 iterations; TPM2B_ECC_PARAMETER n; UINT64 currentCount = gr.commitCounter; UINT16 t1; // if(!CryptEccGetParameter(&n, 'n', curveID)) return FALSE; // If this is the commit phase, use the current value of the commit counter if(c != NULL) { // if the array bit is not set, can't use the value. if(!TEST_BIT((*c & COMMIT_INDEX_MASK), gr.commitArray)) return FALSE; // If it is the sign phase, figure out what the counter value was // when the commitment was made. // // When gr.commitArray has less than 64K bits, the extra // bits of 'c' are used as a check to make sure that the // signing operation is not using an out of range count value t1 = (UINT16)currentCount; // If the lower bits of c are greater or equal to the lower bits of t1 // then the upper bits of t1 must be one more than the upper bits // of c if((*c & COMMIT_INDEX_MASK) >= (t1 & COMMIT_INDEX_MASK)) // Since the counter is behind, reduce the current count currentCount = currentCount - (COMMIT_INDEX_MASK + 1); t1 = (UINT16)currentCount; if((t1 & ~COMMIT_INDEX_MASK) != (*c & ~COMMIT_INDEX_MASK)) return FALSE; // set the counter to the value that was // present when the commitment was made currentCount = (currentCount & 0xffffffffffff0000ULL) | *c; /* libtpms changed */ } // Marshal the count value to a TPM2B buffer for the KDF cntr.t.size = sizeof(currentCount); UINT64_TO_BYTE_ARRAY(currentCount, cntr.t.buffer); // Now can do the KDF to create the random value for the signing operation // During the creation process, we may generate an r that does not meet the // requirements of the random value. // want to generate a new r. r->t.size = n.t.size; for(iterations = 1; iterations < 1000000;) { int i; CryptKDFa(CONTEXT_INTEGRITY_HASH_ALG, &gr.commitNonce.b, COMMIT_STRING, (TPM2B *)name, &cntr.b, n.t.size * 8, // libtpms ubsan r->t.buffer, &iterations, FALSE); // libtpms changed // "random" value must be less than the prime if(UnsignedCompareB(r->b.size, r->b.buffer, n.t.size, n.t.buffer) >= 0) continue; // in this implementation it is required that at least bit // in the upper half of the number be set for(i = n.t.size / 2; i >= 0; i--) if(r->b.buffer[i] != 0) return TRUE; } return FALSE; } /* 10.2.11.2.12 CryptCommit() */ /* This function is called when the count value is committed. The gr.commitArray value associated with the current count value is SET and g_commitCounter is incremented. The low-order 16 bits of old value of the counter is returned. */ UINT16 CryptCommit( void ) { UINT16 oldCount = (UINT16)gr.commitCounter; gr.commitCounter++; SET_BIT(oldCount & COMMIT_INDEX_MASK, gr.commitArray); return oldCount; } /* 10.2.11.2.13 CryptEndCommit() */ /* This function is called when the signing operation using the committed value is completed. It clears the gr.commitArray bit associated with the count value so that it can't be used again. */ void CryptEndCommit( UINT16 c // IN: the counter value of the commitment ) { ClearBit((c & COMMIT_INDEX_MASK), gr.commitArray, sizeof(gr.commitArray)); } /* 10.2.11.2.14 CryptEccGetParameters() */ /* This function returns the ECC parameter details of the given curve */ /* Return Values Meaning */ /* TRUE success */ /* FALSE unsupported ECC curve ID */ BOOL CryptEccGetParameters( TPM_ECC_CURVE curveId, // IN: ECC curve ID TPMS_ALGORITHM_DETAIL_ECC *parameters // OUT: ECC parameters ) { const ECC_CURVE *curve = CryptEccGetParametersByCurveId(curveId); const ECC_CURVE_DATA *data; BOOL found = curve != NULL; if(found) { data = curve->curveData; parameters->curveID = curve->curveId; parameters->keySize = curve->keySizeBits; parameters->kdf = curve->kdf; parameters->sign = curve->sign; /* BnTo2B(data->prime, ¶meters->p.b, 0); */ BnTo2B(data->prime, ¶meters->p.b, parameters->p.t.size); BnTo2B(data->a, ¶meters->a.b, parameters->p.t.size /* libtpms changed for HLK */); BnTo2B(data->b, ¶meters->b.b, parameters->p.t.size /* libtpms changed for HLK */); BnTo2B(data->base.x, ¶meters->gX.b, parameters->p.t.size); BnTo2B(data->base.y, ¶meters->gY.b, parameters->p.t.size); BnTo2B(data->order, ¶meters->n.b, 0); BnTo2B(data->h, ¶meters->h.b, 0); } return found; } /* 10.2.11.2.15 BnGetCurvePrime() */ /* This function is used to get just the prime modulus associated with a curve */ const bignum_t * BnGetCurvePrime( TPM_ECC_CURVE curveId ) { const ECC_CURVE_DATA *C = GetCurveData(curveId); return (C != NULL) ? CurveGetPrime(C) : NULL; } /* 10.2.11.2.16 BnGetCurveOrder() */ /* This function is used to get just the curve order */ const bignum_t * BnGetCurveOrder( TPM_ECC_CURVE curveId ) { const ECC_CURVE_DATA *C = GetCurveData(curveId); return (C != NULL) ? CurveGetOrder(C) : NULL; } /* 10.2.11.2.17 BnIsOnCurve() */ /* This function checks if a point is on the curve. */ BOOL BnIsOnCurve( pointConst Q, const ECC_CURVE_DATA *C ) { BN_VAR(right, (MAX_ECC_KEY_BITS * 3)); BN_VAR(left, (MAX_ECC_KEY_BITS * 2)); bigConst prime = CurveGetPrime(C); // // Show that point is on the curve y^2 = x^3 + ax + b; // Or y^2 = x(x^2 + a) + b // y^2 BnMult(left, Q->y, Q->y); BnMod(left, prime); // x^2 BnMult(right, Q->x, Q->x); // x^2 + a BnAdd(right, right, CurveGet_a(C)); // BnMod(right, CurveGetPrime(C)); // x(x^2 + a) BnMult(right, right, Q->x); // x(x^2 + a) + b BnAdd(right, right, CurveGet_b(C)); BnMod(right, prime); if(BnUnsignedCmp(left, right) == 0) return TRUE; else return FALSE; } /* 10.2.11.2.18 BnIsValidPrivateEcc() */ /* Checks that 0 < x < q */ BOOL BnIsValidPrivateEcc( bigConst x, // IN: private key to check bigCurve E // IN: the curve to check ) { BOOL retVal; retVal = (!BnEqualZero(x) && (BnUnsignedCmp(x, CurveGetOrder(AccessCurveData(E))) < 0)); return retVal; } LIB_EXPORT BOOL CryptEccIsValidPrivateKey( TPM2B_ECC_PARAMETER *d, TPM_ECC_CURVE curveId ) { BN_INITIALIZED(bnD, MAX_ECC_PARAMETER_BYTES * 8, d); return !BnEqualZero(bnD) && (BnUnsignedCmp(bnD, BnGetCurveOrder(curveId)) < 0); } /* 10.2.11.2.19 BnPointMul() */ /* This function does a point multiply of the form R = [d]S + [u]Q where the parameters are bigNum values. If S is NULL and d is not NULL, then it computes R = [d]G + [u]Q or just R = [d]G if u and Q are NULL. If skipChecks is TRUE, then the function will not verify that the inputs are correct for the domain. This would be the case when the values were created by the CryptoEngine() code. It will return TPM_RC_NO_RESULT if the resulting point is the point at infinity. */ /* Error Returns Meaning */ /* TPM_RC_NO_RESULT result of multiplication is a point at infinity */ /* TPM_RC_ECC_POINT S or Q is not on the curve */ /* TPM_RC_VALUE d or u is not < n */ TPM_RC BnPointMult( bigPoint R, // OUT: computed point pointConst S, // IN: optional point to multiply by 'd' bigConst d, // IN: scalar for [d]S or [d]G pointConst Q, // IN: optional second point bigConst u, // IN: optional second scalar bigCurve E // IN: curve parameters ) { BOOL OK; // TEST(TPM_ALG_ECDH); // Need one scalar OK = (d != NULL || u != NULL); // If S is present, then d has to be present. If S is not // present, then d may or may not be present OK = OK && (((S == NULL) == (d == NULL)) || (d != NULL)); // either both u and Q have to be provided or neither can be provided (don't // know what to do if only one is provided. OK = OK && ((u == NULL) == (Q == NULL)); OK = OK && (E != NULL); if(!OK) return TPM_RC_VALUE; OK = (S == NULL) || BnIsOnCurve(S, AccessCurveData(E)); OK = OK && ((Q == NULL) || BnIsOnCurve(Q, AccessCurveData(E))); if(!OK) return TPM_RC_ECC_POINT; if((d != NULL) && (S == NULL)) S = CurveGetG(AccessCurveData(E)); // If only one scalar, don't need Shamir's trick if((d == NULL) || (u == NULL)) { if(d == NULL) OK = BnEccModMult(R, Q, u, E); else OK = BnEccModMult(R, S, d, E); } else { OK = BnEccModMult2(R, S, d, Q, u, E); } return (OK ? TPM_RC_SUCCESS : TPM_RC_NO_RESULT); } /* 10.2.11.2.20 BnEccGetPrivate() */ /* This function gets random values that are the size of the key plus 64 bits. The value is reduced (mod (q - 1)) and incremented by 1 (q is the order of the curve. This produces a value (d) such that 1 <= d < q. This is the method of FIPS 186-4 Section B.4.1 'Key Pair Generation Using Extra Random Value Meaning */ /* TRUE success */ /* FALSE failure generating private key */ #if !USE_OPENSSL_FUNCTIONS_EC // libtpms added BOOL BnEccGetPrivate( bigNum dOut, // OUT: the qualified random value const ECC_CURVE_DATA *C, // IN: curve for which the private key // needs to be appropriate RAND_STATE *rand // IN: state for DRBG ) { bigConst order = CurveGetOrder(C); BOOL OK; UINT32 orderBits = BnSizeInBits(order); UINT32 orderBytes = BITS_TO_BYTES(orderBits); BN_VAR(bnExtraBits, MAX_ECC_KEY_BITS + 64); BN_VAR(nMinus1, MAX_ECC_KEY_BITS); // OK = BnGetRandomBits(bnExtraBits, (orderBytes * 8) + 64, rand); OK = OK && BnSubWord(nMinus1, order, 1); OK = OK && BnMod(bnExtraBits, nMinus1); OK = OK && BnAddWord(dOut, bnExtraBits, 1); return OK && !g_inFailureMode; } #else // libtpms added begin BOOL BnEccGetPrivate( bigNum dOut, // OUT: the qualified random value const ECC_CURVE_DATA *C, // IN: curve for which the private key const EC_GROUP *G, // IN: the EC_GROUP to use; must be != NULL for rand == NULL BOOL noLeadingZeros, // IN: require that all bytes in the private key be set // result may not have leading zero bytes // needs to be appropriate RAND_STATE *rand // IN: state for DRBG ) { bigConst order = CurveGetOrder(C); BOOL OK; UINT32 orderBits = BnSizeInBits(order); UINT32 orderBytes = BITS_TO_BYTES(orderBits); UINT32 requestedBits = 0; BN_VAR(bnExtraBits, MAX_ECC_KEY_BITS + 64); BN_VAR(nMinus1, MAX_ECC_KEY_BITS); if (rand == NULL) { if (noLeadingZeros) requestedBits = orderBits; return OpenSSLEccGetPrivate(dOut, G, requestedBits); } // OK = BnGetRandomBits(bnExtraBits, (orderBytes * 8) + 64, rand); OK = OK && BnSubWord(nMinus1, order, 1); OK = OK && BnMod(bnExtraBits, nMinus1); OK = OK && BnAddWord(dOut, bnExtraBits, 1); return OK && !g_inFailureMode; } #endif // USE_OPENSSL_FUNCTIONS_EC libtpms added end /* 10.2.11.2.21 BnEccGenerateKeyPair() */ /* This function gets a private scalar from the source of random bits and does the point multiply to get the public key. */ #if !USE_OPENSSL_FUNCTIONS_EC // libtpms added BOOL BnEccGenerateKeyPair( bigNum bnD, // OUT: private scalar bn_point_t *ecQ, // OUT: public point bigCurve E, // IN: curve for the point RAND_STATE *rand // IN: DRBG state to use ) { BOOL OK = FALSE; // Get a private scalar OK = BnEccGetPrivate(bnD, AccessCurveData(E), rand); // Do a point multiply OK = OK && BnEccModMult(ecQ, NULL, bnD, E); if(!OK) BnSetWord(ecQ->z, 0); else BnSetWord(ecQ->z, 1); return OK; } #else // libtpms added begin /* In this version of BnEccGenerateKeyPair we take a dual approach to constant time requirements: For curves whose order is at the byte boundary, e.g. NIST P224/P256/P384, we make sure that bnD has all bytes set (no leading zeros) so that OpenSSL BIGNUM code will not reduce the number of bytes and the subsequent BnEccModMult() would run faster for a shoter value. For all other curves whose order is not at the byte boundary, e.g. NIST P521, we simply always add the order of the curve to bnD and call BnEccModMult() with the result bnD1, which leads to the same result. */ BOOL BnEccGenerateKeyPair( bigNum bnD, // OUT: private scalar bn_point_t *ecQ, // OUT: public point bigCurve E, // IN: curve for the point RAND_STATE *rand // IN: DRBG state to use ) { BOOL OK = FALSE; bigConst order = CurveGetOrder(AccessCurveData(E)); UINT32 orderBits = BnSizeInBits(order); BOOL atByteBoundary = (orderBits & 7) == 0; BOOL noLeadingZeros = atByteBoundary; ECC_NUM(bnD1); // We request that bnD not have leading zeros if it is at byte-boundary, // like for example it is the case for NIST P256. OK = BnEccGetPrivate(bnD, AccessCurveData(E), E->G, noLeadingZeros, rand); if (!atByteBoundary) { // for NIST P521 we can add the order to bnD to ensure we have // a constant amount of bytes; the result is the same as if we // were doing the BnEccModMult() calculation with bnD. OK = OK && BnAdd(bnD1, bnD, order); OK = OK && BnEccModMult(ecQ, NULL, bnD1, E); } else { OK = OK && BnEccModMult(ecQ, NULL, bnD, E); } if(!OK) BnSetWord(ecQ->z, 0); else BnSetWord(ecQ->z, 1); return OK; } #endif // libtpms added end /* 10.2.11.2.21 CryptEccNewKeyPair */ /* This function creates an ephemeral ECC. It is ephemeral in that is expected that the private part of the key will be discarded */ LIB_EXPORT TPM_RC CryptEccNewKeyPair( TPMS_ECC_POINT *Qout, // OUT: the public point TPM2B_ECC_PARAMETER *dOut, // OUT: the private scalar TPM_ECC_CURVE curveId // IN: the curve for the key ) { CURVE_INITIALIZED(E, curveId); POINT(ecQ); ECC_NUM(bnD); BOOL OK; if(E == NULL) return TPM_RC_CURVE; TEST(TPM_ALG_ECDH); OK = BnEccGenerateKeyPair(bnD, ecQ, E, NULL); if(OK) { BnPointTo2B(Qout, ecQ, E); BnTo2B(bnD, &dOut->b, Qout->x.t.size); } else { Qout->x.t.size = Qout->y.t.size = dOut->t.size = 0; } CURVE_FREE(E); return OK ? TPM_RC_SUCCESS : TPM_RC_NO_RESULT; } /* 10.2.11.2.22 CryptEccPointMultiply() */ /* This function computes 'R := [dIn]G + [uIn]QIn. Where dIn and uIn are scalars, G and QIn are points on the specified curve and G is the default generator of the curve. */ /* The xOut and yOut parameters are optional and may be set to NULL if not used. */ /* It is not necessary to provide uIn if QIn is specified but one of uIn and dIn must be provided. If dIn and QIn are specified but uIn is not provided, then R = [dIn]QIn. */ /* If the multiply produces the point at infinity, the TPM_RC_NO_RESULT is returned. */ /* The sizes of xOut and yOut' will be set to be the size of the degree of the curve */ /* It is a fatal error if dIn and uIn are both unspecified (NULL) or if Qin or Rout is unspecified. */ /* Error Returns Meaning */ /* TPM_RC_ECC_POINT the point Pin or Qin is not on the curve */ /* TPM_RC_NO_RESULT the product point is at infinity */ /* TPM_RC_CURVE bad curve */ /* TPM_RC_VALUE dIn or uIn out of range */ LIB_EXPORT TPM_RC CryptEccPointMultiply( TPMS_ECC_POINT *Rout, // OUT: the product point R TPM_ECC_CURVE curveId, // IN: the curve to use TPMS_ECC_POINT *Pin, // IN: first point (can be null) TPM2B_ECC_PARAMETER *dIn, // IN: scalar value for [dIn]Qin // the Pin TPMS_ECC_POINT *Qin, // IN: point Q TPM2B_ECC_PARAMETER *uIn // IN: scalar value for the multiplier // of Q ) { CURVE_INITIALIZED(E, curveId); POINT_INITIALIZED(ecP, Pin); ECC_INITIALIZED(bnD, dIn); // If dIn is null, then bnD is null ECC_INITIALIZED(bnU, uIn); POINT_INITIALIZED(ecQ, Qin); POINT(ecR); TPM_RC retVal; // retVal = BnPointMult(ecR, ecP, bnD, ecQ, bnU, E); if(retVal == TPM_RC_SUCCESS) BnPointTo2B(Rout, ecR, E); else ClearPoint2B(Rout); CURVE_FREE(E); return retVal; } /* 10.2.11.2.23 CryptEccIsPointOnCurve() */ /* This function is used to test if a point is on a defined curve. It does this by checking that y^2 mod p = x^3 + a*x + b mod p */ /* It is a fatal error if Q is not specified (is NULL). */ /* Return Values Meaning */ /* TRUE point is on curve */ /* FALSE point is not on curve or curve is not supported */ LIB_EXPORT BOOL CryptEccIsPointOnCurve( TPM_ECC_CURVE curveId, // IN: the curve selector TPMS_ECC_POINT *Qin // IN: the point. ) { const ECC_CURVE_DATA *C = GetCurveData(curveId); POINT_INITIALIZED(ecQ, Qin); BOOL OK; // pAssert(Qin != NULL); OK = (C != NULL && (BnIsOnCurve(ecQ, C))); return OK; } /* 10.2.11.2.24 CryptEccGenerateKey() */ /* This function generates an ECC key pair based on the input parameters. This routine uses KDFa() to produce candidate numbers. The method is according to FIPS 186-3, section B.1.2 "Key Pair Generation by Testing Candidates." According to the method in FIPS 186-3, the resulting private value d should be 1 <= d < n where n is the order of the base point. */ /* It is a fatal error if Qout, dOut, is not provided (is NULL). */ /* If the curve is not supported If seed is not provided, then a random number will be used for the key */ /* Error Returns Meaning */ /* TPM_RC_CURVE curve is not supported */ /* TPM_RC_NO_RESULT could not verify key with signature (FIPS only) */ LIB_EXPORT TPM_RC CryptEccGenerateKey( TPMT_PUBLIC *publicArea, // IN/OUT: The public area template for // the new key. The public key // area will be replaced computed // ECC public key TPMT_SENSITIVE *sensitive, // OUT: the sensitive area will be // updated to contain the private // ECC key and the symmetric // encryption key RAND_STATE *rand // IN: if not NULL, the deterministic // RNG state ) { CURVE_INITIALIZED(E, publicArea->parameters.eccDetail.curveID); ECC_NUM(bnD); POINT(ecQ); BOOL OK; TPM_RC retVal; TEST(TPM_ALG_ECDSA); // ECDSA is used to verify each key // Validate parameters if(E == NULL) ERROR_RETURN(TPM_RC_CURVE); publicArea->unique.ecc.x.t.size = 0; publicArea->unique.ecc.y.t.size = 0; sensitive->sensitive.ecc.t.size = 0; OK = BnEccGenerateKeyPair(bnD, ecQ, E, rand); if(OK) { BnPointTo2B(&publicArea->unique.ecc, ecQ, E); BnTo2B(bnD, &sensitive->sensitive.ecc.b, publicArea->unique.ecc.x.t.size); } #if FIPS_COMPLIANT // See if PWCT is required if(OK && (IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign))) { ECC_NUM(bnT); ECC_NUM(bnS); TPM2B_DIGEST digest; TEST(TPM_ALG_ECDSA); digest.t.size = MIN(sensitive->sensitive.ecc.t.size, sizeof(digest.t.buffer)); // Get a random value to sign using the built in DRBG state DRBG_Generate(NULL, digest.t.buffer, digest.t.size); if(g_inFailureMode) return TPM_RC_FAILURE; BnSignEcdsa(bnT, bnS, E, bnD, &digest, NULL); // and make sure that we can validate the signature OK = BnValidateSignatureEcdsa(bnT, bnS, E, ecQ, &digest) == TPM_RC_SUCCESS; } #endif retVal = (OK) ? TPM_RC_SUCCESS : TPM_RC_NO_RESULT; Exit: CURVE_FREE(E); return retVal; } // libtpms added begin // Support for some curves may be compiled in but they may not be // supported by openssl's crypto library. LIB_EXPORT BOOL CryptEccIsCurveRuntimeUsable( TPMI_ECC_CURVE curveId ) { CURVE_INITIALIZED(E, curveId); if (E == NULL) return FALSE; CURVE_FREE(E); return TRUE; } // libtpms added end #endif // TPM_ALG_ECC libtpms-0.9.3/src/tpm2/crypto/openssl/CryptEccSignature.c000066400000000000000000001155721421143571500234310ustar00rootroot00000000000000/********************************************************************************/ /* */ /* ECC Signatures */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CryptEccSignature.c 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2021 */ /* */ /********************************************************************************/ /* 10.2.12 CryptEccSignature.c */ /* 10.2.12.1 Includes and Defines */ #include "Tpm.h" #include "CryptEccSignature_fp.h" #include "TpmToOsslMath_fp.h" // libtpms added #if ALG_ECC /* 10.2.12.2 Utility Functions */ /* 10.2.12.2.1 EcdsaDigest() */ /* Function to adjust the digest so that it is no larger than the order of the curve. This is used for ECDSA sign and verification. */ #if !USE_OPENSSL_FUNCTIONS_ECDSA // libtpms added static bigNum EcdsaDigest( bigNum bnD, // OUT: the adjusted digest const TPM2B_DIGEST *digest, // IN: digest to adjust bigConst max // IN: value that indicates the maximum // number of bits in the results ) { int bitsInMax = BnSizeInBits(max); int shift; // if(digest == NULL) BnSetWord(bnD, 0); else { BnFromBytes(bnD, digest->t.buffer, (NUMBYTES)MIN(digest->t.size, BITS_TO_BYTES(bitsInMax))); shift = BnSizeInBits(bnD) - bitsInMax; if(shift > 0) BnShiftRight(bnD, bnD, shift); } return bnD; } #endif // libtpms added /* 10.2.12.2.2 BnSchnorrSign() */ /* This contains the Schnorr signature computation. It is used by both ECDSA and Schnorr signing. The result is computed as: [s = k + r * d (mod n)] where */ /* a) s is the signature */ /* b) k is a random value */ /* c) r is the value to sign */ /* d) d is the private EC key */ /* e) n is the order of the curve */ /* Error Returns Meaning */ /* TPM_RC_NO_RESULT the result of the operation was zero or r (mod n) is zero */ static TPM_RC BnSchnorrSign( bigNum bnS, // OUT: s component of the signature bigConst bnK, // IN: a random value bigNum bnR, // IN: the signature 'r' value bigConst bnD, // IN: the private key bigConst bnN // IN: the order of the curve ) { // Need a local temp value to store the intermediate computation because product // size can be larger than will fit in bnS. BN_VAR(bnT1, MAX_ECC_PARAMETER_BYTES * 2 * 8); // // Reduce bnR without changing the input value BnDiv(NULL, bnT1, bnR, bnN); if(BnEqualZero(bnT1)) return TPM_RC_NO_RESULT; // compute s = (k + r * d)(mod n) // r * d BnMult(bnT1, bnT1, bnD); // k * r * d BnAdd(bnT1, bnT1, bnK); // k + r * d (mod n) BnDiv(NULL, bnS, bnT1, bnN); return (BnEqualZero(bnS)) ? TPM_RC_NO_RESULT : TPM_RC_SUCCESS; } /* 10.2.12.3 Signing Functions */ /* 10.2.12.3.1 BnSignEcdsa() */ /* This function implements the ECDSA signing algorithm. The method is described in the comments below. This version works with internal numbers. */ #if !USE_OPENSSL_FUNCTIONS_ECDSA // libtpms added TPM_RC BnSignEcdsa( bigNum bnR, // OUT: r component of the signature bigNum bnS, // OUT: s component of the signature bigCurve E, // IN: the curve used in the signature // process bigNum bnD, // IN: private signing key const TPM2B_DIGEST *digest, // IN: the digest to sign RAND_STATE *rand // IN: used in debug of signing ) { ECC_NUM(bnK); ECC_NUM(bnIk); BN_VAR(bnE, MAX(MAX_ECC_KEY_BYTES, MAX_DIGEST_SIZE) * 8); POINT(ecR); bigConst order = CurveGetOrder(AccessCurveData(E)); TPM_RC retVal = TPM_RC_SUCCESS; INT32 tries = 10; BOOL OK = FALSE; // pAssert(digest != NULL); // The algorithm as described in "Suite B Implementer's Guide to FIPS // 186-3(ECDSA)" // 1. Use one of the routines in Appendix A.2 to generate (k, k^-1), a // per-message secret number and its inverse modulo n. Since n is prime, // the output will be invalid only if there is a failure in the RBG. // 2. Compute the elliptic curve point R = [k]G = (xR, yR) using EC scalar // multiplication (see [Routines]), where G is the base point included in // the set of domain parameters. // 3. Compute r = xR mod n. If r = 0, then return to Step 1. 1. // 4. Use the selected hash function to compute H = Hash(M). // 5. Convert the bit string H to an integer e as described in Appendix B.2. // 6. Compute s = (k^-1 * (e + d * r)) mod q. If s = 0, return to Step 1.2. // 7. Return (r, s). // In the code below, q is n (that it, the order of the curve is p) do // This implements the loop at step 6. If s is zero, start over. { for(; tries > 0; tries--) { // Step 1 and 2 -- generate an ephemeral key and the modular inverse // of the private key. if(!BnEccGenerateKeyPair(bnK, ecR, E, rand)) continue; // x coordinate is mod p. Make it mod q BnMod(ecR->x, order); // Make sure that it is not zero; if(BnEqualZero(ecR->x)) continue; // write the modular reduced version of r as part of the signature BnCopy(bnR, ecR->x); // Make sure that a modular inverse exists and try again if not OK = (BnModInverse(bnIk, bnK, order)); if(OK) break; } if(!OK) goto Exit; EcdsaDigest(bnE, digest, order); // now have inverse of K (bnIk), e (bnE), r (bnR), d (bnD) and // CurveGetOrder(E) // Compute s = k^-1 (e + r*d)(mod q) // first do s = r*d mod q BnModMult(bnS, bnR, bnD, order); // s = e + s = e + r * d BnAdd(bnS, bnE, bnS); // s = k^(-1)s (mod n) = k^(-1)(e + r * d)(mod n) BnModMult(bnS, bnIk, bnS, order); // If S is zero, try again } while(BnEqualZero(bnS)); Exit: return retVal; } #else // !USE_OPENSSL_FUNCTIONS_ECDSA libtpms added begin TPM_RC BnSignEcdsa( bigNum bnR, // OUT: r component of the signature bigNum bnS, // OUT: s component of the signature bigCurve E, // IN: the curve used in the signature // process bigNum bnD, // IN: private signing key const TPM2B_DIGEST *digest, // IN: the digest to sign RAND_STATE *rand // IN: used in debug of signing ) { ECDSA_SIG *sig = NULL; EC_KEY *eckey; int retVal; const BIGNUM *r; const BIGNUM *s; BIGNUM *d = BN_new(); d = BigInitialized(d, bnD); eckey = EC_KEY_new(); if (d == NULL || eckey == NULL) ERROR_RETURN(TPM_RC_FAILURE); if (EC_KEY_set_group(eckey, E->G) != 1) ERROR_RETURN(TPM_RC_FAILURE); if (EC_KEY_set_private_key(eckey, d) != 1) ERROR_RETURN(TPM_RC_FAILURE); sig = ECDSA_do_sign(digest->b.buffer, digest->b.size, eckey); if (sig == NULL) ERROR_RETURN(TPM_RC_FAILURE); ECDSA_SIG_get0(sig, &r, &s); OsslToTpmBn(bnR, r); OsslToTpmBn(bnS, s); retVal = TPM_RC_SUCCESS; Exit: BN_clear_free(d); EC_KEY_free(eckey); ECDSA_SIG_free(sig); return retVal; } #endif // USE_OPENSSL_FUNCTIONS_ECDSA libtpms added end #if ALG_ECDAA /* 10.2.12.3.2 BnSignEcdaa() */ /* This function performs s = r + T * d mod q where */ /* a) 'r is a random, or pseudo-random value created in the commit phase */ /* b) nonceK is a TPM-generated, random value 0 < nonceK < n */ /* c) T is mod q of Hash(nonceK || digest), and */ /* d) d is a private key. */ /* The signature is the tuple (nonceK, s) */ /* Regrettably, the parameters in this function kind of collide with the parameter names used in ECSCHNORR making for a lot of confusion. In particular, the k value in this function is value in this function u */ /* Error Returns Meaning */ /* TPM_RC_SCHEME unsupported hash algorithm */ /* TPM_RC_NO_RESULT cannot get values from random number generator */ static TPM_RC BnSignEcdaa( TPM2B_ECC_PARAMETER *nonceK, // OUT: nonce component of the signature bigNum bnS, // OUT: s component of the signature bigCurve E, // IN: the curve used in signing bigNum bnD, // IN: the private key const TPM2B_DIGEST *digest, // IN: the value to sign (mod q) TPMT_ECC_SCHEME *scheme, // IN: signing scheme (contains the // commit count value). OBJECT *eccKey, // IN: The signing key RAND_STATE *rand // IN: a random number state ) { TPM_RC retVal; TPM2B_ECC_PARAMETER r; HASH_STATE state; TPM2B_DIGEST T; BN_MAX(bnT); // NOT_REFERENCED(rand); if(!CryptGenerateR(&r, &scheme->details.ecdaa.count, eccKey->publicArea.parameters.eccDetail.curveID, &eccKey->name)) retVal = TPM_RC_VALUE; else { // This allocation is here because 'r' doesn't have a value until // CrypGenerateR() is done. ECC_INITIALIZED(bnR, &r); do { // generate nonceK such that 0 < nonceK < n // use bnT as a temp. #if USE_OPENSSL_FUNCTIONS_EC // libtpms added begin if(!BnEccGetPrivate(bnT, AccessCurveData(E), E->G, false, rand)) #else // libtpms added end if(!BnEccGetPrivate(bnT, AccessCurveData(E), rand)) #endif // libtpms added { retVal = TPM_RC_NO_RESULT; break; } BnTo2B(bnT, &nonceK->b, 0); T.t.size = CryptHashStart(&state, scheme->details.ecdaa.hashAlg); if(T.t.size == 0) { retVal = TPM_RC_SCHEME; } else { CryptDigestUpdate2B(&state, &nonceK->b); CryptDigestUpdate2B(&state, &digest->b); CryptHashEnd2B(&state, &T.b); BnFrom2B(bnT, &T.b); // libtpms: Note: T is NOT a concern for constant-timeness // Watch out for the name collisions in this call!! retVal = BnSchnorrSign(bnS, bnR, bnT, bnD, AccessCurveData(E)->order); } } while(retVal == TPM_RC_NO_RESULT); // Because the rule is that internal state is not modified if the command // fails, only end the commit if the command succeeds. // NOTE that if the result of the Schnorr computation was zero // it will probably not be worthwhile to run the same command again because // the result will still be zero. This means that the Commit command will // need to be run again to get a new commit value for the signature. if(retVal == TPM_RC_SUCCESS) CryptEndCommit(scheme->details.ecdaa.count); } return retVal; } #endif // ALG_ECDAA #if ALG_ECSCHNORR /* 10.2.12.3.3 SchnorrReduce() */ /* Function to reduce a hash result if it's magnitude is to large. The size of number is set so that it has no more bytes of significance than the reference value. If the resulting number can have more bits of significance than the reference. */ static void SchnorrReduce( TPM2B *number, // IN/OUT: Value to reduce bigConst reference // IN: the reference value ) { UINT16 maxBytes = (UINT16)BITS_TO_BYTES(BnSizeInBits(reference)); if(number->size > maxBytes) number->size = maxBytes; } /* 10.2.12.3.4 SchnorrEcc() */ /* This function is used to perform a modified Schnorr signature. */ /* This function will generate a random value k and compute */ /* a) (xR, yR) = [k]G */ /* b) r = hash(xR || P)(mod q) */ /* c) rT = truncated r */ /* d) s= k + rT * ds (mod q) */ /* e) return the tuple rT, s */ /* Error Returns Meaning */ /* TPM_RC_NO_RESULT failure in the Schnorr sign process */ /* TPM_RC_SCHEME hashAlg can't produce zero-length digest */ static TPM_RC BnSignEcSchnorr( bigNum bnR, // OUT: r component of the signature bigNum bnS, // OUT: s component of the signature bigCurve E, // IN: the curve used in signing bigNum bnD, // IN: the signing key const TPM2B_DIGEST *digest, // IN: the digest to sign TPM_ALG_ID hashAlg, // IN: signing scheme (contains a hash) RAND_STATE *rand // IN: non-NULL when testing ) { HASH_STATE hashState; UINT16 digestSize = CryptHashGetDigestSize(hashAlg); TPM2B_TYPE(T, MAX(MAX_DIGEST_SIZE, MAX_ECC_KEY_BYTES)); TPM2B_T T2b; TPM2B *e = &T2b.b; TPM_RC retVal = TPM_RC_NO_RESULT; const ECC_CURVE_DATA *C; bigConst order; bigConst prime; ECC_NUM(bnK); POINT(ecR); // // Parameter checks if(E == NULL) ERROR_RETURN(TPM_RC_VALUE); C = AccessCurveData(E); order = CurveGetOrder(C); prime = CurveGetOrder(C); // If the digest does not produce a hash, then null the signature and return // a failure. if(digestSize == 0) { BnSetWord(bnR, 0); BnSetWord(bnS, 0); ERROR_RETURN(TPM_RC_SCHEME); } do { // Generate a random key pair if(!BnEccGenerateKeyPair(bnK, ecR, E, rand)) break; // Convert R.x to a string BnTo2B(ecR->x, e, (NUMBYTES)BITS_TO_BYTES(BnSizeInBits(prime))); // f) compute r = Hash(e || P) (mod n) CryptHashStart(&hashState, hashAlg); CryptDigestUpdate2B(&hashState, e); CryptDigestUpdate2B(&hashState, &digest->b); e->size = CryptHashEnd(&hashState, digestSize, e->buffer); // Reduce the hash size if it is larger than the curve order SchnorrReduce(e, order); // Convert hash to number BnFrom2B(bnR, e); // libtpms: Note: e is NOT a concern for constant-timeness // Do the Schnorr computation retVal = BnSchnorrSign(bnS, bnK, bnR, bnD, CurveGetOrder(C)); } while(retVal == TPM_RC_NO_RESULT); Exit: return retVal; } #endif // ALG_ECSCHNORR #if ALG_SM2 #ifdef _SM2_SIGN_DEBUG /* 10.2.12.3.5 BnHexEqual() */ /* This function compares a bignum value to a hex string. */ /* Return Value Meaning */ /* TRUE(1) values equal */ /* FALSE(0) values not equal */ static BOOL BnHexEqual( bigNum bn, //IN: big number value const char *c //IN: character string number ) { ECC_NUM(bnC); BnFromHex(bnC, c); return (BnUnsignedCmp(bn, bnC) == 0); } #endif // _SM2_SIGN_DEBUG /* 10.2.12.3.5 BnSignEcSm2() */ /* This function signs a digest using the method defined in SM2 Part 2. The method in the standard will add a header to the message to be signed that is a hash of the values that define the key. This then hashed with the message to produce a digest (e) that is signed. This function signs e. */ /* Error Returns Meaning */ /* TPM_RC_VALUE bad curve */ static TPM_RC BnSignEcSm2( bigNum bnR, // OUT: r component of the signature bigNum bnS, // OUT: s component of the signature bigCurve E, // IN: the curve used in signing bigNum bnD, // IN: the private key const TPM2B_DIGEST *digest, // IN: the digest to sign RAND_STATE *rand // IN: random number generator (mostly for // debug) ) { BN_MAX_INITIALIZED(bnE, digest); // Don't know how big digest might be ECC_NUM(bnN); ECC_NUM(bnK); ECC_NUM(bnT); // temp POINT(Q1); bigConst order = (E != NULL) ? CurveGetOrder(AccessCurveData(E)) : NULL; // libtpms added begin UINT32 orderBits = BnSizeInBits(order); BOOL atByteBoundary = (orderBits & 7) == 0; ECC_NUM(bnK1); // libtpms added end // #ifdef _SM2_SIGN_DEBUG BnFromHex(bnE, "B524F552CD82B8B028476E005C377FB1" "9A87E6FC682D48BB5D42E3D9B9EFFE76"); BnFromHex(bnD, "128B2FA8BD433C6C068C8D803DFF7979" "2A519A55171B1B650C23661D15897263"); #endif // A3: Use random number generator to generate random number 1 <= k <= n-1; // NOTE: Ax: numbers are from the SM2 standard loop: { // Get a random number 0 < k < n // libtpms modified begin // // We take a dual approach here. One for curves whose order is not at // the byte boundary, e.g. NIST P521, we get a random number bnK and add // the order to that number to have bnK1. This will not spill over into // a new byte and we can then use bnK1 to do the do the BnEccModMult // with a constant number of bytes. For curves whose order is at the // byte boundary we require that the random number bnK comes back with // a requested number of bytes. if (!atByteBoundary) { BnGenerateRandomInRange(bnK, order, rand); BnAdd(bnK1, bnK, order); #ifdef _SM2_SIGN_DEBUG BnFromHex(bnK1, "6CB28D99385C175C94F94E934817663F" "C176D925DD72B727260DBAAE1FB2F96F"); #endif // A4: Figure out the point of elliptic curve (x1, y1)=[k]G, and according // to details specified in 4.2.7 in Part 1 of this document, transform the // data type of x1 into an integer; if(!BnEccModMult(Q1, NULL, bnK1, E)) goto loop; } else { BnGenerateRandomInRangeAllBytes(bnK, order, rand); #ifdef _SM2_SIGN_DEBUG BnFromHex(bnK, "6CB28D99385C175C94F94E934817663F" "C176D925DD72B727260DBAAE1FB2F96F"); #endif if(!BnEccModMult(Q1, NULL, bnK, E)) goto loop; } // libtpms modified end // A5: Figure out r = (e + x1) mod n, BnAdd(bnR, bnE, Q1->x); BnMod(bnR, order); #ifdef _SM2_SIGN_DEBUG pAssert(BnHexEqual(bnR, "40F1EC59F793D9F49E09DCEF49130D41" "94F79FB1EED2CAA55BACDB49C4E755D1")); #endif // if r=0 or r+k=n, return to A3; if(BnEqualZero(bnR)) goto loop; BnAdd(bnT, bnK, bnR); if(BnUnsignedCmp(bnT, bnN) == 0) goto loop; // A6: Figure out s = ((1 + dA)^-1 (k - r dA)) mod n, // if s=0, return to A3; // compute t = (1+dA)^-1 BnAddWord(bnT, bnD, 1); BnModInverse(bnT, bnT, order); #ifdef _SM2_SIGN_DEBUG pAssert(BnHexEqual(bnT, "79BFCF3052C80DA7B939E0C6914A18CB" "B2D96D8555256E83122743A7D4F5F956")); #endif // compute s = t * (k - r * dA) mod n BnModMult(bnS, bnR, bnD, order); // k - r * dA mod n = k + n - ((r * dA) mod n) BnSub(bnS, order, bnS); BnAdd(bnS, bnK, bnS); BnModMult(bnS, bnS, bnT, order); #ifdef _SM2_SIGN_DEBUG pAssert(BnHexEqual(bnS, "6FC6DAC32C5D5CF10C77DFB20F7C2EB6" "67A457872FB09EC56327A67EC7DEEBE7")); #endif if(BnEqualZero(bnS)) goto loop; } // A7: According to details specified in 4.2.1 in Part 1 of this document, // transform the data type of r, s into bit strings, signature of message M // is (r, s). // This is handled by the common return code #ifdef _SM2_SIGN_DEBUG pAssert(BnHexEqual(bnR, "40F1EC59F793D9F49E09DCEF49130D41" "94F79FB1EED2CAA55BACDB49C4E755D1")); pAssert(BnHexEqual(bnS, "6FC6DAC32C5D5CF10C77DFB20F7C2EB6" "67A457872FB09EC56327A67EC7DEEBE7")); #endif return TPM_RC_SUCCESS; } #endif // ALG_SM2 /* 10.2.12.3.6 CryptEccSign() */ /* This function is the dispatch function for the various ECC-based signing schemes. There is a bit of ugliness to the parameter passing. In order to test this, we sometime would like to use a deterministic RNG so that we can get the same signatures during testing. The easiest way to do this for most schemes is to pass in a deterministic RNG and let it return canned values during testing. There is a competing need for a canned parameter to use in ECDAA. To accommodate both needs with minimal fuss, a special type of RAND_STATE is defined to carry the address of the commit value. The setup and handling of this is not very different for the caller than what was in previous versions of the code. */ /* Error Returns Meaning */ /* TPM_RC_SCHEME scheme is not supported */ LIB_EXPORT TPM_RC CryptEccSign( TPMT_SIGNATURE *signature, // OUT: signature OBJECT *signKey, // IN: ECC key to sign the hash const TPM2B_DIGEST *digest, // IN: digest to sign TPMT_ECC_SCHEME *scheme, // IN: signing scheme RAND_STATE *rand ) { CURVE_INITIALIZED(E, signKey->publicArea.parameters.eccDetail.curveID); ECC_INITIALIZED(bnD, &signKey->sensitive.sensitive.ecc.b); ECC_NUM(bnR); ECC_NUM(bnS); const ECC_CURVE_DATA *C; TPM_RC retVal = TPM_RC_SCHEME; // NOT_REFERENCED(scheme); if(E == NULL) ERROR_RETURN(TPM_RC_VALUE); C = AccessCurveData(E); signature->signature.ecdaa.signatureR.t.size = sizeof(signature->signature.ecdaa.signatureR.t.buffer); signature->signature.ecdaa.signatureS.t.size = sizeof(signature->signature.ecdaa.signatureS.t.buffer); TEST(signature->sigAlg); switch(signature->sigAlg) { case TPM_ALG_ECDSA: retVal = BnSignEcdsa(bnR, bnS, E, bnD, digest, rand); break; #if ALG_ECDAA case TPM_ALG_ECDAA: retVal = BnSignEcdaa(&signature->signature.ecdaa.signatureR, bnS, E, bnD, digest, scheme, signKey, rand); bnR = NULL; break; #endif #if ALG_ECSCHNORR case TPM_ALG_ECSCHNORR: retVal = BnSignEcSchnorr(bnR, bnS, E, bnD, digest, signature->signature.ecschnorr.hash, rand); break; #endif #if ALG_SM2 case TPM_ALG_SM2: retVal = BnSignEcSm2(bnR, bnS, E, bnD, digest, rand); break; #endif default: break; } // If signature generation worked, convert the results. if(retVal == TPM_RC_SUCCESS) { NUMBYTES orderBytes = (NUMBYTES)BITS_TO_BYTES(BnSizeInBits(CurveGetOrder(C))); if(bnR != NULL) BnTo2B(bnR, &signature->signature.ecdaa.signatureR.b, orderBytes); if(bnS != NULL) BnTo2B(bnS, &signature->signature.ecdaa.signatureS.b, orderBytes); } Exit: CURVE_FREE(E); return retVal; } #if ALG_ECDSA /* 10.2.12.3.7 BnValidateSignatureEcdsa() */ /* This function validates an ECDSA signature. rIn and sIn should have been checked to make sure that they are in the range 0 < v < n */ /* Error Returns Meaning */ /* TPM_RC_SIGNATURE signature not valid */ #if !USE_OPENSSL_FUNCTIONS_ECDSA // libtpms added TPM_RC BnValidateSignatureEcdsa( bigNum bnR, // IN: r component of the signature bigNum bnS, // IN: s component of the signature bigCurve E, // IN: the curve used in the signature // process bn_point_t *ecQ, // IN: the public point of the key const TPM2B_DIGEST *digest // IN: the digest that was signed ) { // Make sure that the allocation for the digest is big enough for a maximum // digest BN_VAR(bnE, MAX(MAX_ECC_KEY_BYTES, MAX_DIGEST_SIZE) * 8); POINT(ecR); ECC_NUM(bnU1); ECC_NUM(bnU2); ECC_NUM(bnW); bigConst order = CurveGetOrder(AccessCurveData(E)); TPM_RC retVal = TPM_RC_SIGNATURE; // Get adjusted digest EcdsaDigest(bnE, digest, order); // 1. If r and s are not both integers in the interval [1, n - 1], output // INVALID. // bnR and bnS were validated by the caller // 2. Use the selected hash function to compute H0 = Hash(M0). // This is an input parameter // 3. Convert the bit string H0 to an integer e as described in Appendix B.2. // Done at entry // 4. Compute w = (s')^-1 mod n, using the routine in Appendix B.1. if(!BnModInverse(bnW, bnS, order)) goto Exit; // 5. Compute u1 = (e' * w) mod n, and compute u2 = (r' * w) mod n. BnModMult(bnU1, bnE, bnW, order); BnModMult(bnU2, bnR, bnW, order); // 6. Compute the elliptic curve point R = (xR, yR) = u1G+u2Q, using EC // scalar multiplication and EC addition (see [Routines]). If R is equal to // the point at infinity O, output INVALID. if(BnPointMult(ecR, CurveGetG(AccessCurveData(E)), bnU1, ecQ, bnU2, E) != TPM_RC_SUCCESS) goto Exit; // 7. Compute v = Rx mod n. BnMod(ecR->x, order); // 8. Compare v and r0. If v = r0, output VALID; otherwise, output INVALID if(BnUnsignedCmp(ecR->x, bnR) != 0) goto Exit; retVal = TPM_RC_SUCCESS; Exit: return retVal; } #else // USE_OPENSSL_FUNCTIONS_ECDSA libtpms added begin TPM_RC BnValidateSignatureEcdsa( bigNum bnR, // IN: r component of the signature bigNum bnS, // IN: s component of the signature bigCurve E, // IN: the curve used in the signature // process bn_point_t *ecQ, // IN: the public point of the key const TPM2B_DIGEST *digest // IN: the digest that was signed ) { int retVal; int rc; ECDSA_SIG *sig = NULL; EC_KEY *eckey = NULL; BIGNUM *r = BN_new(); BIGNUM *s = BN_new(); EC_POINT *q = EcPointInitialized(ecQ, E); r = BigInitialized(r, bnR); s = BigInitialized(s, bnS); sig = ECDSA_SIG_new(); eckey = EC_KEY_new(); if (r == NULL || s == NULL || q == NULL || sig == NULL || eckey == NULL) ERROR_RETURN(TPM_RC_FAILURE); if (EC_KEY_set_group(eckey, E->G) != 1) ERROR_RETURN(TPM_RC_FAILURE); if (EC_KEY_set_public_key(eckey, q) != 1) ERROR_RETURN(TPM_RC_FAILURE); if (ECDSA_SIG_set0(sig, r, s) != 1) ERROR_RETURN(TPM_RC_FAILURE); /* sig now owns r and s */ r = NULL; s = NULL; rc = ECDSA_do_verify(digest->b.buffer, digest->b.size, sig, eckey); switch (rc) { case 1: retVal = TPM_RC_SUCCESS; break; case 0: retVal = TPM_RC_SIGNATURE; break; default: retVal = TPM_RC_FAILURE; break; } Exit: EC_KEY_free(eckey); ECDSA_SIG_free(sig); EC_POINT_clear_free(q); BN_clear_free(r); BN_clear_free(s); return retVal; } #endif // USE_OPENSSL_FUNCTIONS_ECDSA libtpms added end #endif // ALG_ECDSA #if ALG_SM2 /* 10.2.12.3.8 BnValidateSignatureEcSm2() */ /* This function is used to validate an SM2 signature. */ /* Error Returns Meaning */ /* TPM_RC_SIGNATURE signature not valid */ static TPM_RC BnValidateSignatureEcSm2( bigNum bnR, // IN: r component of the signature bigNum bnS, // IN: s component of the signature bigCurve E, // IN: the curve used in the signature // process bigPoint ecQ, // IN: the public point of the key const TPM2B_DIGEST *digest // IN: the digest that was signed ) { POINT(P); ECC_NUM(bnRp); ECC_NUM(bnT); BN_MAX_INITIALIZED(bnE, digest); BOOL OK; bigConst order = CurveGetOrder(AccessCurveData(E)); #ifdef _SM2_SIGN_DEBUG // Make sure that the input signature is the test signature pAssert(BnHexEqual(bnR, "40F1EC59F793D9F49E09DCEF49130D41" "94F79FB1EED2CAA55BACDB49C4E755D1")); pAssert(BnHexEqual(bnS, "6FC6DAC32C5D5CF10C77DFB20F7C2EB6" "67A457872FB09EC56327A67EC7DEEBE7")); #endif // b) compute t := (r + s) mod n BnAdd(bnT, bnR, bnS); BnMod(bnT, order); #ifdef _SM2_SIGN_DEBUG pAssert(BnHexEqual(bnT, "2B75F07ED7ECE7CCC1C8986B991F441A" "D324D6D619FE06DD63ED32E0C997C801")); #endif // c) verify that t > 0 OK = !BnEqualZero(bnT); if(!OK) // set T to a value that should allow rest of the computations to run // without trouble BnCopy(bnT, bnS); // d) compute (x, y) := [s]G + [t]Q OK = BnEccModMult2(P, NULL, bnS, ecQ, bnT, E); #ifdef _SM2_SIGN_DEBUG pAssert(OK && BnHexEqual(P->x, "110FCDA57615705D5E7B9324AC4B856D" "23E6D9188B2AE47759514657CE25D112")); #endif // e) compute r' := (e + x) mod n (the x coordinate is in bnT) OK = OK && BnAdd(bnRp, bnE, P->x); OK = OK && BnMod(bnRp, order); // f) verify that r' = r OK = OK && (BnUnsignedCmp(bnR, bnRp) == 0); if(!OK) return TPM_RC_SIGNATURE; else return TPM_RC_SUCCESS; } #endif // ALG_SM2 #if ALG_ECSCHNORR /* 10.2.12.3.9 BnValidateSignatureEcSchnorr() */ /* This function is used to validate an EC Schnorr signature. */ /* Error Returns Meaning */ /* TPM_RC_SIGNATURE signature not valid */ static TPM_RC BnValidateSignatureEcSchnorr( bigNum bnR, // IN: r component of the signature bigNum bnS, // IN: s component of the signature TPM_ALG_ID hashAlg, // IN: hash algorithm of the signature bigCurve E, // IN: the curve used in the signature // process bigPoint ecQ, // IN: the public point of the key const TPM2B_DIGEST *digest // IN: the digest that was signed ) { BN_MAX(bnRn); POINT(ecE); BN_MAX(bnEx); const ECC_CURVE_DATA *C = AccessCurveData(E); bigConst order = CurveGetOrder(C); UINT16 digestSize = CryptHashGetDigestSize(hashAlg); HASH_STATE hashState; TPM2B_TYPE(BUFFER, MAX(MAX_ECC_PARAMETER_BYTES, MAX_DIGEST_SIZE)); TPM2B_BUFFER Ex2 = {{sizeof(Ex2.t.buffer),{ 0 }}}; BOOL OK; // // E = [s]G - [r]Q BnMod(bnR, order); // Make -r = n - r BnSub(bnRn, order, bnR); // E = [s]G + [-r]Q OK = BnPointMult(ecE, CurveGetG(C), bnS, ecQ, bnRn, E) == TPM_RC_SUCCESS; // // reduce the x portion of E mod q // OK = OK && BnMod(ecE->x, order); // Convert to byte string OK = OK && BnTo2B(ecE->x, &Ex2.b, (NUMBYTES)(BITS_TO_BYTES(BnSizeInBits(order)))); if(OK) { // Ex = h(pE.x || digest) CryptHashStart(&hashState, hashAlg); CryptDigestUpdate(&hashState, Ex2.t.size, Ex2.t.buffer); CryptDigestUpdate(&hashState, digest->t.size, digest->t.buffer); Ex2.t.size = CryptHashEnd(&hashState, digestSize, Ex2.t.buffer); SchnorrReduce(&Ex2.b, order); BnFrom2B(bnEx, &Ex2.b); // see if Ex matches R OK = BnUnsignedCmp(bnEx, bnR) == 0; } return (OK) ? TPM_RC_SUCCESS : TPM_RC_SIGNATURE; } #endif // ALG_ECSCHNORR /* 10.2.12.3.10 CryptEccValidateSignature() */ /* This function validates an EcDsa() or EcSchnorr() signature. The point Qin needs to have been validated to be on the curve of curveId. */ /* Error Returns Meaning */ /* TPM_RC_SIGNATURE not a valid signature */ LIB_EXPORT TPM_RC CryptEccValidateSignature( TPMT_SIGNATURE *signature, // IN: signature to be verified OBJECT *signKey, // IN: ECC key signed the hash const TPM2B_DIGEST *digest // IN: digest that was signed ) { CURVE_INITIALIZED(E, signKey->publicArea.parameters.eccDetail.curveID); ECC_NUM(bnR); ECC_NUM(bnS); POINT_INITIALIZED(ecQ, &signKey->publicArea.unique.ecc); bigConst order; TPM_RC retVal; if(E == NULL) ERROR_RETURN(TPM_RC_VALUE); order = CurveGetOrder(AccessCurveData(E)); // // Make sure that the scheme is valid switch(signature->sigAlg) { case TPM_ALG_ECDSA: #if ALG_ECSCHNORR case TPM_ALG_ECSCHNORR: #endif #if ALG_SM2 case TPM_ALG_SM2: #endif break; default: ERROR_RETURN(TPM_RC_SCHEME); break; } // Can convert r and s after determining that the scheme is an ECC scheme. If // this conversion doesn't work, it means that the unmarshaling code for // an ECC signature is broken. BnFrom2B(bnR, &signature->signature.ecdsa.signatureR.b); BnFrom2B(bnS, &signature->signature.ecdsa.signatureS.b); // r and s have to be greater than 0 but less than the curve order if(BnEqualZero(bnR) || BnEqualZero(bnS)) ERROR_RETURN(TPM_RC_SIGNATURE); if((BnUnsignedCmp(bnS, order) >= 0) || (BnUnsignedCmp(bnR, order) >= 0)) ERROR_RETURN(TPM_RC_SIGNATURE); switch(signature->sigAlg) { case TPM_ALG_ECDSA: retVal = BnValidateSignatureEcdsa(bnR, bnS, E, ecQ, digest); break; #if ALG_ECSCHNORR case TPM_ALG_ECSCHNORR: retVal = BnValidateSignatureEcSchnorr(bnR, bnS, signature->signature.any.hashAlg, E, ecQ, digest); break; #endif #if ALG_SM2 case TPM_ALG_SM2: retVal = BnValidateSignatureEcSm2(bnR, bnS, E, ecQ, digest); break; #endif default: FAIL(FATAL_ERROR_INTERNAL); } Exit: CURVE_FREE(E); return retVal; } /* 10.2.12.3.11 CryptEccCommitCompute() */ /* This function performs the point multiply operations required by TPM2_Commit(). */ /* If B or M is provided, they must be on the curve defined by curveId. This routine does not check that they are on the curve and results are unpredictable if they are not. */ /* It is a fatal error if r is NULL. If B is not NULL, then it is a fatal error if d is NULL or if K and L are both NULL. If M is not NULL, then it is a fatal error if E is NULL. */ /* Error Returns Meaning */ /* TPM_RC_NO_RESULT if K, L or E was computed to be the point at infinity */ /* TPM_RC_CANCELED a cancel indication was asserted during this function */ LIB_EXPORT TPM_RC CryptEccCommitCompute( TPMS_ECC_POINT *K, // OUT: [d]B or [r]Q TPMS_ECC_POINT *L, // OUT: [r]B TPMS_ECC_POINT *E, // OUT: [r]M TPM_ECC_CURVE curveId, // IN: the curve for the computations TPMS_ECC_POINT *M, // IN: M (optional) TPMS_ECC_POINT *B, // IN: B (optional) TPM2B_ECC_PARAMETER *d, // IN: d (optional) TPM2B_ECC_PARAMETER *r // IN: the computed r value (required) ) { CURVE_INITIALIZED(curve, curveId); // Normally initialize E as the curve, but E means // something else in this function ECC_INITIALIZED(bnR, r); TPM_RC retVal = TPM_RC_SUCCESS; // // Validate that the required parameters are provided. // Note: E has to be provided if computing E := [r]Q or E := [r]M. Will do // E := [r]Q if both M and B are NULL. pAssert(r != NULL && E != NULL); // Initialize the output points in case they are not computed ClearPoint2B(K); ClearPoint2B(L); ClearPoint2B(E); // Sizes of the r parameter may not be zero pAssert(r->t.size > 0); // If B is provided, compute K=[d]B and L=[r]B if(B != NULL) { ECC_INITIALIZED(bnD, d); POINT_INITIALIZED(pB, B); POINT(pK); POINT(pL); // pAssert(d != NULL && K != NULL && L != NULL); if(!BnIsOnCurve(pB, AccessCurveData(curve))) ERROR_RETURN(TPM_RC_VALUE); // do the math for K = [d]B if((retVal = BnPointMult(pK, pB, bnD, NULL, NULL, curve)) != TPM_RC_SUCCESS) goto Exit; // Convert BN K to TPM2B K BnPointTo2B(K, pK, curve); // compute L= [r]B after checking for cancel if(_plat__IsCanceled()) ERROR_RETURN(TPM_RC_CANCELED); // compute L = [r]B if(!BnIsValidPrivateEcc(bnR, curve)) ERROR_RETURN(TPM_RC_VALUE); if((retVal = BnPointMult(pL, pB, bnR, NULL, NULL, curve)) != TPM_RC_SUCCESS) goto Exit; // Convert BN L to TPM2B L BnPointTo2B(L, pL, curve); } if((M != NULL) || (B == NULL)) { POINT_INITIALIZED(pM, M); POINT(pE); // // Make sure that a place was provided for the result pAssert(E != NULL); // if this is the third point multiply, check for cancel first if((B != NULL) && _plat__IsCanceled()) ERROR_RETURN(TPM_RC_CANCELED); // If M provided, then pM will not be NULL and will compute E = [r]M. // However, if M was not provided, then pM will be NULL and E = [r]G // will be computed if((retVal = BnPointMult(pE, pM, bnR, NULL, NULL, curve)) != TPM_RC_SUCCESS) goto Exit; // Convert E to 2B format BnPointTo2B(E, pE, curve); } Exit: CURVE_FREE(curve); return retVal; } #endif // TPM_ALG_ECC libtpms-0.9.3/src/tpm2/crypto/openssl/CryptHash.c000066400000000000000000001023671421143571500217360ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Implementation of cryptographic functions for hashing. */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CryptHash.c 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2021 */ /* */ /********************************************************************************/ /* 10.2.13 CryptHash.c */ /* 10.2.13.1 Description */ /* This file contains implementation of cryptographic functions for hashing. */ /* 10.2.13.2 Includes, Defines, and Types */ #define _CRYPT_HASH_C_ #include "Tpm.h" #include "CryptHash_fp.h" #include "CryptHash.h" #include "OIDs.h" /* Instance each of the hash descriptors based on the implemented algorithms */ FOR_EACH_HASH(HASH_DEF_TEMPLATE) /* Instance a null def. */ HASH_DEF NULL_Def = {{0}}; /* Create a table of pointers to the defined hash definitions */ #define HASH_DEF_ENTRY(HASH, Hash) &Hash##_Def, PHASH_DEF HashDefArray[] = { // for each implemented HASH, expands to: &HASH_Def, FOR_EACH_HASH(HASH_DEF_ENTRY) &NULL_Def }; /* 10.2.13.3 Obligatory Initialization Functions */ /* 10.2.13.3.1 CryptHashInit() */ /* This function is called by _TPM_Init() do perform the initialization operations for the library. */ BOOL CryptHashInit( void ) { LibHashInit(); return TRUE; } /* 10.2.13.3.2 CryptHashStartup() */ /* This function is called by TPM2_Startup(). It checks that the size of the HashDefArray() is consistent with the HASH_COUNT. */ BOOL CryptHashStartup( void ) { int i = sizeof(HashDefArray) / sizeof(PHASH_DEF) - 1; return (i == HASH_COUNT); } /* 10.2.13.4 Hash Information Access Functions */ /* 10.2.13.4.1 Introduction */ /* These functions provide access to the hash algorithm description information. */ /* 10.2.13.4.2 CryptGetHashDef() */ /* This function accesses the hash descriptor associated with a hash a algorithm. The function returns a pointer to a null descriptor if hashAlg is TPM_ALG_NULL or not a defined algorithm. */ PHASH_DEF CryptGetHashDef( TPM_ALG_ID hashAlg ) { #define GET_DEF(HASH, Hash) case ALG_##HASH##_VALUE: return &Hash##_Def; switch(hashAlg) { FOR_EACH_HASH(GET_DEF) default: return &NULL_Def; } #undef GET_DEF } /* 10.2.13.4.3 CryptHashIsValidAlg() */ /* This function tests to see if an algorithm ID is a valid hash algorithm. If flag is true, then TPM_ALG_NULL is a valid hash. */ /* Return Value Meaning */ /* TRUE(1) hashAlg is a valid, implemented hash on this TPM */ /* FALSE(0) hashAlg is not valid for this TPM */ BOOL CryptHashIsValidAlg( TPM_ALG_ID hashAlg, // IN: the algorithm to check BOOL flag // IN: TRUE if TPM_ALG_NULL is to be treated // as a valid hash ) { if(hashAlg == TPM_ALG_NULL) return flag; return CryptGetHashDef(hashAlg) != &NULL_Def; } /* 10.2.13.4.4 CryptHashGetAlgByIndex() */ /* This function is used to iterate through the hashes. TPM_ALG_NULL is returned for all indexes that are not valid hashes. If the TPM implements 3 hashes, then an index value of 0 will return the first implemented hash and an index of 2 will return the last. All other index values will return TPM_ALG_NULL. */ /* Return Value Meaning */ /* TPM_ALG_xxx a hash algorithm */ /* TPM_ALG_NULL this can be used as a stop value */ LIB_EXPORT TPM_ALG_ID CryptHashGetAlgByIndex( UINT32 index // IN: the index ) { TPM_ALG_ID hashAlg; if(index >= HASH_COUNT) hashAlg = TPM_ALG_NULL; else hashAlg = HashDefArray[index]->hashAlg; return hashAlg; } /* 10.2.13.4.5 CryptHashGetDigestSize() */ /* Returns the size of the digest produced by the hash. If hashAlg is not a hash algorithm, the TPM will FAIL. */ /* Return Value Meaning */ /* 0 TPM_ALG_NULL */ /* > 0 the digest size */ LIB_EXPORT UINT16 CryptHashGetDigestSize( TPM_ALG_ID hashAlg // IN: hash algorithm to look up ) { return CryptGetHashDef(hashAlg)->digestSize; } /* 10.2.13.4.6 CryptHashGetBlockSize() */ /* Returns the size of the block used by the hash. If hashAlg is not a hash algorithm, the TPM will FAIL. */ /* Return Value Meaning */ /* 0 TPM_ALG_NULL */ /* > 0 the digest size */ LIB_EXPORT UINT16 CryptHashGetBlockSize( TPM_ALG_ID hashAlg // IN: hash algorithm to look up ) { return CryptGetHashDef(hashAlg)->blockSize; } /* 10.2.13.4.7 CryptHashGetOid() */ /* This function returns a pointer to DER=encoded OID for a hash algorithm. All OIDs are full OID values including the Tag (0x06) and length byte. */ #if 0 // libtpms added LIB_EXPORT const BYTE * CryptHashGetOid( TPM_ALG_ID hashAlg ) { return CryptGetHashDef(hashAlg)->OID; } #endif // libtpms added /* 10.2.13.4.8 CryptHashGetContextAlg() */ /* This function returns the hash algorithm associated with a hash context. */ #if 0 // libtpms added TPM_ALG_ID CryptHashGetContextAlg( PHASH_STATE state // IN: the context to check ) { return state->hashAlg; } #endif // libtpms added /* 10.2.13.5 State Import and Export */ /* 10.2.13.5.1 CryptHashCopyState */ /* This function is used to clone a HASH_STATE. */ #if 0 // libtpms added LIB_EXPORT void CryptHashCopyState( HASH_STATE *out, // OUT: destination of the state const HASH_STATE *in // IN: source of the state ) { pAssert(out->type == in->type); out->hashAlg = in->hashAlg; out->def = in->def; if(in->hashAlg != TPM_ALG_NULL) { HASH_STATE_COPY(out, in); } if(in->type == HASH_STATE_HMAC) { const HMAC_STATE *hIn = (HMAC_STATE *)in; HMAC_STATE *hOut = (HMAC_STATE *)out; hOut->hmacKey = hIn->hmacKey; } return; } #endif // libtpms added #if 0 // libtpms added /* 10.2.13.5.2 CryptHashExportState() */ /* This function is used to export a hash or HMAC hash state. This function would be called when preparing to context save a sequence object. */ void CryptHashExportState( PCHASH_STATE internalFmt, // IN: the hash state formatted for use by // library PEXPORT_HASH_STATE externalFmt // OUT: the exported hash state ) { BYTE *outBuf = (BYTE *)externalFmt; // cAssert(sizeof(HASH_STATE) <= sizeof(EXPORT_HASH_STATE)); // the following #define is used to move data from an aligned internal data // structure to a byte buffer (external format data. #define CopyToOffset(value) \ memcpy(&outBuf[offsetof(HASH_STATE,value)], &internalFmt->value, \ sizeof(internalFmt->value)) // Copy the hashAlg CopyToOffset(hashAlg); CopyToOffset(type); #ifdef HASH_STATE_SMAC if(internalFmt->type == HASH_STATE_SMAC) { memcpy(outBuf, internalFmt, sizeof(HASH_STATE)); return; } #endif if(internalFmt->type == HASH_STATE_HMAC) { HMAC_STATE *from = (HMAC_STATE *)internalFmt; memcpy(&outBuf[offsetof(HMAC_STATE, hmacKey)], &from->hmacKey, sizeof(from->hmacKey)); } if(internalFmt->hashAlg != TPM_ALG_NULL) HASH_STATE_EXPORT(externalFmt, internalFmt); } /* 10.2.13.5.3 CryptHashImportState() */ /* This function is used to import the hash state. This function would be called to import a hash state when the context of a sequence object was being loaded. */ void CryptHashImportState( PHASH_STATE internalFmt, // OUT: the hash state formatted for use by // the library PCEXPORT_HASH_STATE externalFmt // IN: the exported hash state ) { BYTE *inBuf = (BYTE *)externalFmt; // #define CopyFromOffset(value) \ memcpy(&internalFmt->value, &inBuf[offsetof(HASH_STATE,value)], \ sizeof(internalFmt->value)) // Copy the hashAlg of the byte-aligned input structure to the structure-aligned // internal structure. CopyFromOffset(hashAlg); CopyFromOffset(type); if(internalFmt->hashAlg != TPM_ALG_NULL) { #ifdef HASH_STATE_SMAC if(internalFmt->type == HASH_STATE_SMAC) { memcpy(internalFmt, inBuf, sizeof(HASH_STATE)); return; } #endif internalFmt->def = CryptGetHashDef(internalFmt->hashAlg); HASH_STATE_IMPORT(internalFmt, inBuf); if(internalFmt->type == HASH_STATE_HMAC) { HMAC_STATE *to = (HMAC_STATE *)internalFmt; memcpy(&to->hmacKey, &inBuf[offsetof(HMAC_STATE, hmacKey)], sizeof(to->hmacKey)); } } } #endif // libtpms added /* 10.2.13.6 State Modification Functions */ /* 10.2.13.6.1 HashEnd() */ /* Local function to complete a hash that uses the hashDef instead of an algorithm ID. This function is used to complete the hash and only return a partial digest. The return value is the size of the data copied. */ static UINT16 HashEnd( PHASH_STATE hashState, // IN: the hash state UINT32 dOutSize, // IN: the size of receive buffer PBYTE dOut // OUT: the receive buffer ) { BYTE temp[MAX_DIGEST_SIZE]; if((hashState->hashAlg == TPM_ALG_NULL) || (hashState->type != HASH_STATE_HASH)) dOutSize = 0; if(dOutSize > 0) { hashState->def = CryptGetHashDef(hashState->hashAlg); // Set the final size dOutSize = MIN(dOutSize, hashState->def->digestSize); // Complete into the temp buffer and then copy HASH_END(hashState, temp); // Don't want any other functions calling the HASH_END method // directly. #undef HASH_END memcpy(dOut, &temp, dOutSize); } hashState->type = HASH_STATE_EMPTY; return (UINT16)dOutSize; } /* 10.2.13.6.2 CryptHashStart() */ /* Functions starts a hash stack Start a hash stack and returns the digest size. As a side effect, the value of stateSize in hashState is updated to indicate the number of bytes of state that were saved. This function calls GetHashServer() and that function will put the TPM into failure mode if the hash algorithm is not supported. */ /* This function does not use the sequence parameter. If it is necessary to import or export context, this will start the sequence in a local state and export the state to the input buffer. Will need to add a flag to the state structure to indicate that it needs to be imported before it can be used. (BLEH). */ /* Return Value Meaning */ /* 0 hash is TPM_ALG_NULL */ /* >0 digest size */ LIB_EXPORT UINT16 CryptHashStart( PHASH_STATE hashState, // OUT: the running hash state TPM_ALG_ID hashAlg // IN: hash algorithm ) { UINT16 retVal; TEST(hashAlg); hashState->hashAlg = hashAlg; if(hashAlg == TPM_ALG_NULL) { retVal = 0; } else { hashState->def = CryptGetHashDef(hashAlg); HASH_START(hashState); retVal = hashState->def->digestSize; } #undef HASH_START hashState->type = HASH_STATE_HASH; return retVal; } /* 10.2.13.6.3 CryptDigestUpdate() */ /* Add data to a hash or HMAC, SMAC stack. */ void CryptDigestUpdate( PHASH_STATE hashState, // IN: the hash context information UINT32 dataSize, // IN: the size of data to be added const BYTE *data // IN: data to be hashed ) { if(hashState->hashAlg != TPM_ALG_NULL) { if((hashState->type == HASH_STATE_HASH) || (hashState->type == HASH_STATE_HMAC)) HASH_DATA(hashState, dataSize, (BYTE *)data); #if SMAC_IMPLEMENTED else if(hashState->type == HASH_STATE_SMAC) (hashState->state.smac.smacMethods.data)(&hashState->state.smac.state, dataSize, data); #endif // SMAC_IMPLEMENTED else FAIL(FATAL_ERROR_INTERNAL); } return; } /* 10.2.13.6.4 CryptHashEnd() */ /* Complete a hash or HMAC computation. This function will place the smaller of digestSize or the size of the digest in dOut. The number of bytes in the placed in the buffer is returned. If there is a failure, the returned value is <= 0. */ /* Return Value Meaning */ /* 0 no data returned */ /* > 0 the number of bytes in the digest or dOutSize, whichever is smaller */ LIB_EXPORT UINT16 CryptHashEnd( PHASH_STATE hashState, // IN: the state of hash stack UINT32 dOutSize, // IN: size of digest buffer BYTE *dOut // OUT: hash digest ) { pAssert(hashState->type == HASH_STATE_HASH); return HashEnd(hashState, dOutSize, dOut); } /* 10.2.13.6.5 CryptHashBlock() */ /* Start a hash, hash a single block, update digest and return the size of the results. */ /* The digestSize parameter can be smaller than the digest. If so, only the more significant bytes are returned. */ /* Return Value Meaning */ /* >= 0 number of bytes placed in dOut */ LIB_EXPORT UINT16 CryptHashBlock( TPM_ALG_ID hashAlg, // IN: The hash algorithm UINT32 dataSize, // IN: size of buffer to hash const BYTE *data, // IN: the buffer to hash UINT32 dOutSize, // IN: size of the digest buffer BYTE *dOut // OUT: digest buffer ) { HASH_STATE state; CryptHashStart(&state, hashAlg); CryptDigestUpdate(&state, dataSize, data); return HashEnd(&state, dOutSize, dOut); } /* 10.2.13.6.6 CryptDigestUpdate2B() */ /* This function updates a digest (hash or HMAC) with a TPM2B. */ /* This function can be used for both HMAC and hash functions so the digestState is void so that either state type can be passed. */ LIB_EXPORT void CryptDigestUpdate2B( PHASH_STATE state, // IN: the digest state const TPM2B *bIn // IN: 2B containing the data ) { // Only compute the digest if a pointer to the 2B is provided. // In CryptDigestUpdate(), if size is zero or buffer is NULL, then no change // to the digest occurs. This function should not provide a buffer if bIn is // not provided. pAssert(bIn != NULL); CryptDigestUpdate(state, bIn->size, bIn->buffer); return; } /* 10.2.13.6.7 CryptHashEnd2B() */ /* This function is the same as CryptCompleteHash() but the digest is placed in a TPM2B. This is the most common use and this is provided for specification clarity. digest.size should be set to indicate the number of bytes to place in the buffer */ /* Return Value Meaning */ /* >=0 the number of bytes placed in digest.buffer */ LIB_EXPORT UINT16 CryptHashEnd2B( PHASH_STATE state, // IN: the hash state P2B digest // IN: the size of the buffer Out: requested // number of bytes ) { return CryptHashEnd(state, digest->size, digest->buffer); } /* 10.2.13.6.8 CryptDigestUpdateInt() */ /* This function is used to include an integer value to a hash stack. The function marshals the integer into its canonical form before calling CryptDigestUpdate(). */ LIB_EXPORT void CryptDigestUpdateInt( void *state, // IN: the state of hash stack UINT32 intSize, // IN: the size of 'intValue' in bytes UINT64 intValue // IN: integer value to be hashed ) { #if LITTLE_ENDIAN_TPM intValue = REVERSE_ENDIAN_64(intValue); #endif CryptDigestUpdate(state, intSize, &((BYTE *)&intValue)[8 - intSize]); } /* 10.2.13.7 HMAC Functions */ /* 10.2.13.7.1 CryptHmacStart() */ /* This function is used to start an HMAC using a temp hash context. The function does the initialization of the hash with the HMAC key XOR iPad and updates the HMAC key XOR oPad. */ /* The function returns the number of bytes in a digest produced by hashAlg. */ /* Return Value Meaning */ /* >= 0 number of bytes in digest produced by hashAlg (may be zero) */ LIB_EXPORT UINT16 CryptHmacStart( PHMAC_STATE state, // IN/OUT: the state buffer TPM_ALG_ID hashAlg, // IN: the algorithm to use UINT16 keySize, // IN: the size of the HMAC key const BYTE *key // IN: the HMAC key ) { PHASH_DEF hashDef; BYTE * pb; UINT32 i; // hashDef = CryptGetHashDef(hashAlg); if(hashDef->digestSize != 0) { // If the HMAC key is larger than the hash block size, it has to be reduced // to fit. The reduction is a digest of the hashKey. if(keySize > hashDef->blockSize) { // if the key is too big, reduce it to a digest of itself state->hmacKey.t.size = CryptHashBlock(hashAlg, keySize, key, hashDef->digestSize, state->hmacKey.t.buffer); } else { memcpy(state->hmacKey.t.buffer, key, keySize); state->hmacKey.t.size = keySize; } // XOR the key with iPad (0x36) pb = state->hmacKey.t.buffer; for(i = state->hmacKey.t.size; i > 0; i--) *pb++ ^= 0x36; // if the keySize is smaller than a block, fill the rest with 0x36 for(i = hashDef->blockSize - state->hmacKey.t.size; i > 0; i--) *pb++ = 0x36; // Increase the oPadSize to a full block state->hmacKey.t.size = hashDef->blockSize; // Start a new hash with the HMAC key // This will go in the caller's state structure and may be a sequence or not CryptHashStart((PHASH_STATE)state, hashAlg); CryptDigestUpdate((PHASH_STATE)state, state->hmacKey.t.size, state->hmacKey.t.buffer); // XOR the key block with 0x5c ^ 0x36 for(pb = state->hmacKey.t.buffer, i = hashDef->blockSize; i > 0; i--) *pb++ ^= (0x5c ^ 0x36); } // Set the hash algorithm state->hashState.hashAlg = hashAlg; // Set the hash state type state->hashState.type = HASH_STATE_HMAC; return hashDef->digestSize; } /* 10.2.13.7.2 CryptHmacEnd() */ /* This function is called to complete an HMAC. It will finish the current digest, and start a new digest. It will then add the oPadKey and the completed digest and return the results in dOut. It will not return more than dOutSize bytes. */ /* Return Value Meaning */ /* >= 0 number of bytes in dOut (may be zero) */ LIB_EXPORT UINT16 CryptHmacEnd( PHMAC_STATE state, // IN: the hash state buffer UINT32 dOutSize, // IN: size of digest buffer BYTE *dOut // OUT: hash digest ) { BYTE temp[MAX_DIGEST_SIZE]; PHASH_STATE hState = (PHASH_STATE)&state->hashState; #if SMAC_IMPLEMENTED if(hState->type == HASH_STATE_SMAC) return (state->hashState.state.smac.smacMethods.end) (&state->hashState.state.smac.state, dOutSize, dOut); #endif pAssert(hState->type == HASH_STATE_HMAC); hState->def = CryptGetHashDef(hState->hashAlg); // Change the state type for completion processing hState->type = HASH_STATE_HASH; if(hState->hashAlg == TPM_ALG_NULL) dOutSize = 0; else { // Complete the current hash HashEnd(hState, hState->def->digestSize, temp); // Do another hash starting with the oPad CryptHashStart(hState, hState->hashAlg); CryptDigestUpdate(hState, state->hmacKey.t.size, state->hmacKey.t.buffer); CryptDigestUpdate(hState, hState->def->digestSize, temp); } return HashEnd(hState, dOutSize, dOut); } /* 10.2.13.7.3 CryptHmacStart2B() */ /* This function starts an HMAC and returns the size of the digest that will be produced. */ /* This function is provided to support the most common use of starting an HMAC with a TPM2B key. */ /* The caller must provide a block of memory in which the hash sequence state is kept. The caller should not alter the contents of this buffer until the hash sequence is completed or abandoned. */ /* Return Value Meaning */ /* > 0 the digest size of the algorithm */ /* = 0 the hashAlg was TPM_ALG_NULL */ LIB_EXPORT UINT16 CryptHmacStart2B( PHMAC_STATE hmacState, // OUT: the state of HMAC stack. It will be used // in HMAC update and completion TPMI_ALG_HASH hashAlg, // IN: hash algorithm P2B key // IN: HMAC key ) { return CryptHmacStart(hmacState, hashAlg, key->size, key->buffer); } /* 10.2.13.7.4 CryptHmacEnd2B() */ /* This function is the same as CryptHmacEnd() but the HMAC result is returned in a TPM2B which is the most common use. */ /* Return Value Meaning */ /* >=0 the number of bytes placed in digest */ LIB_EXPORT UINT16 CryptHmacEnd2B( PHMAC_STATE hmacState, // IN: the state of HMAC stack P2B digest // OUT: HMAC ) { return CryptHmacEnd(hmacState, digest->size, digest->buffer); } /* 10.2.13.8 Mask and Key Generation Functions */ /* 10.2.13.8.1 CryptMGF_KDF() */ /* This function performs MGF1/KDF1 or KDF2 using the selected hash. KDF1 and KDF2 are T(n) = T(n-1) || H(seed || counter) with the difference being that, with KDF1, counter starts at 0 but with KDF2, counter starts at 1. The caller determines which version by setting the initial value of counter to either 0 or 1. */ /* Return Value Meaning */ /* 0 hash algorithm was TPM_ALG_NULL */ /* > 0 should be the same as mSize */ LIB_EXPORT UINT16 CryptMGF_KDF( UINT32 mSize, // IN: length of the mask to be produced BYTE *mask, // OUT: buffer to receive the mask TPM_ALG_ID hashAlg, // IN: hash to use UINT32 seedSize, // IN: size of the seed BYTE *seed, // IN: seed size UINT32 counter // IN: counter initial value ) { HASH_STATE hashState; PHASH_DEF hDef = CryptGetHashDef(hashAlg); UINT32 hLen; UINT32 bytes; // // If there is no digest to compute return if((hDef->digestSize == 0) || (mSize == 0)) return 0; if(counter != 0) counter = 1; hLen = hDef->digestSize; for(bytes = 0; bytes < mSize; bytes += hLen) { // Start the hash and include the seed and counter CryptHashStart(&hashState, hashAlg); CryptDigestUpdate(&hashState, seedSize, seed); CryptDigestUpdateInt(&hashState, 4, counter); // Get as much as will fit. CryptHashEnd(&hashState, MIN((mSize - bytes), hLen), &mask[bytes]); counter++; } return (UINT16)mSize; } /* 10.2.13.8.2 CryptKDFa() */ /* This function performs the key generation according to Part 1 of the TPM specification. */ /* This function returns the number of bytes generated which may be zero. */ /* The key and keyStream pointers are not allowed to be NULL. The other pointer values may be NULL. The value of sizeInBits must be no larger than (2^18)-1 = 256K bits (32385 bytes). */ /* The once parameter is set to allow incremental generation of a large value. If this flag is TRUE, sizeInBits will be used in the HMAC computation but only one iteration of the KDF is performed. This would be used for XOR obfuscation so that the mask value can be generated in digest-sized chunks rather than having to be generated all at once in an arbitrarily large buffer and then XORed into the result. If once is TRUE, then sizeInBits must be a multiple of 8. */ /* Any error in the processing of this command is considered fatal. */ /* Return Value Meaning */ /* 0 hash algorithm is not supported or is TPM_ALG_NULL */ /* > 0 the number of bytes in the keyStream buffer */ LIB_EXPORT UINT16 CryptKDFa( TPM_ALG_ID hashAlg, // IN: hash algorithm used in HMAC const TPM2B *key, // IN: HMAC key const TPM2B *label, // IN: a label for the KDF const TPM2B *contextU, // IN: context U const TPM2B *contextV, // IN: context V UINT32 sizeInBits, // IN: size of generated key in bits BYTE *keyStream, // OUT: key buffer UINT32 *counterInOut, // IN/OUT: caller may provide the iteration // counter for incremental operations to // avoid large intermediate buffers. UINT16 blocks // IN: If non-zero, this is the maximum number // of blocks to be returned, regardless // of sizeInBits ) { UINT32 counter = 0; // counter value INT16 bytes; // number of bytes to produce UINT16 generated; // number of bytes generated BYTE *stream = keyStream; HMAC_STATE hState; UINT16 digestSize = CryptHashGetDigestSize(hashAlg); pAssert(key != NULL && keyStream != NULL); TEST(TPM_ALG_KDF1_SP800_108); if(digestSize == 0) return 0; if(counterInOut != NULL) counter = *counterInOut; // If the size of the request is larger than the numbers will handle, // it is a fatal error. pAssert(((sizeInBits + 7) / 8) <= INT16_MAX); // The number of bytes to be generated is the smaller of the sizeInBits bytes or // the number of requested blocks. The number of blocks is the smaller of the // number requested or the number allowed by sizeInBits. A partial block is // a full block. bytes = (blocks > 0) ? blocks * digestSize : (UINT16)BITS_TO_BYTES(sizeInBits); generated = bytes; // Generate required bytes for(; bytes > 0; bytes -= digestSize) { counter++; // Start HMAC if(CryptHmacStart(&hState, hashAlg, key->size, key->buffer) == 0) return 0; // Adding counter CryptDigestUpdateInt(&hState.hashState, 4, counter); // Adding label if(label != NULL) HASH_DATA(&hState.hashState, label->size, (BYTE *)label->buffer); // Add a null. SP108 is not very clear about when the 0 is needed but to // make this like the previous version that did not add an 0x00 after // a null-terminated string, this version will only add a null byte // if the label parameter did not end in a null byte, or if no label // is present. if((label == NULL) || (label->size == 0) || (label->buffer[label->size - 1] != 0)) CryptDigestUpdateInt(&hState.hashState, 1, 0); // Adding contextU if(contextU != NULL) HASH_DATA(&hState.hashState, contextU->size, contextU->buffer); // Adding contextV if(contextV != NULL) HASH_DATA(&hState.hashState, contextV->size, contextV->buffer); // Adding size in bits CryptDigestUpdateInt(&hState.hashState, 4, sizeInBits); // Complete and put the data in the buffer CryptHmacEnd(&hState, bytes, stream); stream = &stream[digestSize]; } // Masking in the KDF is disabled. If the calling function wants something // less than even number of bytes, then the caller should do the masking // because there is no universal way to do it here if(counterInOut != NULL) *counterInOut = counter; return generated; } /* 10.2.13.8.3 CryptKDFe() */ /* This function implements KDFe() as defined in TPM specification part 1. */ /* This function returns the number of bytes generated which may be zero. */ /* The Z and keyStream pointers are not allowed to be NULL. The other pointer values may be NULL. The value of sizeInBits must be no larger than (2^18)-1 = 256K bits (32385 bytes). Any error in the processing of this command is considered fatal. */ /* Return Value Meaning */ /* 0 hash algorithm is not supported or is TPM_ALG_NULL */ /* > 0 the number of bytes in the keyStream buffer */ LIB_EXPORT UINT16 CryptKDFe( TPM_ALG_ID hashAlg, // IN: hash algorithm used in HMAC TPM2B *Z, // IN: Z const TPM2B *label, // IN: a label value for the KDF TPM2B *partyUInfo, // IN: PartyUInfo TPM2B *partyVInfo, // IN: PartyVInfo UINT32 sizeInBits, // IN: size of generated key in bits BYTE *keyStream // OUT: key buffer ) { HASH_STATE hashState; PHASH_DEF hashDef = CryptGetHashDef(hashAlg); UINT32 counter = 0; // counter value UINT16 hLen; BYTE *stream = keyStream; INT16 bytes; // number of bytes to generate pAssert(keyStream != NULL && Z != NULL && ((sizeInBits + 7) / 8) < INT16_MAX); // hLen = hashDef->digestSize; bytes = (INT16)((sizeInBits + 7) / 8); if(hashAlg == TPM_ALG_NULL || bytes == 0) return 0; // Generate required bytes //The inner loop of that KDF uses: // Hash[i] := H(counter | Z | OtherInfo) (5) // Where: // Hash[i] the hash generated on the i-th iteration of the loop. // H() an approved hash function // counter a 32-bit counter that is initialized to 1 and incremented // on each iteration // Z the X coordinate of the product of a public ECC key and a // different private ECC key. // OtherInfo a collection of qualifying data for the KDF defined below. // In this specification, OtherInfo will be constructed by: // OtherInfo := Use | PartyUInfo | PartyVInfo for(; bytes > 0; stream = &stream[hLen], bytes = bytes - hLen) { if(bytes < hLen) hLen = bytes; counter++; // Do the hash CryptHashStart(&hashState, hashAlg); // Add counter CryptDigestUpdateInt(&hashState, 4, counter); // Add Z if(Z != NULL) CryptDigestUpdate2B(&hashState, Z); // Add label if(label != NULL) CryptDigestUpdate2B(&hashState, label); // Add a null. SP108 is not very clear about when the 0 is needed but to // make this like the previous version that did not add an 0x00 after // a null-terminated string, this version will only add a null byte // if the label parameter did not end in a null byte, or if no label // is present. if((label == NULL) || (label->size == 0) || (label->buffer[label->size - 1] != 0)) CryptDigestUpdateInt(&hashState, 1, 0); // Add PartyUInfo if(partyUInfo != NULL) CryptDigestUpdate2B(&hashState, partyUInfo); // Add PartyVInfo if(partyVInfo != NULL) CryptDigestUpdate2B(&hashState, partyVInfo); // Compute Hash. hLen was changed to be the smaller of bytes or hLen // at the start of each iteration. CryptHashEnd(&hashState, hLen, stream); } // Mask off bits if the required bits is not a multiple of byte size if((sizeInBits % 8) != 0) keyStream[0] &= ((1 << (sizeInBits % 8)) - 1); return (UINT16)((sizeInBits + 7) / 8); } libtpms-0.9.3/src/tpm2/crypto/openssl/CryptPrime.c000066400000000000000000000404651421143571500221270ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Code for prime validation. */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CryptPrime.c 1529 2019-11-21 23:29:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ /* 10.2.14 CryptPrime.c */ /* 10.2.14.1 Introduction */ /* This file contains the code for prime validation. */ #include "Tpm.h" #include "CryptPrime_fp.h" //#define CPRI_PRIME //#include "PrimeTable.h" #include "CryptPrimeSieve_fp.h" extern const uint32_t s_LastPrimeInTable; extern const uint32_t s_PrimeTableSize; extern const uint32_t s_PrimesInTable; extern const unsigned char s_PrimeTable[]; extern bigConst s_CompositeOfSmallPrimes; /* 10.2.14.1.1 Root2() */ /* This finds ceil(sqrt(n)) to use as a stopping point for searching the prime table. */ static uint32_t Root2( uint32_t n ) { int32_t last = (int32_t)(n >> 2); int32_t next = (int32_t)(n >> 1); int32_t diff; int32_t stop = 10; // // get a starting point for(; next != 0; last >>= 1, next >>= 2); last++; do { next = (last + (n / last)) >> 1; diff = next - last; last = next; if(stop-- == 0) FAIL(FATAL_ERROR_INTERNAL); } while(diff < -1 || diff > 1); if((n / next) > (unsigned)next) next++; pAssert(next != 0); pAssert(((n / next) <= (unsigned)next) && (n / (next + 1) < (unsigned)next)); return next; } /* 10.2.14.1.2 IsPrimeInt() */ /* This will do a test of a word of up to 32-bits in size. */ BOOL IsPrimeInt( uint32_t n ) { uint32_t i; uint32_t stop; if(n < 3 || ((n & 1) == 0)) return (n == 2); if(n <= s_LastPrimeInTable) { n >>= 1; return ((s_PrimeTable[n >> 3] >> (n & 7)) & 1); } // Need to search stop = Root2(n) >> 1; // starting at 1 is equivalent to staring at (1 << 1) + 1 = 3 for(i = 1; i < stop; i++) { if((s_PrimeTable[i >> 3] >> (i & 7)) & 1) // see if this prime evenly divides the number if((n % ((i << 1) + 1)) == 0) return FALSE; } return TRUE; } #if !RSA_KEY_SIEVE // libtpms added /* 10.2.14.1.3 BnIsProbablyPrime() */ /* This function is used when the key sieve is not implemented. This function Will try to eliminate some of the obvious things before going on to perform MillerRabin() as a final verification of primeness. */ BOOL BnIsProbablyPrime( bigNum prime, // IN: RAND_STATE *rand // IN: the random state just // in case Miller-Rabin is required ) { #if RADIX_BITS > 32 if(BnUnsignedCmpWord(prime, UINT32_MAX) <= 0) #else if(BnGetSize(prime) == 1) #endif return IsPrimeInt((uint32_t)prime->d[0]); if(BnIsEven(prime)) return FALSE; if(BnUnsignedCmpWord(prime, s_LastPrimeInTable) <= 0) { crypt_uword_t temp = prime->d[0] >> 1; return ((s_PrimeTable[temp >> 3] >> (temp & 7)) & 1); } { BN_VAR(n, LARGEST_NUMBER_BITS); BnGcd(n, prime, s_CompositeOfSmallPrimes); if(!BnEqualWord(n, 1)) return FALSE; } return MillerRabin(prime, rand); } #endif // libtpms added /* 10.2.14.1.4 MillerRabinRounds() */ /* Function returns the number of Miller-Rabin rounds necessary to give an error probability equal to the security strength of the prime. These values are from FIPS 186-3. */ UINT32 MillerRabinRounds( UINT32 bits // IN: Number of bits in the RSA prime ) { if(bits < 511) return 8; // don't really expect this if(bits < 1536) return 5; // for 512 and 1K primes return 4; // for 3K public modulus and greater } /* 10.2.14.1.5 MillerRabin() */ /* This function performs a Miller-Rabin test from FIPS 186-3. It does iterations trials on the number. In all likelihood, if the number is not prime, the first test fails. */ /* Return Values Meaning */ /* TRUE probably prime */ /* FALSE composite */ BOOL MillerRabin( bigNum bnW, RAND_STATE *rand ) { BN_MAX(bnWm1); BN_PRIME(bnM); BN_PRIME(bnB); BN_PRIME(bnZ); BOOL ret = FALSE; // Assumed composite for easy exit unsigned int a; unsigned int j; int wLen; int i; int iterations = MillerRabinRounds(BnSizeInBits(bnW)); // INSTRUMENT_INC(MillerRabinTrials[PrimeIndex]); pAssert(bnW->size > 1); // Let a be the largest integer such that 2^a divides w1. BnSubWord(bnWm1, bnW, 1); pAssert(bnWm1->size != 0); // Since w is odd (w-1) is even so start at bit number 1 rather than 0 // Get the number of bits in bnWm1 so that it doesn't have to be recomputed // on each iteration. i = (int)(bnWm1->size * RADIX_BITS); // Now find the largest power of 2 that divides w1 for(a = 1; (a < (bnWm1->size * RADIX_BITS)) && (BnTestBit(bnWm1, a) == 0); a++); // 2. m = (w1) / 2^a BnShiftRight(bnM, bnWm1, a); // 3. wlen = len (w). wLen = BnSizeInBits(bnW); // 4. For i = 1 to iterations do for(i = 0; i < iterations; i++) { // 4.1 Obtain a string b of wlen bits from an RBG. // Ensure that 1 < b < w1. // 4.2 If ((b <= 1) or (b >= w1)), then go to step 4.1. while(BnGetRandomBits(bnB, wLen, rand) && ((BnUnsignedCmpWord(bnB, 1) <= 0) || (BnUnsignedCmp(bnB, bnWm1) >= 0))); if(g_inFailureMode) return FALSE; // 4.3 z = b^m mod w. // if ModExp fails, then say this is not // prime and bail out. BnModExp(bnZ, bnB, bnM, bnW); // 4.4 If ((z == 1) or (z = w == 1)), then go to step 4.7. if((BnUnsignedCmpWord(bnZ, 1) == 0) || (BnUnsignedCmp(bnZ, bnWm1) == 0)) goto step4point7; // 4.5 For j = 1 to a 1 do. for(j = 1; j < a; j++) { // 4.5.1 z = z^2 mod w. BnModMult(bnZ, bnZ, bnZ, bnW); // 4.5.2 If (z = w1), then go to step 4.7. if(BnUnsignedCmp(bnZ, bnWm1) == 0) goto step4point7; // 4.5.3 If (z = 1), then go to step 4.6. if(BnEqualWord(bnZ, 1)) goto step4point6; } // 4.6 Return COMPOSITE. step4point6: INSTRUMENT_INC(failedAtIteration[i]); goto end; // 4.7 Continue. Comment: Increment i for the do-loop in step 4. step4point7: continue; } // 5. Return PROBABLY PRIME ret = TRUE; end: return ret; } #if ALG_RSA /* 10.2.14.1.6 RsaCheckPrime() */ /* This will check to see if a number is prime and appropriate for an RSA prime. */ /* This has different functionality based on whether we are using key sieving or not. If not, the number checked to see if it is divisible by the public exponent, then the number is adjusted either up or down in order to make it a better candidate. It is then checked for being probably prime. */ /* If sieving is used, the number is used to root a sieving process. */ TPM_RC RsaCheckPrime( bigNum prime, UINT32 exponent, RAND_STATE *rand ) { #if !RSA_KEY_SIEVE TPM_RC retVal = TPM_RC_SUCCESS; UINT32 modE = BnModWord(prime, exponent); NOT_REFERENCED(rand); if(modE == 0) // evenly divisible so add two keeping the number odd BnAddWord(prime, prime, 2); // want 0 != (p - 1) mod e // which is 1 != p mod e else if(modE == 1) // subtract 2 keeping number odd and insuring that // 0 != (p - 1) mod e BnSubWord(prime, prime, 2); if(BnIsProbablyPrime(prime, rand) == 0) ERROR_RETURN(g_inFailureMode ? TPM_RC_FAILURE : TPM_RC_VALUE); Exit: return retVal; #else return PrimeSelectWithSieve(prime, exponent, rand); #endif } /* * RsaAdjustPrimeCandidate_PreRev155 is the pre-rev.155 algorithm used; we * still have to use it for old seeds to maintain backwards compatibility. */ static void RsaAdjustPrimeCandidate_PreRev155( bigNum prime ) { UINT16 highBytes; crypt_uword_t *msw = &prime->d[prime->size - 1]; #define MASK (MAX_CRYPT_UWORD >> (RADIX_BITS - 16)) highBytes = *msw >> (RADIX_BITS - 16); // This is fixed point arithmetic on 16-bit values highBytes = ((UINT32)highBytes * (UINT32)0x4AFB) >> 16; highBytes += 0xB505; *msw = ((crypt_uword_t)(highBytes) << (RADIX_BITS - 16)) + (*msw & MASK); prime->d[0] |= 1; } /* 10.2.14.1.7 RsaAdjustPrimeCandidate() */ /* For this math, we assume that the RSA numbers are fixed-point numbers with the decimal point to the left of the most significant bit. This approach helps make it clear what is happening with the MSb of the values. The two RSA primes have to be large enough so that their product will be a number with the necessary number of significant bits. For example, we want to be able to multiply two 1024-bit numbers to produce a number with 2048 significant bits. If we accept any 1024-bit prime that has its MSb set, then it is possible to produce a product that does not have the MSb SET. For example, if we use tiny keys of 16 bits and have two 8-bit primes of 0x80, then the public key would be 0x4000 which is only 15-bits. So, what we need to do is made sure that each of the primes is large enough so that the product of the primes is twice as large as each prime. A little arithmetic will show that the only way to do this is to make sure that each of the primes is no less than root(2)/2. That's what this functions does. This function adjusts the candidate prime so that it is odd and >= root(2)/2. This allows the product of these two numbers to be .5, which, in fixed point notation means that the most significant bit is 1. For this routine, the root(2)/2 (0.7071067811865475) approximated with 0xB505 which is, in fixed point, 0.7071075439453125 or an error of 0.000108%. Just setting the upper two bits would give a value > 0.75 which is an error of > 6%. Given the amount of time all the other computations take, reducing the error is not much of a cost, but it isn't totally required either. */ /* This function can be replaced with a function that just sets the two most significant bits of each prime candidate without introducing any computational issues. */ static void RsaAdjustPrimeCandidate_New( bigNum prime ) { UINT32 msw; UINT32 adjusted; // If the radix is 32, the compiler should turn this into a simple assignment msw = prime->d[prime->size - 1] >> ((RADIX_BITS == 64) ? 32 : 0); // Multiplying 0xff...f by 0x4AFB gives 0xff..f - 0xB5050...0 adjusted = (msw >> 16) * 0x4AFB; adjusted += ((msw & 0xFFFF) * 0x4AFB) >> 16; adjusted += 0xB5050000UL; #if RADIX_BITS == 64 // Save the low-order 32 bits prime->d[prime->size - 1] &= 0xFFFFFFFFUL; // replace the upper 32-bits prime->d[prime->size -1] |= ((crypt_uword_t)adjusted << 32); #else prime->d[prime->size - 1] = (crypt_uword_t)adjusted; #endif // make sure the number is odd prime->d[0] |= 1; } LIB_EXPORT void RsaAdjustPrimeCandidate( bigNum prime, SEED_COMPAT_LEVEL seedCompatLevel // IN: compatibility level; libtpms added ) { switch (seedCompatLevel) { case SEED_COMPAT_LEVEL_ORIGINAL: RsaAdjustPrimeCandidate_PreRev155(prime); break; case SEED_COMPAT_LEVEL_LAST: /* case SEED_COMPAT_LEVEL_RSA_PRIME_ADJUST_FIX: */ RsaAdjustPrimeCandidate_New(prime); break; default: FAIL(FATAL_ERROR_INTERNAL); } } /* 10.2.14.1.8 BnGeneratePrimeForRSA() */ /* Function to generate a prime of the desired size with the proper attributes for an RSA prime. */ TPM_RC BnGeneratePrimeForRSA( bigNum prime, // IN/OUT: points to the BN that will get the // random value UINT32 bits, // IN: number of bits to get UINT32 exponent, // IN: the exponent RAND_STATE *rand // IN: the random state ) { BOOL found = FALSE; // // Make sure that the prime is large enough pAssert(prime->allocated >= BITS_TO_CRYPT_WORDS(bits)); // Only try to handle specific sizes of keys in order to save overhead pAssert((bits % 32) == 0); prime->size = BITS_TO_CRYPT_WORDS(bits); while(!found) { // The change below is to make sure that all keys that are generated from the same // seed value will be the same regardless of the endianness or word size of the CPU. // DRBG_Generate(rand, (BYTE *)prime->d, (UINT16)BITS_TO_BYTES(bits));// old // if(g_inFailureMode) // old // libtpms changed begin switch (DRBG_GetSeedCompatLevel(rand)) { case SEED_COMPAT_LEVEL_ORIGINAL: DRBG_Generate(rand, (BYTE *)prime->d, (UINT16)BITS_TO_BYTES(bits)); if (g_inFailureMode) return TPM_RC_FAILURE; break; case SEED_COMPAT_LEVEL_LAST: /* case SEED_COMPAT_LEVEL_RSA_PRIME_ADJUST_FIX: */ if(!BnGetRandomBits(prime, bits, rand)) // new return TPM_RC_FAILURE; break; default: FAIL(FATAL_ERROR_INTERNAL); } RsaAdjustPrimeCandidate(prime, DRBG_GetSeedCompatLevel(rand)); // libtpms changed end found = RsaCheckPrime(prime, exponent, rand) == TPM_RC_SUCCESS; } return TPM_RC_SUCCESS; } #endif // TPM_ALG_RSA libtpms-0.9.3/src/tpm2/crypto/openssl/CryptPrimeSieve.c000066400000000000000000000545771421143571500231340ustar00rootroot00000000000000/********************************************************************************/ /* */ /* CryptPrimeSieve */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CryptPrimeSieve.c 1519 2019-11-15 20:43:51Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ /* 10.2.17 CryptPrimeSieve.c */ /* 10.2.17.1 Includes and defines */ #include "Tpm.h" #if RSA_KEY_SIEVE #include "CryptPrimeSieve_fp.h" /* This determines the number of bits in the largest sieve field. */ #define MAX_FIELD_SIZE 2048 extern const uint32_t s_LastPrimeInTable; extern const uint32_t s_PrimeTableSize; extern const uint32_t s_PrimesInTable; extern const unsigned char s_PrimeTable[]; /* This table is set of prime markers. Each entry is the prime value for the ((n + 1) * 1024) prime. That is, the entry in s_PrimeMarkers[1] is the value for the 2,048th prime. This is used in the PrimeSieve() to adjust the limit for the prime search. When processing smaller prime candidates, fewer primes are checked directly before going to Miller-Rabin. As the prime grows, it is worth spending more time eliminating primes as, a) the density is lower, and b) the cost of Miller-Rabin is higher. */ const uint32_t s_PrimeMarkersCount = 6; const uint32_t s_PrimeMarkers[] = { 8167, 17881, 28183, 38891, 49871, 60961 }; uint32_t primeLimit; /* 10.2.17.1.1 RsaAdjustPrimeLimit() */ /* This used during the sieve process. The iterator for getting the next prime (RsaNextPrime()) will return primes until it hits the limit (primeLimit) set up by this function. This causes the sieve process to stop when an appropriate number of primes have been sieved. */ void RsaAdjustPrimeLimit( uint32_t requestedPrimes ) { if(requestedPrimes == 0 || requestedPrimes > s_PrimesInTable) requestedPrimes = s_PrimesInTable; requestedPrimes = (requestedPrimes - 1) / 1024; if(requestedPrimes < s_PrimeMarkersCount) primeLimit = s_PrimeMarkers[requestedPrimes]; else primeLimit = s_LastPrimeInTable - 2; // libtpms: Fix for 3072 bit keys to avoid mark=5 primeLimit >>= 1; } /* 10.2.17.1.2 RsaNextPrime() */ /* This the iterator used during the sieve process. The input is the last prime returned (or any starting point) and the output is the next higher prime. The function returns 0 when the primeLimit is reached. */ uint32_t RsaNextPrime( uint32_t lastPrime ) { if(lastPrime == 0) return 0; lastPrime >>= 1; for(lastPrime += 1; lastPrime <= primeLimit; lastPrime++) { if(((s_PrimeTable[lastPrime >> 3] >> (lastPrime & 0x7)) & 1) == 1) return ((lastPrime << 1) + 1); } return 0; } /* This table contains a previously sieved table. It has the bits for 3, 5, and 7 removed. Because of the factors, it needs to be aligned to 105 and has a repeat of 105. */ const BYTE seedValues[] = { 0x16, 0x29, 0xcb, 0xa4, 0x65, 0xda, 0x30, 0x6c, 0x99, 0x96, 0x4c, 0x53, 0xa2, 0x2d, 0x52, 0x96, 0x49, 0xcb, 0xb4, 0x61, 0xd8, 0x32, 0x2d, 0x99, 0xa6, 0x44, 0x5b, 0xa4, 0x2c, 0x93, 0x96, 0x69, 0xc3, 0xb0, 0x65, 0x5a, 0x32, 0x4d, 0x89, 0xb6, 0x48, 0x59, 0x26, 0x2d, 0xd3, 0x86, 0x61, 0xcb, 0xb4, 0x64, 0x9a, 0x12, 0x6d, 0x91, 0xb2, 0x4c, 0x5a, 0xa6, 0x0d, 0xc3, 0x96, 0x69, 0xc9, 0x34, 0x25, 0xda, 0x22, 0x65, 0x99, 0xb4, 0x4c, 0x1b, 0x86, 0x2d, 0xd3, 0x92, 0x69, 0x4a, 0xb4, 0x45, 0xca, 0x32, 0x69, 0x99, 0x36, 0x0c, 0x5b, 0xa6, 0x25, 0xd3, 0x94, 0x68, 0x8b, 0x94, 0x65, 0xd2, 0x32, 0x6d, 0x18, 0xb6, 0x4c, 0x4b, 0xa6, 0x29, 0xd1}; #define USE_NIBBLE #ifndef USE_NIBBLE static const BYTE bitsInByte[256] = { 0x00, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x03, 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, 0x05, 0x06, 0x06, 0x07, 0x06, 0x07, 0x07, 0x08 }; #define BitsInByte(x) bitsInByte[(unsigned char)x] #else const BYTE bitsInNibble[16] = { 0x00, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x03, 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04}; #define BitsInByte(x) \ (bitsInNibble[(unsigned char)(x) & 0xf] \ + bitsInNibble[((unsigned char)(x) >> 4) & 0xf]) #endif /* 10.2.17.1.3 BitsInArry() */ /* This function counts the number of bits set in an array of bytes. */ static int BitsInArray( const unsigned char *a, // IN: A pointer to an array of bytes unsigned int aSize // IN: the number of bytes to sum ) { int j = 0; for(; aSize; a++, aSize--) j += BitsInByte(*a); return j; } /* 10.2.17.1.4 FindNthSetBit() */ /* This function finds the nth SET bit in a bit array. The n parameter is between 1 and the number of bits in the array (always a multiple of 8). If called when the array does not have n bits set, it will return -1 */ /* Return Values Meaning */ /* <0 no bit is set or no bit with the requested number is set */ /* >=0 the number of the bit in the array that is the nth set */ int FindNthSetBit( const UINT16 aSize, // IN: the size of the array to check const BYTE *a, // IN: the array to check const UINT32 n // IN, the number of the SET bit ) { UINT16 i; int retValue; UINT32 sum = 0; BYTE sel; //find the bit for(i = 0; (i < (int)aSize) && (sum < n); i++) sum += BitsInByte(a[i]); i--; // The chosen bit is in the byte that was just accessed // Compute the offset to the start of that byte retValue = i * 8 - 1; sel = a[i]; // Subtract the bits in the last byte added. sum -= BitsInByte(sel); // Now process the byte, one bit at a time. for(; (sel != 0) && (sum != n); retValue++, sel = sel >> 1) sum += (sel & 1) != 0; return (sum == n) ? retValue : -1; } typedef struct { UINT16 prime; UINT16 count; } SIEVE_MARKS; const SIEVE_MARKS sieveMarks[5] = { {31, 7}, {73, 5}, {241, 4}, {1621, 3}, {UINT16_MAX, 2}}; /* 10.2.17.1.5 PrimeSieve() */ /* This function does a prime sieve over the input field which has as its starting address the value in bnN. Since this initializes the Sieve using a precomputed field with the bits associated with 3, 5 and 7 already turned off, the value of pnN may need to be adjusted by a few counts to allow the precomputed field to be used without modification. */ /* To get better performance, one could address the issue of developing the composite numbers. When the size of the prime gets large, the time for doing the divisions goes up, noticeably. It could be better to develop larger composite numbers even if they need to be bigNum's themselves. The object would be to reduce the number of times that the large prime is divided into a few large divides and then use smaller divides to get to the final 16 bit (or smaller) remainders. */ UINT32 PrimeSieve( bigNum bnN, // IN/OUT: number to sieve UINT32 fieldSize, // IN: size of the field area in bytes BYTE *field // IN: field ) { UINT32 i; UINT32 j; UINT32 fieldBits = fieldSize * 8; UINT32 r; BYTE *pField; INT32 iter; UINT32 adjust; UINT32 mark = 0; UINT32 count = sieveMarks[0].count; UINT32 stop = sieveMarks[0].prime; UINT32 composite; UINT32 pList[8]; UINT32 next; pAssert(field != NULL && bnN != NULL); // If the remainder is odd, then subtracting the value will give an even number, // but we want an odd number, so subtract the 105+rem. Otherwise, just subtract // the even remainder. adjust = (UINT32)BnModWord(bnN, 105); if(adjust & 1) adjust += 105; // Adjust the input number so that it points to the first number in a // aligned field. BnSubWord(bnN, bnN, adjust); // pAssert(BnModWord(bnN, 105) == 0); pField = field; for(i = fieldSize; i >= sizeof(seedValues); pField += sizeof(seedValues), i -= sizeof(seedValues)) { memcpy(pField, seedValues, sizeof(seedValues)); } if(i != 0) memcpy(pField, seedValues, i); // Cycle through the primes, clearing bits // Have already done 3, 5, and 7 iter = 7; #define NEXT_PRIME(iter) (iter = RsaNextPrime(iter)) // Get the next N primes where N is determined by the mark in the sieveMarks while((composite = NEXT_PRIME(iter)) != 0) { next = 0; i = count; pList[i--] = composite; for(; i > 0; i--) { next = NEXT_PRIME(iter); pList[i] = next; if(next != 0) composite *= next; } // Get the remainder when dividing the base field address // by the composite composite = (UINT32)BnModWord(bnN, composite); // 'composite' is divisible by the composite components. for each of the // composite components, divide 'composite'. That remainder (r) is used to // pick a starting point for clearing the array. The stride is equal to the // composite component. Note, the field only contains odd numbers. If the // field were expanded to contain all numbers, then half of the bits would // have already been cleared. We can save the trouble of clearing them a // second time by having a stride of 2*next. Or we can take all of the even // numbers out of the field and use a stride of 'next' for(i = count; i > 0; i--) { next = pList[i]; if(next == 0) goto done; r = composite % next; // these computations deal with the fact that we have picked a field-sized // range that is aligned to a 105 count boundary. The problem is, this field // only contains odd numbers. If we take our prime guess and walk through all // the numbers using that prime as the 'stride', then every other 'stride' is // going to be an even number. So, we are actually counting by 2 * the stride // We want the count to start on an odd number at the start of our field. That // is, we want to assume that we have counted up to the edge of the field by // the 'stride' and now we are going to start flipping bits in the field as we // continue to count up by 'stride'. If we take the base of our field and // divide by the stride, we find out how much we find out how short the last // count was from reaching the edge of the bit field. Say we get a quotient of // 3 and remainder of 1. This means that after 3 strides, we are 1 short of // the start of the field and the next stride will either land within the // field or step completely over it. The confounding factor is that our field // only contains odd numbers and our stride is actually 2 * stride. If the // quoitent is even, then that means that when we add 2 * stride, we are going // to hit another even number. So, we have to know if we need to back off // by 1 stride before we start counting by 2 * stride. // We can tell from the remainder whether we are on an even or odd // stride when we hit the beginning of the table. If we are on an odd stride // (r & 1), we would start half a stride in (next - r)/2. If we are on an // even stride, we need 0.5 strides (next - r/2) because the table only has // odd numbers. If the remainder happens to be zero, then the start of the // table is on stride so no adjustment is necessary. if(r & 1) j = (next - r) / 2; else if(r == 0) j = 0; else j = next - (r / 2); for(; j < fieldBits; j += next) ClearBit(j, field, fieldSize); } if(next >= stop) { mark++; count = sieveMarks[mark].count; stop = sieveMarks[mark].prime; } } done: INSTRUMENT_INC(totalFieldsSieved[PrimeIndex]); i = BitsInArray(field, fieldSize); INSTRUMENT_ADD(bitsInFieldAfterSieve[PrimeIndex], i); INSTRUMENT_ADD(emptyFieldsSieved[PrimeIndex], (i == 0)); return i; } #ifdef SIEVE_DEBUG static uint32_t fieldSize = 210; /* 10.2.17.1.6 SetFieldSize() */ /* Function to set the field size used for prime generation. Used for tuning. */ uint32_t SetFieldSize( uint32_t newFieldSize ) { if(newFieldSize == 0 || newFieldSize > MAX_FIELD_SIZE) fieldSize = MAX_FIELD_SIZE; else fieldSize = newFieldSize; return fieldSize; } #endif // SIEVE_DEBUG /* 10.2.17.1.7 PrimeSelectWithSieve() */ /* This function will sieve the field around the input prime candidate. If the sieve field is not empty, one of the one bits in the field is chosen for testing with Miller-Rabin. If the value is prime, pnP is updated with this value and the function returns success. If this value is not prime, another pseudo-random candidate is chosen and tested. This process repeats until all values in the field have been checked. If all bits in the field have been checked and none is prime, the function returns FALSE and a new random value needs to be chosen. */ /* Error Returns Meaning */ /* TPM_RC_FAILURE TPM in failure mode, probably due to entropy source */ /* TPM_RC_SUCCESS candidate is probably prime */ /* TPM_RC_NO_RESULT candidate is not prime and couldn't find and alternative in the field */ LIB_EXPORT TPM_RC PrimeSelectWithSieve( bigNum candidate, // IN/OUT: The candidate to filter UINT32 e, // IN: the exponent RAND_STATE *rand // IN: the random number generator state ) { BYTE field[MAX_FIELD_SIZE]; UINT32 first; UINT32 ones; INT32 chosen; BN_PRIME(test); UINT32 modE; #ifndef SIEVE_DEBUG UINT32 fieldSize = MAX_FIELD_SIZE; #endif UINT32 primeSize; // // Adjust the field size and prime table list to fit the size of the prime // being tested. This is done to try to optimize the trade-off between the // dividing done for sieving and the time for Miller-Rabin. When the size // of the prime is large, the cost of Miller-Rabin is fairly high, as is the // cost of the sieving. However, the time for Miller-Rabin goes up considerably // faster than the cost of dividing by a number of primes. primeSize = BnSizeInBits(candidate); if(primeSize <= 512) { RsaAdjustPrimeLimit(1024); // Use just the first 1024 primes } else if(primeSize <= 1024) { RsaAdjustPrimeLimit(4096); // Use just the first 4K primes } else { RsaAdjustPrimeLimit(0); // Use all available } // Save the low-order word to use as a search generator and make sure that // it has some interesting range to it first = (UINT32)(candidate->d[0] | 0x80000000); // Sieve the field ones = PrimeSieve(candidate, fieldSize, field); pAssert(ones > 0 && ones < (fieldSize * 8)); for(; ones > 0; ones--) { // Decide which bit to look at and find its offset chosen = FindNthSetBit((UINT16)fieldSize, field, ((first % ones) + 1)); if((chosen < 0) || (chosen >= (INT32)(fieldSize * 8))) FAIL(FATAL_ERROR_INTERNAL); // Set this as the trial prime BnAddWord(test, candidate, (crypt_uword_t)(chosen * 2)); // The exponent might not have been one of the tested primes so // make sure that it isn't divisible and make sure that 0 != (p-1) mod e // Note: This is the same as 1 != p mod e modE = (UINT32)BnModWord(test, e); if((modE != 0) && (modE != 1) && MillerRabin(test, rand)) { BnCopy(candidate, test); return TPM_RC_SUCCESS; } // Clear the bit just tested ClearBit(chosen, field, fieldSize); } // Ran out of bits and couldn't find a prime in this field INSTRUMENT_INC(noPrimeFields[PrimeIndex]); return (g_inFailureMode ? TPM_RC_FAILURE : TPM_RC_NO_RESULT); } #if RSA_INSTRUMENT static char a[256]; char * PrintTuple( UINT32 *i ) { sprintf(a, "{%d, %d, %d}", i[0], i[1], i[2]); return a; } #define CLEAR_VALUE(x) memset(x, 0, sizeof(x)) void RsaSimulationEnd( void ) { int i; UINT32 averages[3]; UINT32 nonFirst = 0; if((PrimeCounts[0] + PrimeCounts[1] + PrimeCounts[2]) != 0) { printf("Primes generated = %s\n", PrintTuple(PrimeCounts)); printf("Fields sieved = %s\n", PrintTuple(totalFieldsSieved)); printf("Fields with no primes = %s\n", PrintTuple(noPrimeFields)); printf("Primes checked with Miller-Rabin = %s\n", PrintTuple(MillerRabinTrials)); for(i = 0; i < 3; i++) averages[i] = (totalFieldsSieved[i] != 0 ? bitsInFieldAfterSieve[i] / totalFieldsSieved[i] : 0); printf("Average candidates in field %s\n", PrintTuple(averages)); for(i = 1; i < (sizeof(failedAtIteration) / sizeof(failedAtIteration[0])); i++) nonFirst += failedAtIteration[i]; printf("Miller-Rabin failures not in first round = %d\n", nonFirst); } CLEAR_VALUE(PrimeCounts); CLEAR_VALUE(totalFieldsSieved); CLEAR_VALUE(noPrimeFields); CLEAR_VALUE(MillerRabinTrials); CLEAR_VALUE(bitsInFieldAfterSieve); } void GetSieveStats( uint32_t *trials, uint32_t *emptyFields, uint32_t *averageBits ) { uint32_t totalBits; uint32_t fields; *trials = MillerRabinTrials[0] + MillerRabinTrials[1] + MillerRabinTrials[2]; *emptyFields = noPrimeFields[0] + noPrimeFields[1] + noPrimeFields[2]; fields = totalFieldsSieved[0] + totalFieldsSieved[1] + totalFieldsSieved[2]; totalBits = bitsInFieldAfterSieve[0] + bitsInFieldAfterSieve[1] + bitsInFieldAfterSieve[2]; if(fields != 0) *averageBits = totalBits / fields; else *averageBits = 0; CLEAR_VALUE(PrimeCounts); CLEAR_VALUE(totalFieldsSieved); CLEAR_VALUE(noPrimeFields); CLEAR_VALUE(MillerRabinTrials); CLEAR_VALUE(bitsInFieldAfterSieve); } #endif #endif // RSA_KEY_SIEVE #if !RSA_INSTRUMENT //*** RsaSimulationEnd() // Stub for call when not doing instrumentation. #if 0 // libtpms added void RsaSimulationEnd( void ) { return; } #endif // libtpms added #endif libtpms-0.9.3/src/tpm2/crypto/openssl/CryptRand.c000066400000000000000000000772601421143571500217420ustar00rootroot00000000000000/********************************************************************************/ /* */ /* DRBG with a behavior according to SP800-90A */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CryptRand.c 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2021 */ /* */ /********************************************************************************/ #include "Tpm.h" #include "PRNG_TestVectors.h" const BYTE DRBG_NistTestVector_Entropy[] = {DRBG_TEST_INITIATE_ENTROPY}; const BYTE DRBG_NistTestVector_GeneratedInterm[] = {DRBG_TEST_GENERATED_INTERM}; const BYTE DRBG_NistTestVector_EntropyReseed[] = {DRBG_TEST_RESEED_ENTROPY}; const BYTE DRBG_NistTestVector_Generated[] = {DRBG_TEST_GENERATED}; /* 10.2.16.2.2 Derivation Function Defines and Structures */ #define DF_COUNT (DRBG_KEY_SIZE_WORDS / DRBG_IV_SIZE_WORDS + 1) #if DRBG_KEY_SIZE_BITS != 128 && DRBG_KEY_SIZE_BITS != 256 # error "CryptRand.c only written for AES with 128- or 256-bit keys." #endif typedef struct { DRBG_KEY_SCHEDULE keySchedule; DRBG_IV iv[DF_COUNT]; DRBG_IV out1; DRBG_IV buf; int contents; } DF_STATE, *PDF_STATE; /* 10.2.16.2.3 DfCompute() */ /* This function does the incremental update of the derivation function state. It encrypts the iv value and XOR's the results into each of the blocks of the output. This is equivalent to processing all of input data for each output block. */ static void DfCompute( PDF_STATE dfState ) { int i; int iv; crypt_uword_t *pIv; crypt_uword_t temp[DRBG_IV_SIZE_WORDS] = {0}; // for(iv = 0; iv < DF_COUNT; iv++) { pIv = (crypt_uword_t *)&dfState->iv[iv].words[0]; for(i = 0; i < DRBG_IV_SIZE_WORDS; i++) { temp[i] ^= pIv[i] ^ dfState->buf.words[i]; } DRBG_ENCRYPT(&dfState->keySchedule, &temp, pIv); } for(i = 0; i < DRBG_IV_SIZE_WORDS; i++) dfState->buf.words[i] = 0; dfState->contents = 0; } /* 10.2.16.2.4 DfStart() */ /* This initializes the output blocks with an encrypted counter value and initializes the key schedule. */ static void DfStart( PDF_STATE dfState, uint32_t inputLength ) { BYTE init[8]; int i; UINT32 drbgSeedSize = sizeof(DRBG_SEED); const BYTE dfKey[DRBG_KEY_SIZE_BYTES] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f #if DRBG_KEY_SIZE_BYTES > 16 ,0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f #endif }; memset(dfState, 0, sizeof(DF_STATE)); DRBG_ENCRYPT_SETUP(&dfKey[0], DRBG_KEY_SIZE_BITS, &dfState->keySchedule); // Create the first chaining values for(i = 0; i < DF_COUNT; i++) ((BYTE *)&dfState->iv[i])[3] = (BYTE)i; DfCompute(dfState); // initialize the first 64 bits of the IV in a way that doesn't depend // on the size of the words used. UINT32_TO_BYTE_ARRAY(inputLength, init); UINT32_TO_BYTE_ARRAY(drbgSeedSize, &init[4]); memcpy(&dfState->iv[0], init, 8); dfState->contents = 4; } /* 10.2.16.2.5 DfUpdate() */ /* This updates the state with the input data. A byte at a time is moved into the state buffer until it is full and then that block is encrypted by DfCompute(). */ static void DfUpdate( PDF_STATE dfState, int size, const BYTE *data ) { while(size > 0) { int toFill = DRBG_IV_SIZE_BYTES - dfState->contents; if(size < toFill) toFill = size; // Copy as many bytes as there are or until the state buffer is full memcpy(&dfState->buf.bytes[dfState->contents], data, toFill); // Reduce the size left by the amount copied size -= toFill; // Advance the data pointer by the amount copied data += toFill; // increase the buffer contents count by the amount copied dfState->contents += toFill; pAssert(dfState->contents <= DRBG_IV_SIZE_BYTES); // If we have a full buffer, do a computation pass. if(dfState->contents == DRBG_IV_SIZE_BYTES) DfCompute(dfState); } } /* 10.2.16.2.6 DfEnd() */ /* This function is called to get the result of the derivation function computation. If the buffer is not full, it is padded with zeros. The output buffer is structured to be the same as a DRBG_SEED value so that the function can return a pointer to the DRBG_SEED value in the DF_STATE structure. */ static DRBG_SEED * DfEnd( PDF_STATE dfState ) { // Since DfCompute is always called when a buffer is full, there is always // space in the buffer for the terminator dfState->buf.bytes[dfState->contents++] = 0x80; // If the buffer is not full, pad with zeros while(dfState->contents < DRBG_IV_SIZE_BYTES) dfState->buf.bytes[dfState->contents++] = 0; // Do a final state update DfCompute(dfState); return (DRBG_SEED *)&dfState->iv; } /* 10.2.16.2.7 DfBuffer() */ /* Function to take an input buffer and do the derivation function to produce a DRBG_SEED value that can be used in DRBG_Reseed(); */ static DRBG_SEED * DfBuffer( DRBG_SEED *output, // OUT: receives the result int size, // IN: size of the buffer to add BYTE *buf // IN: address of the buffer ) { DF_STATE dfState; if(size == 0 || buf == NULL) return NULL; // Initialize the derivation function DfStart(&dfState, size); DfUpdate(&dfState, size, buf); DfEnd(&dfState); memcpy(output, &dfState.iv[0], sizeof(DRBG_SEED)); return output; } /* 10.2.16.2.8 DRBG_GetEntropy() */ /* Even though this implementation never fails, it may get blocked indefinitely long in the call to get entropy from the platform (DRBG_GetEntropy32()). This function is only used during instantiation of the DRBG for manufacturing and on each start-up after an non-orderly shutdown. */ /* Return Values Meaning */ /* TRUE Requested entropy returned */ /* FALSE Entropy Failure */ BOOL DRBG_GetEntropy( UINT32 requiredEntropy, // IN: requested number of bytes of full // entropy BYTE *entropy // OUT: buffer to return collected entropy ) { #if !USE_DEBUG_RNG UINT32 obtainedEntropy; INT32 returnedEntropy; // If in debug mode, always use the self-test values for initialization if(IsSelfTest()) { #endif // If doing simulated DRBG, then check to see if the // entropyFailure condition is being tested if(!IsEntropyBad())/* This function increments the IV value by 1. It is used by EncryptDRBG(). */ { // In self-test, the caller should be asking for exactly the seed // size of entropy. pAssert(requiredEntropy == sizeof(DRBG_NistTestVector_Entropy)); memcpy(entropy, DRBG_NistTestVector_Entropy, sizeof(DRBG_NistTestVector_Entropy)); } #if !USE_DEBUG_RNG } else if(!IsEntropyBad()) { // Collect entropy // Note: In debug mode, the only "entropy" value ever returned // is the value of the self-test vector. for(returnedEntropy = 1, obtainedEntropy = 0; obtainedEntropy < requiredEntropy && !IsEntropyBad(); obtainedEntropy += returnedEntropy) { returnedEntropy = _plat__GetEntropy(&entropy[obtainedEntropy], requiredEntropy - obtainedEntropy); if(returnedEntropy <= 0) SetEntropyBad(); } } #endif return !IsEntropyBad(); } void IncrementIv( DRBG_IV *iv ) { BYTE *ivP = ((BYTE *)iv) + DRBG_IV_SIZE_BYTES; while((--ivP >= (BYTE *)iv) && ((*ivP = ((*ivP + 1) & 0xFF)) == 0)); } /* 10.2.16.2.10 EncryptDRBG() */ /* This does the encryption operation for the DRBG. It will encrypt the input state counter (IV) using the state key. Into the output buffer for as many times as it takes to generate the required number of bytes. */ static BOOL EncryptDRBG( BYTE *dOut, UINT32 dOutBytes, DRBG_KEY_SCHEDULE *keySchedule, DRBG_IV *iv, UINT32 *lastValue // Points to the last output value ) { #if FIPS_COMPLIANT // For FIPS compliance, the DRBG has to do a continuous self-test to make sure that // no two consecutive values are the same. This overhead is not incurred if the TPM // is not required to be FIPS compliant // UINT32 temp[DRBG_IV_SIZE_BYTES / sizeof(UINT32)]; int i; BYTE *p; for(; dOutBytes > 0;) { // Increment the IV before each encryption (this is what makes this // different from normal counter-mode encryption IncrementIv(iv); DRBG_ENCRYPT(keySchedule, iv, temp); // Expect a 16 byte block #if DRBG_IV_SIZE_BITS != 128 #error "Unsuppored IV size in DRBG" #endif if((lastValue[0] == temp[0]) && (lastValue[1] == temp[1]) && (lastValue[2] == temp[2]) && (lastValue[3] == temp[3]) ) { LOG_FAILURE(FATAL_ERROR_ENTROPY); return FALSE; } lastValue[0] = temp[0]; lastValue[1] = temp[1]; lastValue[2] = temp[2]; lastValue[3] = temp[3]; i = MIN(dOutBytes, DRBG_IV_SIZE_BYTES); dOutBytes -= i; for(p = (BYTE *)temp; i > 0; i--) *dOut++ = *p++; } #else // version without continuous self-test NOT_REFERENCED(lastValue); for(; dOutBytes >= DRBG_IV_SIZE_BYTES; dOut = &dOut[DRBG_IV_SIZE_BYTES], dOutBytes -= DRBG_IV_SIZE_BYTES) { // Increment the IV IncrementIv(iv); DRBG_ENCRYPT(keySchedule, iv, dOut); } // If there is a partial, generate into a block-sized // temp buffer and copy to the output. if(dOutBytes != 0) { BYTE temp[DRBG_IV_SIZE_BYTES]; // Increment the IV IncrementIv(iv); DRBG_ENCRYPT(keySchedule, iv, temp); memcpy(dOut, temp, dOutBytes); } #endif return TRUE; } /* 10.2.16.2.11 DRBG_Update() */ /* This function performs the state update function. According to SP800-90A, a temp value is created by doing CTR mode encryption of providedData and replacing the key and IV with these values. The one difference is that, with counter mode, the IV is incremented after each block is encrypted and in this operation, the counter is incremented before each block is encrypted. This function implements an optimized version of the algorithm in that it does the update of the drbgState->seed in place and then providedData is XORed into drbgState->seed to complete the encryption of providedData. This works because the IV is the last thing that gets encrypted. */ static BOOL DRBG_Update( DRBG_STATE *drbgState, // IN:OUT state to update DRBG_KEY_SCHEDULE *keySchedule, // IN: the key schedule (optional) DRBG_SEED *providedData // IN: additional data ) { UINT32 i; BYTE *temp = (BYTE *)&drbgState->seed; DRBG_KEY *key = pDRBG_KEY(&drbgState->seed); DRBG_IV *iv = pDRBG_IV(&drbgState->seed); DRBG_KEY_SCHEDULE localKeySchedule; memset(&localKeySchedule, 0, sizeof(localKeySchedule)); /* libtpms added: coverity */ // pAssert(drbgState->magic == DRBG_MAGIC); // If an key schedule was not provided, make one if(keySchedule == NULL) { if(DRBG_ENCRYPT_SETUP((BYTE *)key, DRBG_KEY_SIZE_BITS, &localKeySchedule) != 0) { LOG_FAILURE(FATAL_ERROR_INTERNAL); return FALSE; } keySchedule = &localKeySchedule; } // Encrypt the temp value EncryptDRBG(temp, sizeof(DRBG_SEED), keySchedule, iv, drbgState->lastValue); if(providedData != NULL) { BYTE *pP = (BYTE *)providedData; for(i = DRBG_SEED_SIZE_BYTES; i != 0; i--) *temp++ ^= *pP++; } // Since temp points to the input key and IV, we are done and // don't need to copy the resulting 'temp' to drbgState->seed return TRUE; } /* 10.2.16.2.12 DRBG_Reseed() */ /* This function is used when reseeding of the DRBG is required. If entropy is provided, it is used in lieu of using hardware entropy. */ /* NOTE: the provided entropy must be the required size. */ /* Return Values Meaning */ /* TRUE reseed succeeded */ /* FALSE reseed failed, probably due to the entropy generation */ BOOL DRBG_Reseed( DRBG_STATE *drbgState, // IN: the state to update DRBG_SEED *providedEntropy, // IN: entropy DRBG_SEED *additionalData // IN: ) { DRBG_SEED seed; pAssert((drbgState != NULL) && (drbgState->magic == DRBG_MAGIC)); if(providedEntropy == NULL) { providedEntropy = &seed; if(!DRBG_GetEntropy(sizeof(DRBG_SEED), (BYTE *)providedEntropy)) return FALSE; } if(additionalData != NULL) { unsigned int i; // XOR the provided data into the provided entropy for(i = 0; i < sizeof(DRBG_SEED); i++) ((BYTE *)providedEntropy)[i] ^= ((BYTE *)additionalData)[i]; } DRBG_Update(drbgState, NULL, providedEntropy); drbgState->reseedCounter = 1; return TRUE; } /* 10.2.16.2.13 DRBG_SelfTest() */ /* This is run when the DRBG is instantiated and at startup */ /* Return Values Meaning */ /* FALSE test failed */ /* TRUE test OK */ BOOL DRBG_SelfTest( void ) { BYTE buf[sizeof(DRBG_NistTestVector_Generated)]; DRBG_SEED seed; UINT32 i; BYTE *p; DRBG_STATE testState; // pAssert(!IsSelfTest()); SetSelfTest(); SetDrbgTested(); // Do an instantiate if(!DRBG_Instantiate(&testState, 0, NULL)) return FALSE; #if DRBG_DEBUG_PRINT dbgDumpMemBlock(pDRBG_KEY(&testState), DRBG_KEY_SIZE_BYTES, "Key after Instantiate"); dbgDumpMemBlock(pDRBG_IV(&testState), DRBG_IV_SIZE_BYTES, "Value after Instantiate"); #endif if(DRBG_Generate((RAND_STATE *)&testState, buf, sizeof(buf)) == 0) return FALSE; #if DRBG_DEBUG_PRINT dbgDumpMemBlock(pDRBG_KEY(&testState.seed), DRBG_KEY_SIZE_BYTES, "Key after 1st Generate"); dbgDumpMemBlock(pDRBG_IV(&testState.seed), DRBG_IV_SIZE_BYTES, "Value after 1st Generate"); #endif if(memcmp(buf, DRBG_NistTestVector_GeneratedInterm, sizeof(buf)) != 0) return FALSE; memcpy(seed.bytes, DRBG_NistTestVector_EntropyReseed, sizeof(seed)); DRBG_Reseed(&testState, &seed, NULL); #if DRBG_DEBUG_PRINT dbgDumpMemBlock((BYTE *)pDRBG_KEY(&testState.seed), DRBG_KEY_SIZE_BYTES, "Key after 2nd Generate"); dbgDumpMemBlock((BYTE *)pDRBG_IV(&testState.seed), DRBG_IV_SIZE_BYTES, "Value after 2nd Generate"); dbgDumpMemBlock(buf, sizeof(buf), "2nd Generated"); #endif if(DRBG_Generate((RAND_STATE *)&testState, buf, sizeof(buf)) == 0) return FALSE; if(memcmp(buf, DRBG_NistTestVector_Generated, sizeof(buf)) != 0) return FALSE; ClearSelfTest(); DRBG_Uninstantiate(&testState); for(p = (BYTE *)&testState, i = 0; i < sizeof(DRBG_STATE); i++) { if(*p++) return FALSE; } // Simulate hardware failure to make sure that we get an error when // trying to instantiate SetEntropyBad(); if(DRBG_Instantiate(&testState, 0, NULL)) return FALSE; ClearEntropyBad(); return TRUE; } /* 10.2.16.3 Public Interface */ /* 10.2.16.3.1 Description */ /* The functions in this section are the interface to the RNG. These are the functions that are used by TPM.lib. */ /* 10.2.16.3.2 CryptRandomStir() */ /* This function is used to cause a reseed. A DRBG_SEED amount of entropy is collected from the hardware and then additional data is added. */ /* Error Returns Meaning */ /* TPM_RC_NO_RESULT failure of the entropy generator */ LIB_EXPORT TPM_RC CryptRandomStir( UINT16 additionalDataSize, BYTE *additionalData ) { #if !USE_DEBUG_RNG DRBG_SEED tmpBuf; DRBG_SEED dfResult; // // All reseed with outside data starts with a buffer full of entropy if(!DRBG_GetEntropy(sizeof(tmpBuf), (BYTE *)&tmpBuf)) return TPM_RC_NO_RESULT; DRBG_Reseed(&drbgDefault, &tmpBuf, DfBuffer(&dfResult, additionalDataSize, additionalData)); drbgDefault.reseedCounter = 1; return TPM_RC_SUCCESS; #else // If doing debug, use the input data as the initial setting for the RNG state // so that the test can be reset at any time. // Note: If this is called with a data size of 0 or less, nothing happens. The // presumption is that, in a debug environment, the caller will have specific // values for initialization, so this check is just a simple way to prevent // inadvertent programming errors from screwing things up. This doesn't use an // pAssert() because the non-debug version of this function will accept these // parameters as meaning that there is no additionalData and only hardware // entropy is used. if((additionalDataSize > 0) && (additionalData != NULL)) { memset(drbgDefault.seed.bytes, 0, sizeof(drbgDefault.seed.bytes)); memcpy(drbgDefault.seed.bytes, additionalData, MIN(additionalDataSize, sizeof(drbgDefault.seed.bytes))); } drbgDefault.reseedCounter = 1; return TPM_RC_SUCCESS; #endif } /* 10.2.16.3.3 CryptRandomGenerate() */ /* Generate a randomSize number or random bytes. */ LIB_EXPORT UINT16 CryptRandomGenerate( UINT16 randomSize, BYTE *buffer ) { return DRBG_Generate((RAND_STATE *)&drbgDefault, buffer, randomSize); } /* 10.2.16.3.4 DRBG_InstantiateSeededKdf() */ /* Function used to instantiate a KDF-based RNG. This is used for derivations. This function always returns TRUE. */ LIB_EXPORT BOOL DRBG_InstantiateSeededKdf( KDF_STATE *state, // OUT: buffer to hold the state TPM_ALG_ID hashAlg, // IN: hash algorithm TPM_ALG_ID kdf, // IN: the KDF to use TPM2B *seed, // IN: the seed to use const TPM2B *label, // IN: a label for the generation process. TPM2B *context, // IN: the context value UINT32 limit // IN: Maximum number of bits from the KDF ) { state->magic = KDF_MAGIC; state->limit = limit; state->seed = seed; state->hash = hashAlg; state->kdf = kdf; state->label = label; state->context = context; state->digestSize = CryptHashGetDigestSize(hashAlg); state->counter = 0; state->residual.t.size = 0; return TRUE; } /* 10.2.16.3.5 DRBG_AdditionalData() */ /* Function to reseed the DRBG with additional entropy. This is normally called before computing the protection value of a primary key in the Endorsement hierarchy. */ LIB_EXPORT void DRBG_AdditionalData( DRBG_STATE *drbgState, // IN:OUT state to update TPM2B *additionalData // IN: value to incorporate ) { DRBG_SEED dfResult; if(drbgState->magic == DRBG_MAGIC) { DfBuffer(&dfResult, additionalData->size, additionalData->buffer); DRBG_Reseed(drbgState, &dfResult, NULL); } } /* 10.2.16.3.6 DRBG_InstantiateSeeded() */ /* This function is used to instantiate a random number generator from seed values. The nominal use of this generator is to create sequences of pseudo-random numbers from a seed value. */ /* Returns TPM_RC_FAILURE DRBG self-test failure */ LIB_EXPORT TPM_RC DRBG_InstantiateSeeded( DRBG_STATE *drbgState, // IN/OUT: buffer to hold the state const TPM2B *seed, // IN: the seed to use const TPM2B *purpose, // IN: a label for the generation process. const TPM2B *name, // IN: name of the object const TPM2B *additional, // IN: additional data SEED_COMPAT_LEVEL seedCompatLevel // IN: compatibility level; libtpms added ) { DF_STATE dfState; int totalInputSize; // DRBG should have been tested, but... if(!IsDrbgTested() && !DRBG_SelfTest()) { LOG_FAILURE(FATAL_ERROR_SELF_TEST); return TPM_RC_FAILURE; } // Initialize the DRBG state memset(drbgState, 0, sizeof(DRBG_STATE)); drbgState->magic = DRBG_MAGIC; drbgState->seedCompatLevel = seedCompatLevel; // libtpms added // Size all of the values totalInputSize = (seed != NULL) ? seed->size : 0; totalInputSize += (purpose != NULL) ? purpose->size : 0; totalInputSize += (name != NULL) ? name->size : 0; totalInputSize += (additional != NULL) ? additional->size : 0; // Initialize the derivation DfStart(&dfState, totalInputSize); // Run all the input strings through the derivation function if(seed != NULL) DfUpdate(&dfState, seed->size, seed->buffer); if(purpose != NULL) DfUpdate(&dfState, purpose->size, purpose->buffer); if(name != NULL) DfUpdate(&dfState, name->size, name->buffer); if(additional != NULL) DfUpdate(&dfState, additional->size, additional->buffer); // Used the derivation function output as the "entropy" input. This is not // how it is described in SP800-90A but this is the equivalent function DRBG_Reseed(((DRBG_STATE *)drbgState), DfEnd(&dfState), NULL); return TPM_RC_SUCCESS; } /* 10.2.16.3.7 CryptRandStartup() */ /* This function is called when TPM_Startup() is executed. */ /* TRUE instantiation succeeded */ /* kgold */ /* FALSE instantiation failed */ LIB_EXPORT BOOL CryptRandStartup( void ) { #if ! _DRBG_STATE_SAVE // If not saved in NV, re-instantiate on each startup return DRBG_Instantiate(&drbgDefault, 0, NULL); #else // If the running state is saved in NV, NV has to be loaded before it can // be updated if(go.drbgState.magic == DRBG_MAGIC) return DRBG_Reseed(&go.drbgState, NULL, NULL); else return DRBG_Instantiate(&go.drbgState, 0, NULL); #endif } /* 10.2.16.3.8 CryptRandInit() */ /* This function is called when _TPM_Init() is being processed */ LIB_EXPORT BOOL CryptRandInit( void ) { #if !USE_DEBUG_RNG _plat__GetEntropy(NULL, 0); #endif return DRBG_SelfTest(); } // libtpms added begin LIB_EXPORT SEED_COMPAT_LEVEL DRBG_GetSeedCompatLevel( RAND_STATE *state ) { if(state == NULL) { return SEED_COMPAT_LEVEL_LAST; } else if(state->drbg.magic == DRBG_MAGIC) { DRBG_STATE *drbgState = (DRBG_STATE *)state; return drbgState->seedCompatLevel; } else { return SEED_COMPAT_LEVEL_LAST; } } // libtpms added end /* 10.2.16.5 DRBG_Generate() */ /* This function generates a random sequence according SP800-90A. If random is not NULL, then randomSize bytes of random values are generated. If random is NULL or randomSize is zero, then the function returns TRUE without generating any bits or updating the reseed counter. This function returns 0 if a reseed is required. Otherwise, it returns the number of bytes produced which could be less than the number requested if the request is too large.("too large" is implementation dependent.) */ LIB_EXPORT UINT16 DRBG_Generate( RAND_STATE *state, BYTE *random, // OUT: buffer to receive the random values UINT16 randomSize // IN: the number of bytes to generate ) { if(state == NULL) state = (RAND_STATE *)&drbgDefault; if(random == NULL) return 0; // If the caller used a KDF state, generate a sequence from the KDF not to // exceed the limit. if(state->kdf.magic == KDF_MAGIC) { KDF_STATE *kdf = (KDF_STATE *)state; UINT32 counter = (UINT32)kdf->counter; INT32 bytesLeft = randomSize; // If the number of bytes to be returned would put the generator // over the limit, then return 0 if((((kdf->counter * kdf->digestSize) + randomSize) * 8) > kdf->limit) return 0; // Process partial and full blocks until all requested bytes provided while(bytesLeft > 0) { // If there is any residual data in the buffer, copy it to the output // buffer if(kdf->residual.t.size > 0) { INT32 size; // // Don't use more of the residual than will fit or more than are // available size = MIN(kdf->residual.t.size, bytesLeft); // Copy some or all of the residual to the output. The residual is // at the end of the buffer. The residual might be a full buffer. MemoryCopy(random, &kdf->residual.t.buffer [kdf->digestSize - kdf->residual.t.size], size); // Advance the buffer pointer random += size; // Reduce the number of bytes left to get bytesLeft -= size; // And reduce the residual size appropriately kdf->residual.t.size -= (UINT16)size; } else { UINT16 blocks = (UINT16)(bytesLeft / kdf->digestSize); // // Get the number of required full blocks if(blocks > 0) { UINT16 size = blocks * kdf->digestSize; // Get some number of full blocks and put them in the return buffer CryptKDFa(kdf->hash, kdf->seed, kdf->label, kdf->context, NULL, kdf->limit, random, &counter, blocks); // reduce the size remaining to be moved and advance the pointer bytesLeft -= size; random += size; } else { // Fill the residual buffer with a full block and then loop to // top to get part of it copied to the output. kdf->residual.t.size = CryptKDFa(kdf->hash, kdf->seed, kdf->label, kdf->context, NULL, kdf->limit, kdf->residual.t.buffer, &counter, 1); } } } kdf->counter = counter; return randomSize; } else if(state->drbg.magic == DRBG_MAGIC) { DRBG_STATE *drbgState = (DRBG_STATE *)state; DRBG_KEY_SCHEDULE keySchedule; DRBG_SEED *seed = &drbgState->seed; memset(&keySchedule, 0, sizeof(keySchedule)); /* libtpms added: coverity */ if(drbgState->reseedCounter >= CTR_DRBG_MAX_REQUESTS_PER_RESEED) { if(drbgState == &drbgDefault) { DRBG_Reseed(drbgState, NULL, NULL); if(IsEntropyBad() && !IsSelfTest()) return 0; } else { // If this is a PRNG then the only way to get // here is if the SW has run away. LOG_FAILURE(FATAL_ERROR_INTERNAL); return 0; } } // if the allowed number of bytes in a request is larger than the // less than the number of bytes that can be requested, then check #if UINT16_MAX >= CTR_DRBG_MAX_BYTES_PER_REQUEST if(randomSize > CTR_DRBG_MAX_BYTES_PER_REQUEST) randomSize = CTR_DRBG_MAX_BYTES_PER_REQUEST; #endif // Create encryption schedule if(DRBG_ENCRYPT_SETUP((BYTE *)pDRBG_KEY(seed), DRBG_KEY_SIZE_BITS, &keySchedule) != 0) { LOG_FAILURE(FATAL_ERROR_INTERNAL); return 0; } // Generate the random data EncryptDRBG(random, randomSize, &keySchedule, pDRBG_IV(seed), drbgState->lastValue); // Do a key update DRBG_Update(drbgState, &keySchedule, NULL); // Increment the reseed counter drbgState->reseedCounter += 1; } else { LOG_FAILURE(FATAL_ERROR_INTERNAL); return 0; // libtpms changed from FALSE } return randomSize; } /* 10.2.16.6 DRBG_Instantiate() */ /* This is CTR_DRBG_Instantiate_algorithm() from [SP 800-90A 10.2.1.3.1]. This is called when a the TPM DRBG is to be instantiated. This is called to instantiate a DRBG used by the TPM for normal operations. */ /* Return Values Meaning */ /* TRUE instantiation succeeded */ /* FALSE instantiation failed */ LIB_EXPORT BOOL DRBG_Instantiate( DRBG_STATE *drbgState, // OUT: the instantiated value UINT16 pSize, // IN: Size of personalization string BYTE *personalization // IN: The personalization string ) { DRBG_SEED seed; DRBG_SEED dfResult; // pAssert((pSize == 0) || (pSize <= sizeof(seed)) || (personalization != NULL)); // If the DRBG has not been tested, test when doing an instantiation. Since // Instantiation is called during self test, make sure we don't get stuck in a // loop. if(!IsDrbgTested() && !IsSelfTest() && !DRBG_SelfTest()) return FALSE; // If doing a self test, DRBG_GetEntropy will return the NIST // test vector value. if(!DRBG_GetEntropy(sizeof(seed), (BYTE *)&seed)) return FALSE; // set everything to zero memset(drbgState, 0, sizeof(DRBG_STATE)); drbgState->magic = DRBG_MAGIC; // Steps 1, 2, 3, 6, 7 of SP 800-90A 10.2.1.3.1 are exactly what // reseeding does. So, do a reduction on the personalization value (if any) // and do a reseed. DRBG_Reseed(drbgState, &seed, DfBuffer(&dfResult, pSize, personalization)); return TRUE; } /* 10.2.16.7 DRBG_Uninstantiate() */ /* This is Uninstantiate_function() from [SP 800-90A 9.4]. */ /* Error Returns Meaning */ /* TPM_RC_VALUE not a valid state */ LIB_EXPORT TPM_RC DRBG_Uninstantiate( DRBG_STATE *drbgState // IN/OUT: working state to erase ) { if((drbgState == NULL) || (drbgState->magic != DRBG_MAGIC)) return TPM_RC_VALUE; memset(drbgState, 0, sizeof(DRBG_STATE)); return TPM_RC_SUCCESS; } libtpms-0.9.3/src/tpm2/crypto/openssl/CryptRsa.c000066400000000000000000001664051421143571500216030ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Implementation of cryptographic primitives for RSA */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CryptRsa.c 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2021 */ /* */ /********************************************************************************/ /* 10.2.17 CryptRsa.c */ /* 10.2.17.1 Introduction */ /* This file contains implementation of cryptographic primitives for RSA. Vendors may replace the implementation in this file with their own library functions. */ /* 10.2.17.2 Includes */ /* Need this define to get the private defines for this function */ #define CRYPT_RSA_C #include "Tpm.h" #include "Helpers_fp.h" // libtpms added #include // libtpms added #if ALG_RSA /* 10.2.17.3 Obligatory Initialization Functions */ /* 10.2.17.3.1 CryptRsaInit() */ /* Function called at _TPM_Init(). */ BOOL CryptRsaInit( void ) { return TRUE; } /* 10.2.17.3.2 CryptRsaStartup() */ /* Function called at TPM2_Startup() */ BOOL CryptRsaStartup( void ) { return TRUE; } /* 10.2.17.4 Internal Functions */ void RsaInitializeExponent( privateExponent_t *pExp ) { #if CRT_FORMAT_RSA == NO BN_INIT(pExp->D); #else BN_INIT(pExp->Q); BN_INIT(pExp->dP); BN_INIT(pExp->dQ); BN_INIT(pExp->qInv); #endif } /* 10.2.17.4.1 ComputePrivateExponent() */ /* This function computes the private exponent from the primes. */ /* Return Value Meaning */ /* TRUE(1) success */ /* FALSE(0) failure */ static BOOL ComputePrivateExponent( bigNum P, // IN: first prime (size is 1/2 of bnN) bigNum Q, // IN: second prime (size is 1/2 of bnN) bigNum E, // IN: the public exponent bigNum N, // IN: the public modulus privateExponent_t *pExp // OUT: ) { BOOL pOK; BOOL qOK; #if CRT_FORMAT_RSA == NO BN_RSA(bnPhi); // RsaInitializeExponent(pExp); // Get compute Phi = (p - 1)(q - 1) = pq - p - q + 1 = n - p - q + 1 pOK = BnCopy(bnPhi, N); pOK = pOK && BnSub(bnPhi, bnPhi, P); pOK = pOK && BnSub(bnPhi, bnPhi, Q); pOK = pOK && BnAddWord(bnPhi, bnPhi, 1); // Compute the multiplicative inverse d = 1/e mod Phi pOK = pOK && BnModInverse((bigNum)&pExp->D, E, bnPhi); qOK = pOK; #else BN_PRIME(temp); bigNum pT; // NOT_REFERENCED(N); RsaInitializeExponent(pExp); BnCopy((bigNum)&pExp->Q, Q); // make p the larger value so that m2 is always less than p if(BnUnsignedCmp(P, Q) < 0) { pT = P; P = Q; Q = pT; } //dP = (1/e) mod (p-1) = d mod (p-1) pOK = BnSubWord(temp, P, 1); pOK = pOK && BnModInverse((bigNum)&pExp->dP, E, temp); //dQ = (1/e) mod (q-1) = d mod (q-1) qOK = BnSubWord(temp, Q, 1); qOK = qOK && BnModInverse((bigNum)&pExp->dQ, E, temp); // qInv = (1/q) mod p if(pOK && qOK) pOK = qOK = BnModInverse((bigNum)&pExp->qInv, Q, P); #endif if(!pOK) BnSetWord(P, 0); if(!qOK) BnSetWord(Q, 0); return pOK && qOK; } /* 10.2.17.4.2 RsaPrivateKeyOp() */ /* This function is called to do the exponentiation with the private key. Compile options allow use of the simple (but slow) private exponent, or the more complex but faster CRT method. */ /* Return Value Meaning */ /* TRUE(1) success */ /* FALSE(0) failure */ static BOOL RsaPrivateKeyOp( bigNum inOut, // IN/OUT: number to be exponentiated bigNum N, // IN: public modulus (can be NULL if CRT) bigNum P, // IN: one of the primes (can be NULL if not CRT) privateExponent_t *pExp ) { BOOL OK; #if CRT_FORMAT_RSA == NO (P); OK = BnModExp(inOut, inOut, (bigNum)&pExp->D, N); #else BN_RSA(M1); BN_RSA(M2); BN_RSA(M); BN_RSA(H); bigNum Q = (bigNum)&pExp->Q; NOT_REFERENCED(N); // Make P the larger prime. // NOTE that when the CRT form of the private key is created, dP will always // be computed using the larger of p and q so the only thing needed here is that // the primes be selected so that they agree with dP. if(BnUnsignedCmp(P, Q) < 0) { bigNum T = P; P = Q; Q = T; } // m1 = cdP mod p OK = BnModExp(M1, inOut, (bigNum)&pExp->dP, P); // m2 = cdQ mod q OK = OK && BnModExp(M2, inOut, (bigNum)&pExp->dQ, Q); // h = qInv * (m1 - m2) mod p = qInv * (m1 + P - m2) mod P because Q < P // so m2 < P OK = OK && BnSub(H, P, M2); OK = OK && BnAdd(H, H, M1); OK = OK && BnModMult(H, H, (bigNum)&pExp->qInv, P); // m = m2 + h * q OK = OK && BnMult(M, H, Q); OK = OK && BnAdd(inOut, M2, M); #endif return OK; } /* 10.2.17.4.3 RSAEP() */ /* This function performs the RSAEP operation defined in PKCS#1v2.1. It is an exponentiation of a value (m) with the public exponent (e), modulo the public (n). */ /* Error Returns Meaning */ /* TPM_RC_VALUE number to exponentiate is larger than the modulus */ #if !USE_OPENSSL_FUNCTIONS_RSA // libtpms added static TPM_RC RSAEP( TPM2B *dInOut, // IN: size of the encrypted block and the size of // the encrypted value. It must be the size of // the modulus. // OUT: the encrypted data. Will receive the // decrypted value OBJECT *key // IN: the key to use ) { TPM2B_TYPE(4BYTES, 4); TPM2B_4BYTES(e) = {{4, {(BYTE)((RSA_DEFAULT_PUBLIC_EXPONENT >> 24) & 0xff), (BYTE)((RSA_DEFAULT_PUBLIC_EXPONENT >> 16) & 0xff), (BYTE)((RSA_DEFAULT_PUBLIC_EXPONENT >> 8) & 0xff), (BYTE)((RSA_DEFAULT_PUBLIC_EXPONENT)& 0xff)}}}; // if(key->publicArea.parameters.rsaDetail.exponent != 0) UINT32_TO_BYTE_ARRAY(key->publicArea.parameters.rsaDetail.exponent, e.t.buffer); return ModExpB(dInOut->size, dInOut->buffer, dInOut->size, dInOut->buffer, e.t.size, e.t.buffer, key->publicArea.unique.rsa.t.size, key->publicArea.unique.rsa.t.buffer); } /* 10.2.17.4.4 RSADP() */ /* This function performs the RSADP operation defined in PKCS#1v2.1. It is an exponentiation of a value (c) with the private exponent (d), modulo the public modulus (n). The decryption is in place. */ /* This function also checks the size of the private key. If the size indicates that only a prime value is present, the key is converted to being a private exponent. */ /* Error Returns Meaning */ /* TPM_RC_SIZE the value to decrypt is larger than the modulus */ static TPM_RC RSADP( TPM2B *inOut, // IN/OUT: the value to encrypt OBJECT *key // IN: the key ) { BN_RSA_INITIALIZED(bnM, inOut); BN_RSA_INITIALIZED(bnN, &key->publicArea.unique.rsa); BN_RSA_INITIALIZED(bnP, &key->sensitive.sensitive.rsa); if(BnUnsignedCmp(bnM, bnN) >= 0) return TPM_RC_SIZE; // private key operation requires that private exponent be loaded // During self-test, this might not be the case so load it up if it hasn't // already done // been done if(!key->attributes.privateExp) CryptRsaLoadPrivateExponent(key); if(!RsaPrivateKeyOp(bnM, bnN, bnP, &key->privateExponent)) FAIL(FATAL_ERROR_INTERNAL); BnTo2B(bnM, inOut, inOut->size); return TPM_RC_SUCCESS; } /* 10.2.17.4.5 OaepEncode() */ /* This function performs OAEP padding. The size of the buffer to receive the OAEP padded data must equal the size of the modulus */ /* Error Returns Meaning */ /* TPM_RC_VALUE hashAlg is not valid or message size is too large */ static TPM_RC OaepEncode( TPM2B *padded, // OUT: the pad data TPM_ALG_ID hashAlg, // IN: algorithm to use for padding const TPM2B *label, // IN: null-terminated string (may be NULL) TPM2B *message, // IN: the message being padded RAND_STATE *rand // IN: the random number generator to use ) { INT32 padLen; INT32 dbSize; INT32 i; BYTE mySeed[MAX_DIGEST_SIZE]; BYTE *seed = mySeed; UINT16 hLen = CryptHashGetDigestSize(hashAlg); BYTE mask[MAX_RSA_KEY_BYTES]; BYTE *pp; BYTE *pm; TPM_RC retVal = TPM_RC_SUCCESS; pAssert(padded != NULL && message != NULL); // A value of zero is not allowed because the KDF can't produce a result // if the digest size is zero. if(hLen == 0) return TPM_RC_VALUE; // Basic size checks // make sure digest isn't too big for key size if(padded->size < (2 * hLen) + 2) ERROR_RETURN(TPM_RC_HASH); // and that message will fit messageSize <= k - 2hLen - 2 if(message->size > (padded->size - (2 * hLen) - 2)) ERROR_RETURN(TPM_RC_VALUE); // Hash L even if it is null // Offset into padded leaving room for masked seed and byte of zero pp = &padded->buffer[hLen + 1]; if(CryptHashBlock(hashAlg, label->size, (BYTE *)label->buffer, hLen, pp) != hLen) ERROR_RETURN(TPM_RC_FAILURE); // concatenate PS of k mLen 2hLen 2 padLen = padded->size - message->size - (2 * hLen) - 2; MemorySet(&pp[hLen], 0, padLen); pp[hLen + padLen] = 0x01; padLen += 1; memcpy(&pp[hLen + padLen], message->buffer, message->size); // The total size of db = hLen + pad + mSize; dbSize = hLen + padLen + message->size; // If testing, then use the provided seed. Otherwise, use values // from the RNG CryptRandomGenerate(hLen, mySeed); DRBG_Generate(rand, mySeed, (UINT16)hLen); // mask = MGF1 (seed, nSize hLen 1) CryptMGF_KDF(dbSize, mask, hashAlg, hLen, seed, 0); // Create the masked db pm = mask; for(i = dbSize; i > 0; i--) *pp++ ^= *pm++; pp = &padded->buffer[hLen + 1]; // Run the masked data through MGF1 if(CryptMGF_KDF(hLen, &padded->buffer[1], hashAlg, dbSize, pp, 0) != (unsigned)hLen) ERROR_RETURN(TPM_RC_VALUE); // Now XOR the seed to create masked seed pp = &padded->buffer[1]; pm = seed; for(i = hLen; i > 0; i--) *pp++ ^= *pm++; // Set the first byte to zero padded->buffer[0] = 0x00; Exit: return retVal; } /* 10.2.17.4.6 OaepDecode() */ /* This function performs OAEP padding checking. The size of the buffer to receive the recovered data. If the padding is not valid, the dSize size is set to zero and the function returns TPM_RC_VALUE. */ /* The dSize parameter is used as an input to indicate the size available in the buffer. If insufficient space is available, the size is not changed and the return code is TPM_RC_VALUE. */ /* Error Returns Meaning */ /* TPM_RC_VALUE the value to decode was larger than the modulus, or the padding is wrong or the buffer to receive the results is too small */ static TPM_RC OaepDecode( TPM2B *dataOut, // OUT: the recovered data TPM_ALG_ID hashAlg, // IN: algorithm to use for padding const TPM2B *label, // IN: null-terminated string (may be NULL) TPM2B *padded // IN: the padded data ) { UINT32 i; BYTE seedMask[MAX_DIGEST_SIZE]; UINT32 hLen = CryptHashGetDigestSize(hashAlg); BYTE mask[MAX_RSA_KEY_BYTES]; BYTE *pp; BYTE *pm; TPM_RC retVal = TPM_RC_SUCCESS; // Strange size (anything smaller can't be an OAEP padded block) // Also check for no leading 0 if((padded->size < (unsigned)((2 * hLen) + 2)) || (padded->buffer[0] != 0)) ERROR_RETURN(TPM_RC_VALUE); // Use the hash size to determine what to put through MGF1 in order // to recover the seedMask CryptMGF_KDF(hLen, seedMask, hashAlg, padded->size - hLen - 1, &padded->buffer[hLen + 1], 0); // Recover the seed into seedMask pAssert(hLen <= sizeof(seedMask)); pp = &padded->buffer[1]; pm = seedMask; for(i = hLen; i > 0; i--) *pm++ ^= *pp++; // Use the seed to generate the data mask CryptMGF_KDF(padded->size - hLen - 1, mask, hashAlg, hLen, seedMask, 0); // Use the mask generated from seed to recover the padded data pp = &padded->buffer[hLen + 1]; pm = mask; for(i = (padded->size - hLen - 1); i > 0; i--) *pm++ ^= *pp++; // Make sure that the recovered data has the hash of the label // Put trial value in the seed mask if((CryptHashBlock(hashAlg, label->size, (BYTE *)label->buffer, hLen, seedMask)) != hLen) FAIL(FATAL_ERROR_INTERNAL); if(memcmp(seedMask, mask, hLen) != 0) ERROR_RETURN(TPM_RC_VALUE); // find the start of the data pm = &mask[hLen]; for(i = (UINT32)padded->size - (2 * hLen) - 1; i > 0; i--) { if(*pm++ != 0) break; } // If we ran out of data or didn't end with 0x01, then return an error if(i == 0 || pm[-1] != 0x01) ERROR_RETURN(TPM_RC_VALUE); // pm should be pointing at the first part of the data // and i is one greater than the number of bytes to move i--; if(i > dataOut->size) // Special exit to preserve the size of the output buffer return TPM_RC_VALUE; memcpy(dataOut->buffer, pm, i); dataOut->size = (UINT16)i; Exit: if(retVal != TPM_RC_SUCCESS) dataOut->size = 0; return retVal; } /* 10.2.17.4.7 PKCS1v1_5Encode() */ /* This function performs the encoding for RSAES-PKCS1-V1_5-ENCRYPT as defined in PKCS#1V2.1 */ /* Error Returns Meaning */ /* TPM_RC_VALUE message size is too large */ static TPM_RC RSAES_PKCS1v1_5Encode( TPM2B *padded, // OUT: the pad data TPM2B *message, // IN: the message being padded RAND_STATE *rand ) { UINT32 ps = padded->size - message->size - 3; // if(message->size > padded->size - 11) return TPM_RC_VALUE; // move the message to the end of the buffer memcpy(&padded->buffer[padded->size - message->size], message->buffer, message->size); // Set the first byte to 0x00 and the second to 0x02 padded->buffer[0] = 0; padded->buffer[1] = 2; // Fill with random bytes DRBG_Generate(rand, &padded->buffer[2], (UINT16)ps); // Set the delimiter for the random field to 0 padded->buffer[2 + ps] = 0; // Now, the only messy part. Make sure that all the 'ps' bytes are non-zero // In this implementation, use the value of the current index for(ps++; ps > 1; ps--) { if(padded->buffer[ps] == 0) padded->buffer[ps] = 0x55; // In the < 0.5% of the cases that the // random value is 0, just pick a value to // put into the spot. } return TPM_RC_SUCCESS; } /* 10.2.17.4.8 RSAES_Decode() */ /* This function performs the decoding for RSAES-PKCS1-V1_5-ENCRYPT as defined in PKCS#1V2.1 */ /* Error Returns Meaning */ /* TPM_RC_FAIL decoding error or results would no fit into provided buffer */ static TPM_RC RSAES_Decode( TPM2B *message, // OUT: the recovered message TPM2B *coded // IN: the encoded message ) { BOOL fail = FALSE; UINT16 pSize; fail = (coded->size < 11); fail = (coded->buffer[0] != 0x00) | fail; fail = (coded->buffer[1] != 0x02) | fail; for(pSize = 2; pSize < coded->size; pSize++) { if(coded->buffer[pSize] == 0) break; } pSize++; // Make sure that pSize has not gone over the end and that there are at least 8 // bytes of pad data. fail = (pSize > coded->size) | fail; fail = ((pSize - 2) <= 8) | fail; if((message->size < (UINT16)(coded->size - pSize)) || fail) return TPM_RC_VALUE; message->size = coded->size - pSize; memcpy(message->buffer, &coded->buffer[pSize], coded->size - pSize); return TPM_RC_SUCCESS; } #endif // libtpms added /* 10.2.17.4.13 CryptRsaPssSaltSize() */ /* This function computes the salt size used in PSS. It is broken out so that the X509 code can get the same value that is used by the encoding function in this module. */ INT16 CryptRsaPssSaltSize( INT16 hashSize, INT16 outSize ) { INT16 saltSize; // // (Mask Length) = (outSize - hashSize - 1); // Max saltSize is (Mask Length) - 1 saltSize = (outSize - hashSize - 1) - 1; // Use the maximum salt size allowed by FIPS 186-4 if (saltSize > hashSize) saltSize = hashSize; else if (saltSize < 0) saltSize = 0; return saltSize; } #if !USE_OPENSSL_FUNCTIONS_RSA // libtpms added /* 10.2.17.4.9 PssEncode() */ /* This function creates an encoded block of data that is the size of modulus. The function uses the maximum salt size that will fit in the encoded block. */ /* Returns TPM_RC_SUCCESS or goes into failure mode. */ static TPM_RC PssEncode( TPM2B *out, // OUT: the encoded buffer TPM_ALG_ID hashAlg, // IN: hash algorithm for the encoding TPM2B *digest, // IN: the digest RAND_STATE *rand // IN: random number source ) { UINT32 hLen = CryptHashGetDigestSize(hashAlg); BYTE salt[MAX_RSA_KEY_BYTES - 1]; UINT16 saltSize; BYTE *ps = salt; BYTE *pOut; UINT16 mLen; HASH_STATE hashState; // These are fatal errors indicating bad TPM firmware pAssert(out != NULL && hLen > 0 && digest != NULL); // Get the size of the mask mLen = (UINT16)(out->size - hLen - 1); // Maximum possible salt size is mask length - 1 saltSize = mLen - 1; // Use the maximum salt size allowed by FIPS 186-4 if(saltSize > hLen) saltSize = (UINT16)hLen; //using eOut for scratch space // Set the first 8 bytes to zero pOut = out->buffer; memset(pOut, 0, 8); // Get set the salt DRBG_Generate(rand, salt, saltSize); // Create the hash of the pad || input hash || salt CryptHashStart(&hashState, hashAlg); CryptDigestUpdate(&hashState, 8, pOut); CryptDigestUpdate2B(&hashState, digest); CryptDigestUpdate(&hashState, saltSize, salt); CryptHashEnd(&hashState, hLen, &pOut[out->size - hLen - 1]); // Create a mask if(CryptMGF_KDF(mLen, pOut, hashAlg, hLen, &pOut[mLen], 0) != mLen) FAIL(FATAL_ERROR_INTERNAL); // Since this implementation uses key sizes that are all even multiples of // 8, just need to make sure that the most significant bit is CLEAR *pOut &= 0x7f; // Before we mess up the pOut value, set the last byte to 0xbc pOut[out->size - 1] = 0xbc; // XOR a byte of 0x01 at the position just before where the salt will be XOR'ed pOut = &pOut[mLen - saltSize - 1]; *pOut++ ^= 0x01; // XOR the salt data into the buffer for(; saltSize > 0; saltSize--) *pOut++ ^= *ps++; // and we are done return TPM_RC_SUCCESS; } /* 10.2.17.4.10 PssDecode() */ /* This function checks that the PSS encoded block was built from the provided digest. If the check is successful, TPM_RC_SUCCESS is returned. Any other value indicates an error. */ /* This implementation of PSS decoding is intended for the reference TPM implementation and is not at all generalized. It is used to check signatures over hashes and assumptions are made about the sizes of values. Those assumptions are enforce by this implementation. This implementation does allow for a variable size salt value to have been used by the creator of the signature. */ /* Error Returns Meaning */ /* TPM_RC_SCHEME hashAlg is not a supported hash algorithm */ /* TPM_RC_VALUE decode operation failed */ static TPM_RC PssDecode( TPM_ALG_ID hashAlg, // IN: hash algorithm to use for the encoding TPM2B *dIn, // In: the digest to compare TPM2B *eIn // IN: the encoded data ) { UINT32 hLen = CryptHashGetDigestSize(hashAlg); BYTE mask[MAX_RSA_KEY_BYTES]; BYTE *pm = mask; BYTE *pe; BYTE pad[8] = {0}; UINT32 i; UINT32 mLen; BYTE fail; TPM_RC retVal = TPM_RC_SUCCESS; HASH_STATE hashState; // These errors are indicative of failures due to programmer error pAssert(dIn != NULL && eIn != NULL); pe = eIn->buffer; // check the hash scheme if(hLen == 0) ERROR_RETURN(TPM_RC_SCHEME); // most significant bit must be zero fail = pe[0] & 0x80; // last byte must be 0xbc fail |= pe[eIn->size - 1] ^ 0xbc; // Use the hLen bytes at the end of the buffer to generate a mask // Doesn't start at the end which is a flag byte mLen = eIn->size - hLen - 1; CryptMGF_KDF(mLen, mask, hashAlg, hLen, &pe[mLen], 0); // Clear the MSO of the mask to make it consistent with the encoding. mask[0] &= 0x7F; pAssert(mLen <= sizeof(mask)); // XOR the data into the mask to recover the salt. This sequence // advances eIn so that it will end up pointing to the seed data // which is the hash of the signature data for(i = mLen; i > 0; i--) *pm++ ^= *pe++; // Find the first byte of 0x01 after a string of all 0x00 for(pm = mask, i = mLen; i > 0; i--) { if(*pm == 0x01) break; else fail |= *pm++; } // i should not be zero fail |= (i == 0); // if we have failed, will continue using the entire mask as the salt value so // that the timing attacks will not disclose anything (I don't think that this // is a problem for TPM applications but, usually, we don't fail so this // doesn't cost anything). if(fail) { i = mLen; pm = mask; } else { pm++; i--; } // i contains the salt size and pm points to the salt. Going to use the input // hash and the seed to recreate the hash in the lower portion of eIn. CryptHashStart(&hashState, hashAlg); // add the pad of 8 zeros CryptDigestUpdate(&hashState, 8, pad); // add the provided digest value CryptDigestUpdate(&hashState, dIn->size, dIn->buffer); // and the salt CryptDigestUpdate(&hashState, i, pm); // get the result fail |= (CryptHashEnd(&hashState, hLen, mask) != hLen); // Compare all bytes for(pm = mask; hLen > 0; hLen--) // don't use fail = because that could skip the increment and compare // operations after the first failure and that gives away timing // information. fail |= *pm++ ^ *pe++; retVal = (fail != 0) ? TPM_RC_VALUE : TPM_RC_SUCCESS; Exit: return retVal; } /* 10.2.17.4.16 MakeDerTag() */ /* Construct the DER value that is used in RSASSA */ /* Return Value Meaning */ /* > 0 size of value */ /* <= 0 no hash exists */ INT16 MakeDerTag( TPM_ALG_ID hashAlg, INT16 sizeOfBuffer, BYTE *buffer ) { // 0x30, 0x31, // SEQUENCE (2 elements) 1st // 0x30, 0x0D, // SEQUENCE (2 elements) // 0x06, 0x09, // HASH OID // 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, // 0x05, 0x00, // NULL // 0x04, 0x20 // OCTET STRING HASH_DEF *info = CryptGetHashDef(hashAlg); INT16 oidSize; // If no OID, can't do encode VERIFY(info != NULL); oidSize = 2 + (info->OID)[1]; // make sure this fits in the buffer VERIFY(sizeOfBuffer >= (oidSize + 8)); *buffer++ = 0x30; // 1st SEQUENCE // Size of the 1st SEQUENCE is 6 bytes + size of the hash OID + size of the // digest size *buffer++ = (BYTE)(6 + oidSize + info->digestSize); // *buffer++ = 0x30; // 2nd SEQUENCE // size is 4 bytes of overhead plus the side of the OID *buffer++ = (BYTE)(2 + oidSize); MemoryCopy(buffer, info->OID, oidSize); buffer += oidSize; *buffer++ = 0x05; // Add a NULL *buffer++ = 0x00; *buffer++ = 0x04; *buffer++ = (BYTE)(info->digestSize); return oidSize + 8; Error: return 0; } /* 10.2.17.4.17 RSASSA_Encode() */ /* Encode a message using PKCS1v1.5 method. */ /* Error Returns Meaning */ /* TPM_RC_SCHEME hashAlg is not a supported hash algorithm */ /* TPM_RC_SIZE eOutSize is not large enough */ /* TPM_RC_VALUE hInSize does not match the digest size of hashAlg */ static TPM_RC RSASSA_Encode( TPM2B *pOut, // IN:OUT on in, the size of the public key // on out, the encoded area TPM_ALG_ID hashAlg, // IN: hash algorithm for PKCS1v1_5 TPM2B *hIn // IN: digest value to encode ) { BYTE DER[20]; BYTE *der = DER; INT32 derSize = MakeDerTag(hashAlg, sizeof(DER), DER); BYTE *eOut; INT32 fillSize; TPM_RC retVal = TPM_RC_SUCCESS; // Can't use this scheme if the algorithm doesn't have a DER string defined. if(derSize == 0) ERROR_RETURN(TPM_RC_SCHEME); // If the digest size of 'hashAl' doesn't match the input digest size, then // the DER will misidentify the digest so return an error if(CryptHashGetDigestSize(hashAlg) != hIn->size) ERROR_RETURN(TPM_RC_VALUE); fillSize = pOut->size - derSize - hIn->size - 3; eOut = pOut->buffer; // Make sure that this combination will fit in the provided space if(fillSize < 8) ERROR_RETURN(TPM_RC_SIZE); // Start filling *eOut++ = 0; // initial byte of zero *eOut++ = 1; // byte of 0x01 for(; fillSize > 0; fillSize--) *eOut++ = 0xff; // bunch of 0xff *eOut++ = 0; // another 0 for(; derSize > 0; derSize--) *eOut++ = *der++; // copy the DER der = hIn->buffer; for(fillSize = hIn->size; fillSize > 0; fillSize--) *eOut++ = *der++; // copy the hash Exit: return retVal; } /* 10.2.17.4.18 RSASSA_Decode() */ /* This function performs the RSASSA decoding of a signature. */ /* Error Returns Meaning */ /* TPM_RC_VALUE decode unsuccessful */ /* TPM_RC_SCHEME haslAlg is not supported */ static TPM_RC RSASSA_Decode( TPM_ALG_ID hashAlg, // IN: hash algorithm to use for the encoding TPM2B *hIn, // In: the digest to compare TPM2B *eIn // IN: the encoded data ) { BYTE fail; BYTE DER[20]; BYTE *der = DER; INT32 derSize = MakeDerTag(hashAlg, sizeof(DER), DER); BYTE *pe; INT32 hashSize = CryptHashGetDigestSize(hashAlg); INT32 fillSize; TPM_RC retVal; BYTE *digest; UINT16 digestSize; pAssert(hIn != NULL && eIn != NULL); pe = eIn->buffer; // Can't use this scheme if the algorithm doesn't have a DER string // defined or if the provided hash isn't the right size if(derSize == 0 || (unsigned)hashSize != hIn->size) ERROR_RETURN(TPM_RC_SCHEME); // Make sure that this combination will fit in the provided space // Since no data movement takes place, can just walk though this // and accept nearly random values. This can only be called from // CryptValidateSignature() so eInSize is known to be in range. fillSize = eIn->size - derSize - hashSize - 3; // Start checking (fail will become non-zero if any of the bytes do not have // the expected value. fail = *pe++; // initial byte of zero fail |= *pe++ ^ 1; // byte of 0x01 for(; fillSize > 0; fillSize--) fail |= *pe++ ^ 0xff; // bunch of 0xff fail |= *pe++; // another 0 for(; derSize > 0; derSize--) fail |= *pe++ ^ *der++; // match the DER digestSize = hIn->size; digest = hIn->buffer; for(; digestSize > 0; digestSize--) fail |= *pe++ ^ *digest++; // match the hash retVal = (fail != 0) ? TPM_RC_VALUE : TPM_RC_SUCCESS; Exit: return retVal; } #endif // libtpms added /* 10.2.17.4.13 CryptRsaSelectScheme() */ /* This function is used by TPM2_RSA_Decrypt() and TPM2_RSA_Encrypt(). It sets up the rules to select a scheme between input and object default. This function assume the RSA object is loaded. If a default scheme is defined in object, the default scheme should be chosen, otherwise, the input scheme should be chosen. In the case that both the object and scheme are not TPM_ALG_NULL, then if the schemes are the same, the input scheme will be chosen. if the scheme are not compatible, a NULL pointer will be returned. */ /* The return pointer may point to a TPM_ALG_NULL scheme. */ TPMT_RSA_DECRYPT* CryptRsaSelectScheme( TPMI_DH_OBJECT rsaHandle, // IN: handle of an RSA key TPMT_RSA_DECRYPT *scheme // IN: a sign or decrypt scheme ) { OBJECT *rsaObject; TPMT_ASYM_SCHEME *keyScheme; TPMT_RSA_DECRYPT *retVal = NULL; // Get sign object pointer rsaObject = HandleToObject(rsaHandle); keyScheme = &rsaObject->publicArea.parameters.asymDetail.scheme; // if the default scheme of the object is TPM_ALG_NULL, then select the // input scheme if(keyScheme->scheme == TPM_ALG_NULL) { retVal = scheme; } // if the object scheme is not TPM_ALG_NULL and the input scheme is // TPM_ALG_NULL, then select the default scheme of the object. else if(scheme->scheme == TPM_ALG_NULL) { // if input scheme is NULL retVal = (TPMT_RSA_DECRYPT *)keyScheme; } // get here if both the object scheme and the input scheme are // not TPM_ALG_NULL. Need to insure that they are the same. // IMPLEMENTATION NOTE: This could cause problems if future versions have // schemes that have more values than just a hash algorithm. A new function // (IsSchemeSame()) might be needed then. else if(keyScheme->scheme == scheme->scheme && keyScheme->details.anySig.hashAlg == scheme->details.anySig.hashAlg) { retVal = scheme; } // two different, incompatible schemes specified will return NULL return retVal; } /* 10.2.17.4.14 CryptRsaLoadPrivateExponent() */ /* Error Returns Meaning */ /* TPM_RC_BINDING public and private parts of rsaKey are not matched */ TPM_RC CryptRsaLoadPrivateExponent( OBJECT *rsaKey // IN: the RSA key object ) { BN_RSA_INITIALIZED(bnN, &rsaKey->publicArea.unique.rsa); BN_PRIME_INITIALIZED(bnP, &rsaKey->sensitive.sensitive.rsa); BN_RSA(bnQ); BN_PRIME(bnQr); BN_WORD_INITIALIZED(bnE, (rsaKey->publicArea.parameters.rsaDetail.exponent == 0) ? RSA_DEFAULT_PUBLIC_EXPONENT : rsaKey->publicArea.parameters.rsaDetail.exponent); TPM_RC retVal = TPM_RC_SUCCESS; if(!rsaKey->attributes.privateExp) { TEST(TPM_ALG_NULL); // Make sure that the bigNum used for the exponent is properly initialized RsaInitializeExponent(&rsaKey->privateExponent); // Find the second prime by division BnDiv(bnQ, bnQr, bnN, bnP); if(!BnEqualZero(bnQr)) ERROR_RETURN(TPM_RC_BINDING); // Compute the private exponent and return it if found if(!ComputePrivateExponent(bnP, bnQ, bnE, bnN, &rsaKey->privateExponent)) ERROR_RETURN(TPM_RC_BINDING); } Exit: rsaKey->attributes.privateExp = (retVal == TPM_RC_SUCCESS); return retVal; } #if !USE_OPENSSL_FUNCTIONS_RSA // libtpms added /* 10.2.17.4.15 CryptRsaEncrypt() */ /* This is the entry point for encryption using RSA. Encryption is use of the public exponent. The padding parameter determines what padding will be used. */ /* The cOutSize parameter must be at least as large as the size of the key. */ /* If the padding is RSA_PAD_NONE, dIn is treated as a number. It must be lower in value than the key modulus. */ /* NOTE: If dIn has fewer bytes than cOut, then we don't add low-order zeros to dIn to make it the size of the RSA key for the call to RSAEP. This is because the high order bytes of dIn might have a numeric value that is greater than the value of the key modulus. If this had low-order zeros added, it would have a numeric value larger than the modulus even though it started out with a lower numeric value. */ /* Error Returns Meaning */ /* TPM_RC_VALUE cOutSize is too small (must be the size of the modulus) */ /* TPM_RC_SCHEME padType is not a supported scheme */ LIB_EXPORT TPM_RC CryptRsaEncrypt( TPM2B_PUBLIC_KEY_RSA *cOut, // OUT: the encrypted data TPM2B *dIn, // IN: the data to encrypt OBJECT *key, // IN: the key used for encryption TPMT_RSA_DECRYPT *scheme, // IN: the type of padding and hash // if needed const TPM2B *label, // IN: in case it is needed RAND_STATE *rand // IN: random number generator // state (mostly for testing) ) { TPM_RC retVal = TPM_RC_SUCCESS; TPM2B_PUBLIC_KEY_RSA dataIn; // // if the input and output buffers are the same, copy the input to a scratch // buffer so that things don't get messed up. if(dIn == &cOut->b) { MemoryCopy2B(&dataIn.b, dIn, sizeof(dataIn.t.buffer)); dIn = &dataIn.b; } // All encryption schemes return the same size of data cOut->t.size = key->publicArea.unique.rsa.t.size; TEST(scheme->scheme); switch(scheme->scheme) { case TPM_ALG_NULL: // 'raw' encryption { INT32 i; INT32 dSize = dIn->size; // dIn can have more bytes than cOut as long as the extra bytes // are zero. Note: the more significant bytes of a number in a byte // buffer are the bytes at the start of the array. for(i = 0; (i < dSize) && (dIn->buffer[i] == 0); i++); dSize -= i; if(dSize > cOut->t.size) ERROR_RETURN(TPM_RC_VALUE); // Pad cOut with zeros if dIn is smaller memset(cOut->t.buffer, 0, cOut->t.size - dSize); // And copy the rest of the value memcpy(&cOut->t.buffer[cOut->t.size - dSize], &dIn->buffer[i], dSize); // If the size of dIn is the same as cOut dIn could be larger than // the modulus. If it is, then RSAEP() will catch it. } break; case TPM_ALG_RSAES: retVal = RSAES_PKCS1v1_5Encode(&cOut->b, dIn, rand); break; case TPM_ALG_OAEP: retVal = OaepEncode(&cOut->b, scheme->details.oaep.hashAlg, label, dIn, rand); break; default: ERROR_RETURN(TPM_RC_SCHEME); break; } // All the schemes that do padding will come here for the encryption step // Check that the Encoding worked if(retVal == TPM_RC_SUCCESS) // Padding OK so do the encryption retVal = RSAEP(&cOut->b, key); Exit: return retVal; } /* 10.2.17.4.16 CryptRsaDecrypt() */ /* This is the entry point for decryption using RSA. Decryption is use of the private exponent. The padType parameter determines what padding was used. */ /* Error Returns Meaning */ /* TPM_RC_SIZE cInSize is not the same as the size of the public modulus of key; or numeric value of the encrypted data is greater than the modulus */ /* TPM_RC_VALUE dOutSize is not large enough for the result */ /* TPM_RC_SCHEME padType is not supported */ LIB_EXPORT TPM_RC CryptRsaDecrypt( TPM2B *dOut, // OUT: the decrypted data TPM2B *cIn, // IN: the data to decrypt OBJECT *key, // IN: the key to use for decryption TPMT_RSA_DECRYPT *scheme, // IN: the padding scheme const TPM2B *label // IN: in case it is needed for the scheme ) { TPM_RC retVal; // Make sure that the necessary parameters are provided pAssert(cIn != NULL && dOut != NULL && key != NULL); // Size is checked to make sure that the encrypted value is the right size if(cIn->size != key->publicArea.unique.rsa.t.size) ERROR_RETURN(TPM_RC_SIZE); TEST(scheme->scheme); // For others that do padding, do the decryption in place and then // go handle the decoding. retVal = RSADP(cIn, key); if(retVal == TPM_RC_SUCCESS) { // Remove padding switch(scheme->scheme) { case TPM_ALG_NULL: if(dOut->size < cIn->size) return TPM_RC_VALUE; MemoryCopy2B(dOut, cIn, dOut->size); break; case TPM_ALG_RSAES: retVal = RSAES_Decode(dOut, cIn); break; case TPM_ALG_OAEP: retVal = OaepDecode(dOut, scheme->details.oaep.hashAlg, label, cIn); break; default: retVal = TPM_RC_SCHEME; break; } } Exit: return retVal; } /* 10.2.17.4.17 CryptRsaSign() */ /* This function is used to generate an RSA signature of the type indicated in scheme. */ /* Error Returns Meaning */ /* TPM_RC_SCHEME scheme or hashAlg are not supported */ /* TPM_RC_VALUE hInSize does not match hashAlg (for RSASSA) */ LIB_EXPORT TPM_RC CryptRsaSign( TPMT_SIGNATURE *sigOut, OBJECT *key, // IN: key to use TPM2B_DIGEST *hIn, // IN: the digest to sign RAND_STATE *rand // IN: the random number generator // to use (mostly for testing) ) { TPM_RC retVal = TPM_RC_SUCCESS; UINT16 modSize; // parameter checks pAssert(sigOut != NULL && key != NULL && hIn != NULL); modSize = key->publicArea.unique.rsa.t.size; // for all non-null signatures, the size is the size of the key modulus sigOut->signature.rsapss.sig.t.size = modSize; TEST(sigOut->sigAlg); switch(sigOut->sigAlg) { case TPM_ALG_NULL: sigOut->signature.rsapss.sig.t.size = 0; return TPM_RC_SUCCESS; case TPM_ALG_RSAPSS: retVal = PssEncode(&sigOut->signature.rsapss.sig.b, sigOut->signature.rsapss.hash, &hIn->b, rand); break; case TPM_ALG_RSASSA: retVal = RSASSA_Encode(&sigOut->signature.rsassa.sig.b, sigOut->signature.rsassa.hash, &hIn->b); break; default: retVal = TPM_RC_SCHEME; } if(retVal == TPM_RC_SUCCESS) { // Do the encryption using the private key retVal = RSADP(&sigOut->signature.rsapss.sig.b, key); } return retVal; } /* 10.2.17.4.18 CryptRsaValidateSignature() */ /* This function is used to validate an RSA signature. If the signature is valid TPM_RC_SUCCESS is returned. If the signature is not valid, TPM_RC_SIGNATURE is returned. Other return codes indicate either parameter problems or fatal errors. */ /* Error Returns Meaning */ /* TPM_RC_SIGNATURE the signature does not check */ /* TPM_RC_SCHEME unsupported scheme or hash algorithm */ LIB_EXPORT TPM_RC CryptRsaValidateSignature( TPMT_SIGNATURE *sig, // IN: signature OBJECT *key, // IN: public modulus TPM2B_DIGEST *digest // IN: The digest being validated ) { TPM_RC retVal; // // Fatal programming errors pAssert(key != NULL && sig != NULL && digest != NULL); switch(sig->sigAlg) { case TPM_ALG_RSAPSS: case TPM_ALG_RSASSA: break; default: return TPM_RC_SCHEME; } // Errors that might be caused by calling parameters if(sig->signature.rsassa.sig.t.size != key->publicArea.unique.rsa.t.size) ERROR_RETURN(TPM_RC_SIGNATURE); TEST(sig->sigAlg); // Decrypt the block retVal = RSAEP(&sig->signature.rsassa.sig.b, key); if(retVal == TPM_RC_SUCCESS) { switch(sig->sigAlg) { case TPM_ALG_RSAPSS: retVal = PssDecode(sig->signature.any.hashAlg, &digest->b, &sig->signature.rsassa.sig.b); break; case TPM_ALG_RSASSA: retVal = RSASSA_Decode(sig->signature.any.hashAlg, &digest->b, &sig->signature.rsassa.sig.b); break; default: return TPM_RC_SCHEME; } } Exit: return (retVal != TPM_RC_SUCCESS) ? TPM_RC_SIGNATURE : TPM_RC_SUCCESS; } #endif // libtpms added #if SIMULATION && USE_RSA_KEY_CACHE extern int s_rsaKeyCacheEnabled; int GetCachedRsaKey(OBJECT *key, RAND_STATE *rand); #define GET_CACHED_KEY(key, rand) \ (s_rsaKeyCacheEnabled && GetCachedRsaKey(key, rand)) #else #define GET_CACHED_KEY(key, rand) #endif /* 10.2.17.4.19 CryptRsaGenerateKey() */ /* Generate an RSA key from a provided seed */ /* Error Returns Meaning */ /* TPM_RC_CANCELED operation was canceled */ /* TPM_RC_RANGE public exponent is not supported */ /* TPM_RC_VALUE could not find a prime using the provided parameters */ LIB_EXPORT TPM_RC CryptRsaGenerateKey( OBJECT *rsaKey, // IN/OUT: The object structure in which // the key is created. RAND_STATE *rand // IN: if not NULL, the deterministic // RNG state ) { UINT32 i; BN_PRIME(bnP); // These four declarations initialize the number to 0 BN_PRIME(bnQ); BN_RSA(bnD); BN_RSA(bnN); BN_WORD(bnE); UINT32 e; int keySizeInBits; TPMT_PUBLIC *publicArea = &rsaKey->publicArea; TPMT_SENSITIVE *sensitive = &rsaKey->sensitive; TPM_RC retVal = TPM_RC_NO_RESULT; // // Need to make sure that the caller did not specify an exponent that is // not supported e = publicArea->parameters.rsaDetail.exponent; if(e == 0) e = RSA_DEFAULT_PUBLIC_EXPONENT; if(e < 65537) ERROR_RETURN(TPM_RC_RANGE); if(e != RSA_DEFAULT_PUBLIC_EXPONENT && !IsPrimeInt(e)) ERROR_RETURN(TPM_RC_RANGE); BnSetWord(bnE, e); // Check that e is prime // check for supported key size. keySizeInBits = publicArea->parameters.rsaDetail.keyBits; if(((keySizeInBits % 1024) != 0) || (keySizeInBits > MAX_RSA_KEY_BITS) // this might be redundant, but... || (keySizeInBits == 0)) ERROR_RETURN(TPM_RC_VALUE); // Set the prime size for instrumentation purposes INSTRUMENT_SET(PrimeIndex, PRIME_INDEX(keySizeInBits / 2)); #if SIMULATION && USE_RSA_KEY_CACHE if(GET_CACHED_KEY(rsaKey, rand)) return TPM_RC_SUCCESS; #endif // Make sure that key generation has been tested TEST(TPM_ALG_NULL); #if USE_OPENSSL_FUNCTIONS_RSA // libtpms added begin if (rand == NULL) return OpenSSLCryptRsaGenerateKey(rsaKey, e, keySizeInBits); #endif // libtpms added end // Need to initialize the privateExponent structure RsaInitializeExponent(&rsaKey->privateExponent); // The prime is computed in P. When a new prime is found, Q is checked to // see if it is zero. If so, P is copied to Q and a new P is found. // When both P and Q are non-zero, the modulus and // private exponent are computed and a trial encryption/decryption is // performed. If the encrypt/decrypt fails, assume that at least one of the // primes is composite. Since we don't know which one, set Q to zero and start // over and find a new pair of primes. for(i = 1; (retVal != TPM_RC_SUCCESS) && (i != 100); i++) { if(_plat__IsCanceled()) ERROR_RETURN(TPM_RC_CANCELED); BnGeneratePrimeForRSA(bnP, keySizeInBits / 2, e, rand); INSTRUMENT_INC(PrimeCounts[PrimeIndex]); // If this is the second prime, make sure that it differs from the // first prime by at least 2^100 if(BnEqualZero(bnQ)) { // copy p to q and compute another prime in p BnCopy(bnQ, bnP); continue; } // Make sure that the difference is at least 100 bits. Need to do it this // way because the big numbers are only positive values if(BnUnsignedCmp(bnP, bnQ) < 0) BnSub(bnD, bnQ, bnP); else BnSub(bnD, bnP, bnQ); if(BnMsb(bnD) < 100) continue; //Form the public modulus and set the unique value BnMult(bnN, bnP, bnQ); BnTo2B(bnN, &publicArea->unique.rsa.b, (NUMBYTES)BITS_TO_BYTES(keySizeInBits)); // And the prime to the sensitive area BnTo2B(bnP, &sensitive->sensitive.rsa.b, (NUMBYTES)BITS_TO_BYTES(keySizeInBits) / 2); // Make sure everything came out right. The MSb of the values must be // one if(((publicArea->unique.rsa.t.buffer[0] & 0x80) == 0) || ((sensitive->sensitive.rsa.t.buffer[0] & 0x80) == 0)) FAIL(FATAL_ERROR_INTERNAL); // Make sure that we can form the private exponent values if(ComputePrivateExponent(bnP, bnQ, bnE, bnN, &rsaKey->privateExponent) != TRUE) { // If ComputePrivateExponent could not find an inverse for // Q, then copy P and recompute P. This might // cause both to be recomputed if P is also zero if(BnEqualZero(bnQ)) BnCopy(bnQ, bnP); continue; } retVal = TPM_RC_SUCCESS; // Do a trial encryption decryption if this is a signing key if(IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign)) { BN_RSA(temp1); BN_RSA(temp2); BnGenerateRandomInRange(temp1, bnN, rand); // Encrypt with public exponent... BnModExp(temp2, temp1, bnE, bnN); // ... then decrypt with private exponent RsaPrivateKeyOp(temp2, bnN, bnP, &rsaKey->privateExponent); // If the starting and ending values are not the same, // start over )-; if(BnUnsignedCmp(temp2, temp1) != 0) { BnSetWord(bnQ, 0); retVal = TPM_RC_NO_RESULT; } } } Exit: if(retVal == TPM_RC_SUCCESS) rsaKey->attributes.privateExp = SET; return retVal; } #if USE_OPENSSL_FUNCTIONS_RSA // libtpms added begin LIB_EXPORT TPM_RC CryptRsaEncrypt( TPM2B_PUBLIC_KEY_RSA *cOut, // OUT: the encrypted data TPM2B *dIn, // IN: the data to encrypt OBJECT *key, // IN: the key used for encryption TPMT_RSA_DECRYPT *scheme, // IN: the type of padding and hash // if needed const TPM2B *label, // IN: in case it is needed RAND_STATE *rand // IN: random number generator // state (mostly for testing) ) { TPM_RC retVal; TPM2B_PUBLIC_KEY_RSA dataIn; TPM2B_PUBLIC_KEY_RSA scratch; size_t outlen; EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *ctx = NULL; const EVP_MD *md; const char *digestname; unsigned char *tmp = NULL; // // if the input and output buffers are the same, copy the input to a scratch // buffer so that things don't get messed up. if(dIn == &cOut->b) { MemoryCopy2B(&dataIn.b, dIn, sizeof(dataIn.t.buffer)); dIn = &dataIn.b; } // All encryption schemes return the same size of data pAssert(sizeof(cOut->t.buffer) >= key->publicArea.unique.rsa.t.size); cOut->t.size = key->publicArea.unique.rsa.t.size; TEST(scheme->scheme); retVal = InitOpenSSLRSAPublicKey(key, &pkey); if (retVal != TPM_RC_SUCCESS) return retVal; ctx = EVP_PKEY_CTX_new(pkey, NULL); if (ctx == NULL || EVP_PKEY_encrypt_init(ctx) <= 0) ERROR_RETURN(TPM_RC_FAILURE); switch(scheme->scheme) { case TPM_ALG_NULL: // 'raw' encryption { INT32 i; INT32 dSize = dIn->size; // dIn can have more bytes than cOut as long as the extra bytes // are zero. Note: the more significant bytes of a number in a byte // buffer are the bytes at the start of the array. for(i = 0; (i < dSize) && (dIn->buffer[i] == 0); i++); dSize -= i; scratch.t.size = cOut->t.size; pAssert(scratch.t.size <= sizeof(scratch.t.buffer)); if(dSize > scratch.t.size) ERROR_RETURN(TPM_RC_VALUE); // Pad cOut with zeros if dIn is smaller memset(scratch.t.buffer, 0, scratch.t.size - dSize); // And copy the rest of the value; value is then right-aligned memcpy(&scratch.t.buffer[scratch.t.size - dSize], &dIn->buffer[i], dSize); dIn = &scratch.b; } if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_NO_PADDING) <= 0) ERROR_RETURN(TPM_RC_FAILURE); break; case TPM_ALG_RSAES: if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0) ERROR_RETURN(TPM_RC_FAILURE); break; case TPM_ALG_OAEP: digestname = GetDigestNameByHashAlg(scheme->details.oaep.hashAlg); if (digestname == NULL) ERROR_RETURN(TPM_RC_VALUE); md = EVP_get_digestbyname(digestname); if (md == NULL || EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0 || EVP_PKEY_CTX_set_rsa_oaep_md(ctx, md) <= 0) ERROR_RETURN(TPM_RC_FAILURE); if (label->size > 0) { tmp = malloc(label->size); if (tmp == NULL) ERROR_RETURN(TPM_RC_FAILURE); memcpy(tmp, label->buffer, label->size); if (EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, tmp, label->size) <= 0) ERROR_RETURN(TPM_RC_FAILURE); } tmp = NULL; break; default: ERROR_RETURN(TPM_RC_SCHEME); break; } outlen = cOut->t.size; if (EVP_PKEY_encrypt(ctx, cOut->t.buffer, &outlen, dIn->buffer, dIn->size) <= 0) ERROR_RETURN(TPM_RC_FAILURE); cOut->t.size = outlen; Exit: EVP_PKEY_free(pkey); EVP_PKEY_CTX_free(ctx); free(tmp); return retVal; } LIB_EXPORT TPM_RC CryptRsaDecrypt( TPM2B *dOut, // OUT: the decrypted data TPM2B *cIn, // IN: the data to decrypt OBJECT *key, // IN: the key to use for decryption TPMT_RSA_DECRYPT *scheme, // IN: the padding scheme const TPM2B *label // IN: in case it is needed for the scheme ) { TPM_RC retVal; EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *ctx = NULL; const EVP_MD *md = NULL; const char *digestname; size_t outlen; unsigned char *tmp = NULL; unsigned char buffer[MAX_RSA_KEY_BYTES]; // Make sure that the necessary parameters are provided pAssert(cIn != NULL && dOut != NULL && key != NULL); // Size is checked to make sure that the encrypted value is the right size if(cIn->size != key->publicArea.unique.rsa.t.size) ERROR_RETURN(TPM_RC_SIZE); TEST(scheme->scheme); retVal = InitOpenSSLRSAPrivateKey(key, &pkey); if (retVal != TPM_RC_SUCCESS) return retVal; ctx = EVP_PKEY_CTX_new(pkey, NULL); if (ctx == NULL || EVP_PKEY_decrypt_init(ctx) <= 0) ERROR_RETURN(TPM_RC_FAILURE); switch(scheme->scheme) { case TPM_ALG_NULL: // 'raw' encryption if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_NO_PADDING) <= 0) ERROR_RETURN(TPM_RC_FAILURE); break; case TPM_ALG_RSAES: if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0) ERROR_RETURN(TPM_RC_FAILURE); break; case TPM_ALG_OAEP: digestname = GetDigestNameByHashAlg(scheme->details.oaep.hashAlg); if (digestname == NULL) ERROR_RETURN(TPM_RC_VALUE); md = EVP_get_digestbyname(digestname); if (md == NULL || EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0 || EVP_PKEY_CTX_set_rsa_oaep_md(ctx, md) <= 0) ERROR_RETURN(TPM_RC_FAILURE); if (label->size > 0) { tmp = malloc(label->size); if (tmp == NULL) ERROR_RETURN(TPM_RC_FAILURE); memcpy(tmp, label->buffer, label->size); if (EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, tmp, label->size) <= 0) ERROR_RETURN(TPM_RC_FAILURE); tmp = NULL; } break; default: ERROR_RETURN(TPM_RC_SCHEME); break; } /* cannot use cOut->buffer */ outlen = sizeof(buffer); if (EVP_PKEY_decrypt(ctx, buffer, &outlen, cIn->buffer, cIn->size) <= 0) ERROR_RETURN(TPM_RC_FAILURE); if (outlen > dOut->size) ERROR_RETURN(TPM_RC_FAILURE); memcpy(dOut->buffer, buffer, outlen); dOut->size = outlen; retVal = TPM_RC_SUCCESS; Exit: EVP_PKEY_free(pkey); EVP_PKEY_CTX_free(ctx); free(tmp); return retVal; } LIB_EXPORT TPM_RC CryptRsaSign( TPMT_SIGNATURE *sigOut, OBJECT *key, // IN: key to use TPM2B_DIGEST *hIn, // IN: the digest to sign RAND_STATE *rand // IN: the random number generator // to use (mostly for testing) ) { TPM_RC retVal = TPM_RC_SUCCESS; UINT16 modSize; size_t outlen; int padding; EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *ctx = NULL; const EVP_MD *md; const char *digestname; TPMI_ALG_HASH hashAlg; // parameter checks pAssert(sigOut != NULL && key != NULL && hIn != NULL); modSize = key->publicArea.unique.rsa.t.size; // for all non-null signatures, the size is the size of the key modulus sigOut->signature.rsapss.sig.t.size = modSize; TEST(sigOut->sigAlg); switch(sigOut->sigAlg) { case TPM_ALG_NULL: sigOut->signature.rsapss.sig.t.size = 0; return TPM_RC_SUCCESS; case TPM_ALG_RSAPSS: padding = RSA_PKCS1_PSS_PADDING; hashAlg = sigOut->signature.rsapss.hash; break; case TPM_ALG_RSASSA: padding = RSA_PKCS1_PADDING; hashAlg = sigOut->signature.rsassa.hash; break; default: ERROR_RETURN(TPM_RC_SCHEME); } digestname = GetDigestNameByHashAlg(hashAlg); if (digestname == NULL) ERROR_RETURN(TPM_RC_VALUE); md = EVP_get_digestbyname(digestname); if (md == NULL) ERROR_RETURN(TPM_RC_FAILURE); retVal = InitOpenSSLRSAPrivateKey(key, &pkey); if (retVal != TPM_RC_SUCCESS) return retVal; ctx = EVP_PKEY_CTX_new(pkey, NULL); if (ctx == NULL || EVP_PKEY_sign_init(ctx) <= 0) ERROR_RETURN(TPM_RC_FAILURE); if (EVP_PKEY_CTX_set_rsa_padding(ctx, padding) <= 0 || EVP_PKEY_CTX_set_signature_md(ctx, md) <= 0) ERROR_RETURN(TPM_RC_FAILURE); /* careful with PSS padding: Use salt length = hash length (-1) if * length(digest) + length(hash-to-sign) + 2 <= modSize * otherwise use the max. possible salt length, which is the default (-2) * test case: 1024 bit key PSS signing sha512 hash */ if (padding == RSA_PKCS1_PSS_PADDING && EVP_MD_size(md) + hIn->b.size + 2 <= modSize && /* OSSL: RSA_padding_add_PKCS1_PSS_mgf1 */ EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, -1) <= 0) ERROR_RETURN(TPM_RC_FAILURE); outlen = sigOut->signature.rsapss.sig.t.size; if (EVP_PKEY_sign(ctx, sigOut->signature.rsapss.sig.t.buffer, &outlen, hIn->b.buffer, hIn->b.size) <= 0) ERROR_RETURN(TPM_RC_FAILURE); sigOut->signature.rsapss.sig.t.size = outlen; Exit: EVP_PKEY_free(pkey); EVP_PKEY_CTX_free(ctx); return retVal; } LIB_EXPORT TPM_RC CryptRsaValidateSignature( TPMT_SIGNATURE *sig, // IN: signature OBJECT *key, // IN: public modulus TPM2B_DIGEST *digest // IN: The digest being validated ) { TPM_RC retVal; int padding; EVP_PKEY *pkey = NULL; EVP_PKEY_CTX *ctx = NULL; const EVP_MD *md; const char *digestname; // // Fatal programming errors pAssert(key != NULL && sig != NULL && digest != NULL); switch(sig->sigAlg) { case TPM_ALG_RSAPSS: padding = RSA_PKCS1_PSS_PADDING; break; case TPM_ALG_RSASSA: padding = RSA_PKCS1_PADDING; break; default: return TPM_RC_SCHEME; } // Errors that might be caused by calling parameters if(sig->signature.rsassa.sig.t.size != key->publicArea.unique.rsa.t.size) ERROR_RETURN(TPM_RC_SIGNATURE); TEST(sig->sigAlg); retVal = InitOpenSSLRSAPublicKey(key, &pkey); if (retVal != TPM_RC_SUCCESS) return retVal; digestname = GetDigestNameByHashAlg(sig->signature.any.hashAlg); if (digestname == NULL) ERROR_RETURN(TPM_RC_VALUE); md = EVP_get_digestbyname(digestname); ctx = EVP_PKEY_CTX_new(pkey, NULL); if (md == NULL || ctx == NULL || EVP_PKEY_verify_init(ctx) <= 0) ERROR_RETURN(TPM_RC_FAILURE); if (EVP_PKEY_CTX_set_rsa_padding(ctx, padding) <= 0 || EVP_PKEY_CTX_set_signature_md(ctx, md) <= 0) ERROR_RETURN(TPM_RC_FAILURE); if (EVP_PKEY_verify(ctx, sig->signature.rsassa.sig.t.buffer, sig->signature.rsassa.sig.t.size, digest->t.buffer, digest->t.size) <= 0) ERROR_RETURN(TPM_RC_SIGNATURE); retVal = TPM_RC_SUCCESS; Exit: EVP_PKEY_free(pkey); EVP_PKEY_CTX_free(ctx); return (retVal != TPM_RC_SUCCESS) ? TPM_RC_SIGNATURE : TPM_RC_SUCCESS; } #endif // USE_OPENSSL_FUNCTIONS_RSA libtpms added end #endif // TPM_ALG_RSA libtpms-0.9.3/src/tpm2/crypto/openssl/CryptSmac.c000066400000000000000000000142611421143571500217310ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Message Authentication Codes Based on a Symmetric Block Cipher */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CryptSmac.c 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2018 - 2021 */ /* */ /********************************************************************************/ /* 10.2.20 CryptSmac.c */ /* 10.2.20.1 Introduction */ /* This file contains the implementation of the message authentication codes based on a symmetric block cipher. These functions only use the single block encryption functions of the selected symmetric cryptographic library. */ /* 10.2.20.2 Includes, Defines, and Typedefs */ #define _CRYPT_HASH_C_ #include "Tpm.h" #if SMAC_IMPLEMENTED /* 10.2.20.2.1 CryptSmacStart() */ /* Function to start an SMAC. */ UINT16 CryptSmacStart( HASH_STATE *state, TPMU_PUBLIC_PARMS *keyParameters, TPM_ALG_ID macAlg, // IN: the type of MAC TPM2B *key ) { UINT16 retVal = 0; // // Make sure that the key size is correct. This should have been checked // at key load, but... if(BITS_TO_BYTES(keyParameters->symDetail.sym.keyBits.sym) == key->size) { switch(macAlg) { #if ALG_CMAC case TPM_ALG_CMAC: retVal = CryptCmacStart(&state->state.smac, keyParameters, macAlg, key); break; #endif default: break; } } state->type = (retVal != 0) ? HASH_STATE_SMAC : HASH_STATE_EMPTY; return retVal; } /* 10.2.20.2.2 CryptMacStart() */ /* Function to start either an HMAC or an SMAC. Cannot reuse the CryptHmacStart() function because of the difference in number of parameters. */ UINT16 CryptMacStart( HMAC_STATE *state, TPMU_PUBLIC_PARMS *keyParameters, TPM_ALG_ID macAlg, // IN: the type of MAC TPM2B *key ) { MemorySet(state, 0, sizeof(HMAC_STATE)); if(CryptHashIsValidAlg(macAlg, FALSE)) { return CryptHmacStart(state, macAlg, key->size, key->buffer); } else if(CryptSmacIsValidAlg(macAlg, FALSE)) { return CryptSmacStart(&state->hashState, keyParameters, macAlg, key); } else return 0; } /* 10.2.20.2.3 CryptMacEnd() */ /* Dispatch to the MAC end function using a size and buffer pointer. */ UINT16 CryptMacEnd( HMAC_STATE *state, UINT32 size, BYTE *buffer ) { UINT16 retVal = 0; if(state->hashState.type == HASH_STATE_SMAC) retVal = (state->hashState.state.smac.smacMethods.end)( &state->hashState.state.smac.state, size, buffer); else if(state->hashState.type == HASH_STATE_HMAC) retVal = CryptHmacEnd(state, size, buffer); state->hashState.type = HASH_STATE_EMPTY; return retVal; } #if 0 /* libtpms added */ /* 10.2.20.2.4 CryptMacEnd2B() */ /* Dispatch to the MAC end function using a 2B. */ UINT16 CryptMacEnd2B ( HMAC_STATE *state, TPM2B *data ) { return CryptMacEnd(state, data->size, data->buffer); } #endif /* libtpms added */ #endif // SMAC_IMPLEMENTED libtpms-0.9.3/src/tpm2/crypto/openssl/CryptSym.c000066400000000000000000000655121421143571500216230ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Symmetric block cipher modes */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: CryptSym.c 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2021 */ /* */ /********************************************************************************/ /* 10.2.19 CryptSym.c */ /* 10.2.19.1 Introduction */ /* This file contains the implementation of the symmetric block cipher modes allowed for a TPM. These functions only use the single block encryption functions of the selected symmetric crypto library. */ /* 10.2.19.2 Includes, Defines, and Typedefs */ #include "Tpm.h" #include "CryptSym.h" #include "Helpers_fp.h" // libtpms changed #define KEY_BLOCK_SIZES(ALG, alg) \ static const INT16 alg##KeyBlockSizes[] = { \ ALG##_KEY_SIZES_BITS, -1, ALG##_BLOCK_SIZES }; FOR_EACH_SYM(KEY_BLOCK_SIZES) /* 10.2.19.3 Initialization and Data Access Functions */ /* 10.2.19.3.1 CryptSymInit() */ /* This function is called to do _TPM_Init() processing */ BOOL CryptSymInit( void ) { return TRUE; } /* 10.2.19.3.2 CryptSymStartup() */ /* This function is called to do TPM2_Startup() processing */ BOOL CryptSymStartup( void ) { return TRUE; } /* 10.2.20.4 Data Access Functions */ /* 10.2.20.4.1 CryptGetSymmetricBlockSize() */ /* This function returns the block size of the algorithm. The table of bit sizes has an entry for each allowed key size. The entry for a key size is 0 if the TPM does not implement that key size. The key size table is delimited with a negative number (-1). After the delimiter is a list of block sizes with each entry corresponding to the key bit size. For most symmetric algorithms, the block size is the same regardless of the key size but this arrangement allows them to be different. */ /* Return Values Meaning */ /* <= 0 cipher not supported */ /* > 0 the cipher block size in bytes */ LIB_EXPORT INT16 CryptGetSymmetricBlockSize( TPM_ALG_ID symmetricAlg, // IN: the symmetric algorithm UINT16 keySizeInBits // IN: the key size ) { const INT16 *sizes; INT16 i; #if 0 // libtpms added #define ALG_CASE(SYM, sym) case TPM_ALG_##SYM: sizes = sym##KeyBlockSizes; break #endif // libtpms added switch(symmetricAlg) { #define GET_KEY_BLOCK_POINTER(SYM, sym) \ case TPM_ALG_##SYM: \ sizes = sym##KeyBlockSizes; \ break; // Get the pointer to the block size array FOR_EACH_SYM(GET_KEY_BLOCK_POINTER); default: return 0; } // Find the index of the indicated keySizeInBits for(i = 0; *sizes >= 0; i++, sizes++) { if(*sizes == keySizeInBits) break; } // If sizes is pointing at the end of the list of key sizes, then the desired // key size was not found so set the block size to zero. if(*sizes++ < 0) return 0; // Advance until the end of the list is found while(*sizes++ >= 0); // sizes is pointing to the first entry in the list of block sizes. Use the // ith index to find the block size for the corresponding key size. return sizes[i]; } #if !USE_OPENSSL_FUNCTIONS_SYMMETRIC // libtpms added /* 10.2.20.5 Symmetric Encryption */ /* This function performs symmetric encryption based on the mode. */ /* Error Returns Meaning */ /* TPM_RC_SIZE dSize is not a multiple of the block size for an algorithm that requires it */ /* TPM_RC_FAILURE Fatal error */ LIB_EXPORT TPM_RC CryptSymmetricEncrypt( BYTE *dOut, // OUT: TPM_ALG_ID algorithm, // IN: the symmetric algorithm UINT16 keySizeInBits, // IN: key size in bits const BYTE *key, // IN: key buffer. The size of this buffer // in bytes is (keySizeInBits + 7) / 8 TPM2B_IV *ivInOut, // IN/OUT: IV for decryption. TPM_ALG_ID mode, // IN: Mode to use INT32 dSize, // IN: data size (may need to be a // multiple of the blockSize) const BYTE *dIn // IN: data buffer ) { BYTE *pIv; int i; BYTE tmp[MAX_SYM_BLOCK_SIZE]; BYTE *pT; tpmCryptKeySchedule_t keySchedule; INT16 blockSize; TpmCryptSetSymKeyCall_t encrypt; BYTE *iv; BYTE defaultIv[MAX_SYM_BLOCK_SIZE] = {0}; // memset(&keySchedule, 0, sizeof(keySchedule)); // libtpms added; coverity pAssert(dOut != NULL && key != NULL && dIn != NULL); if(dSize == 0) return TPM_RC_SUCCESS; TEST(algorithm); blockSize = CryptGetSymmetricBlockSize(algorithm, keySizeInBits); if(blockSize == 0) return TPM_RC_FAILURE; // If the iv is provided, then it is expected to be block sized. In some cases, // the caller is providing an array of 0's that is equal to [MAX_SYM_BLOCK_SIZE] // with no knowledge of the actual block size. This function will set it. if((ivInOut != NULL) && (mode != TPM_ALG_ECB)) { ivInOut->t.size = blockSize; iv = ivInOut->t.buffer; } else iv = defaultIv; pIv = iv; // Create encrypt key schedule and set the encryption function pointer. switch (algorithm) { FOR_EACH_SYM(ENCRYPT_CASE) default: return TPM_RC_SYMMETRIC; } switch(mode) { #if ALG_CTR case TPM_ALG_CTR: for(; dSize > 0; dSize -= blockSize) { // Encrypt the current value of the IV(counter) ENCRYPT(&keySchedule, iv, tmp); //increment the counter (counter is big-endian so start at end) for(i = blockSize - 1; i >= 0; i--) if((iv[i] += 1) != 0) break; // XOR the encrypted counter value with input and put into output pT = tmp; for(i = (dSize < blockSize) ? dSize : blockSize; i > 0; i--) *dOut++ = *dIn++ ^ *pT++; } break; #endif #if ALG_OFB case TPM_ALG_OFB: // This is written so that dIn and dOut may be the same for(; dSize > 0; dSize -= blockSize) { // Encrypt the current value of the "IV" ENCRYPT(&keySchedule, iv, iv); // XOR the encrypted IV into dIn to create the cipher text (dOut) pIv = iv; for(i = (dSize < blockSize) ? dSize : blockSize; i > 0; i--) *dOut++ = (*pIv++ ^ *dIn++); } break; #endif #if ALG_CBC case TPM_ALG_CBC: // For CBC the data size must be an even multiple of the // cipher block size if((dSize % blockSize) != 0) return TPM_RC_SIZE; // XOR the data block into the IV, encrypt the IV into the IV // and then copy the IV to the output for(; dSize > 0; dSize -= blockSize) { pIv = iv; for(i = blockSize; i > 0; i--) *pIv++ ^= *dIn++; ENCRYPT(&keySchedule, iv, iv); pIv = iv; for(i = blockSize; i > 0; i--) *dOut++ = *pIv++; } break; #endif // CFB is not optional case TPM_ALG_CFB: // Encrypt the IV into the IV, XOR in the data, and copy to output for(; dSize > 0; dSize -= blockSize) { // Encrypt the current value of the IV ENCRYPT(&keySchedule, iv, iv); pIv = iv; for(i = (int)(dSize < blockSize) ? dSize : blockSize; i > 0; i--) // XOR the data into the IV to create the cipher text // and put into the output *dOut++ = *pIv++ ^= *dIn++; } // If the inner loop (i loop) was smaller than blockSize, then dSize // would have been smaller than blockSize and it is now negative. If // it is negative, then it indicates how many bytes are needed to pad // out the IV for the next round. for(; dSize < 0; dSize++) *pIv++ = 0; break; #if ALG_ECB case TPM_ALG_ECB: // For ECB the data size must be an even multiple of the // cipher block size if((dSize % blockSize) != 0) return TPM_RC_SIZE; // Encrypt the input block to the output block for(; dSize > 0; dSize -= blockSize) { ENCRYPT(&keySchedule, dIn, dOut); dIn = &dIn[blockSize]; dOut = &dOut[blockSize]; } break; #endif default: return TPM_RC_FAILURE; } return TPM_RC_SUCCESS; } /* 10.2.20.5.1 CryptSymmetricDecrypt() */ /* This function performs symmetric decryption based on the mode. */ /* Error Returns Meaning */ /* TPM_RC_FAILURE A fatal error */ /* TPM_RCS_SIZE dSize is not a multiple of the block size for an algorithm that requires it */ LIB_EXPORT TPM_RC CryptSymmetricDecrypt( BYTE *dOut, // OUT: decrypted data TPM_ALG_ID algorithm, // IN: the symmetric algorithm UINT16 keySizeInBits, // IN: key size in bits const BYTE *key, // IN: key buffer. The size of this buffer // in bytes is (keySizeInBits + 7) / 8 TPM2B_IV *ivInOut, // IN/OUT: IV for decryption. TPM_ALG_ID mode, // IN: Mode to use INT32 dSize, // IN: data size (may need to be a // multiple of the blockSize) const BYTE *dIn // IN: data buffer ) { BYTE *pIv; int i; BYTE tmp[MAX_SYM_BLOCK_SIZE]; BYTE *pT; tpmCryptKeySchedule_t keySchedule; INT16 blockSize; BYTE *iv; TpmCryptSetSymKeyCall_t encrypt; TpmCryptSetSymKeyCall_t decrypt; BYTE defaultIv[MAX_SYM_BLOCK_SIZE] = {0}; memset(&keySchedule, 0, sizeof(keySchedule)); // libtpms added; coverity // These are used but the compiler can't tell because they are initialized // in case statements and it can't tell if they are always initialized // when needed, so... Comment these out if the compiler can tell or doesn't // care that these are initialized before use. encrypt = NULL; decrypt = NULL; pAssert(dOut != NULL && key != NULL && dIn != NULL); if(dSize == 0) return TPM_RC_SUCCESS; TEST(algorithm); blockSize = CryptGetSymmetricBlockSize(algorithm, keySizeInBits); if(blockSize == 0) return TPM_RC_FAILURE; // If the iv is provided, then it is expected to be block sized. In some cases, // the caller is providing an array of 0's that is equal to [MAX_SYM_BLOCK_SIZE] // with no knowledge of the actual block size. This function will set it. if((ivInOut != NULL) && (mode != TPM_ALG_ECB)) { ivInOut->t.size = blockSize; iv = ivInOut->t.buffer; } else iv = defaultIv; pIv = iv; // Use the mode to select the key schedule to create. Encrypt always uses the // encryption schedule. Depending on the mode, decryption might use either // the decryption or encryption schedule. switch(mode) { #if ALG_CBC || ALG_ECB case TPM_ALG_CBC: // decrypt = decrypt case TPM_ALG_ECB: // For ECB and CBC, the data size must be an even multiple of the // cipher block size if((dSize % blockSize) != 0) return TPM_RC_SIZE; switch (algorithm) { FOR_EACH_SYM(DECRYPT_CASE) default: return TPM_RC_SYMMETRIC; } break; #endif default: // For the remaining stream ciphers, use encryption to decrypt switch (algorithm) { FOR_EACH_SYM(ENCRYPT_CASE) default: return TPM_RC_SYMMETRIC; } } // Now do the mode-dependent decryption switch(mode) { #if ALG_CBC case TPM_ALG_CBC: // Copy the input data to a temp buffer, decrypt the buffer into the // output, XOR in the IV, and copy the temp buffer to the IV and repeat. for(; dSize > 0; dSize -= blockSize) { pT = tmp; for(i = blockSize; i > 0; i--) *pT++ = *dIn++; DECRYPT(&keySchedule, tmp, dOut); pIv = iv; pT = tmp; for(i = blockSize; i > 0; i--) { *dOut++ ^= *pIv; *pIv++ = *pT++; } } break; #endif case TPM_ALG_CFB: for(; dSize > 0; dSize -= blockSize) { // Encrypt the IV into the temp buffer ENCRYPT(&keySchedule, iv, tmp); pT = tmp; pIv = iv; for(i = (dSize < blockSize) ? dSize : blockSize; i > 0; i--) // Copy the current cipher text to IV, XOR // with the temp buffer and put into the output *dOut++ = *pT++ ^ (*pIv++ = *dIn++); } // If the inner loop (i loop) was smaller than blockSize, then dSize // would have been smaller than blockSize and it is now negative // If it is negative, then it indicates how may fill bytes // are needed to pad out the IV for the next round. for(; dSize < 0; dSize++) *pIv++ = 0; break; #if ALG_CTR case TPM_ALG_CTR: for(; dSize > 0; dSize -= blockSize) { // Encrypt the current value of the IV(counter) ENCRYPT(&keySchedule, iv, tmp); //increment the counter (counter is big-endian so start at end) for(i = blockSize - 1; i >= 0; i--) if((iv[i] += 1) != 0) break; // XOR the encrypted counter value with input and put into output pT = tmp; for(i = (dSize < blockSize) ? dSize : blockSize; i > 0; i--) *dOut++ = *dIn++ ^ *pT++; } break; #endif #if ALG_ECB case TPM_ALG_ECB: for(; dSize > 0; dSize -= blockSize) { DECRYPT(&keySchedule, dIn, dOut); dIn = &dIn[blockSize]; dOut = &dOut[blockSize]; } break; #endif #if ALG_OFB case TPM_ALG_OFB: // This is written so that dIn and dOut may be the same for(; dSize > 0; dSize -= blockSize) { // Encrypt the current value of the "IV" ENCRYPT(&keySchedule, iv, iv); // XOR the encrypted IV into dIn to create the cipher text (dOut) pIv = iv; for(i = (dSize < blockSize) ? dSize : blockSize; i > 0; i--) *dOut++ = (*pIv++ ^ *dIn++); } break; #endif default: return TPM_RC_FAILURE; } return TPM_RC_SUCCESS; } #else // libtpms added begin #if ALG_TDES && ALG_CTR // Emulated TDES Counter mode since OpenSSL does not implement it static void TDES_CTR(const BYTE *key, // IN INT32 keySizeInBits, // IN INT32 dSize, // IN const BYTE *dIn, // IN BYTE *iv, // IN BYTE *dOut, // OUT INT16 blockSize // IN ) { tpmCryptKeySchedule_t keySchedule; int i; BYTE tmp[MAX_SYM_BLOCK_SIZE]; BYTE *pT; TDES_set_encrypt_key(key, keySizeInBits, (tpmKeyScheduleTDES *)&keySchedule.tdes); for(; dSize > 0; dSize -= blockSize) { // Encrypt the current value of the IV(counter) TDES_encrypt(iv, tmp, (tpmKeyScheduleTDES *)&keySchedule.tdes); //increment the counter (counter is big-endian so start at end) for(i = blockSize - 1; i >= 0; i--) if((iv[i] += 1) != 0) break; // XOR the encrypted counter value with input and put into output pT = tmp; for(i = (dSize < blockSize) ? dSize : blockSize; i > 0; i--) *dOut++ = *dIn++ ^ *pT++; } } #endif /* 10.2.20.5 Symmetric Encryption */ /* This function performs symmetric encryption based on the mode. */ /* Error Returns Meaning */ /* TPM_RC_SIZE dSize is not a multiple of the block size for an algorithm that requires it */ /* TPM_RC_FAILURE Fatal error */ LIB_EXPORT TPM_RC CryptSymmetricEncrypt( BYTE *dOut, // OUT: TPM_ALG_ID algorithm, // IN: the symmetric algorithm UINT16 keySizeInBits, // IN: key size in bits const BYTE *key, // IN: key buffer. The size of this buffer // in bytes is (keySizeInBits + 7) / 8 TPM2B_IV *ivInOut, // IN/OUT: IV for decryption. TPM_ALG_ID mode, // IN: Mode to use INT32 dSize, // IN: data size (may need to be a // multiple of the blockSize) const BYTE *dIn // IN: data buffer ) { INT16 blockSize; BYTE *iv; BYTE defaultIv[MAX_SYM_BLOCK_SIZE] = {0}; evpfunc evpfn; EVP_CIPHER_CTX *ctx = NULL; int outlen1 = 0; int outlen2 = 0; BYTE *pOut = dOut; BYTE *buffer = NULL; // for in-place encryption UINT32 buffersize = 0; BYTE keyToUse[MAX_SYM_KEY_BYTES]; UINT16 keyToUseLen = (UINT16)sizeof(keyToUse); TPM_RC retVal = TPM_RC_SUCCESS; int ivLen; pAssert(dOut != NULL && key != NULL && dIn != NULL); if(dSize == 0) return TPM_RC_SUCCESS; TEST(algorithm); blockSize = CryptGetSymmetricBlockSize(algorithm, keySizeInBits); if(blockSize == 0) return TPM_RC_FAILURE; // If the iv is provided, then it is expected to be block sized. In some cases, // the caller is providing an array of 0's that is equal to [MAX_SYM_BLOCK_SIZE] // with no knowledge of the actual block size. This function will set it. if((ivInOut != NULL) && (mode != TPM_ALG_ECB)) { ivInOut->t.size = blockSize; iv = ivInOut->t.buffer; } else iv = defaultIv; switch (mode) { case TPM_ALG_ECB: case TPM_ALG_CBC: // For ECB & CBC the data size must be an even multiple of the // cipher block size if((dSize % blockSize) != 0) return TPM_RC_SIZE; } evpfn = GetEVPCipher(algorithm, keySizeInBits, mode, key, keyToUse, &keyToUseLen); if (evpfn == NULL) return TPM_RC_FAILURE; if (dIn == dOut) { // in-place encryption; we use a temp buffer buffersize = TPM2_ROUNDUP(dSize, blockSize); buffer = malloc(buffersize); if (buffer == NULL) ERROR_RETURN(TPM_RC_FAILURE); pOut = buffer; } #if ALG_TDES && ALG_CTR if (algorithm == TPM_ALG_TDES && mode == TPM_ALG_CTR) { TDES_CTR(keyToUse, keyToUseLen * 8, dSize, dIn, iv, pOut, blockSize); outlen1 = dSize; ERROR_RETURN(TPM_RC_SUCCESS); } #endif ctx = EVP_CIPHER_CTX_new(); if (!ctx || EVP_EncryptInit_ex(ctx, evpfn(), NULL, keyToUse, iv) != 1 || EVP_CIPHER_CTX_set_padding(ctx, 0) != 1 || EVP_EncryptUpdate(ctx, pOut, &outlen1, dIn, dSize) != 1) ERROR_RETURN(TPM_RC_FAILURE); pAssert(outlen1 <= dSize || dSize >= outlen1 + blockSize); if (EVP_EncryptFinal_ex(ctx, pOut + outlen1, &outlen2) != 1) ERROR_RETURN(TPM_RC_FAILURE); if (ivInOut) { ivLen = EVP_CIPHER_CTX_iv_length(ctx); if (ivLen < 0 || (size_t)ivLen > sizeof(ivInOut->t.buffer)) ERROR_RETURN(TPM_RC_FAILURE); ivInOut->t.size = ivLen; memcpy(ivInOut->t.buffer, EVP_CIPHER_CTX_iv(ctx), ivInOut->t.size); } Exit: if (retVal == TPM_RC_SUCCESS && pOut != dOut) memcpy(dOut, pOut, outlen1 + outlen2); clear_and_free(buffer, buffersize); EVP_CIPHER_CTX_free(ctx); return retVal; } /* 10.2.20.5.1 CryptSymmetricDecrypt() */ /* This function performs symmetric decryption based on the mode. */ /* Error Returns Meaning */ /* TPM_RC_FAILURE A fatal error */ /* TPM_RCS_SIZE dSize is not a multiple of the block size for an algorithm that requires it */ LIB_EXPORT TPM_RC CryptSymmetricDecrypt( BYTE *dOut, // OUT: decrypted data TPM_ALG_ID algorithm, // IN: the symmetric algorithm UINT16 keySizeInBits, // IN: key size in bits const BYTE *key, // IN: key buffer. The size of this buffer // in bytes is (keySizeInBits + 7) / 8 TPM2B_IV *ivInOut, // IN/OUT: IV for decryption. TPM_ALG_ID mode, // IN: Mode to use INT32 dSize, // IN: data size (may need to be a // multiple of the blockSize) const BYTE *dIn // IN: data buffer ) { INT16 blockSize; BYTE *iv; BYTE defaultIv[MAX_SYM_BLOCK_SIZE] = {0}; evpfunc evpfn; EVP_CIPHER_CTX *ctx = NULL; int outlen1 = 0; int outlen2 = 0; BYTE *buffer; UINT32 buffersize = 0; BYTE keyToUse[MAX_SYM_KEY_BYTES]; UINT16 keyToUseLen = (UINT16)sizeof(keyToUse); TPM_RC retVal = TPM_RC_SUCCESS; int ivLen; // These are used but the compiler can't tell because they are initialized // in case statements and it can't tell if they are always initialized // when needed, so... Comment these out if the compiler can tell or doesn't // care that these are initialized before use. pAssert(dOut != NULL && key != NULL && dIn != NULL); if(dSize == 0) return TPM_RC_SUCCESS; TEST(algorithm); blockSize = CryptGetSymmetricBlockSize(algorithm, keySizeInBits); if(blockSize == 0) return TPM_RC_FAILURE; // If the iv is provided, then it is expected to be block sized. In some cases, // the caller is providing an array of 0's that is equal to [MAX_SYM_BLOCK_SIZE] // with no knowledge of the actual block size. This function will set it. if((ivInOut != NULL) && (mode != TPM_ALG_ECB)) { ivInOut->t.size = blockSize; iv = ivInOut->t.buffer; } else iv = defaultIv; switch(mode) { #if ALG_CBC || ALG_ECB case TPM_ALG_CBC: case TPM_ALG_ECB: // For ECB and CBC, the data size must be an even multiple of the // cipher block size if((dSize % blockSize) != 0) return TPM_RC_SIZE; break; #endif default: break; } evpfn = GetEVPCipher(algorithm, keySizeInBits, mode, key, keyToUse, &keyToUseLen); if (evpfn == NULL) return TPM_RC_FAILURE; /* a buffer with a 'safety margin' for EVP_DecryptUpdate */ buffersize = TPM2_ROUNDUP(dSize + blockSize, blockSize); buffer = malloc(buffersize); if (buffer == NULL) ERROR_RETURN(TPM_RC_FAILURE); #if ALG_TDES && ALG_CTR if (algorithm == TPM_ALG_TDES && mode == TPM_ALG_CTR) { TDES_CTR(keyToUse, keyToUseLen * 8, dSize, dIn, iv, buffer, blockSize); outlen1 = dSize; ERROR_RETURN(TPM_RC_SUCCESS); } #endif ctx = EVP_CIPHER_CTX_new(); if (!ctx || EVP_DecryptInit_ex(ctx, evpfn(), NULL, keyToUse, iv) != 1 || EVP_CIPHER_CTX_set_padding(ctx, 0) != 1 || EVP_DecryptUpdate(ctx, buffer, &outlen1, dIn, dSize) != 1) ERROR_RETURN(TPM_RC_FAILURE); pAssert((int)buffersize >= outlen1); if ((int)buffersize <= outlen1 /* coverity */ || EVP_DecryptFinal(ctx, &buffer[outlen1], &outlen2) != 1) ERROR_RETURN(TPM_RC_FAILURE); pAssert((int)buffersize >= outlen1 + outlen2); if (ivInOut) { ivLen = EVP_CIPHER_CTX_iv_length(ctx); if (ivLen < 0 || (size_t)ivLen > sizeof(ivInOut->t.buffer)) ERROR_RETURN(TPM_RC_FAILURE); ivInOut->t.size = ivLen; memcpy(ivInOut->t.buffer, EVP_CIPHER_CTX_iv(ctx), ivInOut->t.size); } Exit: if (retVal == TPM_RC_SUCCESS) { pAssert(dSize >= outlen1 + outlen2); memcpy(dOut, buffer, outlen1 + outlen2); } clear_and_free(buffer, buffersize); EVP_CIPHER_CTX_free(ctx); return retVal; } #endif // libtpms added end /* 10.2.20.5.2 CryptSymKeyValidate() */ /* Validate that a provided symmetric key meets the requirements of the TPM */ /* Error Returns Meaning */ /* TPM_RC_KEY_SIZE Key size specifiers do not match */ /* TPM_RC_KEY Key is not allowed */ TPM_RC CryptSymKeyValidate( TPMT_SYM_DEF_OBJECT *symDef, TPM2B_SYM_KEY *key ) { if(key->t.size != BITS_TO_BYTES(symDef->keyBits.sym)) return TPM_RCS_KEY_SIZE; #if ALG_TDES if(symDef->algorithm == TPM_ALG_TDES && !CryptDesValidateKey(key)) return TPM_RCS_KEY; #endif // TPM_ALG_TDES return TPM_RC_SUCCESS; } libtpms-0.9.3/src/tpm2/crypto/openssl/ExpDCache.c000066400000000000000000000162371421143571500216150ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Private Exponent D cache functions */ /* Written by Stefan Berger */ /* IBM Thomas J. Watson Research Center */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp., 2021 */ /* */ /********************************************************************************/ #include "Tpm.h" #include "ExpDCache_fp.h" /* Implement a cache for the private exponent D so it doesn't need to be * recalculated every time from P, Q, E and N (modulus). The cache has a * number of entries that cache D and use P, Q, and E for lookup. * A least-recently-used cache eviction strategy is implemented that evicts * the oldest cache entry in case space is needed. An entry is young once * it is added or made young when it was found via lookup. All other entries * age by '1' when an entry is added or accessed. */ struct ExpDCacheEntry { /* The age of the entry; the higher the number the more likely it * will be evicted soon */ unsigned int age; BIGNUM *P; /* input */ BIGNUM *N; /* input */ BIGNUM *E; /* input */ BIGNUM *Q; /* cached */ BIGNUM *D; /* cached */ }; #define DCACHE_NUM_ENTRIES 64 static struct ExpDCacheEntry ExpDCache[DCACHE_NUM_ENTRIES]; /* Increment the age of all cache entries that have a current age <= maxage */ static void ExpDCacheIncrementAge(unsigned maxage) { size_t i; for (i = 0; i < ARRAY_SIZE(ExpDCache); i++) { if (ExpDCache[i].age <= maxage && ExpDCache[i].D != NULL) ExpDCache[i].age++; } } /* Free the data associated with a ExpDCacheEntry and initialize it */ static void ExpDCacheEntryFree(struct ExpDCacheEntry *dce) { BN_clear_free(dce->P); BN_free(dce->N); BN_free(dce->E); BN_clear_free(dce->Q); BN_clear_free(dce->D); memset(dce, 0, sizeof(*dce)); } void ExpDCacheFree(void) { size_t i; for (i = 0; i < ARRAY_SIZE(ExpDCache); i++) ExpDCacheEntryFree(&ExpDCache[i]); } /* Get a ExpDCacheEntry by finding either an unused entry or evicting the oldest * entry. The returned entry will have all NULL pointers and age 0. */ static struct ExpDCacheEntry *ExpDCacheEntryGet(void) { size_t i, use_i = 0; unsigned oldest_age = 0; struct ExpDCacheEntry *dce; for (i = 0; i < ARRAY_SIZE(ExpDCache); i++) { if (ExpDCache[i].D == NULL) { /* use this free entry */ use_i = i; break; } if (ExpDCache[i].age > oldest_age) { /* this one is currently the oldest */ use_i = i; oldest_age = ExpDCache[i].age; } } dce = &ExpDCache[use_i]; ExpDCacheEntryFree(dce); return dce; } /* Add 'D' to the ExpDCache. This function does not check for duplicates */ void ExpDCacheAdd(const BIGNUM *P, const BIGNUM *N, const BIGNUM *E, const BIGNUM *Q, const BIGNUM *D) { struct ExpDCacheEntry *dce = ExpDCacheEntryGet(); /* age of 'dce' is '0' */ dce->P = BN_dup(P); dce->N = BN_dup(N); dce->E = BN_dup(E); dce->Q = BN_dup(Q); dce->D = BN_dup(D); if (!dce->P || !dce->N || !dce->E || !dce->Q || !dce->D) ExpDCacheEntryFree(dce); else ExpDCacheIncrementAge(~0); } BIGNUM *ExpDCacheFind(const BIGNUM *P, const BIGNUM *N, const BIGNUM *E, BIGNUM **Q) { size_t i; unsigned myage; BIGNUM *D; for (i = 0; i < ARRAY_SIZE(ExpDCache); i++) { if (BN_cmp(ExpDCache[i].P, P) == 0 && BN_cmp(ExpDCache[i].N, N) == 0 && BN_cmp(ExpDCache[i].E, E) == 0) { /* entry found */ myage = ExpDCache[i].age; /* mark this entry as most recently used */ ExpDCache[i].age = 0; /* Increment everyone who is <= 'myage'. * The age of this entry will be '1' after that. */ ExpDCacheIncrementAge(myage); *Q = BN_dup(ExpDCache[i].Q); if (*Q == NULL) return NULL; D = BN_dup(ExpDCache[i].D); if (D == NULL) { BN_clear_free(*Q); *Q = NULL; return NULL; } BN_set_flags(*Q, BN_FLG_CONSTTIME); BN_set_flags(D, BN_FLG_CONSTTIME); return D; } } return NULL; } libtpms-0.9.3/src/tpm2/crypto/openssl/ExpDCache_fp.h000066400000000000000000000071351421143571500223040ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Private Exponent D cache functions */ /* Written by Stefan Berger */ /* IBM Thomas J. Watson Research Center */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp., 2021 */ /* */ /********************************************************************************/ #ifndef DCACHE_FP_H #define DCACHE_FP_H #include BIGNUM *ExpDCacheFind(const BIGNUM *P, const BIGNUM *N, const BIGNUM *E, BIGNUM **Q); void ExpDCacheAdd(const BIGNUM *P, const BIGNUM *N, const BIGNUM *E, const BIGNUM *Q, const BIGNUM *D); void ExpDCacheFree(void); #endif /* DCACHE_FP_H */ libtpms-0.9.3/src/tpm2/crypto/openssl/Helpers.c000066400000000000000000000446111421143571500214300ustar00rootroot00000000000000/********************************************************************************/ /* */ /* OpenSSL helper functions */ /* Written by Stefan Berger */ /* IBM Thomas J. Watson Research Center */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2019 */ /* */ /********************************************************************************/ #include "Tpm.h" #include "ExpDCache_fp.h" #include "Helpers_fp.h" #include "TpmToOsslMath_fp.h" #include "config.h" #include #include /* to enable RSA_check_key() on private keys set to != 0 */ #ifndef DO_RSA_CHECK_KEY #define DO_RSA_CHECK_KEY 0 #endif #if USE_OPENSSL_FUNCTIONS_SYMMETRIC TPM_RC OpenSSLCryptGenerateKeyDes( TPMT_SENSITIVE *sensitive // OUT: sensitive area ) { DES_cblock *key; size_t offset; size_t limit; limit = MIN(sizeof(sensitive->sensitive.sym.t.buffer), sensitive->sensitive.sym.t.size); limit = TPM2_ROUNDUP(limit, sizeof(*key)); pAssert(limit < sizeof(sensitive->sensitive.sym.t.buffer)); for (offset = 0; offset < limit; offset += sizeof(*key)) { key = (DES_cblock *)&sensitive->sensitive.sym.t.buffer[offset]; if (DES_random_key(key) != 1) return TPM_RC_NO_RESULT; } return TPM_RC_SUCCESS; } evpfunc GetEVPCipher(TPM_ALG_ID algorithm, // IN UINT16 keySizeInBits, // IN TPM_ALG_ID mode, // IN const BYTE *key, // IN BYTE *keyToUse, // OUT same as key or stretched key UINT16 *keyToUseLen // IN/OUT ) { int i; UINT16 keySizeInBytes = keySizeInBits / 8; evpfunc evpfn = NULL; // key size to array index: 128 -> 0, 192 -> 1, 256 -> 2 i = (keySizeInBits >> 6) - 2; if (i < 0 || i > 2) return NULL; pAssert(*keyToUseLen >= keySizeInBytes) memcpy(keyToUse, key, keySizeInBytes); switch (algorithm) { #if ALG_AES case TPM_ALG_AES: *keyToUseLen = keySizeInBytes; switch (mode) { #if ALG_CTR case TPM_ALG_CTR: evpfn = (evpfunc []){EVP_aes_128_ctr, EVP_aes_192_ctr, EVP_aes_256_ctr}[i]; break; #endif #if ALG_OFB case TPM_ALG_OFB: evpfn = (evpfunc[]){EVP_aes_128_ofb, EVP_aes_192_ofb, EVP_aes_256_ofb}[i]; break; #endif #if ALG_CBC case TPM_ALG_CBC: evpfn = (evpfunc[]){EVP_aes_128_cbc, EVP_aes_192_cbc, EVP_aes_256_cbc}[i]; break; #endif #if ALG_CFB case TPM_ALG_CFB: evpfn = (evpfunc[]){EVP_aes_128_cfb, EVP_aes_192_cfb, EVP_aes_256_cfb}[i]; break; #endif #if ALG_ECB case TPM_ALG_ECB: evpfn = (evpfunc[]){EVP_aes_128_ecb, EVP_aes_192_ecb, EVP_aes_256_ecb}[i]; break; #endif } break; #endif #if ALG_TDES case TPM_ALG_TDES: if (keySizeInBits == 128) { pAssert(*keyToUseLen >= BITS_TO_BYTES(192)) // stretch the key memcpy(&keyToUse[16], &keyToUse[0], 8); *keyToUseLen = BITS_TO_BYTES(192); } switch (mode) { #if ALG_CTR case TPM_ALG_CTR: evpfn = (evpfunc[]){EVP_des_ede3, EVP_des_ede3, NULL}[i]; break; #endif #if ALG_OFB case TPM_ALG_OFB: evpfn = (evpfunc[]){EVP_des_ede3_ofb, EVP_des_ede3_ofb, NULL}[i]; break; #endif #if ALG_CBC case TPM_ALG_CBC: evpfn = (evpfunc[]){EVP_des_ede3_cbc, EVP_des_ede3_cbc, NULL}[i]; break; #endif #if ALG_CFB case TPM_ALG_CFB: evpfn = (evpfunc[]){EVP_des_ede3_cfb64, EVP_des_ede3_cfb64, NULL}[i]; break; #endif #if ALG_ECB case TPM_ALG_ECB: evpfn = (evpfunc[]){EVP_des_ede3_ecb, EVP_des_ede3_ecb, NULL}[i]; break; #endif } break; #endif #if ALG_SM4 case TPM_ALG_SM4: *keyToUseLen = keySizeInBytes; switch (mode) { #if ALG_CTR case TPM_ALG_CTR: evpfn = (evpfunc[]){EVP_sm4_ctr, NULL, NULL}[i]; break; #endif #if ALG_OFB case TPM_ALG_OFB: evpfn = (evpfunc[]){EVP_sm4_ofb, NULL, NULL}[i]; break; #endif #if ALG_CBC case TPM_ALG_CBC: evpfn = (evpfunc[]){EVP_sm4_cbc, NULL, NULL}[i]; break; #endif #if ALG_CFB case TPM_ALG_CFB: evpfn = (evpfunc[]){EVP_sm4_cfb, NULL, NULL}[i]; break; #endif #if ALG_ECB case TPM_ALG_ECB: evpfn = (evpfunc[]){EVP_sm4_ecb, NULL, NULL}[i]; break; #endif } break; #endif #if ALG_CAMELLIA case TPM_ALG_CAMELLIA: *keyToUseLen = keySizeInBytes; switch (mode) { #if ALG_CTR case TPM_ALG_CTR: evpfn = (evpfunc []){EVP_camellia_128_ctr, EVP_camellia_192_ctr, EVP_camellia_256_ctr}[i]; break; #endif #if ALG_OFB case TPM_ALG_OFB: evpfn = (evpfunc[]){EVP_camellia_128_ofb, EVP_camellia_192_ofb, EVP_camellia_256_ofb}[i]; break; #endif #if ALG_CBC case TPM_ALG_CBC: evpfn = (evpfunc[]){EVP_camellia_128_cbc, EVP_camellia_192_cbc, EVP_camellia_256_cbc}[i]; break; #endif #if ALG_CFB case TPM_ALG_CFB: evpfn = (evpfunc[]){EVP_camellia_128_cfb, EVP_camellia_192_cfb, EVP_camellia_256_cfb}[i]; break; #endif #if ALG_ECB case TPM_ALG_ECB: evpfn = (evpfunc[]){EVP_camellia_128_ecb, EVP_camellia_192_ecb, EVP_camellia_256_ecb}[i]; break; #endif } break; #endif } if (evpfn == NULL) MemorySet(keyToUse, 0, *keyToUseLen); return evpfn; } #endif // USE_OPENSSL_FUNCTIONS_SYMMETRIC #if USE_OPENSSL_FUNCTIONS_EC BOOL OpenSSLEccGetPrivate( bigNum dOut, // OUT: the qualified random value const EC_GROUP *G, // IN: the EC_GROUP to use const UINT32 requestedBits // IN: if not 0, then dOut must have that many bits ) { BOOL OK = FALSE; const BIGNUM *D; EC_KEY *eckey = EC_KEY_new(); UINT32 requestedBytes = BITS_TO_BYTES(requestedBits); int repeats = 0; int maxRepeats; int numBytes; pAssert(G != NULL); if (!eckey) return FALSE; if (EC_KEY_set_group(eckey, G) != 1) goto Exit; maxRepeats = 8; // non-byte boundary order'ed curves, like NIST P521, need more loops to // have a result with topmost byte != 0 if (requestedBits & 7) maxRepeats += (9 - (requestedBits & 7)); while (true) { if (EC_KEY_generate_key(eckey) == 1) { D = EC_KEY_get0_private_key(eckey); // if we need a certain amount of bytes and we are below a threshold // of loops, check the number of bytes we have, otherwise take the // result if ((requestedBytes != 0) && (repeats < maxRepeats)) { numBytes = BN_num_bytes(D); if ((int)requestedBytes != numBytes) { // result does not have enough bytes repeats++; continue; } // result is sufficient } OK = TRUE; OsslToTpmBn(dOut, D); } break; } Exit: EC_KEY_free(eckey); return OK; } #endif // USE_OPENSSL_FUNCTIONS_EC #if USE_OPENSSL_FUNCTIONS_RSA static const struct hnames { const char *name; TPM_ALG_ID hashAlg; } hnames[HASH_COUNT + 1] = { { #if ALG_SHA1 .name = "sha1", .hashAlg = ALG_SHA1_VALUE, }, { #endif #if ALG_SHA256 .name = "sha256", .hashAlg = ALG_SHA256_VALUE, }, { #endif #if ALG_SHA384 .name = "sha384", .hashAlg = ALG_SHA384_VALUE, }, { #endif #if ALG_SHA512 .name = "sha512", .hashAlg = ALG_SHA512_VALUE, }, { #endif .name = NULL, } }; #if HASH_COUNT != ALG_SHA1 + ALG_SHA256 + ALG_SHA384 + ALG_SHA512 # error Missing entry in hnames array! #endif LIB_EXPORT const char * GetDigestNameByHashAlg(const TPM_ALG_ID hashAlg) { unsigned i; for (i = 0; i < HASH_COUNT; i++) { if (hashAlg == hnames[i].hashAlg) return hnames[i].name; } return NULL; } static BOOL ComputePrivateExponentD( const BIGNUM *P, // IN: first prime (size is 1/2 of bnN) const BIGNUM *Q, // IN: second prime (size is 1/2 of bnN) const BIGNUM *E, // IN: the public exponent const BIGNUM *N, // IN: the public modulus BIGNUM **D // OUT: ) { BOOL pOK = FALSE; BIGNUM *phi; BN_CTX *ctx; // // compute Phi = (p - 1)(q - 1) = pq - p - q + 1 = n - p - q + 1 phi = BN_dup(N); ctx = BN_CTX_new(); if (phi && ctx) { pOK = BN_sub(phi, phi, P); pOK = pOK && BN_sub(phi, phi, Q); pOK = pOK && BN_add_word(phi, 1); // Compute the multiplicative inverse d = 1/e mod Phi BN_set_flags(phi, BN_FLG_CONSTTIME); // phi is secret pOK = pOK && (*D = BN_mod_inverse(NULL, E, phi, ctx)) != NULL; } BN_CTX_free(ctx); BN_clear_free(phi); return pOK; } LIB_EXPORT TPM_RC InitOpenSSLRSAPublicKey(OBJECT *key, // IN EVP_PKEY **pkey // OUT ) { TPM_RC retVal; RSA *rsakey = RSA_new(); BIGNUM *N = NULL; BIGNUM *E = BN_new(); BN_ULONG eval; *pkey = EVP_PKEY_new(); if (rsakey == NULL || *pkey == NULL || E == NULL) ERROR_RETURN(TPM_RC_FAILURE); if(key->publicArea.parameters.rsaDetail.exponent != 0) eval = key->publicArea.parameters.rsaDetail.exponent; else eval = RSA_DEFAULT_PUBLIC_EXPONENT; if (BN_set_word(E, eval) != 1) ERROR_RETURN(TPM_RC_FAILURE); N = BN_bin2bn(key->publicArea.unique.rsa.b.buffer, key->publicArea.unique.rsa.b.size, NULL); if (N == NULL || RSA_set0_key(rsakey, N, E, NULL) != 1 || EVP_PKEY_assign_RSA(*pkey, rsakey) == 0) ERROR_RETURN(TPM_RC_FAILURE) RSA_set_flags(rsakey, RSA_FLAG_NO_BLINDING); retVal = TPM_RC_SUCCESS; Exit: if (retVal != TPM_RC_SUCCESS) { RSA_free(rsakey); EVP_PKEY_free(*pkey); *pkey = NULL; } return retVal; } static void DoRSACheckKey(const BIGNUM *P, const BIGNUM *Q, const BIGNUM *N, const BIGNUM *E, const BIGNUM *D) { RSA *mykey; static int disp; if (!DO_RSA_CHECK_KEY) return; if (!disp) { fprintf(stderr, "RSA key checking is enabled\n"); disp = 1; } mykey = RSA_new(); RSA_set0_factors(mykey, BN_dup(P), BN_dup(Q)); RSA_set0_key(mykey, BN_dup(N), BN_dup(E), BN_dup(D)); if (RSA_check_key(mykey) != 1) { fprintf(stderr, "Detected bad RSA key. STOP.\n"); while (1); } RSA_free(mykey); } LIB_EXPORT TPM_RC InitOpenSSLRSAPrivateKey(OBJECT *rsaKey, // IN EVP_PKEY **pkey // OUT ) { const BIGNUM *N = NULL; const BIGNUM *E = NULL; BIGNUM *P = NULL; BIGNUM *Q = NULL; BIGNUM *Qr = NULL; BIGNUM *D = NULL; #if CRT_FORMAT_RSA == YES BIGNUM *dP = BN_new(); BIGNUM *dQ = BN_new(); BIGNUM *qInv = BN_new(); #endif RSA *key = NULL; BN_CTX *ctx = NULL; TPM_RC retVal = InitOpenSSLRSAPublicKey(rsaKey, pkey); if (retVal != TPM_RC_SUCCESS) return retVal; if(!rsaKey->attributes.privateExp) CryptRsaLoadPrivateExponent(rsaKey); P = BN_bin2bn(rsaKey->sensitive.sensitive.rsa.t.buffer, rsaKey->sensitive.sensitive.rsa.t.size, NULL); if (P == NULL) ERROR_RETURN(TPM_RC_FAILURE) key = EVP_PKEY_get1_RSA(*pkey); if (key == NULL) ERROR_RETURN(TPM_RC_FAILURE); RSA_get0_key(key, &N, &E, NULL); D = ExpDCacheFind(P, N, E, &Q); if (D == NULL) { ctx = BN_CTX_new(); Q = BN_new(); Qr = BN_new(); if (ctx == NULL || Q == NULL || Qr == NULL) ERROR_RETURN(TPM_RC_FAILURE); /* Q = N/P; no remainder */ BN_set_flags(P, BN_FLG_CONSTTIME); // P is secret BN_div(Q, Qr, N, P, ctx); if(!BN_is_zero(Qr)) ERROR_RETURN(TPM_RC_BINDING); BN_set_flags(Q, BN_FLG_CONSTTIME); // Q is secret if (ComputePrivateExponentD(P, Q, E, N, &D) == FALSE) ERROR_RETURN(TPM_RC_FAILURE); ExpDCacheAdd(P, N, E, Q, D); } if (RSA_set0_key(key, NULL, NULL, D) != 1) ERROR_RETURN(TPM_RC_FAILURE); DoRSACheckKey(P, Q, N, E, D); D = NULL; #if CRT_FORMAT_RSA == YES /* CRT parameters are not absolutely needed but may speed up ops */ dP = BigInitialized(dP, (bigConst)&rsaKey->privateExponent.dP); dQ = BigInitialized(dQ, (bigConst)&rsaKey->privateExponent.dQ); qInv = BigInitialized(qInv, (bigConst)&rsaKey->privateExponent.qInv); if (dP == NULL || dQ == NULL || qInv == NULL || RSA_set0_crt_params(key, dP, dQ, qInv) != 1) ERROR_RETURN(TPM_RC_FAILURE); #endif retVal = TPM_RC_SUCCESS; Exit: BN_CTX_free(ctx); BN_clear_free(P); BN_clear_free(Q); BN_free(Qr); RSA_free(key); // undo reference from EVP_PKEY_get1_RSA() if (retVal != TPM_RC_SUCCESS) { BN_clear_free(D); #if CRT_FORMAT_RSA == YES BN_clear_free(dP); BN_clear_free(dQ); BN_clear_free(qInv); #endif EVP_PKEY_free(*pkey); *pkey = NULL; } return retVal; } LIB_EXPORT TPM_RC OpenSSLCryptRsaGenerateKey( OBJECT *rsaKey, // IN/OUT: The object structure in which // the key is created. UINT32 e, int keySizeInBits ) { TPMT_PUBLIC *publicArea = &rsaKey->publicArea; TPMT_SENSITIVE *sensitive = &rsaKey->sensitive; TPM_RC retVal = TPM_RC_SUCCESS; int rc; RSA *rsa = NULL; const BIGNUM *bnP = NULL; const BIGNUM *bnN = NULL; BIGNUM *bnE = BN_new(); BN_RSA(tmp); if (bnE == NULL || BN_set_word(bnE, e) != 1) ERROR_RETURN(TPM_RC_FAILURE); // Need to initialize the privateExponent structure RsaInitializeExponent(&rsaKey->privateExponent); rsa = RSA_new(); if (rsa == NULL) ERROR_RETURN(TPM_RC_FAILURE); rc = RSA_generate_key_ex(rsa, keySizeInBits, bnE, NULL); if (rc == 0) ERROR_RETURN(TPM_RC_NO_RESULT); RSA_get0_key(rsa, &bnN, NULL, NULL); RSA_get0_factors(rsa, &bnP, NULL); OsslToTpmBn(tmp, bnN); BnTo2B((bigNum)tmp, &publicArea->unique.rsa.b, 0); OsslToTpmBn(tmp, bnP); BnTo2B((bigNum)tmp, &sensitive->sensitive.rsa.b, 0); // CryptRsaGenerateKey calls ComputePrivateExponent; we have to call // it via CryptRsaLoadPrivateExponent retVal = CryptRsaLoadPrivateExponent(rsaKey); Exit: BN_free(bnE); RSA_free(rsa); return retVal; } #endif // USE_OPENSSL_FUNCTIONS_RSA libtpms-0.9.3/src/tpm2/crypto/openssl/Helpers_fp.h000066400000000000000000000120251421143571500221140ustar00rootroot00000000000000/********************************************************************************/ /* */ /* OpenSSL helper functions */ /* Written by Stefan Berger */ /* IBM Thomas J. Watson Research Center */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2019 */ /* */ /********************************************************************************/ #ifndef HELPERS_FP_H #define HELPERS_FP_H #include "TpmTypes.h" #include #if USE_OPENSSL_FUNCTIONS_SYMMETRIC TPM_RC OpenSSLCryptGenerateKeyDes( TPMT_SENSITIVE *sensitive // OUT: sensitive area ); typedef const EVP_CIPHER *(*evpfunc)(void); evpfunc GetEVPCipher(TPM_ALG_ID algorithm, // IN UINT16 keySizeInBits, // IN TPM_ALG_ID mode, // IN const BYTE *key, // IN BYTE *keyToUse, // OUT same as key or stretched key UINT16 *keyToUseLen // IN/OUT ); #endif #if USE_OPENSSL_FUNCTIONS_EC BOOL OpenSSLEccGetPrivate( bigNum dOut, // OUT: the qualified random value const EC_GROUP *G, // IN: the EC_GROUP to use const UINT32 requestedBits // IN: if not 0, then dOut must have that many bits ); #endif #if USE_OPENSSL_FUNCTIONS_RSA const char *GetDigestNameByHashAlg(const TPM_ALG_ID hashAlg); LIB_EXPORT TPM_RC OpenSSLCryptRsaGenerateKey( OBJECT *rsaKey, // IN/OUT: The object structure in which // the key is created. UINT32 e, int keySizeInBits ); LIB_EXPORT TPM_RC InitOpenSSLRSAPublicKey(OBJECT *key, // IN EVP_PKEY **pkey //OUT ); LIB_EXPORT TPM_RC InitOpenSSLRSAPrivateKey(OBJECT *rsaKey, // IN EVP_PKEY **pkey // OUT ); #endif // USE_OPENSSL_FUNCTIONS_RSA #endif /* HELPERS_FP_H */ libtpms-0.9.3/src/tpm2/crypto/openssl/LibSupport.h000066400000000000000000000115121421143571500221300ustar00rootroot00000000000000/********************************************************************************/ /* */ /* select the library code that gets included in the TPM build */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: LibSupport.h 1656 2021-01-15 21:45:18Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2020 */ /* */ /********************************************************************************/ // 5.12 LibSupport.h // This header file is used to select the library code that gets included in the TPM build #ifndef _LIB_SUPPORT_H_ #define _LIB_SUPPORT_H_ #if 0 // libtpms added /* kgold added power and s390 */ #ifndef RADIX_BITS # if defined(__x86_64__) || defined(__x86_64) \ || defined(__amd64__) || defined(__amd64) \ || defined(_WIN64) || defined(_M_X64) \ || defined(_M_ARM64) || defined(__aarch64__) \ || defined(__powerpc64__) || defined(__PPC64__) || defined(__ppc64__) \ || defined(__s390x__) # define RADIX_BITS 64 # elif defined(__i386__) || defined(__i386) || defined(i386) \ || defined(_WIN32) || defined(_M_IX86) \ || defined(_M_ARM) || defined(__arm__) || defined(__thumb__) \ || defined(__powerpc__) || defined(__PPC__) # define RADIX_BITS 32 # else # error Unable to determine RADIX_BITS from compiler environment # endif #endif // RADIX_BITS #endif // libtpms added // These macros use the selected libraries to the proper include files. #define LIB_QUOTE(_STRING_) #_STRING_ #define LIB_INCLUDE2(_LIB_, _TYPE_) LIB_QUOTE(TpmTo##_LIB_##_TYPE_.h) #define LIB_INCLUDE(_LIB_, _TYPE_) LIB_INCLUDE2(_LIB_, _TYPE_) // Include the options for hashing and symmetric. Defer the load of the math package until the // bignum parameters are defined. #include LIB_INCLUDE(SYM_LIB, Sym) #include LIB_INCLUDE(HASH_LIB, Hash) #undef MIN #undef MAX #endif // _LIB_SUPPORT_H_ libtpms-0.9.3/src/tpm2/crypto/openssl/TpmToOsslDesSupport.c000066400000000000000000000126541421143571500237650ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM DES Support */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: TpmToOsslDesSupport.c 1476 2019-06-10 19:32:03Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ /* B.2.3.1. TpmToOsslDesSupport.c */ /* B.2.3.1.1. Introduction */ /* The functions in this file are used for initialization of the interface to the OpenSSL library. */ /* B.2.3.1.2. Defines and Includes */ #include "Tpm.h" #if (defined SYM_LIB_OSSL) && ALG_TDES /* B.2.3.1.3. Functions */ /* B.2.3.1.3.1. TDES_set_encyrpt_key() */ /* This function makes creation of a TDES key look like the creation of a key for any of the other OpenSSL block ciphers. It will create three key schedules, one for each of the DES keys. If there are only two keys, then the third schedule is a copy of the first. */ void TDES_set_encrypt_key( const BYTE *key, UINT16 keySizeInBits, tpmKeyScheduleTDES *keySchedule ) { DES_set_key_unchecked((const_DES_cblock *)key, &keySchedule[0]); DES_set_key_unchecked((const_DES_cblock *)&key[8], &keySchedule[1]); // If is two-key, copy the schedule for K1 into K3, otherwise, compute the // the schedule for K3 if(keySizeInBits == 128) keySchedule[2] = keySchedule[0]; else DES_set_key_unchecked((const_DES_cblock *)&key[16], &keySchedule[2]); } /* B.2.3.1.3.2. TDES_encyrpt() */ /* The TPM code uses one key schedule. For TDES, the schedule contains three schedules. OpenSSL wants the schedules referenced separately. This function does that. */ void TDES_encrypt( const BYTE *in, BYTE *out, tpmKeyScheduleTDES *ks ) { DES_ecb3_encrypt((const_DES_cblock *)in, (DES_cblock *)out, &ks[0], &ks[1], &ks[2], DES_ENCRYPT); } #if !USE_OPENSSL_FUNCTIONS_SYMMETRIC /* B.2.3.1.3.3. TDES_decrypt() */ /* As with TDES_encypt() this function bridges between the TPM single schedule model and the OpenSSL three schedule model. */ void TDES_decrypt( const BYTE *in, BYTE *out, tpmKeyScheduleTDES *ks ) { DES_ecb3_encrypt((const_DES_cblock *)in, (DES_cblock *)out, &ks[0], &ks[1], &ks[2], DES_DECRYPT); } #endif // !USE_OPENSSL_FUNCTIONS_SYMMETRIC #endif // SYM_LIB_OSSL libtpms-0.9.3/src/tpm2/crypto/openssl/TpmToOsslDesSupport_fp.h000066400000000000000000000074531421143571500244600ustar00rootroot00000000000000/********************************************************************************/ /* */ /* */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: TpmToOsslDesSupport_fp.h 809 2016-11-16 18:31:54Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 */ /* */ /********************************************************************************/ #ifndef TPMTOOSSLDESSUPPORT_FP_H #define TPMTOOSSLDESSUPPORT_FP_H void TDES_set_encrypt_key( const BYTE *key, UINT16 keySizeInBits, tpmKeyScheduleTDES *keySchedule ); void TDES_encrypt( const BYTE *in, BYTE *out, tpmKeyScheduleTDES *ks ); void TDES_decrypt( const BYTE *in, BYTE *out, tpmKeyScheduleTDES *ks ); #endif libtpms-0.9.3/src/tpm2/crypto/openssl/TpmToOsslHash.h000066400000000000000000000242521421143571500225420ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Used to splice the OpenSSL() hash code into the TPM code */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: TpmToOsslHash.h 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2021 */ /* */ /********************************************************************************/ /* B.2.2.1. TpmToOsslHash.h */ /* B.2.2.1.1. Introduction */ /* This header file is used to splice the OpenSSL hash code into the TPM code. */ #ifndef HASH_LIB_DEFINED #define HASH_LIB_DEFINED #define HASH_LIB_OSSL #include #include #if ALG_SM3_256 # if defined(OPENSSL_NO_SM3) || OPENSSL_VERSION_NUMBER < 0x10101010L # if ALG_SM3_256 // libtpms added begin # error This version of OpenSSL does not support SM3 # endif // libtpms added end # undef ALG_SM3_256 # define ALG_SM3_256 ALG_NO # elif OPENSSL_VERSION_NUMBER >= 0x10200000L # include # else // OpenSSL 1.1.1 keeps smX.h headers in the include/crypto directory, // and they do not get installed as part of the libssl package # define SM3_LBLOCK (64/4) # error Check support for this version of SM3 in OpenSSL (libtpms) typedef struct SM3state_st { unsigned int A, B, C, D, E, F, G, H; unsigned int Nl, Nh; unsigned int data[SM3_LBLOCK]; unsigned int num; } SM3_CTX; int sm3_init(SM3_CTX *c); int sm3_update(SM3_CTX *c, const void *data, size_t len); int sm3_final(unsigned char *md, SM3_CTX *c); # endif // OpenSSL < 1.2 #endif // ALG_SM3_256 #include #define HASH_ALIGNMENT RADIX_BYTES /* libtpms: keep; not sure whether needed */ /* B.2.2.1.2. Links to the OpenSSL HASH code */ /* Redefine the internal name used for each of the hash state structures to the name used by the library. These defines need to be known in all parts of the TPM so that the structure sizes can be properly computed when needed. */ #define tpmHashStateSHA1_t SHA_CTX #define tpmHashStateSHA256_t SHA256_CTX #define tpmHashStateSHA384_t SHA512_CTX #define tpmHashStateSHA512_t SHA512_CTX #define tpmHashStateSM3_256_t SM3_CTX #if ALG_SM3_256 # error "The version of OpenSSL used by this code does not support SM3" #endif /* The defines below are only needed when compiling CryptHash.c or CryptSmac.c. This isolation is primarily to avoid name space collision. However, if there is a real collision, it will likely show up when the linker tries to put things together. */ #ifdef _CRYPT_HASH_C_ typedef BYTE *PBYTE; typedef const BYTE *PCBYTE; /* Define the interface between CryptHash.c to the functions provided by the library. For each method, define the calling parameters of the method and then define how the method is invoked in CryptHash.c. */ /* All hashes are required to have the same calling sequence. If they don't, create a simple adaptation function that converts from the standard form of the call to the form used by the specific hash (and then send a nasty letter to the person who wrote the hash function for the library). */ /* The macro that calls the method also defines how the parameters get swizzled between the default form (in CryptHash.c)and the library form. */ #define HASH_ALIGNMENT RADIX_BYTES /* Initialize the hash context */ #define HASH_START_METHOD_DEF void (HASH_START_METHOD)(PANY_HASH_STATE state) #define HASH_START(hashState) \ ((hashState)->def->method.start)(&(hashState)->state); /* Add data to the hash */ #define HASH_DATA_METHOD_DEF \ void (HASH_DATA_METHOD)(PANY_HASH_STATE state, \ PCBYTE buffer, \ size_t size) #define HASH_DATA(hashState, dInSize, dIn) \ ((hashState)->def->method.data)(&(hashState)->state, dIn, dInSize) /* Finalize the hash and get the digest */ #define HASH_END_METHOD_DEF \ void (HASH_END_METHOD)(BYTE *buffer, PANY_HASH_STATE state) #define HASH_END(hashState, buffer) \ ((hashState)->def->method.end)(buffer, &(hashState)->state) /* Copy the hash context */ /* NOTE: For import, export, and copy, memcpy() is used since there is no reformatting necessary between the internal and external forms. */ #define HASH_STATE_COPY_METHOD_DEF \ void (HASH_STATE_COPY_METHOD)(PANY_HASH_STATE to, \ PCANY_HASH_STATE from, \ size_t size) #define HASH_STATE_COPY(hashStateOut, hashStateIn) \ ((hashStateIn)->def->method.copy)(&(hashStateOut)->state, \ &(hashStateIn)->state, \ (hashStateIn)->def->contextSize) /* Copy (with reformatting when necessary) an internal hash structure to an external blob */ #define HASH_STATE_EXPORT_METHOD_DEF \ void (HASH_STATE_EXPORT_METHOD)(BYTE *to, \ PCANY_HASH_STATE from, \ size_t size) #define HASH_STATE_EXPORT(to, hashStateFrom) \ ((hashStateFrom)->def->method.copyOut) \ (&(((BYTE *)(to))[offsetof(HASH_STATE, state)]), \ &(hashStateFrom)->state, \ (hashStateFrom)->def->contextSize) /* Copy from an external blob to an internal format (with reformatting when necessary) */ #define HASH_STATE_IMPORT_METHOD_DEF \ void (HASH_STATE_IMPORT_METHOD)(PANY_HASH_STATE to, \ const BYTE *from, \ size_t size) #define HASH_STATE_IMPORT(hashStateTo, from) \ ((hashStateTo)->def->method.copyIn) \ (&(hashStateTo)->state, \ &(((const BYTE *)(from))[offsetof(HASH_STATE, state)]), \ (hashStateTo)->def->contextSize) /* Function aliases. The code in CryptHash.c uses the internal designation for the functions. These need to be translated to the function names of the library. */ #define tpmHashStart_SHA1 SHA1_Init // external name of the initialization method #define tpmHashData_SHA1 SHA1_Update #define tpmHashEnd_SHA1 SHA1_Final #define tpmHashStateCopy_SHA1 memcpy #define tpmHashStateExport_SHA1 memcpy #define tpmHashStateImport_SHA1 memcpy #define tpmHashStart_SHA256 SHA256_Init #define tpmHashData_SHA256 SHA256_Update #define tpmHashEnd_SHA256 SHA256_Final #define tpmHashStateCopy_SHA256 memcpy #define tpmHashStateExport_SHA256 memcpy #define tpmHashStateImport_SHA256 memcpy #define tpmHashStart_SHA384 SHA384_Init #define tpmHashData_SHA384 SHA384_Update #define tpmHashEnd_SHA384 SHA384_Final #define tpmHashStateCopy_SHA384 memcpy #define tpmHashStateExport_SHA384 memcpy #define tpmHashStateImport_SHA384 memcpy #define tpmHashStart_SHA512 SHA512_Init #define tpmHashData_SHA512 SHA512_Update #define tpmHashEnd_SHA512 SHA512_Final #define tpmHashStateCopy_SHA512 memcpy #define tpmHashStateExport_SHA512 memcpy #define tpmHashStateImport_SHA512 memcpy #define tpmHashStart_SM3_256 sm3_init #define tpmHashData_SM3_256 sm3_update #define tpmHashEnd_SM3_256 sm3_final #define tpmHashStateCopy_SM3_256 memcpy #define tpmHashStateExport_SM3_256 memcpy #define tpmHashStateImport_SM3_256 memcpy #endif // _CRYPT_HASH_C_ #define LibHashInit() /* This definition would change if there were something to report */ #define HashLibSimulationEnd() #endif // // HASH_LIB_DEFINED libtpms-0.9.3/src/tpm2/crypto/openssl/TpmToOsslMath.c000066400000000000000000000560761421143571500225540ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM to OpenSSL BigNum Shim Layer */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: TpmToOsslMath.c 1598 2020-03-27 21:59:49Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2020 */ /* */ /********************************************************************************/ /* B.2.3.2. TpmToOsslMath.c */ /* B.2.3.2.1. Introduction */ /* The functions in this file provide the low-level interface between the TPM code and the big number and elliptic curve math routines in OpenSSL. */ /* Most math on big numbers require a context. The context contains the memory in which OpenSSL creates and manages the big number values. When a OpenSSL math function will be called that modifies a BIGNUM value, that value must be created in an OpenSSL context. The first line of code in such a function must be: OSSL_ENTER(); and the last operation before returning must be OSSL_LEAVE(). OpenSSL variables can then be created with BnNewVariable(). Constant values to be used by OpenSSL are created from the bigNum values passed to the functions in this file. Space for the BIGNUM control block is allocated in the stack of the function and then it is initialized by calling BigInitialized(). That function sets up the values in the BIGNUM structure and sets the data pointer to point to the data in the bignum_t. This is only used when the value is known to be a constant in the called function. */ /* Because the allocations of constants is on the local stack and the OSSL_ENTER()/OSSL_LEAVE() pair flushes everything created in OpenSSL memory, there should be no chance of a memory leak. */ #include "Tpm.h" #ifdef MATH_LIB_OSSL #include "TpmToOsslMath_fp.h" /* B.2.3.2.3.1. OsslToTpmBn() */ /* This function converts an OpenSSL BIGNUM to a TPM bignum. In this implementation it is assumed that OpenSSL uses a different control structure but the same data layout -- an array of native-endian words in little-endian order. */ /* Return Value Meaning */ /* TRUE(1) success */ /* FALSE(0) failure because value will not fit or OpenSSL variable doesn't exist */ BOOL OsslToTpmBn( bigNum bn, const BIGNUM *osslBn // libtpms: added 'const' ) { VERIFY(osslBn != NULL); // If the bn is NULL, it means that an output value pointer was NULL meaning that // the results is simply to be discarded. unsigned char buffer[LARGEST_NUMBER + 1]; // libtpms added int buffer_len; // libtpms added if(bn != NULL) { #if 1 //libtpms added begin int num_bytes; num_bytes = BN_num_bytes(osslBn); VERIFY(num_bytes >= 0 && sizeof(buffer) >= (size_t)num_bytes); buffer_len = BN_bn2bin(osslBn, buffer); /* ossl to bin */ BnFromBytes(bn, buffer, buffer_len); /* bin to TPM */ #else // libtpms added end int i; // VERIFY((unsigned)osslBn->top <= BnGetAllocated(bn)); for(i = 0; i < osslBn->top; i++) bn->d[i] = osslBn->d[i]; BnSetTop(bn, osslBn->top); #endif // libtpms added } return TRUE; Error: return FALSE; } /* B.2.3.2.3.2. BigInitialized() */ /* This function initializes an OSSL BIGNUM from a TPM bigConst. Do not use this for values that are passed to OpenSLL when they are not declared as const in the function prototype. Instead, use BnNewVariable(). */ BIGNUM * BigInitialized( BIGNUM *toInit, bigConst initializer ) { #if 1 // libtpms added begin BIGNUM *_toInit; unsigned char buffer[LARGEST_NUMBER + 1]; NUMBYTES buffer_len = (NUMBYTES )sizeof(buffer); #endif // libtpms added end if(initializer == NULL) FAIL(FATAL_ERROR_PARAMETER); if(toInit == NULL || initializer == NULL) return NULL; #if 1 // libtpms added begin BnToBytes(initializer, buffer, &buffer_len); /* TPM to bin */ _toInit = BN_bin2bn(buffer, buffer_len, NULL); /* bin to ossl */ BN_set_flags(_toInit, BN_FLG_CONSTTIME); BN_copy(toInit, _toInit); BN_clear_free(_toInit); #else // libtpms added end toInit->d = (BN_ULONG *)&initializer->d[0]; toInit->dmax = (int)initializer->allocated; toInit->top = (int)initializer->size; toInit->neg = 0; toInit->flags = 0; #endif return toInit; } #ifndef OSSL_DEBUG # define BIGNUM_PRINT(label, bn, eol) # define DEBUG_PRINT(x) #else # define DEBUG_PRINT(x) printf("%s", x) # define BIGNUM_PRINT(label, bn, eol) BIGNUM_print((label), (bn), (eol)) static void BIGNUM_print( const char *label, const BIGNUM *a, BOOL eol ) { BN_ULONG *d; int i; int notZero = FALSE; if(label != NULL) printf("%s", label); if(a == NULL) { printf("NULL"); goto done; } if (a->neg) printf("-"); for(i = a->top, d = &a->d[i - 1]; i > 0; i--) { int j; BN_ULONG l = *d--; for(j = BN_BITS2 - 8; j >= 0; j -= 8) { BYTE b = (BYTE)((l >> j) & 0xFF); notZero = notZero || (b != 0); if(notZero) printf("%02x", b); } if(!notZero) printf("0"); } done: if(eol) printf("\n"); return; } #endif /* B.2.3.2.3.4. BnNewVariable() */ /* This function allocates a new variable in the provided context. If the context does not exist or the allocation fails, it is a catastrophic failure. */ static BIGNUM * BnNewVariable( BN_CTX *CTX ) { BIGNUM *new; // // This check is intended to protect against calling this function without // having initialized the CTX. if((CTX == NULL) || ((new = BN_CTX_get(CTX)) == NULL)) FAIL(FATAL_ERROR_ALLOCATION); return new; } #if LIBRARY_COMPATIBILITY_CHECK BOOL MathLibraryCompatibilityCheck( void ) { OSSL_ENTER(); BIGNUM *osslTemp = BnNewVariable(CTX); #if 0 crypt_uword_t i; #endif BYTE test[] = {0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00}; BN_VAR(tpmTemp, sizeof(test) * 8); // allocate some space for a test value // // Convert the test data to a bigNum BnFromBytes(tpmTemp, test, sizeof(test)); // Convert the test data to an OpenSSL BIGNUM BN_bin2bn(test, sizeof(test), osslTemp); // Make sure the values are consistent #if 0 VERIFY(osslTemp->top == (int)tpmTemp->size); for(i = 0; i < tpmTemp->size; i++) VERIFY(osslTemp->d[i] == tpmTemp->d[i]); #endif OSSL_LEAVE(); return 1; #if 0 Error: return 0; #endif } #endif /* B.2.3.2.3.3. BnModMult() */ /* Does multiply and divide returning the remainder of the divide. */ /* Return Value Meaning */ /* TRUE(1) success */ /* FALSE(0) failure in operation */ LIB_EXPORT BOOL BnModMult( bigNum result, bigConst op1, bigConst op2, bigConst modulus ) { OSSL_ENTER(); BOOL OK = TRUE; BIGNUM *bnResult = BN_NEW(); BIGNUM *bnTemp = BN_NEW(); BIG_INITIALIZED(bnOp1, op1); BIG_INITIALIZED(bnOp2, op2); BIG_INITIALIZED(bnMod, modulus); // VERIFY(BN_mul(bnTemp, bnOp1, bnOp2, CTX)); VERIFY(BN_div(NULL, bnResult, bnTemp, bnMod, CTX)); VERIFY(OsslToTpmBn(result, bnResult)); goto Exit; Error: OK = FALSE; Exit: BN_clear_free(bnMod); // libtpms added BN_clear_free(bnOp2); // libtpms added BN_clear_free(bnOp1); // libtpms added OSSL_LEAVE(); return OK; } /* B.2.3.2.3.4. BnMult() */ /* Multiplies two numbers */ /* Return Value Meaning */ /* TRUE(1) success */ /* FALSE(0) failure in operation */ LIB_EXPORT BOOL BnMult( bigNum result, bigConst multiplicand, bigConst multiplier ) { OSSL_ENTER(); BIGNUM *bnTemp = BN_NEW(); BOOL OK = TRUE; BIG_INITIALIZED(bnA, multiplicand); BIG_INITIALIZED(bnB, multiplier); // VERIFY(BN_mul(bnTemp, bnA, bnB, CTX)); VERIFY(OsslToTpmBn(result, bnTemp)); goto Exit; Error: OK = FALSE; Exit: BN_clear_free(bnB); // libtpms added BN_clear_free(bnA); // libtpms added OSSL_LEAVE(); return OK; } /* B.2.3.2.3.5. BnDiv() */ /* This function divides two bigNum values. The function returns FALSE if there is an error in the operation. */ /* Return Value Meaning */ /* TRUE(1) success */ /* FALSE(0) failure in operation */ LIB_EXPORT BOOL BnDiv( bigNum quotient, bigNum remainder, bigConst dividend, bigConst divisor ) { OSSL_ENTER(); BIGNUM *bnQ = BN_NEW(); BIGNUM *bnR = BN_NEW(); BOOL OK = TRUE; BIG_INITIALIZED(bnDend, dividend); BIG_INITIALIZED(bnSor, divisor); // if(BnEqualZero(divisor)) FAIL(FATAL_ERROR_DIVIDE_ZERO); VERIFY(BN_div(bnQ, bnR, bnDend, bnSor, CTX)); VERIFY(OsslToTpmBn(quotient, bnQ)); VERIFY(OsslToTpmBn(remainder, bnR)); DEBUG_PRINT("In BnDiv:\n"); BIGNUM_PRINT(" bnDividend: ", bnDend, TRUE); BIGNUM_PRINT(" bnDivisor: ", bnSor, TRUE); BIGNUM_PRINT(" bnQuotient: ", bnQ, TRUE); BIGNUM_PRINT(" bnRemainder: ", bnR, TRUE); goto Exit; Error: OK = FALSE; Exit: BN_clear_free(bnSor); // libtpms added BN_clear_free(bnDend); // libtpms added OSSL_LEAVE(); return OK; } #if ALG_RSA #if !RSA_KEY_SIEVE // libtpms added /* B.2.3.2.3.6. BnGcd() */ /* Get the greatest common divisor of two numbers */ /* Return Value Meaning */ /* TRUE(1) success */ /* FALSE(0) failure in operation */ LIB_EXPORT BOOL BnGcd( bigNum gcd, // OUT: the common divisor bigConst number1, // IN: bigConst number2 // IN: ) { OSSL_ENTER(); BIGNUM *bnGcd = BN_NEW(); BOOL OK = TRUE; BIG_INITIALIZED(bn1, number1); BIG_INITIALIZED(bn2, number2); // BN_set_flags(bn1, BN_FLG_CONSTTIME); // number1 is secret prime number VERIFY(BN_gcd(bnGcd, bn1, bn2, CTX)); VERIFY(OsslToTpmBn(gcd, bnGcd)); goto Exit; Error: OK = FALSE; Exit: BN_clear_free(bn2); // libtpms added BN_clear_free(bn1); // libtpms added OSSL_LEAVE(); return OK; } #endif // libtpms added /* B.2.3.2.3.7. BnModExp() */ /* Do modular exponentiation using bigNum values. The conversion from a bignum_t to a bigNum is trivial as they are based on the same structure */ /* Return Value Meaning */ /* TRUE(1) success */ /* FALSE(0) failure in operation */ LIB_EXPORT BOOL BnModExp( bigNum result, // OUT: the result bigConst number, // IN: number to exponentiate bigConst exponent, // IN: bigConst modulus // IN: ) { OSSL_ENTER(); BIGNUM *bnResult = BN_NEW(); BOOL OK = TRUE; BIG_INITIALIZED(bnN, number); BIG_INITIALIZED(bnE, exponent); BIG_INITIALIZED(bnM, modulus); // BN_set_flags(bnE, BN_FLG_CONSTTIME); // exponent may be private VERIFY(BN_mod_exp(bnResult, bnN, bnE, bnM, CTX)); VERIFY(OsslToTpmBn(result, bnResult)); goto Exit; Error: OK = FALSE; Exit: BN_clear_free(bnM); // libtpms added BN_clear_free(bnE); // libtpms added BN_clear_free(bnN); // libtpms added OSSL_LEAVE(); return OK; } /* B.2.3.2.3.8. BnModInverse() */ /* Modular multiplicative inverse */ /* Return Value Meaning */ /* TRUE(1) success */ /* FALSE(0) failure in operation */ LIB_EXPORT BOOL BnModInverse( bigNum result, bigConst number, bigConst modulus ) { OSSL_ENTER(); BIGNUM *bnResult = BN_NEW(); BOOL OK = TRUE; BIG_INITIALIZED(bnN, number); BIG_INITIALIZED(bnM, modulus); // BN_set_flags(bnN, BN_FLG_CONSTTIME); // number may be private VERIFY(BN_mod_inverse(bnResult, bnN, bnM, CTX) != NULL); VERIFY(OsslToTpmBn(result, bnResult)); goto Exit; Error: OK = FALSE; Exit: BN_clear_free(bnM); // libtpms added BN_clear_free(bnN); // libtpms added OSSL_LEAVE(); return OK; } #endif // TPM_ALG_RSA #if ALG_ECC /* B.2.3.2.3.9. PointFromOssl() */ /* Function to copy the point result from an OSSL function to a bigNum */ /* Return Value Meaning */ /* TRUE(1) success */ /* FALSE(0) failure in operation */ static BOOL PointFromOssl( bigPoint pOut, // OUT: resulting point EC_POINT *pIn, // IN: the point to return bigCurve E // IN: the curve ) { BIGNUM *x = NULL; BIGNUM *y = NULL; BOOL OK; BN_CTX_start(E->CTX); // x = BN_CTX_get(E->CTX); y = BN_CTX_get(E->CTX); if(y == NULL) FAIL(FATAL_ERROR_ALLOCATION); // If this returns false, then the point is at infinity #if OPENSSL_VERSION_NUMBER >= 0x10100000L && \ !defined(LIBRESSL_VERSION_NUMBER) // libtpms added begin OK = EC_POINT_get_affine_coordinates(E->G, pIn, x, y, E->CTX); #else // libtpms added begin OK = EC_POINT_get_affine_coordinates_GFp(E->G, pIn, x, y, E->CTX); #endif // libtpms added end if(OK) { OsslToTpmBn(pOut->x, x); OsslToTpmBn(pOut->y, y); BnSetWord(pOut->z, 1); } else BnSetWord(pOut->z, 0); BN_CTX_end(E->CTX); return OK; } /* B.2.3.2.3.10. EcPointInitialized() */ /* Allocate and initialize a point. */ LIB_EXPORT EC_POINT * // libtpms: exported function EcPointInitialized( pointConst initializer, bigCurve E ) { EC_POINT *P = NULL; if(initializer != NULL) { BIG_INITIALIZED(bnX, initializer->x); BIG_INITIALIZED(bnY, initializer->y); if(E == NULL) FAIL(FATAL_ERROR_ALLOCATION); P = EC_POINT_new(E->G); #if OPENSSL_VERSION_NUMBER >= 0x10100000L && \ !defined(LIBRESSL_VERSION_NUMBER) // libtpms added begin if(!EC_POINT_set_affine_coordinates(E->G, P, bnX, bnY, E->CTX)) #else // libtpms added end if(!EC_POINT_set_affine_coordinates_GFp(E->G, P, bnX, bnY, E->CTX)) #endif // libtpms added P = NULL; BN_clear_free(bnX); // libtpms added BN_clear_free(bnY); // libtpms added } return P; } /* B.2.3.2.3.11. BnCurveInitialize() */ /* This function initializes the OpenSSL group definition */ /* It is a fatal error if groupContext is not provided. */ /* Return Values Meaning */ /* NULL the TPM_ECC_CURVE is not valid */ /* non-NULL points to a structure in groupContext */ LIB_EXPORT bigCurve BnCurveInitialize( bigCurve E, // IN: curve structure to initialize TPM_ECC_CURVE curveId // IN: curve identifier ) { const ECC_CURVE_DATA *C = GetCurveData(curveId); if(C == NULL) E = NULL; if(E != NULL) { // This creates the OpenSSL memory context that stays in effect as long as the // curve (E) is defined. OSSL_ENTER(); // if the allocation fails, the TPM fails EC_POINT *P = NULL; BIG_INITIALIZED(bnP, C->prime); BIG_INITIALIZED(bnA, C->a); BIG_INITIALIZED(bnB, C->b); BIG_INITIALIZED(bnX, C->base.x); BIG_INITIALIZED(bnY, C->base.y); BIG_INITIALIZED(bnN, C->order); BIG_INITIALIZED(bnH, C->h); // E->C = C; E->CTX = CTX; // initialize EC group, associate a generator point and initialize the point // from the parameter data // Create a group structure E->G = EC_GROUP_new_curve_GFp(bnP, bnA, bnB, CTX); VERIFY(E->G != NULL); // Allocate a point in the group that will be used in setting the // generator. This is not needed after the generator is set. P = EC_POINT_new(E->G); VERIFY(P != NULL); // Need to use this in case Montgomery method is being used #if OPENSSL_VERSION_NUMBER >= 0x10100000L && \ !defined(LIBRESSL_VERSION_NUMBER) // libtpms added begin VERIFY(EC_POINT_set_affine_coordinates(E->G, P, bnX, bnY, CTX)); #else // libtpms added end VERIFY(EC_POINT_set_affine_coordinates_GFp(E->G, P, bnX, bnY, CTX)); #endif // libtpms added // Now set the generator VERIFY(EC_GROUP_set_generator(E->G, P, bnN, bnH)); EC_POINT_free(P); goto Exit_free; // libtpms changed Error: EC_POINT_free(P); BnCurveFree(E); E = NULL; Exit_free: // libtpms added begin BN_clear_free(bnH); BN_clear_free(bnN); BN_clear_free(bnY); BN_clear_free(bnX); BN_clear_free(bnB); BN_clear_free(bnA); BN_clear_free(bnP); // libtpms added end } // Exit: return E; } /* B.2.3.2.3.15. BnCurveFree() */ /* This function will free the allocated components of the curve and end the frame in which the curve data exists */ LIB_EXPORT void BnCurveFree( bigCurve E ) { if(E) { EC_GROUP_free(E->G); OsslContextLeave(E->CTX); } } /* B.2.3.2.3.11. BnEccModMult() */ /* This functi2n does a point multiply of the form R = [d]S */ /* Return Values Meaning */ /* FALSE failure in operation; treat as result being point at infinity */ LIB_EXPORT BOOL BnEccModMult( bigPoint R, // OUT: computed point pointConst S, // IN: point to multiply by 'd' (optional) bigConst d, // IN: scalar for [d]S bigCurve E ) { EC_POINT *pR = EC_POINT_new(E->G); EC_POINT *pS = EcPointInitialized(S, E); BIG_INITIALIZED(bnD, d); if(S == NULL) EC_POINT_mul(E->G, pR, bnD, NULL, NULL, E->CTX); else EC_POINT_mul(E->G, pR, NULL, pS, bnD, E->CTX); PointFromOssl(R, pR, E); EC_POINT_clear_free(pR); // libtpms changed EC_POINT_clear_free(pS); // libtpms changed BN_clear_free(bnD); // libtpms added return !BnEqualZero(R->z); } /* B.2.3.2.3.13. BnEccModMult2() */ /* This function does a point multiply of the form R = [d]G + [u]Q */ /* FALSE failure in operation; treat as result being point at infinity */ LIB_EXPORT BOOL BnEccModMult2( bigPoint R, // OUT: computed point pointConst S, // IN: optional point bigConst d, // IN: scalar for [d]S or [d]G pointConst Q, // IN: second point bigConst u, // IN: second scalar bigCurve E // IN: curve ) { EC_POINT *pR = EC_POINT_new(E->G); EC_POINT *pS = EcPointInitialized(S, E); BIG_INITIALIZED(bnD, d); EC_POINT *pQ = EcPointInitialized(Q, E); BIG_INITIALIZED(bnU, u); if(S == NULL || S == (pointConst)&(AccessCurveData(E)->base)) EC_POINT_mul(E->G, pR, bnD, pQ, bnU, E->CTX); else { const EC_POINT *points[2]; const BIGNUM *scalars[2]; points[0] = pS; points[1] = pQ; scalars[0] = bnD; scalars[1] = bnU; EC_POINTs_mul(E->G, pR, NULL, 2, points, scalars, E->CTX); } PointFromOssl(R, pR, E); EC_POINT_clear_free(pR); // libtpms changed EC_POINT_clear_free(pS); // libtpms changed EC_POINT_clear_free(pQ); // libtpms changed BN_clear_free(bnD); // libtpms added BN_clear_free(bnU); // libtpms added return !BnEqualZero(R->z); } /* B.2.3.2.4. BnEccAdd() */ /* This function does addition of two points. */ /* Return Values Meaning */ /* FALSE failure in operation; treat as result being point at infinity */ LIB_EXPORT BOOL BnEccAdd( bigPoint R, // OUT: computed point pointConst S, // IN: point to multiply by 'd' pointConst Q, // IN: second point bigCurve E // IN: curve ) { EC_POINT *pR = EC_POINT_new(E->G); EC_POINT *pS = EcPointInitialized(S, E); EC_POINT *pQ = EcPointInitialized(Q, E); // EC_POINT_add(E->G, pR, pS, pQ, E->CTX); PointFromOssl(R, pR, E); EC_POINT_clear_free(pR); // libtpms changed EC_POINT_clear_free(pS); // libtpms changed EC_POINT_clear_free(pQ); // libtpms changed return !BnEqualZero(R->z); } #endif // ALG_ECC #endif // MATH_LIB_OSSL libtpms-0.9.3/src/tpm2/crypto/openssl/TpmToOsslMath.h000066400000000000000000000156401421143571500225510ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM to OpenSSL BigNum Shim Layer */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: TpmToOsslMath.h 1658 2021-01-22 23:14:01Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2021 */ /* */ /********************************************************************************/ /* B.2.2.1. TpmToOsslMath.h */ /* B.2.2.1.1. Introduction */ /* This file contains the structure definitions used for ECC in the OpenSSL version of the code. These definitions would change, based on the library. The ECC-related structures that cross the TPM interface are defined in TpmTypes.h */ #ifndef MATH_LIB_DEFINED #define MATH_LIB_DEFINED #define MATH_LIB_OSSL #include #include #define SYMMETRIC_ALIGNMENT RADIX_BYTES #if 0 // libtpms added #if OPENSSL_VERSION_NUMBER >= 0x10200000L // Check the bignum_st definition in crypto/bn/bn_lcl.h and either update the // version check or provide the new definition for this version. # error Untested OpenSSL version #elif OPENSSL_VERSION_NUMBER >= 0x10100000L // from crypto/bn/bn_lcl.h struct bignum_st { BN_ULONG *d; int top; int dmax; int neg; int flags; }; #if 0 // libtpms added # define EC_POINT_get_affine_coordinates EC_POINT_get_affine_coordinates_GFp # define EC_POINT_set_affine_coordinates EC_POINT_set_affine_coordinates_GFp #endif // libtpms added #endif // OPENSSL_VERSION_NUMBER #endif // libtpms added #include #if USE_OPENSSL_FUNCTIONS_ECDSA // libtpms added begin #include #endif // libtpms added end /* B.2.2.2.2. Macros and Defines */ /* Make sure that the library is using the correct size for a crypt word */ #if defined THIRTY_TWO_BIT && (RADIX_BITS != 32) \ || ((defined SIXTY_FOUR_BIT_LONG || defined SIXTY_FOUR_BIT) \ && (RADIX_BITS != 64)) # error Ossl library is using different radix #endif /* Allocate a local BIGNUM value. For the allocation, a bigNum structure is created as is a local BIGNUM. The bigNum is initialized and then the BIGNUM is set to reference the local value. */ #define BIG_VAR(name, bits) \ BN_VAR(name##Bn, (bits)); \ BIGNUM *_##name = BN_new(); /* libtpms */ \ BIGNUM *name = BigInitialized(_##name, /* libtpms */ \ BnInit(name##Bn, \ BYTES_TO_CRYPT_WORDS(sizeof(_##name##Bn.d)))) /* Allocate a BIGNUM and initialize with the values in a bigNum initializer */ #define BIG_INITIALIZED(name, initializer) \ BIGNUM *_##name = BN_new(); /* libtpms */ \ BIGNUM *name = BigInitialized(_##name, initializer) /* libtpms */ typedef struct { const ECC_CURVE_DATA *C; // the TPM curve values EC_GROUP *G; // group parameters BN_CTX *CTX; // the context for the math (this might not be // the context in which the curve was created>; } OSSL_CURVE_DATA; typedef OSSL_CURVE_DATA *bigCurve; #define AccessCurveData(E) ((E)->C) #include "TpmToOsslSupport_fp.h" #define OSSL_ENTER() BN_CTX *CTX = OsslContextEnter() #define OSSL_LEAVE() OsslContextLeave(CTX) /* Start and end a context that spans multiple ECC functions. This is used so that the group for the curve can persist across multiple frames. */ #define CURVE_INITIALIZED(name, initializer) \ OSSL_CURVE_DATA _##name; \ bigCurve name = BnCurveInitialize(&_##name, initializer) #define CURVE_FREE(name) BnCurveFree(name) /* Start and end a local stack frame within the context of the curve frame */ #if 0 /* kgold not used */ #define ECC_ENTER() BN_CTX *CTX = OsslPushContext(E->CTX) #define ECC_LEAVE() OsslPopContext(CTX) #endif #define BN_NEW() BnNewVariable(CTX) /* This definition would change if there were something to report */ #define MathLibSimulationEnd() #endif // MATH_LIB_DEFINED libtpms-0.9.3/src/tpm2/crypto/openssl/TpmToOsslMath_fp.h000066400000000000000000000136031421143571500232330ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM to OpenSSL BigNum Shim Layer */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: TpmToOsslMath_fp.h 1519 2019-11-15 20:43:51Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ #ifndef TPMTOOSSLMATH_FP_H #define TPMTOOSSLMATH_FP_H #include BOOL OsslToTpmBn( bigNum bn, const BIGNUM *osslBn // libtpms added 'const' ); BIGNUM * BigInitialized( BIGNUM *toInit, bigConst initializer ); // libtpms added begin EC_POINT * EcPointInitialized( pointConst initializer, bigCurve E ); // libtpms added end LIB_EXPORT BOOL BnModMult( bigNum result, bigConst op1, bigConst op2, bigConst modulus ); LIB_EXPORT BOOL BnMult( bigNum result, bigConst multiplicand, bigConst multiplier ); LIB_EXPORT BOOL BnDiv( bigNum quotient, bigNum remainder, bigConst dividend, bigConst divisor ); LIB_EXPORT BOOL BnGcd( bigNum gcd, // OUT: the common divisor bigConst number1, // IN: bigConst number2 // IN: ); LIB_EXPORT BOOL BnModExp( bigNum result, // OUT: the result bigConst number, // IN: number to exponentiate bigConst exponent, // IN: bigConst modulus // IN: ); LIB_EXPORT BOOL BnModInverse( bigNum result, bigConst number, bigConst modulus ); bigCurve BnCurveInitialize( bigCurve E, // IN: curve structure to initialize TPM_ECC_CURVE curveId // IN: curve identifier ); LIB_EXPORT BOOL BnEccModMult( bigPoint R, // OUT: computed point pointConst S, // IN: point to multiply by 'd' (optional) bigConst d, // IN: scalar for [d]S bigCurve E ); LIB_EXPORT BOOL BnEccModMult2( bigPoint R, // OUT: computed point pointConst S, // IN: optional point bigConst d, // IN: scalar for [d]S or [d]G pointConst Q, // IN: second point bigConst u, // IN: second scalar bigCurve E // IN: curve ); LIB_EXPORT BOOL BnEccAdd( bigPoint R, // OUT: computed point pointConst S, // IN: point to multiply by 'd' pointConst Q, // IN: second point bigCurve E // IN: curve ); #endif libtpms-0.9.3/src/tpm2/crypto/openssl/TpmToOsslSupport.c000066400000000000000000000121341421143571500233220ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Initialization of the Interface to the OpenSSL Library. */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: TpmToOsslSupport.c 1519 2019-11-15 20:43:51Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ /* B.2.3.3. TpmToOsslSupport.c */ /* B.2.3.3.1. Introduction */ /* The functions in this file are used for initialization of the interface to the OpenSSL library. */ /* B.2.3.3.2. Defines and Includes */ #include "Tpm.h" #if defined(HASH_LIB_OSSL) || defined(MATH_LIB_OSSL) || defined(SYM_LIB_OSSL) /* Used to pass the pointers to the correct sub-keys */ typedef const BYTE *desKeyPointers[3]; /* B.2.3.3.2.1. SupportLibInit() */ /* This does any initialization required by the support library. */ LIB_EXPORT int SupportLibInit( void ) { return TRUE; } /* B.2.3.3.2.2. OsslContextEnter() */ /* This function is used to initialize an OpenSSL context at the start of a function that will call to an OpenSSL math function. */ BN_CTX * OsslContextEnter( void ) { BN_CTX *CTX = BN_CTX_new(); return OsslPushContext(CTX); } /* B.2.3.3.2.3. OsslContextLeave() */ /* This is the companion function to OsslContextEnter(). */ void OsslContextLeave( BN_CTX *CTX ) { OsslPopContext(CTX); BN_CTX_free(CTX); } /* B.2.3.3.2.4. OsslPushContext() */ /* This function is used to create a frame in a context. All values allocated within this context after the frame is started will be automatically freed when the context (OsslPopContext() */ BN_CTX * OsslPushContext( BN_CTX *CTX ) { if(CTX == NULL) FAIL(FATAL_ERROR_ALLOCATION); BN_CTX_start(CTX); return CTX; } /* B.2.3.3.2.5. OsslPopContext() */ /* This is the companion function to OsslPushContext(). */ void OsslPopContext( BN_CTX *CTX ) { // BN_CTX_end can't be called with NULL. It will blow up. if(CTX != NULL) BN_CTX_end(CTX); } #endif // HASH_LIB_OSSL || MATH_LIB_OSSL || SYM_LIB_OSSL libtpms-0.9.3/src/tpm2/crypto/openssl/TpmToOsslSupport_fp.h000066400000000000000000000072121421143571500240150ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Initialization of the Interface to the OpenSSL Library */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: TpmToOsslSupport_fp.h 1476 2019-06-10 19:32:03Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2019 */ /* */ /********************************************************************************/ #ifndef TPMTOOSSLSUPPORT_FP_H #define TPMTOOSSLSUPPORT_FP_H BN_CTX * OsslContextEnter( void ); void OsslContextLeave( BN_CTX *context ); BN_CTX * OsslPushContext( BN_CTX *CTX ); void OsslPopContext( BN_CTX *CTX ); #endif libtpms-0.9.3/src/tpm2/crypto/openssl/TpmToOsslSym.h000066400000000000000000000207221421143571500224250ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Splice the OpenSSL() library into the TPM code. */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: TpmToOsslSym.h 1619 2020-05-19 16:51:47Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2020 */ /* */ /********************************************************************************/ /* B.2.3.2. TpmToOsslSym.h */ /* B.2.3.2.1. Introduction */ /* This header file is used to splice the OpenSSL() library into the TPM code. */ /* The support required of a library are a hash module, a block cipher module and portions of a big number library. All of the library-dependent headers should have the same guard to that only the first one gets defined. */ #ifndef SYM_LIB_DEFINED #define SYM_LIB_DEFINED #define SYM_LIB_OSSL #include #if ALG_TDES #include #endif #if ALG_SM4 # if defined(OPENSSL_NO_SM4) || OPENSSL_VERSION_NUMBER < 0x10101010L # undef ALG_SM4 # define ALG_SM4 ALG_NO # elif OPENSSL_VERSION_NUMBER >= 0x10200000L # include # else // OpenSSL 1.1.1 keeps smX.h headers in the include/crypto directory, // and they do not get installed as part of the libssl package # define SM4_KEY_SCHEDULE 32 typedef struct SM4_KEY_st { uint32_t rk[SM4_KEY_SCHEDULE]; } SM4_KEY; int SM4_set_key(const uint8_t *key, SM4_KEY *ks); void SM4_encrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *ks); void SM4_decrypt(const uint8_t *in, uint8_t *out, const SM4_KEY *ks); # endif // OpenSSL < 1.2 #endif // ALG_SM4 #if ALG_CAMELLIA #include #endif #include #include /* B.2.2.3.2. Links to the OpenSSL symmetric algorithms */ // The Crypt functions that call the block encryption function use the parameters in the order: // a) keySchedule // b) in buffer // c) out buffer Since open SSL uses the order in encryptoCall_t above, need to swizzle the values // to the order required by the library. #define SWIZZLE(keySchedule, in, out) \ (const BYTE *)(in), (BYTE *)(out), (void *)(keySchedule) // Define the order of parameters to the library functions that do block encryption and decryption. typedef void(*TpmCryptSetSymKeyCall_t)( const BYTE *in, BYTE *out, void *keySchedule ); #define SYM_ALIGNMENT 4 /* libtpms: keep old value */ /* B.2.2.3.3. Links to the OpenSSL AES code */ /* Macros to set up the encryption/decryption key schedules */ #define TpmCryptSetEncryptKeyAES(key, keySizeInBits, schedule) \ AES_set_encrypt_key((key), (keySizeInBits), (tpmKeyScheduleAES *)(schedule)) #define TpmCryptSetDecryptKeyAES(key, keySizeInBits, schedule) \ AES_set_decrypt_key((key), (keySizeInBits), (tpmKeyScheduleAES *)(schedule)) /* Macros to alias encryption calls to specific algorithms. This should be used sparingly. Currently, only used by CryptSym.c and CryptRand.c */ /* When using these calls, to call the AES block encryption code, the caller should use: TpmCryptEncryptAES(SWIZZLE(keySchedule, in, out)); */ #define TpmCryptEncryptAES AES_encrypt #define TpmCryptDecryptAES AES_decrypt #define tpmKeyScheduleAES AES_KEY /* B.2.2.3.4. Links to the OpenSSL DES code */ #if ALG_TDES && 0 // libtpms changed #include "TpmToOsslDesSupport_fp.h" #endif #define TpmCryptSetEncryptKeyTDES(key, keySizeInBits, schedule) \ TDES_set_encrypt_key((key), (keySizeInBits), (tpmKeyScheduleTDES *)(schedule)) #define TpmCryptSetDecryptKeyTDES(key, keySizeInBits, schedule) \ TDES_set_encrypt_key((key), (keySizeInBits), (tpmKeyScheduleTDES *)(schedule)) /* Macros to alias encryption calls to specific algorithms. This should be used sparingly. Currently, only used by CryptRand.c */ #define TpmCryptEncryptTDES TDES_encrypt #define TpmCryptDecryptTDES TDES_decrypt #define tpmKeyScheduleTDES DES_key_schedule #if ALG_TDES // libtpms added begin #include "TpmToOsslDesSupport_fp.h" #endif // libtpms added end /* B.2.2.3.5. Links to the OpenSSL SM4 code */ /* Macros to set up the encryption/decryption key schedules */ #define TpmCryptSetEncryptKeySM4(key, keySizeInBits, schedule) \ SM4_set_key((key), (tpmKeyScheduleSM4 *)(schedule)) #define TpmCryptSetDecryptKeySM4(key, keySizeInBits, schedule) \ SM4_set_key((key), (tpmKeyScheduleSM4 *)(schedule)) /* Macros to alias encryption calls to specific algorithms. This should be used sparingly. */ #define TpmCryptEncryptSM4 SM4_encrypt #define TpmCryptDecryptSM4 SM4_decrypt #define tpmKeyScheduleSM4 SM4_KEY /* B.2.2.3.6. Links to the OpenSSL CAMELLIA code */ /* Macros to set up the encryption/decryption key schedules */ #define TpmCryptSetEncryptKeyCAMELLIA(key, keySizeInBits, schedule) \ Camellia_set_key((key), (keySizeInBits), (tpmKeyScheduleCAMELLIA *)(schedule)) #define TpmCryptSetDecryptKeyCAMELLIA(key, keySizeInBits, schedule) \ Camellia_set_key((key), (keySizeInBits), (tpmKeyScheduleCAMELLIA *)(schedule)) /* Macros to alias encryption calls to specific algorithms. This should be used sparingly. */ #define TpmCryptEncryptCAMELLIA Camellia_encrypt #define TpmCryptDecryptCAMELLIA Camellia_decrypt #define tpmKeyScheduleCAMELLIA CAMELLIA_KEY /* Forward reference */ // kgold typedef union tpmCryptKeySchedule_t tpmCryptKeySchedule_t; /* This definition would change if there were something to report */ #define SymLibSimulationEnd() #endif // SYM_LIB_DEFINED libtpms-0.9.3/src/tpm2/crypto/openssl/consttime.txt000066400000000000000000000035111421143571500224220ustar00rootroot00000000000000The following (top level) OpenSSL public BIGNUM functions check for the BN_FLG_CONSTTIME: bn_blind.c: BN_BLINDING_new() bn_exp.c: BN_exp : must not be set for input bignums ! BN_mod_exp : SHOULD be set for any one of input bignums (only) if m is odd BN_mod_exp_recp: must NOT be set for input bignums BN_mod_exp_mont: SHOULD be set for any one of input bignums BN_mod_exp_mont_word: must NOT be set for input bignums BN_mod_exp_simple: must NOT bet set for input bignums bn_gcd.c: ! BN_mod_inverse: SHOULD be set for any one of input bignums bn_lib: BN_num_bits ! BN_copy bn_mont.c: BN_MONT_CTX_set bn.h: ! BN_num_bytes: Calls BN_num_bits Relevant files and functions in the files: Helpers.c ComputePrivateExponentD: - BN_dup: -> BN_copy: YES, BN_FLG_CONSTTIME set by caller on P and Q - BN_sub: no - BN_add_word: no - BN_mod_inverse: YES, DONE InitOpenSSLRSAPublicKey: - BN_set_word: no - BN_bin2bn: no InitOpenSSLRSAPrivateKey: - BN_bin2bn: no - BN_div: -> BN_copy: YES, DONE - BN_is_zero: no TpmToOsslMath: OsslToTpmBn: - BN_num_bytes: need not - BN_bn2bin: -> BN_num_bytes: need not BigInitialized: - BN_bin2bn: no - BN_copy: YES, DONE BnModMult: - BN_mul: no - BN_div: -> BN_copy: ? BnMult: - BN_mul: no BnDiv: - BN_div: -> BN_copy: ? BnGcd: /* FUNCTION IS NOT USED */ - BN_gcd: -> BN_copy, BN_num_bits: YES, DONE BnModExp: - BN_mod_exp: YES, DONE BnModInverse: - BN_mod_inverse: YES, DONE Elliptic curve signing : CryptEccMain.c: BnEccGenerateKeyPair: - BnEccModMult: YES, DONE (we have control over random number bnD) called by BnSignEcSchnorr called by BnSignEcdsa (if OpenSSL function not used) CryptEccSignature.c: BnEccSignSM2: - BnEccModMult: YES, DONE (we have control over random number bnK) libtpms-0.9.3/src/tpm2/crypto/openssl/consttime.txt'000066400000000000000000000021371421143571500224740ustar00rootroot00000000000000The following OpenSSL public BIGNUM functions check for the BN_FLG_CONSTTIME: bn_blind.c: BN_BLINDING_new() bn_exp.c: BN_exp : must not be set for input bignums ! BN_mod_exp : SHOULD be set for any one of input bignums (only) if m is odd BN_mod_exp_recp: must NOT be set for input bignums BN_mod_exp_mont: SHOULD be set for any one of input bignums BN_mod_exp_mont_word: must NOT be set for input bignums BN_mod_exp_simple: must NOT bet set for input bignums bn_gcd.c: ! BN_mod_inverse: SHOULD be set for any one of input bignums bn_lib: BN_num_bits ! BN_copy bn_mont.c: BN_MONT_CTX_set bn.h: ! BN_num_bytes: Calls BN_num_bits Relevant files and functions in the files: Helpers.c - BN_dup: - BN_sub: - BN_add_word: - BN_mod_inverse: yes - BN_set_word: - BN_bin2bn: - BN_div: - BN_is_zero: TpmToOsslMath: OsslToTpmBn: - BN_num_bytes: - BN_bn2bin: BigInitialized: - BN_bin2bn: - BN_copy: BnModMult: - BN_mul: - BN_div: BnMult: - BN_mul: BnDiv: - BN_div: BnGcd: - BN_gcd: BnModExp: - BN_mod_exp: YES BnModInverse: - BN_mod_inverse: YES libtpms-0.9.3/src/tpm2/gensymtestsdata.sh000077500000000000000000000130421421143571500204270ustar00rootroot00000000000000#!/bin/bash function do_aes() { local data="$1" local osslflag="$2" for keysize in 128 192 256; do tmp=AES_KEY_${keysize} key=$(eval echo \$$tmp) for mode in ecb cbc cfb ofb ctr; do cipher="aes-${keysize}-${mode}" bs=$((128 / 8)) iv="" ivparm="" case $mode in ecb) ;; ctr) v=255 for ((c=0; c < bs; c++)); do iv="$(printf "%02x" $v)${iv}" v=$((v - 1)) done ivparm="-iv ${iv}" ;; *) for ((c=0; c < bs; c++)); do iv="${iv}$(printf "%02x" $c)" done ivparm="-iv ${iv}" ;; esac echo -n "$cipher: " openssl enc -e -K "${key}" ${ivparm} -${cipher} -in <(echo -en "$data") ${osslflag} | \ od -t x1 -w128 -An | \ sed -n 's/ \([a-f0-9]\{2\}\)/ 0x\1/pg' done done } function do_camellia() { local data="$1" local osslflag="$2" for keysize in 128 192 256; do tmp=CAMELLIA_KEY_${keysize} key=$(eval echo \$$tmp) for mode in ecb cbc cfb ofb ctr; do cipher="camellia-${keysize}-${mode}" bs=$((128 / 8)) iv="" ivparm="" case $mode in ecb) ;; ctr) v=255 for ((c=0; c < bs; c++)); do iv="$(printf "%02x" $v)${iv}" v=$((v - 1)) done ivparm="-iv ${iv}" ;; *) for ((c=0; c < bs; c++)); do iv="${iv}$(printf "%02x" $c)" done ivparm="-iv ${iv}" ;; esac echo -n "$cipher: " openssl enc -e -K "${key}" ${ivparm} -${cipher} -in <(echo -en "$data") ${osslflag} | \ od -t x1 -w128 -An | \ sed -n 's/ \([a-f0-9]\{2\}\)/ 0x\1/pg' done done } function do_tdes() { local data="$1" local osslflag="$2" for keysize in 128 192; do tmp=TDES_KEY_${keysize} key=$(eval echo \$$tmp) for mode in ecb cbc cfb ofb; do cipher="des-ede3-${mode}" iv="" ivparm="" bs=8 case $mode in ecb) ;; *) for ((c=0; c < bs; c++)); do iv="${iv}$(printf "%02x" $c)" done ivparm="-iv ${iv}" ;; esac echo -n "$cipher [${keysize}]: " case $mode in ecb|cbc) if [[ "${osslflag}" =~ "nopad" ]]; then echo " Not supported without padding to blocksize" continue fi ;; esac openssl enc -e -K "${key}" ${ivparm} -${cipher} -in <(echo -en "$data") ${osslflag} | \ od -t x1 -w128 -An | \ sed -n 's/ \([a-f0-9]\{2\}\)/ 0x\1/pg' done done } function do_sm4() { local data="$1" local osslflag="$2" for keysize in 128; do tmp=SM4_KEY_${keysize} key=$(eval echo \$$tmp) for mode in ecb cbc cfb ofb ctr; do cipher="sm4-${mode}" bs=$((128 / 8)) iv="" ivparm="" case $mode in ecb) ;; ctr) v=255 for ((c=0; c < bs; c++)); do iv="$(printf "%02x" $v)${iv}" v=$((v - 1)) done ivparm="-iv ${iv}" ;; *) for ((c=0; c < bs; c++)); do iv="${iv}$(printf "%02x" $c)" done ivparm="-iv ${iv}" ;; esac echo -n "$cipher: " openssl enc -e -K "${key}" ${ivparm} -${cipher} -in <(echo -en "$data") ${osslflag} | \ od -t x1 -w128 -An | \ sed -n 's/ \([a-f0-9]\{2\}\)/ 0x\1/pg' done done } AES_KEY_128='2b7e151628aed2a6abf7158809cf4f3c' AES_KEY_192='8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b' AES_KEY_256='603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4' AES_DATA_IN='\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51' echo "----- AES -----" do_aes "${AES_DATA_IN}" "" echo "---------------" # We need to extend the 128 bit key to be 192 bit key otherwise 3rd schedule is all zeroes TDES_KEY_128=${AES_KEY_128}${AES_KEY_128:0:16} TDES_KEY_192=${AES_KEY_192} TDES_DATA_IN=${AES_DATA_IN} echo "----- TDES -----" do_tdes "${TDES_DATA_IN}" "" echo "----------------" echo "---- TDES (short input) -----" do_tdes "\x31\x32\x33\x34\x35" "-nopad" echo "----------------" CAMELLIA_KEY_128=${AES_KEY_128} CAMELLIA_KEY_192=${AES_KEY_192} CAMELLIA_KEY_256=${AES_KEY_256} CAMELLIA_DATA_IN=${AES_DATA_IN} echo "----- CAMELLIA -----" do_camellia "${CAMELLIA_DATA_IN}" "" echo "--------------------" if [ -n "$(openssl enc -ciphers | grep sm4)" ]; then SM4_KEY_128='0123456789abcdeffedcba9876543210' SM4_DATA_IN='\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb\xcc\xcc\xcc\xcc\xdd\xdd\xdd\xdd\xee\xee\xee\xee\xff\xff\xff\xff\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb' echo "-------- SM4 -------" do_sm4 "${SM4_DATA_IN}" "" echo "--------------------" fi libtpms-0.9.3/src/tpm2/swap.h000066400000000000000000000142101421143571500157720ustar00rootroot00000000000000/********************************************************************************/ /* */ /* Swap */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: swap.h 1490 2019-07-26 21:13:22Z kgoldman $ */ /* */ /* Licenses and Notices */ /* */ /* 1. Copyright Licenses: */ /* */ /* - Trusted Computing Group (TCG) grants to the user of the source code in */ /* this specification (the "Source Code") a worldwide, irrevocable, */ /* nonexclusive, royalty free, copyright license to reproduce, create */ /* derivative works, distribute, display and perform the Source Code and */ /* derivative works thereof, and to grant others the rights granted herein. */ /* */ /* - The TCG grants to the user of the other parts of the specification */ /* (other than the Source Code) the rights to reproduce, distribute, */ /* display, and perform the specification solely for the purpose of */ /* developing products based on such documents. */ /* */ /* 2. Source Code Distribution Conditions: */ /* */ /* - Redistributions of Source Code must retain the above copyright licenses, */ /* this list of conditions and the following disclaimers. */ /* */ /* - Redistributions in binary form must reproduce the above copyright */ /* licenses, this list of conditions and the following disclaimers in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* 3. Disclaimers: */ /* */ /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ /* information on specification licensing rights available through TCG */ /* membership agreements. */ /* */ /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ /* */ /* - Without limitation, TCG and its members and licensors disclaim all */ /* liability, including liability for infringement of any proprietary */ /* rights, relating to use of information in this specification and to the */ /* implementation of this specification, and TCG disclaims all liability for */ /* cost of procurement of substitute goods or services, lost profits, loss */ /* of use, loss of data or any incidental, consequential, direct, indirect, */ /* or special damages, whether under contract, tort, warranty or otherwise, */ /* arising in any way out of use or reliance upon this specification or any */ /* information herein. */ /* */ /* (c) Copyright IBM Corp. and others, 2016 - 2018 */ /* */ /********************************************************************************/ #ifndef SWAP_H #define SWAP_H #if LITTLE_ENDIAN_TPM #define TO_BIG_ENDIAN_UINT16(i) REVERSE_ENDIAN_16(i) #define FROM_BIG_ENDIAN_UINT16(i) REVERSE_ENDIAN_16(i) #define TO_BIG_ENDIAN_UINT32(i) REVERSE_ENDIAN_32(i) #define FROM_BIG_ENDIAN_UINT32(i) REVERSE_ENDIAN_32(i) #define TO_BIG_ENDIAN_UINT64(i) REVERSE_ENDIAN_64(i) #define FROM_BIG_ENDIAN_UINT64(i) REVERSE_ENDIAN_64(i) #else #define TO_BIG_ENDIAN_UINT16(i) (i) #define FROM_BIG_ENDIAN_UINT16(i) (i) #define TO_BIG_ENDIAN_UINT32(i) (i) #define FROM_BIG_ENDIAN_UINT32(i) (i) #define TO_BIG_ENDIAN_UINT64(i) (i) #define FROM_BIG_ENDIAN_UINT64(i) (i) #endif #if AUTO_ALIGN == NO /* The aggregation macros for machines that do not allow unaligned access or for little-endian machines. Aggregate bytes into an UINT */ #define BYTE_ARRAY_TO_UINT8(b) (uint8_t)((b)[0]) #define BYTE_ARRAY_TO_UINT16(b) ByteArrayToUint16((BYTE *)(b)) #define BYTE_ARRAY_TO_UINT32(b) ByteArrayToUint32((BYTE *)(b)) #define BYTE_ARRAY_TO_UINT64(b) ByteArrayToUint64((BYTE *)(b)) #define UINT8_TO_BYTE_ARRAY(i, b) ((b)[0] = (uint8_t)(i)) #define UINT16_TO_BYTE_ARRAY(i, b) Uint16ToByteArray((i), (BYTE *)(b)) #define UINT32_TO_BYTE_ARRAY(i, b) Uint32ToByteArray((i), (BYTE *)(b)) #define UINT64_TO_BYTE_ARRAY(i, b) Uint64ToByteArray((i), (BYTE *)(b)) #else // AUTO_ALIGN #if BIG_ENDIAN_TPM /* The big-endian macros for machines that allow unaligned memory access Aggregate a byte array into a UINT */ #define BYTE_ARRAY_TO_UINT8(b) *((uint8_t *)(b)) #define BYTE_ARRAY_TO_UINT16(b) *((uint16_t *)(b)) #define BYTE_ARRAY_TO_UINT32(b) *((uint32_t *)(b)) #define BYTE_ARRAY_TO_UINT64(b) *((uint64_t *)(b)) /* Disaggregate a UINT into a byte array */ #define UINT8_TO_BYTE_ARRAY(i, b) {*((uint8_t *)(b)) = (i);} #define UINT16_TO_BYTE_ARRAY(i, b) {*((uint16_t *)(b)) = (i);} #define UINT32_TO_BYTE_ARRAY(i, b) {*((uint32_t *)(b)) = (i);} #define UINT64_TO_BYTE_ARRAY(i, b) {*((uint64_t *)(b)) = (i);} #else /* the little endian macros for machines that allow unaligned memory access the big-endian macros for machines that allow unaligned memory access Aggregate a byte array into a UINT */ #define BYTE_ARRAY_TO_UINT8(b) *((uint8_t *)(b)) #define BYTE_ARRAY_TO_UINT16(b) REVERSE_ENDIAN_16(*((uint16_t *)(b))) #define BYTE_ARRAY_TO_UINT32(b) REVERSE_ENDIAN_32(*((uint32_t *)(b))) #define BYTE_ARRAY_TO_UINT64(b) REVERSE_ENDIAN_64(*((uint64_t *)(b))) /* Disaggregate a UINT into a byte array */ #define UINT8_TO_BYTE_ARRAY(i, b) {*((uint8_t *)(b)) = (i);} #define UINT16_TO_BYTE_ARRAY(i, b) {*((uint16_t *)(b)) = REVERSE_ENDIAN_16(i);} #define UINT32_TO_BYTE_ARRAY(i, b) {*((uint32_t *)(b)) = REVERSE_ENDIAN_32(i);} #define UINT64_TO_BYTE_ARRAY(i, b) {*((uint64_t *)(b)) = REVERSE_ENDIAN_64(i);} #endif // BIG_ENDIAN_TPM #endif // AUTO_ALIGN == NO #endif libtpms-0.9.3/src/tpm_debug.c000066400000000000000000000110031421143571500160740ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM Debug Utilities */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_debug.c 4179 2010-11-10 20:10:24Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include #include "tpm_debug.h" #undef printf #if 0 int swallow_rc = 0; int tpm_swallow_printf_args(const char *format, ...) { format = format; /* to silence compiler */ return 0; } #else void TPM_PrintFourLimit(const char *string, const unsigned char *buff, size_t buflen) { if (buff != NULL) { switch (buflen) { case 0: TPMLIB_LogPrintf("%s (no data)\n", string); break; case 1: TPMLIB_LogPrintf("%s %02x\n", string, buff[0]); break; case 2: TPMLIB_LogPrintf("%s %02x %02x\n", string, buff[0], buff[1]); break; case 3: TPMLIB_LogPrintf("%s %02x %02x %02x\n", string, buff[0], buff[1], buff[2]); break; default: TPMLIB_LogPrintf("%s %02x %02x %02x %02x\n", string, buff[0], buff[1], buff[2], buff[3]); } } else { TPMLIB_LogPrintf("%s null\n", string); } return; } /* TPM_PrintFour() prints a prefix plus 4 bytes of a buffer */ void TPM_PrintFour(const char *string, const unsigned char* buff) { TPM_PrintFourLimit(string, buff, 4); } #endif /* TPM_PrintAll() prints 'string', the length, and then the entire byte array */ void TPM_PrintAll(const char *string, const unsigned char* buff, uint32_t length) { uint32_t i; int indent; if (buff != NULL) { indent = TPMLIB_LogPrintf("%s length %u\n", string, length); if (indent < 0) return; for (i = 0 ; i < length ; i++) { if (i && !( i % 16 )) TPMLIB_LogPrintfA(0, "\n"); if (!(i % 16)) TPMLIB_LogPrintf(" %.2X ", buff[i]); else TPMLIB_LogPrintfA(0, "%.2X ", buff[i]); } TPMLIB_LogPrintfA(0, "\n"); } else { TPMLIB_LogPrintf("%s null\n", string); } return; } libtpms-0.9.3/src/tpm_debug.h000066400000000000000000000063311421143571500161110ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM Debug Utilities */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_debug.h 4179 2010-11-10 20:10:24Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_DEBUG_H #define TPM_DEBUG_H #include "tpm_types.h" #include "tpm_library_intern.h" /* prototypes */ void TPM_PrintFour(const char *string, const unsigned char* buff); void TPM_PrintFourLimit(const char *string, const unsigned char* buff, size_t bufflen); void TPM_PrintAll(const char *string, const unsigned char* buff, uint32_t length); #if 0 #ifndef TPM_DEBUG /* if debug is turned off */ /* dummy function to match the printf prototype */ int tpm_swallow_printf_args(const char *format, ...); /* assign to this dummy value to eliminate "statement has no effect" warnings */ extern int swallow_rc; /* redefine printf to null */ #define printf swallow_rc = swallow_rc && tpm_swallow_printf_args #define TPM_PrintFour(arg1, arg2) #endif /* TPM_DEBUG */ #endif #define printf(...) TPMLIB_LogPrintf(__VA_ARGS__); #endif libtpms-0.9.3/src/tpm_library.c000066400000000000000000000426441421143571500164710ustar00rootroot00000000000000/********************************************************************************/ /* */ /* LibTPM interface functions */ /* Written by Stefan Berger */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_library.c 4615 2011-08-30 15:35:24Z stefanb $ */ /* */ /* (c) Copyright IBM Corporation 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include #include #include #if defined __FreeBSD__ # define _WITH_DPRINTF #endif #include #include #include #include #include #include #ifdef USE_FREEBL_CRYPTO_LIBRARY # include #endif #ifdef USE_OPENSSL_CRYPTO_LIBRARY # include # include #endif #include "tpm_debug.h" #include "tpm_error.h" #include "tpm_library.h" #include "tpm_library_intern.h" #include "tpm_nvfilename.h" #include "tpm_tis.h" static const struct tags_and_indices { const char *starttag; const char *endtag; } tags_and_indices[] = { [TPMLIB_BLOB_TYPE_INITSTATE] = { .starttag = TPMLIB_INITSTATE_START_TAG, .endtag = TPMLIB_INITSTATE_END_TAG, }, }; static const struct tpm_interface *const tpm_iface[] = { #if WITH_TPM1 &TPM12Interface, #else &DisabledInterface, #endif #if WITH_TPM2 &TPM2Interface, #else &DisabledInterface, #endif NULL, }; static int debug_fd = -1; static unsigned debug_level = 0; static char *debug_prefix = NULL; static struct sized_buffer cached_blobs[TPMLIB_STATE_SAVE_STATE + 1]; static int tpmvers_choice = 0; /* default is TPM1.2 */ static TPM_BOOL tpmvers_locked = FALSE; uint32_t TPMLIB_GetVersion(void) { return TPM_LIBRARY_VERSION; } TPM_RESULT TPMLIB_ChooseTPMVersion(TPMLIB_TPMVersion ver) { /* TPMLIB_Terminate will reset previous choice */ if (tpmvers_locked) return TPM_FAIL; switch (ver) { #if WITH_TPM1 case TPMLIB_TPM_VERSION_1_2: if (tpmvers_choice != 0) ClearAllCachedState(); tpmvers_choice = 0; // entry 0 in tpm_iface return TPM_SUCCESS; #endif #if WITH_TPM2 case TPMLIB_TPM_VERSION_2: if (tpmvers_choice != 1) ClearAllCachedState(); tpmvers_choice = 1; // entry 1 in tpm_iface return TPM_SUCCESS; #endif default: return TPM_FAIL; } } TPM_RESULT TPMLIB_MainInit(void) { if (!tpm_iface[tpmvers_choice]) { return TPM_FAIL; } tpmvers_locked = TRUE; return tpm_iface[tpmvers_choice]->MainInit(); } void TPMLIB_Terminate(void) { tpm_iface[tpmvers_choice]->Terminate(); tpmvers_locked = FALSE; } /* * Send a command to the TPM. The command buffer must hold a well formatted * TPM command and the command_size indicate the size of the command. * The respbuffer parameter may be provided by the user and grow if * the respbufsize size indicator is determined to be too small for the * response. In that case a new buffer will be allocated and the size of that * buffer returned in the respbufsize parameter. resp_size describes the * size of the actual response within the respbuffer. */ TPM_RESULT TPMLIB_Process(unsigned char **respbuffer, uint32_t *resp_size, uint32_t *respbufsize, unsigned char *command, uint32_t command_size) { return tpm_iface[tpmvers_choice]->Process(respbuffer, resp_size, respbufsize, command, command_size); } /* * Get the volatile state from the TPM. This function will return the * buffer and the length of the buffer to the caller in case everything * went alright. */ TPM_RESULT TPMLIB_VolatileAll_Store(unsigned char **buffer, uint32_t *buflen) { return tpm_iface[tpmvers_choice]->VolatileAllStore(buffer, buflen); } /* * Have the TPM cancel an ongoing command */ TPM_RESULT TPMLIB_CancelCommand(void) { return tpm_iface[tpmvers_choice]->CancelCommand(); } /* * Get a property of the TPM. The functions currently only * return compile-time #defines but this may change in future * versions where we may return parameters with which the TPM * was created (rather than compiled). */ TPM_RESULT TPMLIB_GetTPMProperty(enum TPMLIB_TPMProperty prop, int *result) { switch (prop) { case TPMPROP_TPM_BUFFER_MAX: *result = TPM_BUFFER_MAX; break; default: return tpm_iface[tpmvers_choice]->GetTPMProperty(prop, result); } return TPM_SUCCESS; } char *TPMLIB_GetInfo(enum TPMLIB_InfoFlags flags) { return tpm_iface[tpmvers_choice]->GetInfo(flags); } TPM_RESULT TPMLIB_SetState(enum TPMLIB_StateType st, const unsigned char *buffer, uint32_t buflen) { return tpm_iface[tpmvers_choice]->SetState(st, buffer, buflen); } TPM_RESULT TPMLIB_GetState(enum TPMLIB_StateType st, unsigned char **buffer, uint32_t *buflen) { return tpm_iface[tpmvers_choice]->GetState(st, buffer, buflen); } TPM_RESULT TPM_IO_Hash_Start(void) { return tpm_iface[tpmvers_choice]->HashStart(); } TPM_RESULT TPM_IO_Hash_Data(const unsigned char *data, uint32_t data_length) { return tpm_iface[tpmvers_choice]->HashData(data, data_length); } TPM_RESULT TPM_IO_Hash_End(void) { return tpm_iface[tpmvers_choice]->HashEnd(); } TPM_RESULT TPM_IO_TpmEstablished_Get(TPM_BOOL *tpmEstablished) { return tpm_iface[tpmvers_choice]->TpmEstablishedGet(tpmEstablished); } TPM_RESULT TPM_IO_TpmEstablished_Reset(void) { return tpm_iface[tpmvers_choice]->TpmEstablishedReset(); } uint32_t TPMLIB_SetBufferSize(uint32_t wanted_size, uint32_t *min_size, uint32_t *max_size) { return tpm_iface[tpmvers_choice]->SetBufferSize(wanted_size, min_size, max_size); } TPM_RESULT TPMLIB_ValidateState(enum TPMLIB_StateType st, unsigned int flags) { return tpm_iface[tpmvers_choice]->ValidateState(st, flags); } static struct libtpms_callbacks libtpms_cbs; struct libtpms_callbacks *TPMLIB_GetCallbacks(void) { return &libtpms_cbs; } TPM_RESULT TPMLIB_RegisterCallbacks(struct libtpms_callbacks *callbacks) { int max_size = sizeof(struct libtpms_callbacks); /* restrict the size of the structure to what we know currently future versions may know more callbacks */ if (callbacks->sizeOfStruct < max_size) max_size = callbacks->sizeOfStruct; /* clear the internal callback structure and copy the user provided callbacks into it */ memset(&libtpms_cbs, 0x0, sizeof(libtpms_cbs)); memcpy(&libtpms_cbs, callbacks, max_size); return TPM_SUCCESS; } static int is_base64ltr(char c) { return ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '+' || c == '/' || c == '='); } #ifdef USE_OPENSSL_CRYPTO_LIBRARY static unsigned char *TPMLIB_OpenSSL_Base64Decode(char *input, unsigned int outputlen) { BIO *b64, *bmem; unsigned char *res = NULL; int n; b64 = BIO_new(BIO_f_base64()); if (!b64) { return NULL; } bmem = BIO_new_mem_buf(input, strlen(input)); if (!bmem) { BIO_free(b64); goto cleanup; } bmem = BIO_push(b64, bmem); BIO_set_flags(bmem, BIO_FLAGS_BASE64_NO_NL); res = malloc(outputlen); if (!res) { TPMLIB_LogError("Could not allocate %u bytes.\n", outputlen); goto cleanup; } n = BIO_read(bmem, res, outputlen); if (n <= 0) { free(res); res = NULL; goto cleanup; } cleanup: BIO_free_all(bmem); return res; } #endif /* * Base64 decode the string starting at 'start' and the last * valid character may be a 'end'. The length of the decoded string * is returned in *length. */ static unsigned char *TPMLIB_Base64Decode(const char *start, const char *end, size_t *length) { unsigned char *ret = NULL; char *input = NULL, *d; const char *s; char c; unsigned int numbase64chars = 0; if (end < start) return NULL; while (end > start && !is_base64ltr(*end)) end--; end++; input = malloc(end - start + 1); if (!input) { TPMLIB_LogError("Could not allocate %u bytes.\n", (unsigned int)(end - start + 1)); return NULL; } /* copy from source string skipping '\n' and '\r' and using '=' to calculate the exact length */ d = input; s = start; while (s < end) { c = *s; if (is_base64ltr(c)) { *d = c; d++; if (c != '=') { numbase64chars++; } } else if (c == 0) { break; } s++; } *d = 0; *length = (numbase64chars / 4) * 3; switch (numbase64chars % 4) { case 2: case 3: *length += (numbase64chars % 4) - 1; break; case 0: break; case 1: fprintf(stderr,"malformed base64\n"); goto err_exit; break; } #ifdef USE_FREEBL_CRYPTO_LIBRARY ret = (unsigned char *)PL_Base64Decode(input, 0, NULL); #endif #ifdef USE_OPENSSL_CRYPTO_LIBRARY ret = TPMLIB_OpenSSL_Base64Decode(input, *length); #endif err_exit: free(input); return ret; } static unsigned char *TPMLIB_GetPlaintext(const char *stream, const char *starttag, const char *endtag, size_t *length) { char *start, *end; unsigned char *plaintext = NULL; start = strstr(stream, starttag); if (start) { start += strlen(starttag); while (isspace((int)*start)) start++; end = strstr(start, endtag); if (end) { plaintext = TPMLIB_Base64Decode(start, --end, length); } } return plaintext; } TPM_RESULT TPMLIB_DecodeBlob(const char *buffer, enum TPMLIB_BlobType type, unsigned char **result, size_t *result_len) { TPM_RESULT res = TPM_SUCCESS; *result = TPMLIB_GetPlaintext(buffer, tags_and_indices[type].starttag, tags_and_indices[type].endtag, result_len); if (*result == NULL) { res = TPM_FAIL; } return res; } void TPMLIB_SetDebugFD(int fd) { debug_fd = fd; } void TPMLIB_SetDebugLevel(unsigned level) { debug_level = level; } TPM_RESULT TPMLIB_SetDebugPrefix(const char *prefix) { free(debug_prefix); if (prefix) { debug_prefix = strdup(prefix); if (!debug_prefix) return TPM_FAIL; } else { debug_prefix = NULL; } return TPM_SUCCESS; } int TPMLIB_LogPrintf(const char *format, ...) { unsigned level = debug_level, i; va_list args; char buffer[256]; int n; if (!debug_fd || !debug_level) return -1; va_start(args, format); n = vsnprintf(buffer, sizeof(buffer), format, args); va_end(args); if (n < 0 || n >= (int)sizeof(buffer)) return -1; level--; i = 0; while (1) { if (buffer[i] == 0) return -1; if (buffer[i] != ' ') break; if (i == level) return -1; i++; } if (debug_prefix) dprintf(debug_fd, "%s", debug_prefix); dprintf(debug_fd, "%s", buffer); return i; } /* * TPMLIB_LogPrintfA: Printf to the logfd without indentation check * * @indent: how many spaces to indent; indent of ~0 forces logging * with indent 0 even if not debug_level is set * @format: format to use for formatting the following parameters * @...: varargs */ void TPMLIB_LogPrintfA(unsigned int indent, const char *format, ...) { va_list args; char spaces[20]; int fd; if (indent != (unsigned int)~0) { if (!debug_fd || !debug_level) return; fd = debug_fd; } else { indent = 0; fd = (debug_fd >= 0) ? debug_fd : STDERR_FILENO; } if (indent) { if (indent > sizeof(spaces) - 1) indent = sizeof(spaces) - 1; memset(spaces, ' ', indent); spaces[indent] = 0; dprintf(fd, "%s", spaces); } va_start(args, format); vdprintf(fd, format, args); va_end(args); } /* * TPMLIB_LogArray: Display an array of data * * @indent: how many spaces to indent; indent of ~0 forces logging * with indent 0 even if not debug_level is set * @data: the data to print * @datalen: length of the data */ void TPMLIB_LogArray(unsigned int indent, const unsigned char *data, size_t datalen) { char line[80]; size_t i, o = 0; for (i = 0; i < datalen; i++) { snprintf(&line[o], sizeof(line) - o, "%02x ", data[i]); o += 3; if (o >= 16 * 3) { TPMLIB_LogPrintfA(indent, "%s\n", line); o = 0; } } if (o > 0) { TPMLIB_LogPrintfA(indent, "%s\n", line); } } void ClearCachedState(enum TPMLIB_StateType st) { free(cached_blobs[st].buffer); cached_blobs[st].buffer = NULL; cached_blobs[st].buflen = 0; } void ClearAllCachedState(void) { ClearCachedState(TPMLIB_STATE_VOLATILE); ClearCachedState(TPMLIB_STATE_PERMANENT); ClearCachedState(TPMLIB_STATE_SAVE_STATE); } /* * Set buffer for cached state; we allow setting an empty cached state * by the caller passing a NULL pointer for the buffer. */ void SetCachedState(enum TPMLIB_StateType st, unsigned char *buffer, uint32_t buflen) { free(cached_blobs[st].buffer); cached_blobs[st].buffer = buffer; cached_blobs[st].buflen = buffer ? buflen : BUFLEN_EMPTY_BUFFER; } void GetCachedState(enum TPMLIB_StateType st, unsigned char **buffer, uint32_t *buflen, bool *is_empty_buffer) { /* caller owns blob now */ *buffer = cached_blobs[st].buffer; *buflen = cached_blobs[st].buflen; *is_empty_buffer = (*buflen == BUFLEN_EMPTY_BUFFER); cached_blobs[st].buffer = NULL; cached_blobs[st].buflen = 0; } bool HasCachedState(enum TPMLIB_StateType st) { return (cached_blobs[st].buffer != NULL || cached_blobs[st].buflen != 0); } TPM_RESULT CopyCachedState(enum TPMLIB_StateType st, unsigned char **buffer, uint32_t *buflen, bool *is_empty_buffer) { TPM_RESULT ret = TPM_SUCCESS; /* buflen may indicate an empty buffer */ *buflen = cached_blobs[st].buflen; *is_empty_buffer = (*buflen == BUFLEN_EMPTY_BUFFER); if (cached_blobs[st].buffer) { *buffer = malloc(*buflen); if (!*buffer) { TPMLIB_LogError("Could not allocate %u bytes.\n", *buflen); ret = TPM_SIZE; } else { memcpy(*buffer, cached_blobs[st].buffer, *buflen); } } else { *buffer = NULL; } return ret; } const char *TPMLIB_StateTypeToName(enum TPMLIB_StateType st) { switch (st) { case TPMLIB_STATE_PERMANENT: return TPM_PERMANENT_ALL_NAME; case TPMLIB_STATE_VOLATILE: return TPM_VOLATILESTATE_NAME; case TPMLIB_STATE_SAVE_STATE: return TPM_SAVESTATE_NAME; } return NULL; } enum TPMLIB_StateType TPMLIB_NameToStateType(const char *name) { if (!name) return 0; if (!strcmp(name, TPM_PERMANENT_ALL_NAME)) return TPMLIB_STATE_PERMANENT; if (!strcmp(name, TPM_VOLATILESTATE_NAME)) return TPMLIB_STATE_VOLATILE; if (!strcmp(name, TPM_SAVESTATE_NAME)) return TPMLIB_STATE_SAVE_STATE; return 0; } libtpms-0.9.3/src/tpm_library_conf.h000066400000000000000000000162461421143571500175020ustar00rootroot00000000000000/********************************************************************************/ /* */ /* LibTPM compile-time choices (#defines) */ /* Written by Stefan Berger */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_library_conf.h 4589 2011-07-05 12:22:40Z stefanb $ */ /* */ /* (c) Copyright IBM Corporation 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_LIBRARY_CONF_H #define TPM_LIBRARY_CONF_H /* Note: None of these defines should be used directly; rather, * the TPMLIB_GetTPMProperty() call should be used to * query their value. * Since tpm_constants.h defines some default values if none * other are defined, this header should be included before * tpm_constants.h is included. */ /* need to restrict the maximum size of keys to cap the below blobs */ #define TPM_RSA_KEY_LENGTH_MAX 2048 /* maximum size of the IO buffer used for requests and responses */ #define TPM_BUFFER_MAX 4096 /* * Below the following acronyms are used to identify what * #define influences which one of the state blobs the TPM * produces. * * PA : permanentall * SS : savestate * VA : volatileall * * BAL: contributes to the ballooning of the state blob */ /* * Do not touch these #define's anymore. They are fixed forever * and define the properties of the TPM library and have a * direct influence on the size requirements of the TPM's block * store and the organization of data inside that block store. */ /* * Every 2048 bit key in volatile space accounts for an * increase of maximum of 559 bytes (PCR_INFO_LONG, tied to PCRs). */ #define TPM_KEY_HANDLES 20 /* SS, VA, BAL */ /* * Every 2048 bit key on which the owner evict key flag is set * accounts for an increase of 559 bytes of the permanentall * blob. */ #define TPM_OWNER_EVICT_KEY_HANDLES 10 /* PA, BAL */ /* * The largest auth session is DSAP; each such session consumes 119 bytes */ #define TPM_MIN_AUTH_SESSIONS 16 /* SS, VA, BAL */ /* * Every transport session accounts for an increase of 78 bytes */ #define TPM_MIN_TRANS_SESSIONS 16 /* SS, VA, BAL */ /* * Every DAA session accounts for an increase of 844 bytes. */ #define TPM_MIN_DAA_SESSIONS 2 /* SS, VA, BAL */ #define TPM_MIN_SESSION_LIST 128 /* SS, VA */ #define TPM_MIN_COUNTERS 8 /* PA */ #define TPM_NUM_FAMILY_TABLE_ENTRY_MIN 16 /* PA */ #define TPM_NUM_DELEGATE_TABLE_ENTRY_MIN 4 /* PA */ /* * NB: above #defines directly influence the largest size of the * 'permanentall', 'savestate' and 'volatileall' data. If these * #define's allow the below space requirements to be exceeded, the * TPM may go into shutdown mode, something we would definitely * like to prevent. We are mostly concerned about the size of * the 'permanentall' blob, which is capped by TPM_MAX_NV_SPACE, * and that of the 'savestate' blob, which is capped by * TPM_MAX_SAVESTATE_SPACE. */ #define TPM_SPACE_SAFETY_MARGIN (4 * 1024) /* * As of V0.5.1 (may have increased since then): * permanent space + 10 keys = 7920 bytes * full volatile space = 17223 bytes * full savestate space = 16992 bytes */ /* * For the TPM_MAX_NV_SPACE we cannot provide a safety margin here * since the TPM will allow NVRAM spaces to allocate everything. * So, we tell the user in TPMLIB_GetTPMProperty that it's 20kb. This * gives us some safety margin for the future. */ #define TPM_PERMANENT_ALL_BASE_SIZE (2334 /* incl. SRK, EK */ + \ 2048 /* extra space */) #define TPM_MAX_NV_DEFINED_SIZE (2048 /* min. NVRAM spaces */ + \ 26*1024 /* extra NVRAM space */ ) #define TPM_MAX_NV_SPACE (TPM_PERMANENT_ALL_BASE_SIZE + \ TPM_OWNER_EVICT_KEY_HANDLES * 559 + \ TPM_MAX_NV_DEFINED_SIZE) #define TPM_MAX_SAVESTATE_SPACE (972 + /* base size */ \ TPM_KEY_HANDLES * 559 + \ TPM_MIN_TRANS_SESSIONS * 78 + \ TPM_MIN_DAA_SESSIONS * 844 + \ TPM_MIN_AUTH_SESSIONS * 119 + \ TPM_SPACE_SAFETY_MARGIN) #define TPM_MAX_VOLATILESTATE_SPACE (1203 + /* base size */ \ TPM_KEY_HANDLES * 559 + \ TPM_MIN_TRANS_SESSIONS * 78 + \ TPM_MIN_DAA_SESSIONS * 844 + \ TPM_MIN_AUTH_SESSIONS * 119 + \ TPM_SPACE_SAFETY_MARGIN) /* * The timeouts in microseconds. * * The problem with the timeouts is that on a heavily utilized * virtualized platform, the processing of the TPM's commands will * take much longer than on a system that's not very busy. So, we * now choose values that are very high so that we don't hit timeouts * in TPM drivers just because the system is busy. However, hitting * timeouts on a very busy system may be inevitable... */ #define TPM_SMALL_DURATION ( 50 * 1000 * 1000) #define TPM_MEDIUM_DURATION (100 * 1000 * 1000) #define TPM_LONG_DURATION (300 * 1000 * 1000) #endif /* TPM_LIBRARY_CONF_H */ libtpms-0.9.3/src/tpm_library_intern.h000066400000000000000000000143461421143571500200530ustar00rootroot00000000000000/********************************************************************************/ /* */ /* LibTPM internal interface functions */ /* Written by Stefan Berger */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_library_intern.h 4432 2011-02-11 15:30:31Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2011. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_LIBRARY_INTERN_H #define TPM_LIBRARY_INTERN_H #include #include "compiler.h" #include "tpm_library.h" #define ROUNDUP(VAL, SIZE) \ ( ( (VAL) + (SIZE) - 1 ) / (SIZE) ) * (SIZE) #define _STRINGIFY(x) #x #define STRINGIFY(x) _STRINGIFY(x) struct libtpms_callbacks *TPMLIB_GetCallbacks(void); /* additional TPM 2 error codes from TPM 1.2 */ #define TPM_RC_BAD_PARAMETER 0x03 #define TPM_RC_BAD_VERSION 0x2e /* * TPM functionality must all be accessible with this interface */ struct tpm_interface { TPM_RESULT (*MainInit)(void); void (*Terminate)(void); uint32_t (*SetBufferSize)(uint32_t wanted_size, uint32_t *min_size, uint32_t *max_size); TPM_RESULT (*Process)(unsigned char **respbuffer, uint32_t *resp_size, uint32_t *respbufsize, unsigned char *command, uint32_t command_size); TPM_RESULT (*VolatileAllStore)(unsigned char **buffer, uint32_t *buflen); TPM_RESULT (*CancelCommand)(void); TPM_RESULT (*GetTPMProperty)(enum TPMLIB_TPMProperty prop, int *result); char *(*GetInfo)(enum TPMLIB_InfoFlags flags); TPM_RESULT (*TpmEstablishedGet)(TPM_BOOL *tpmEstablished); TPM_RESULT (*TpmEstablishedReset)(void); TPM_RESULT (*HashStart)(void); TPM_RESULT (*HashData)(const unsigned char *data, uint32_t data_length); TPM_RESULT (*HashEnd)(void); TPM_RESULT (*ValidateState)(enum TPMLIB_StateType st, unsigned int flags); TPM_RESULT (*SetState)(enum TPMLIB_StateType st, const unsigned char *buffer, uint32_t buflen); TPM_RESULT (*GetState)(enum TPMLIB_StateType st, unsigned char **buffer, uint32_t *buflen); }; extern const struct tpm_interface DisabledInterface; extern const struct tpm_interface TPM12Interface; extern const struct tpm_interface TPM2Interface; /* prototypes for TPM 1.2 */ TPM_RESULT TPM12_IO_Hash_Start(void); TPM_RESULT TPM12_IO_Hash_Data(const unsigned char *data, uint32_t data_length); TPM_RESULT TPM12_IO_Hash_End(void); TPM_RESULT TPM12_IO_TpmEstablished_Get(TPM_BOOL *tpmEstablished); uint32_t TPM12_GetBufferSize(void); TPM_RESULT TPM12_IO_TpmEstablished_Reset(void); /* internal logging function */ int TPMLIB_LogPrintf(const char *format, ...); void TPMLIB_LogPrintfA(unsigned int indent, const char *format, ...) \ ATTRIBUTE_FORMAT(2, 3); void TPMLIB_LogArray(unsigned int indent, const unsigned char *data, size_t datalen); #define TPMLIB_LogError(format, ...) \ TPMLIB_LogPrintfA(~0, "libtpms: "format, __VA_ARGS__) #define TPMLIB_LogTPM12Error(format, ...) \ TPMLIB_LogPrintfA(~0, "libtpms/tpm12: "format, __VA_ARGS__) #define TPMLIB_LogTPM2Error(format, ...) \ TPMLIB_LogPrintfA(~0, "libtpms/tpm2: "format, __VA_ARGS__) /* prototypes for TPM2 */ TPM_RESULT TPM2_IO_Hash_Start(void); TPM_RESULT TPM2_IO_Hash_Data(const unsigned char *data, uint32_t data_length); TPM_RESULT TPM2_IO_Hash_End(void); TPM_RESULT TPM2_IO_TpmEstablished_Get(TPM_BOOL *tpmEstablished); TPM_RESULT TPM2_IO_TpmEstablished_Reset(void); struct sized_buffer { unsigned char *buffer; uint32_t buflen; #define BUFLEN_EMPTY_BUFFER 0xFFFFFFFF }; void ClearCachedState(enum TPMLIB_StateType st); void ClearAllCachedState(void); void SetCachedState(enum TPMLIB_StateType st, unsigned char *buffer, uint32_t buflen); void GetCachedState(enum TPMLIB_StateType st, unsigned char **buffer, uint32_t *buflen, bool *is_empty_buffer); bool HasCachedState(enum TPMLIB_StateType st); TPM_RESULT CopyCachedState(enum TPMLIB_StateType st, unsigned char **buffer, uint32_t *buflen, bool *is_empty_buffer); const char *TPMLIB_StateTypeToName(enum TPMLIB_StateType st); enum TPMLIB_StateType TPMLIB_NameToStateType(const char *name); uint32_t TPM2_GetBufferSize(void); TPM_RESULT TPM2_PersistentAllStore(unsigned char **buf, uint32_t *buflen); #endif /* TPM_LIBRARY_INTERN_H */ libtpms-0.9.3/src/tpm_memory.c000066400000000000000000000116431421143571500163300ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM Memory Allocation */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_memory.c 4609 2011-08-26 19:27:38Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include #include #include "tpm_debug.h" #include "tpm_error.h" #include "tpm_memory.h" /* TPM_Malloc() is a general purpose wrapper around malloc() */ TPM_RESULT TPM_Malloc(unsigned char **buffer, uint32_t size) { TPM_RESULT rc = 0; /* assertion test. The coding style requires that all allocated pointers are initialized to NULL. A non-NULL value indicates either a missing initialization or a pointer reuse (a memory leak). */ if (rc == 0) { if (*buffer != NULL) { printf("TPM_Malloc: Error (fatal), *buffer %p should be NULL before malloc\n", *buffer); rc = TPM_FAIL; } } /* verify that the size is not "too large" */ if (rc == 0) { if (size > TPM_ALLOC_MAX) { printf("TPM_Malloc: Error, size %u greater than maximum allowed\n", size); rc = TPM_SIZE; } } /* verify that the size is not 0, this would be implementation defined and should never occur */ if (rc == 0) { if (size == 0) { printf("TPM_Malloc: Error (fatal), size is zero\n"); rc = TPM_FAIL; } } if (rc == 0) { *buffer = malloc(size); if (*buffer == NULL) { printf("TPM_Malloc: Error allocating %u bytes\n", size); rc = TPM_SIZE; } } return rc; } /* TPM_Realloc() is a general purpose wrapper around realloc() */ TPM_RESULT TPM_Realloc(unsigned char **buffer, uint32_t size) { TPM_RESULT rc = 0; unsigned char *tmpptr = NULL; /* verify that the size is not "too large" */ if (rc == 0) { if (size > TPM_ALLOC_MAX) { printf("TPM_Realloc: Error, size %u greater than maximum allowed\n", size); rc = TPM_SIZE; } } if (rc == 0) { tmpptr = realloc(*buffer, size); if (tmpptr == NULL) { printf("TPM_Realloc: Error reallocating %u bytes\n", size); rc = TPM_SIZE; } } if (rc == 0) { *buffer = tmpptr; } return rc; } /* TPM_Free() is the companion to the TPM allocation functions. It is not used internally. The intent is for use by an application that links directly to a TPM and wants to free memory allocated by the TPM. It avoids a potential problem if the application uses a different allocation library, perhaps one that wraps the functions to detect overflows or memory leaks. */ void TPM_Free(unsigned char *buffer) { free(buffer); return; } libtpms-0.9.3/src/tpm_nvfile.c000066400000000000000000000343471421143571500163110ustar00rootroot00000000000000/********************************************************************************/ /* */ /* NVRAM File Abstraction Layer */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_nvfile.c 4664 2012-01-03 22:15:08Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ /* This module abstracts out all NVRAM read and write operations. This implementation uses standard, portable C files. The basic high level abstractions are: TPM_NVRAM_LoadData(); TPM_NVRAM_StoreData(); TPM_NVRAM_DeleteName(); They take a 'name' that is mapped to a rooted file name. */ #include #include #include #include #include "tpm_debug.h" #include "tpm_error.h" #include "tpm_memory.h" #include "tpm_nvfile.h" #ifdef TPM_LIBTPMS_CALLBACKS #include "tpm_library_intern.h" #include "tpm_library.h" #endif /* local prototypes */ static TPM_RESULT TPM_NVRAM_GetFilenameForName(char *filename, size_t filename_len, uint32_t tpm_number, const char *name); /* A file name in NVRAM is composed of 3 parts: 1 - 'state_directory' is the rooted path to the TPM state home directory 2 = 'tpm_number' is the TPM instance, 00 for a single TPM 2 - the file name For the IBM cryptographic coprocessor version, the root path is hard coded. For the Linux and Windows versions, the path comes from an environment variable. This variable is used once in TPM_NVRAM_Init(). One root path is used for all virtual TPM's, so it can be a static variable. */ char state_directory[FILENAME_MAX]; /* TPM_NVRAM_Init() is called once at startup. It does any NVRAM required initialization. This function sets some static variables that are used by all TPM's. */ TPM_RESULT TPM_NVRAM_Init(void) { TPM_RESULT rc = 0; char *tpm_state_path = NULL; size_t length; #ifdef TPM_LIBTPMS_CALLBACKS struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks(); /* call user-provided function if available, otherwise execute default behavior */ if (cbs->tpm_nvram_init) { rc = cbs->tpm_nvram_init(); return rc; } #endif printf(" TPM_NVRAM_Init:\n"); #ifdef TPM_NV_DISK /* TPM_NV_DISK TPM emulation stores in local directory determined by environment variable. */ if (rc == 0) { tpm_state_path = getenv("TPM_PATH"); if (tpm_state_path == NULL) { printf("TPM_NVRAM_Init: Error (fatal), TPM_PATH environment variable not set\n"); rc = TPM_FAIL; } } #endif /* check that the directory name plus a file name will not overflow FILENAME_MAX */ if (rc == 0) { length = strlen(tpm_state_path); if ((length + TPM_FILENAME_MAX) > FILENAME_MAX) { printf("TPM_NVRAM_Init: Error (fatal), TPM state path name %s too large\n", tpm_state_path); rc = TPM_FAIL; } } if (rc == 0) { strcpy(state_directory, tpm_state_path); printf("TPM_NVRAM_Init: Rooted state path %s\n", state_directory); } return rc; } /* Load 'data' of 'length' from the 'name'. 'data' must be freed after use. Returns 0 on success. TPM_RETRY and NULL,0 on non-existent file (non-fatal, first time start up) TPM_FAIL on failure to load (fatal), since it should never occur */ TPM_RESULT TPM_NVRAM_LoadData(unsigned char **data, /* freed by caller */ uint32_t *length, uint32_t tpm_number, const char *name) { TPM_RESULT rc = 0; long lrc; size_t src; int irc; FILE *file = NULL; char filename[FILENAME_MAX]; /* rooted file name from name */ #ifdef TPM_LIBTPMS_CALLBACKS struct libtpms_callbacks *cbs; bool is_empty_buffer; /* try to get state blob set with TPMLIB_SetState() */ GetCachedState(TPMLIB_NameToStateType(name), data, length, &is_empty_buffer); if (is_empty_buffer) return TPM_RETRY; if (*data) return TPM_SUCCESS; cbs = TPMLIB_GetCallbacks(); /* call user-provided function if available, otherwise execute default behavior */ if (cbs->tpm_nvram_loaddata) { rc = cbs->tpm_nvram_loaddata(data, length, tpm_number, name); return rc; } #endif printf(" TPM_NVRAM_LoadData: From file %s\n", name); *data = NULL; *length = 0; /* open the file */ if (rc == 0) { /* map name to the rooted filename */ rc = TPM_NVRAM_GetFilenameForName(filename, sizeof(filename), tpm_number, name); } if (rc == 0) { printf(" TPM_NVRAM_LoadData: Opening file %s\n", filename); file = fopen(filename, "rb"); /* closed @1 */ if (file == NULL) { /* if failure, determine cause */ if (errno == ENOENT) { printf("TPM_NVRAM_LoadData: No such file %s\n", filename); rc = TPM_RETRY; /* first time start up */ } else { printf("TPM_NVRAM_LoadData: Error (fatal) opening %s for read, %s\n", filename, strerror(errno)); rc = TPM_FAIL; } } } /* determine the file length */ if (rc == 0) { irc = fseek(file, 0L, SEEK_END); /* seek to end of file */ if (irc == -1L) { printf("TPM_NVRAM_LoadData: Error (fatal) fseek'ing %s, %s\n", filename, strerror(errno)); rc = TPM_FAIL; } } if (rc == 0) { lrc = ftell(file); /* get position in the stream */ if (lrc == -1L) { printf("TPM_NVRAM_LoadData: Error (fatal) ftell'ing %s, %s\n", filename, strerror(errno)); rc = TPM_FAIL; } else { *length = (uint32_t)lrc; /* save the length */ } } if (rc == 0) { irc = fseek(file, 0L, SEEK_SET); /* seek back to the beginning of the file */ if (irc == -1L) { printf("TPM_NVRAM_LoadData: Error (fatal) fseek'ing %s, %s\n", filename, strerror(errno)); rc = TPM_FAIL; } } /* allocate a buffer for the actual data */ if ((rc == 0) && *length != 0) { printf(" TPM_NVRAM_LoadData: Reading %u bytes of data\n", *length); rc = TPM_Malloc(data, *length); if (rc != 0) { printf("TPM_NVRAM_LoadData: Error (fatal) allocating %u bytes\n", *length); rc = TPM_FAIL; } } /* read the contents of the file into the data buffer */ if ((rc == 0) && *length != 0) { src = fread(*data, 1, *length, file); if (src != *length) { printf("TPM_NVRAM_LoadData: Error (fatal), data read of %u only read %lu\n", *length, (unsigned long)src); rc = TPM_FAIL; } } /* close the file */ if (file != NULL) { printf(" TPM_NVRAM_LoadData: Closing file %s\n", filename); irc = fclose(file); /* @1 */ if (irc != 0) { printf("TPM_NVRAM_LoadData: Error (fatal) closing file %s\n", filename); rc = TPM_FAIL; } else { printf(" TPM_NVRAM_LoadData: Closed file %s\n", filename); } } return rc; } /* TPM_NVRAM_StoreData stores 'data' of 'length' to the rooted 'filename' Returns 0 on success TPM_FAIL for other fatal errors */ TPM_RESULT TPM_NVRAM_StoreData(const unsigned char *data, uint32_t length, uint32_t tpm_number, const char *name) { TPM_RESULT rc = 0; uint32_t lrc; int irc; FILE *file = NULL; char filename[FILENAME_MAX]; /* rooted file name from name */ #ifdef TPM_LIBTPMS_CALLBACKS struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks(); /* call user-provided function if available, otherwise execute default behavior */ if (cbs->tpm_nvram_storedata) { rc = cbs->tpm_nvram_storedata(data, length, tpm_number, name); return rc; } #endif printf(" TPM_NVRAM_StoreData: To name %s\n", name); if (rc == 0) { /* map name to the rooted filename */ rc = TPM_NVRAM_GetFilenameForName(filename, sizeof(filename), tpm_number, name); } if (rc == 0) { /* open the file */ printf(" TPM_NVRAM_StoreData: Opening file %s\n", filename); file = fopen(filename, "wb"); /* closed @1 */ if (file == NULL) { printf("TPM_NVRAM_StoreData: Error (fatal) opening %s for write failed, %s\n", filename, strerror(errno)); rc = TPM_FAIL; } } /* write the data to the file */ if (rc == 0) { printf(" TPM_NVRAM_StoreData: Writing %u bytes of data\n", length); lrc = fwrite(data, 1, length, file); if (lrc != length) { printf("TPM_NVRAM_StoreData: Error (fatal), data write of %u only wrote %u\n", length, lrc); rc = TPM_FAIL; } } if (file != NULL) { printf(" TPM_NVRAM_StoreData: Closing file %s\n", filename); irc = fclose(file); /* @1 */ if (irc != 0) { printf("TPM_NVRAM_StoreData: Error (fatal) closing file\n"); rc = TPM_FAIL; } else { printf(" TPM_NVRAM_StoreData: Closed file %s\n", filename); } } return rc; } /* TPM_NVRAM_GetFilenameForName() constructs a rooted file name from the name. The filename is of the form: state_directory/tpm_number.name */ static TPM_RESULT TPM_NVRAM_GetFilenameForName(char *filename, /* output: rooted filename */ size_t filename_len, uint32_t tpm_number, const char *name) /* input: abstract name */ { int n; TPM_RESULT rc = TPM_FAIL; printf(" TPM_NVRAM_GetFilenameForName: For name %s\n", name); n = snprintf(filename, filename_len, "%s/%02lx.%s", state_directory, (unsigned long)tpm_number, name); if (n < 0) { printf(" TPM_NVRAM_GetFilenameForName: Error (fatal), snprintf failed\n"); } else if ((size_t)n >= filename_len) { printf(" TPM_NVRAM_GetFilenameForName: Error (fatal), buffer too small\n"); } else { printf(" TPM_NVRAM_GetFilenameForName: File name %s\n", filename); rc = TPM_SUCCESS; } return rc; } /* TPM_NVRAM_DeleteName() deletes the 'name' from NVRAM Returns: 0 on success, or if the file does not exist and mustExist is FALSE TPM_FAIL if the file could not be removed, since this should never occur and there is no recovery NOTE: Not portable code, but supported by Linux and Windows */ TPM_RESULT TPM_NVRAM_DeleteName(uint32_t tpm_number, const char *name, TPM_BOOL mustExist) { TPM_RESULT rc = 0; int irc; char filename[FILENAME_MAX]; /* rooted file name from name */ #ifdef TPM_LIBTPMS_CALLBACKS struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks(); /* call user-provided function if available, otherwise execute default behavior */ if (cbs->tpm_nvram_deletename) { rc = cbs->tpm_nvram_deletename(tpm_number, name, mustExist); return rc; } #endif printf(" TPM_NVRAM_DeleteName: Name %s\n", name); /* map name to the rooted filename */ if (rc == 0) { rc = TPM_NVRAM_GetFilenameForName(filename, sizeof(filename), tpm_number, name); } if (rc == 0) { irc = remove(filename); if ((irc != 0) && /* if the remove failed */ (mustExist || /* if any error is a failure, or */ (errno != ENOENT))) { /* if error other than no such file */ printf("TPM_NVRAM_DeleteName: Error, (fatal) file remove failed, errno %d\n", errno); rc = TPM_FAIL; } } return rc; } libtpms-0.9.3/src/tpm_nvfile.h000066400000000000000000000064431421143571500163120ustar00rootroot00000000000000/********************************************************************************/ /* */ /* NVRAM Utilities */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_nvfile.h 4623 2011-09-28 15:15:09Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2010. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #ifndef TPM_NVFILE_H #define TPM_NVFILE_H #include "tpm_types.h" /* characters in the TPM base file name, 14 for file name, slash, NUL terminator, etc. This macro is used once during initialization to ensure that the TPM_PATH environment variable length will not cause the rooted file name to overflow file name buffers. */ #define TPM_FILENAME_MAX 20 TPM_RESULT TPM_NVRAM_Init(void); /* Basic abstraction for read and write */ TPM_RESULT TPM_NVRAM_LoadData(unsigned char **data, uint32_t *length, uint32_t tpm_number, const char *name); TPM_RESULT TPM_NVRAM_StoreData(const unsigned char *data, uint32_t length, uint32_t tpm_number, const char *name); TPM_RESULT TPM_NVRAM_DeleteName(uint32_t tpm_number, const char *name, TPM_BOOL mustExist); #endif libtpms-0.9.3/src/tpm_tpm12_interface.c000066400000000000000000000356741421143571500200150ustar00rootroot00000000000000/********************************************************************************/ /* */ /* LibTPM TPM 1.2 call interface functions */ /* Written by Stefan Berger */ /* IBM Thomas J. Watson Research Center */ /* */ /* (c) Copyright IBM Corporation 2015. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include #define _GNU_SOURCE #include #include #include #include #include #include "tpm_debug.h" #include "tpm_error.h" #include "tpm12/tpm_init.h" #include "tpm_library_intern.h" #include "tpm12/tpm_process.h" #include "tpm12/tpm_startup.h" #include "tpm12/tpm_global.h" #include "tpm12/tpm_permanent.h" #include "tpm_nvfile.h" static TPM_RESULT TPM12_MainInit(void) { return TPM_MainInit(); } static void TPM12_Terminate(void) { TPM_Global_Delete(tpm_instances[0]); free(tpm_instances[0]); tpm_instances[0] = NULL; } static TPM_RESULT TPM12_Process(unsigned char **respbuffer, uint32_t *resp_size, uint32_t *respbufsize, unsigned char *command, uint32_t command_size) { *resp_size = 0; return TPM_ProcessA(respbuffer, resp_size, respbufsize, command, command_size); } static TPM_RESULT TPM12_VolatileAllStore(unsigned char **buffer, uint32_t *buflen) { TPM_RESULT rc; TPM_STORE_BUFFER tsb; TPM_Sbuffer_Init(&tsb); uint32_t total; #ifdef TPM_DEBUG assert(tpm_instances[0] != NULL); #endif rc = TPM_VolatileAll_Store(&tsb, tpm_instances[0]); if (rc == TPM_SUCCESS) { /* caller now owns the buffer and needs to free it */ TPM_Sbuffer_GetAll(&tsb, buffer, buflen, &total); } else { TPM_Sbuffer_Delete(&tsb); *buflen = 0; *buffer = NULL; } return rc; } static TPM_RESULT TPM12_CancelCommand(void) { return TPM_FAIL; /* not supported */ } static TPM_RESULT TPM12_GetTPMProperty(enum TPMLIB_TPMProperty prop, int *result) { switch (prop) { case TPMPROP_TPM_RSA_KEY_LENGTH_MAX: *result = TPM_RSA_KEY_LENGTH_MAX; break; case TPMPROP_TPM_KEY_HANDLES: *result = TPM_KEY_HANDLES; break; case TPMPROP_TPM_OWNER_EVICT_KEY_HANDLES: *result = TPM_OWNER_EVICT_KEY_HANDLES; break; case TPMPROP_TPM_MIN_AUTH_SESSIONS: *result = TPM_MIN_AUTH_SESSIONS; break; case TPMPROP_TPM_MIN_TRANS_SESSIONS: *result = TPM_MIN_TRANS_SESSIONS; break; case TPMPROP_TPM_MIN_DAA_SESSIONS: *result = TPM_MIN_DAA_SESSIONS; break; case TPMPROP_TPM_MIN_SESSION_LIST: *result = TPM_MIN_SESSION_LIST; break; case TPMPROP_TPM_MIN_COUNTERS: *result = TPM_MIN_COUNTERS; break; case TPMPROP_TPM_NUM_FAMILY_TABLE_ENTRY_MIN: *result = TPM_NUM_FAMILY_TABLE_ENTRY_MIN; break; case TPMPROP_TPM_NUM_DELEGATE_TABLE_ENTRY_MIN: *result = TPM_NUM_DELEGATE_TABLE_ENTRY_MIN; break; case TPMPROP_TPM_SPACE_SAFETY_MARGIN: *result = TPM_SPACE_SAFETY_MARGIN; break; case TPMPROP_TPM_MAX_NV_SPACE: /* fill up 20 kb.; this provides some safety margin (currently >4Kb) for possible future expansion of this blob */ *result = ROUNDUP(TPM_MAX_NV_SPACE, 20 * 1024); break; case TPMPROP_TPM_MAX_SAVESTATE_SPACE: *result = TPM_MAX_SAVESTATE_SPACE; break; case TPMPROP_TPM_MAX_VOLATILESTATE_SPACE: *result = TPM_MAX_VOLATILESTATE_SPACE; break; default: return TPM_FAIL; } return TPM_SUCCESS; } /* * TPM12_GetInfo: * * @flags: logical or of flags that query for information * * Return a JSON document with contents queried for by the user's passed flags */ static char *TPM12_GetInfo(enum TPMLIB_InfoFlags flags) { const char *tpmspec = "\"TPMSpecification\":{" "\"family\":\"1.2\"," "\"level\":2," "\"revision\":116" "}"; const char *tpmattrs = "\"TPMAttributes\":{" "\"manufacturer\":\"id:00001014\"," "\"version\":\"id:00740001\"," /* 146.1 */ "\"model\":\"swtpm\"" "}"; char *fmt = NULL, *buffer; bool printed = false; if (!(buffer = strdup("{%s%s%s}"))) return NULL; if ((flags & TPMLIB_INFO_TPMSPECIFICATION)) { fmt = buffer; buffer = NULL; if (asprintf(&buffer, fmt, "", tpmspec, "%s%s%s") < 0) goto error; free(fmt); printed = true; } if ((flags & TPMLIB_INFO_TPMATTRIBUTES)) { fmt = buffer; buffer = NULL; if (asprintf(&buffer, fmt, printed ? "," : "", tpmattrs, "%s%s%s") < 0) goto error; free(fmt); printed = true; } /* nothing else to add */ fmt = buffer; buffer = NULL; if (asprintf(&buffer, fmt, "", "", "") < 0) goto error; free(fmt); return buffer; error: free(fmt); free(buffer); return NULL; } static uint32_t tpm12_buffersize = TPM_BUFFER_MAX; static uint32_t TPM12_SetBufferSize(uint32_t wanted_size, uint32_t *min_size, uint32_t *max_size) { if (min_size) *min_size = TPM_BUFFER_MIN; if (max_size) *max_size = TPM_BUFFER_MAX; if (wanted_size == 0) return tpm12_buffersize; if (wanted_size > TPM_BUFFER_MAX) wanted_size = TPM_BUFFER_MAX; else if (wanted_size < TPM_BUFFER_MIN) wanted_size = TPM_BUFFER_MIN; tpm12_buffersize = wanted_size; return tpm12_buffersize; } uint32_t TPM12_GetBufferSize(void) { return TPM12_SetBufferSize(0, NULL, NULL); } static TPM_RESULT TPM12_ValidateState(enum TPMLIB_StateType st, unsigned int flags) { TPM_RESULT ret = TPM_SUCCESS; tpm_state_t tpm_state; enum TPMLIB_StateType sts[] = { TPMLIB_STATE_PERMANENT, TPMLIB_STATE_VOLATILE, TPMLIB_STATE_SAVE_STATE, 0, }; enum TPMLIB_StateType c_st; unsigned i; #ifdef TPM_LIBTPMS_CALLBACKS struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks(); if (cbs->tpm_nvram_init) { ret = cbs->tpm_nvram_init(); if (ret != TPM_SUCCESS) return ret; } #endif ret = TPM_Global_Init(&tpm_state); tpm_state.tpm_number = 0; if (ret == TPM_SUCCESS) { /* permanent state needs to be there and loaded first */ ret = TPM_PermanentAll_NVLoad(&tpm_state); } for (i = 0; sts[i] && ret == TPM_SUCCESS; i++) { c_st = st & sts[i]; /* 'cached' state is known to 'work', so skip it */ if (!c_st || HasCachedState(c_st)) continue; switch (c_st) { case TPMLIB_STATE_PERMANENT: break; case TPMLIB_STATE_VOLATILE: ret = TPM_VolatileAll_NVLoad(&tpm_state); break; case TPMLIB_STATE_SAVE_STATE: ret = TPM_SaveState_NVLoad(&tpm_state); break; } } TPM_Global_Delete(&tpm_state); return ret; } static TPM_RESULT _TPM_PermanentAll_Store(TPM_STORE_BUFFER *sbuffer, tpm_state_t *tpm_state) { const unsigned char *buffer = NULL; uint32_t buflen; return TPM_PermanentAll_Store(sbuffer, &buffer, &buflen, tpm_state); } /* * TPM_PermanentAll_NVLoad_Preserve * * @tpm_state: The tpm_state to load the permanent state into * * Call TPM_PermanentAll_NVLoad and preserve any cached data that a call * to TPM_PermanentAll_NVLoad (TPM_NVRAM_LoadData) may otherwise consume * and remove if it was available. */ static TPM_RESULT TPM_PermanentAll_NVLoad_Preserve(tpm_state_t *tpm_state) { TPM_RESULT ret; unsigned char *buffer = NULL; uint32_t buffer_len; bool is_empty_buffer; ret = CopyCachedState(TPMLIB_STATE_PERMANENT, &buffer, &buffer_len, &is_empty_buffer); if (ret == TPM_SUCCESS) { ret = TPM_PermanentAll_NVLoad(tpm_state); /* restore a previous empty buffer or any valid buffer */ if (is_empty_buffer || buffer != NULL) SetCachedState(TPMLIB_STATE_PERMANENT, buffer, buffer_len); } return ret; } /* * Get the state blob of the given type. If we TPM is not running, we * get the cached state blobs, if available, otherwise we try to read * it from files. In case the TPM is running, we get it from the running * TPM. */ static TPM_RESULT TPM12_GetState(enum TPMLIB_StateType st, unsigned char **buffer, uint32_t *buflen) { TPM_RESULT ret = TPM_FAIL; TPM_STORE_BUFFER tsb; uint32_t total; /* TPM not running ? */ if (tpm_instances[0] == NULL) { struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks(); bool is_empty_buffer; /* try cached blob before file */ ret = CopyCachedState(st, buffer, buflen, &is_empty_buffer); if (ret != TPM_SUCCESS || *buffer != NULL || is_empty_buffer) return ret; if (cbs->tpm_nvram_init) { ret = cbs->tpm_nvram_init(); if (ret != TPM_SUCCESS) return ret; ret = TPM_NVRAM_LoadData(buffer, buflen, 0, TPMLIB_StateTypeToName(st)); } else { ret = TPM_FAIL; } return ret; } TPM_Sbuffer_Init(&tsb); switch (st) { case TPMLIB_STATE_PERMANENT: ret = _TPM_PermanentAll_Store(&tsb, tpm_instances[0]); break; case TPMLIB_STATE_VOLATILE: ret = TPM_VolatileAll_Store(&tsb, tpm_instances[0]); break; case TPMLIB_STATE_SAVE_STATE: ret = TPM_SaveState_Store(&tsb, tpm_instances[0]); break; } if (ret == TPM_SUCCESS) { /* caller now owns the buffer and needs to free it */ TPM_Sbuffer_GetAll(&tsb, buffer, buflen, &total); } else { TPM_Sbuffer_Delete(&tsb); *buflen = 0; *buffer = NULL; } return ret; } /* * Set the state the TPM 1.2 will use upon next TPM_MainInit(). The TPM 1.2 * must not have been started, yet, or it must have been terminated for this * function to set the state. * * @st: The TPMLIB_StateType describing the type of blob in the buffer * @buffer: pointer to the buffer containing the state blob; NULL pointer clears * previous state * @buflen: length of the buffer */ static TPM_RESULT TPM12_SetState(enum TPMLIB_StateType st, const unsigned char *buffer, uint32_t buflen) { TPM_RESULT ret = TPM_SUCCESS; unsigned char *stream = NULL, *orig_stream = NULL; uint32_t stream_size = buflen; tpm_state_t *tpm_state = NULL; if (buffer == NULL) { SetCachedState(st, NULL, 0); return TPM_SUCCESS; } if (tpm_instances[0]) return TPM_INVALID_POSTINIT; if (ret == TPM_SUCCESS) { stream = malloc(buflen); if (!stream) { TPMLIB_LogError("Could not allocate %u bytes.\n", buflen); ret = TPM_SIZE; } } if (ret == TPM_SUCCESS) { orig_stream = stream; memcpy(stream, buffer, buflen); tpm_state = malloc(sizeof(tpm_state_t)); if (!tpm_state) { TPMLIB_LogError("Could not allocated %zu bytes.\n", sizeof(tpm_state_t)); ret = TPM_SIZE; } } if (ret == TPM_SUCCESS) { ret = TPM_Global_Init(tpm_state); } /* test whether we can accept the blob */ if (ret == TPM_SUCCESS) { tpm_state->tpm_number = 0; switch (st) { case TPMLIB_STATE_PERMANENT: ret = TPM_PermanentAll_Load(tpm_state, &stream, &stream_size); break; case TPMLIB_STATE_VOLATILE: /* permanent state needs to be there and loaded first */ ret = TPM_PermanentAll_NVLoad_Preserve(tpm_state); if (ret == TPM_SUCCESS) ret = TPM_VolatileAll_Load(tpm_state, &stream, &stream_size); break; case TPMLIB_STATE_SAVE_STATE: ret = TPM_PermanentAll_NVLoad_Preserve(tpm_state); if (ret == TPM_SUCCESS) ret = TPM_SaveState_Load(tpm_state, &stream, &stream_size); break; } if (ret) ClearAllCachedState(); } /* cache the blob for the TPM_MainInit() to pick it up */ if (ret == TPM_SUCCESS) { SetCachedState(st, orig_stream, buflen); } else { free(orig_stream); } TPM_Global_Delete(tpm_state); free(tpm_state); return ret; } const struct tpm_interface TPM12Interface = { .MainInit = TPM12_MainInit, .Terminate = TPM12_Terminate, .Process = TPM12_Process, .VolatileAllStore = TPM12_VolatileAllStore, .CancelCommand = TPM12_CancelCommand, .GetTPMProperty = TPM12_GetTPMProperty, .GetInfo = TPM12_GetInfo, .TpmEstablishedGet = TPM12_IO_TpmEstablished_Get, .TpmEstablishedReset = TPM12_IO_TpmEstablished_Reset, .HashStart = TPM12_IO_Hash_Start, .HashData = TPM12_IO_Hash_Data, .HashEnd = TPM12_IO_Hash_End, .SetBufferSize = TPM12_SetBufferSize, .ValidateState = TPM12_ValidateState, .SetState = TPM12_SetState, .GetState = TPM12_GetState, }; libtpms-0.9.3/src/tpm_tpm12_tis.c000066400000000000000000000255121421143571500166420ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM TIS I/O */ /* Written by Ken Goldman */ /* IBM Thomas J. Watson Research Center */ /* $Id: tpm_tis.c 4505 2011-03-20 17:43:27Z kgoldman $ */ /* */ /* (c) Copyright IBM Corporation 2006, 2011. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ /* This file implements the TPM TIS interface out-of-band commands. */ #include #include #include "tpm12/tpm_crypto.h" #include "tpm12/tpm_cryptoh.h" #include "tpm_debug.h" #include "tpm_error.h" #include "tpm12/tpm_digest.h" #include "tpm12/tpm_global.h" #include "tpm12/tpm_pcr.h" #include "tpm12/tpm_permanent.h" #include "tpm12/tpm_platform.h" #include "tpm12/tpm_process.h" #include "tpm12/tpm_transport.h" #include "tpm_tis.h" /* These commands do not test for TPM_ContinueSelfTest: The following operations MUST be available after TPM_Init and before a call to TPM_ContinueSelfTest 1.9. TPM_HASH_START / TPM_HASH_DATA / TPM_HASH_END */ /* TPM_IO_Hash_Start() implements the LPC bus TPM_HASH_START command */ TPM_RESULT TPM12_IO_Hash_Start(void) { TPM_RESULT rc = 0; tpm_state_t *tpm_state = tpm_instances[0]; /* TPM global state */ TPM_PCRVALUE zeroPCR; TPM_BOOL altered = FALSE; /* TRUE if the structure has been changed */ printf("\nTPM_IO_Hash_Start: Ordinal Entry\n"); TPM_Digest_Init(zeroPCR); /* Prior to receiving the TPM_HASH_START command the TPM must have received a TPM_Startup command. If the TPM receives a TPM_HASH_START after a TPM_Init but before a startup command, the TPM treats this as an error */ if (rc == 0) { if (tpm_state->tpm_stany_flags.postInitialise) { printf("TPM_IO_Hash_Start: Error, postInitialise is TRUE\n"); rc = TPM_INVALID_POSTINIT; } } /* NOTE: Done by caller (1) If no TPM_ACCESS_x.activeLocality field is set, the TPM MUST set the TPM_ACCESS_x.activeLocality field to indicate Locality 4. Any currently executing command MUST be aborted per and subject to Section 11.2.3. */ /* NOTE: Done by caller (2) If TPM_ACCESS_x.activeLocality is set, and if the TPM_ACCESS_x.activeLocality field is not 4, the TPM MUST ignore this command. */ /* NOTE: Done by caller (3) The TPM MUST clear the write FIFO. */ if (rc == 0) { /* (4) If there is an exclusive transport session, it MUST be invalidated. */ if (tpm_state->tpm_stany_flags.transportExclusive != 0) { /* active exclusive */ rc = TPM_TransportSessions_TerminateHandle (tpm_state->tpm_stclear_data.transSessions, tpm_state->tpm_stany_flags.transportExclusive, &(tpm_state->tpm_stany_flags.transportExclusive)); } } if (rc == 0) { /* (5) Set the TPM_PERMANENT_FLAGS->tpmEstablished flag to TRUE (1). Note: see description of Bit Field: tpmEstablishment in 11.2.11 Access Register. */ TPM_SetCapability_Flag(&altered, &(tpm_state->tpm_permanent_flags.tpmEstablished), TRUE); } if (rc == 0) { /* (6) Set the TPM_STANY_FLAGS->TOSPresent flag to TRUE (1). */ tpm_state->tpm_stany_flags.TOSPresent = TRUE; /* (7) Set PCRs per column labeled TPM_HASH_START in Table 5: PCR Initial and Reset Values. (PCR 17-22 to zero, others unchanged */ TPM_PCR_Store(tpm_state->tpm_stclear_data.PCRS, 17, zeroPCR); TPM_PCR_Store(tpm_state->tpm_stclear_data.PCRS, 18, zeroPCR); TPM_PCR_Store(tpm_state->tpm_stclear_data.PCRS, 19, zeroPCR); TPM_PCR_Store(tpm_state->tpm_stclear_data.PCRS, 20, zeroPCR); TPM_PCR_Store(tpm_state->tpm_stclear_data.PCRS, 21, zeroPCR); TPM_PCR_Store(tpm_state->tpm_stclear_data.PCRS, 22, zeroPCR); /* (8) Ignore any data component of the TPM_HASH_START LPC command. */ /* (9) Allocate tempLocation of a size required to perform the SHA-1 operation. */ /* (10) Initialize tempLocation per SHA-1. */ rc = TPM_SHA1InitCmd(&(tpm_state->sha1_context_tis)); } rc = TPM_PermanentAll_NVStore(tpm_state, altered, rc); /* 1) Upon any error in the above steps the TPM: a) MUST enter Failure Mode. NOTE: Done by caller b) MUST release locality. */ if (rc != 0) { printf("TPM_IO_Hash_Start: Error, (fatal)\n"); printf(" TPM_IO_Hash_Start: Set testState to %u \n", TPM_TEST_STATE_FAILURE); tpm_state->testState = TPM_TEST_STATE_FAILURE; } return rc; } /* TPM_IO_Hash_Data() implements the LPC bus TPM_HASH_DATA command */ TPM_RESULT TPM12_IO_Hash_Data(const unsigned char *data, uint32_t data_length) { TPM_RESULT rc = 0; tpm_state_t *tpm_state = tpm_instances[0]; /* TPM global state */ printf("\nTPM_IO_Hash_Data: Ordinal Entry\n"); /* (1) Transform tempLocation per SHA-1 with data received from this command. */ /* (2) Repeat for each TPM_HASH_DATA LPC command received. */ if (rc == 0) { if (tpm_state->sha1_context_tis == NULL) { printf("TPM_IO_Hash_Data: Error, no existing SHA1 thread\n"); rc = TPM_SHA_THREAD; } } if (rc == 0) { rc = TPM_SHA1UpdateCmd(tpm_state->sha1_context_tis, data, data_length); } /* 1) Upon any error in the above steps the TPM: a) MUST enter Failure Mode. NOTE: Done by caller b) MUST release locality. */ if (rc != 0) { printf("TPM_IO_Hash_Data: Error, (fatal)\n"); printf(" TPM_IO_Hash_Data: Set testState to %u \n", TPM_TEST_STATE_FAILURE); tpm_state->testState = TPM_TEST_STATE_FAILURE; } return rc; } /* TPM_IO_Hash_End() implements the LPC bus TPM_HASH_END command */ TPM_RESULT TPM12_IO_Hash_End(void) { TPM_RESULT rc = 0; TPM_PCRVALUE zeroPCR; TPM_DIGEST extendDigest; tpm_state_t *tpm_state = tpm_instances[0]; /* TPM global state */ printf("\nTPM_IO_Hash_End: Ordinal Entry\n"); if (rc == 0) { if (tpm_state->sha1_context_tis == NULL) { printf("TPM_IO_Hash_End: Error, no existing SHA1 thread\n"); rc = TPM_SHA_THREAD; } } /* (1) Ignore any data sent with the command. */ /* (2) Perform finalize operation on tempLocation per SHA-1. */ if (rc == 0) { rc = TPM_SHA1FinalCmd(extendDigest, tpm_state->sha1_context_tis); } /* (3) Perform an “extend” operation, as defined in the TPM_Extend command, of the value within tempLocation into PCR[Locality 4]. */ if (rc == 0) { /* In the previous line above, “PCR[Locality 4]” within and before the SHA-1 function is TPM_PCRVALUE = 0 (i.e., 20 bytes of all zeros). */ TPM_Digest_Init(zeroPCR); /* initial PCR value */ /* PCR[Locality 4] = SHA-1( PCR[Locality 4] || tempLoc) */ rc = TPM_SHA1(tpm_state->tpm_stclear_data.PCRS[TPM_LOCALITY_4_PCR], TPM_DIGEST_SIZE, zeroPCR, TPM_DIGEST_SIZE, extendDigest, 0, NULL); } /* NOTE: Done by caller (4) Clear TPM_ACCESS_x.activeLocality for Locality 4. */ /* 1) Upon any error in the above steps the TPM: a) MUST enter Failure Mode. NOTE: Done by caller b) MUST release locality. */ if (rc != 0) { printf("TPM_IO_Hash_End: Error, (fatal)\n"); printf(" TPM_IO_Hash_End: Set testState to %u \n", TPM_TEST_STATE_FAILURE); tpm_state->testState = TPM_TEST_STATE_FAILURE; } TPM_SHA1Delete(&(tpm_state->sha1_context_tis)); return rc; } TPM_RESULT TPM12_IO_TpmEstablished_Get(TPM_BOOL *tpmEstablished) { TPM_RESULT rc = 0; tpm_state_t *tpm_state = tpm_instances[0]; /* TPM global state */ if (rc == 0) { *tpmEstablished = tpm_state->tpm_permanent_flags.tpmEstablished; } /* 1) Upon any error in the above steps the TPM: a) MUST enter Failure Mode. NOTE: Done by caller b) MUST release locality. */ if (rc != 0) { printf("TPM_IO_TpmEstablished_Get: Error, (fatal)\n"); printf(" TPM_IO_TpmEstablished_Get: Set testState to %u \n", TPM_TEST_STATE_FAILURE); tpm_state->testState = TPM_TEST_STATE_FAILURE; } return 0; } TPM_RESULT TPM12_IO_TpmEstablished_Reset(void) { TPM_RESULT returnCode = 0; tpm_state_t *tpm_state = tpm_instances[0]; /* TPM global state */ TPM_BOOL writeAllNV = FALSE; /* flag to write back flags */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_IO_GetLocality(&(tpm_state->tpm_stany_flags.localityModifier), tpm_state->tpm_number); } /* 1. Validate the assertion of locality 3 or locality 4 */ if (returnCode == TPM_SUCCESS) { returnCode = TPM_Locality_Check(TPM_LOC_THREE | TPM_LOC_FOUR, /* BYTE bitmap */ tpm_state->tpm_stany_flags.localityModifier); } /* 2. Set TPM_PERMANENT_FLAGS -> tpmEstablished to FALSE */ if (returnCode == TPM_SUCCESS) { TPM_SetCapability_Flag(&writeAllNV, /* altered */ &(tpm_state->tpm_permanent_flags.tpmEstablished), /* flag */ FALSE); /* value */ } /* Store the permanent flags back to NVRAM */ returnCode = TPM_PermanentAll_NVStore(tpm_state, writeAllNV, returnCode); return returnCode; } libtpms-0.9.3/src/tpm_tpm2_interface.c000066400000000000000000000464241421143571500177270ustar00rootroot00000000000000/********************************************************************************/ /* */ /* LibTPM TPM 2 call interface functions */ /* Written by Stefan Berger */ /* IBM Thomas J. Watson Research Center */ /* */ /* (c) Copyright IBM Corporation 2015. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include #define _GNU_SOURCE #include #include #include #include #ifndef LIB_EXPORT #define LIB_EXPORT #endif #include "tpm2/Tpm.h" #include "tpm2/Manufacture_fp.h" #include "tpm2/Platform_fp.h" #include "tpm2/ExecCommand_fp.h" #include "tpm2/TpmTcpProtocol.h" #include "tpm2/Simulator_fp.h" #include "tpm2/_TPM_Hash_Data_fp.h" #include "tpm2/_TPM_Init_fp.h" #include "tpm2/StateMarshal.h" #include "tpm2/PlatformACT.h" #include "tpm2/PlatformData.h" #include "tpm2/Volatile.h" #include "tpm2/crypto/openssl/ExpDCache_fp.h" #define TPM_HAVE_TPM2_DECLARATIONS #include "tpm_nvfile.h" // TPM_NVRAM_Loaddata() #include "tpm_error.h" #include "tpm_library_intern.h" #include "tpm_nvfilename.h" extern BOOL g_inFailureMode; static BOOL reportedFailureCommand; /* * Check whether the main NVRAM file exists. Return TRUE if it doesn, FALSE otherwise */ static TPM_BOOL _TPM2_CheckNVRAMFileExists(bool *has_nvram_loaddata_callback) { #ifdef TPM_LIBTPMS_CALLBACKS struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks(); const char *name = TPM_PERMANENT_ALL_NAME; unsigned char *data = NULL; uint32_t length = 0; uint32_t tpm_number = 0; TPM_RESULT ret; *has_nvram_loaddata_callback = cbs->tpm_nvram_loaddata != NULL; if (cbs->tpm_nvram_loaddata) { ret = cbs->tpm_nvram_loaddata(&data, &length, tpm_number, name); free(data); /* a file exists once NOT TPM_RETRY is returned */ if (ret != TPM_RETRY) return TRUE; } #else *has_nvram_loaddata_callback = FALSE; #endif /* TPM_LIBTPMS_CALLBACKS */ return FALSE; } static TPM_RESULT TPM2_MainInit(void) { TPM_RESULT ret = TPM_SUCCESS; bool has_cached_state; bool has_nvram_file; bool has_nvram_loaddata_callback; g_inFailureMode = FALSE; reportedFailureCommand = FALSE; #ifdef TPM_LIBTPMS_CALLBACKS struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks(); if (cbs->tpm_io_init) { ret = cbs->tpm_io_init(); if (ret != TPM_SUCCESS) return ret; } if (cbs->tpm_nvram_init) { ret = cbs->tpm_nvram_init(); if (ret != TPM_SUCCESS) return ret; } #endif /* TPM_LIBTPMS_CALLBACKS */ _rpc__Signal_PowerOff(); has_cached_state = HasCachedState(TPMLIB_STATE_PERMANENT); has_nvram_file = _TPM2_CheckNVRAMFileExists(&has_nvram_loaddata_callback); if (!has_cached_state) { if (!has_nvram_file) { ret = _plat__NVEnable(NULL); if (ret) TPMLIB_LogTPM2Error( "%s: _plat__NVEnable(NULL) failed: %d\n", __func__, ret); if (TPM_Manufacture(TRUE) < 0 || g_inFailureMode) { TPMLIB_LogTPM2Error("%s: TPM_Manufacture(TRUE) failed or TPM in " "failure mode\n", __func__); reportedFailureCommand = TRUE; } } } else if (!has_nvram_loaddata_callback) { ret = _plat__NVEnable_NVChipFile(NULL); if (ret) TPMLIB_LogTPM2Error("%s: _plat__NVEnable_File(NULL) failed: %d\n", __func__, ret); } _rpc__Signal_PowerOn(FALSE); _rpc__Signal_NvOn(); if (ret == TPM_SUCCESS) { if (g_inFailureMode) ret = TPM_RC_FAILURE; } if (ret == TPM_SUCCESS && has_cached_state) { NvCommit(); } return ret; } static void TPM2_Terminate(void) { TPM_TearDown(); _rpc__Signal_PowerOff(); ExpDCacheFree(); } static TPM_RESULT TPM2_Process(unsigned char **respbuffer, uint32_t *resp_size, uint32_t *respbufsize, unsigned char *command, uint32_t command_size) { uint8_t locality = 0; _IN_BUFFER req; _OUT_BUFFER resp; unsigned char *tmp; #ifdef TPM_LIBTPMS_CALLBACKS struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks(); if (cbs->tpm_io_getlocality) { TPM_MODIFIER_INDICATOR locty; locality = cbs->tpm_io_getlocality(&locty, 0); locality = locty; } #endif /* TPM_LIBTPMS_CALLBACKS */ req.BufferSize = command_size; req.Buffer = command; /* have the TPM 2 write directly into the response buffer */ if (*respbufsize < TPM_BUFFER_MAX || !*respbuffer) { tmp = realloc(*respbuffer, TPM_BUFFER_MAX); if (!tmp) { TPMLIB_LogTPM2Error("Could not allocated %u bytes.\n", TPM_BUFFER_MAX); return TPM_SIZE; } *respbuffer = tmp; *respbufsize = TPM_BUFFER_MAX; } resp.BufferSize = *respbufsize; resp.Buffer = *respbuffer; /* * signals for cancellation have to come after we start processing */ _rpc__Signal_CancelOff(); _rpc__Send_Command(locality, req, &resp); /* it may come back with a different buffer, especially in failure mode */ if (resp.Buffer != *respbuffer) { if (resp.BufferSize > *respbufsize) resp.BufferSize = *respbufsize; memcpy(*respbuffer, resp.Buffer, resp.BufferSize); } *resp_size = resp.BufferSize; if (g_inFailureMode && !reportedFailureCommand) { reportedFailureCommand = TRUE; TPMLIB_LogTPM2Error("%s: Entered failure mode through command:\n", __func__); TPMLIB_LogArray(~0, command, command_size); } return TPM_SUCCESS; } TPM_RESULT TPM2_PersistentAllStore(unsigned char **buf, uint32_t *buflen) { BYTE *buffer; INT32 size; unsigned char *nbuffer; TPM_RESULT ret = TPM_SUCCESS; UINT32 written = 0; *buflen = NV_MEMORY_SIZE + 32 * 1024; *buf = NULL; /* the marshal functions do not indicate insufficient buffer; to make sure we didn't run out of buffer, we check that enough room for the biggest type of chunk (64k) is available and try again. */ do { *buflen += 66 * 1024; nbuffer = realloc(*buf, *buflen); if (nbuffer == NULL) { free(*buf); *buf = NULL; ret = TPM_SIZE; written = 0; break; } *buf = buffer = nbuffer; size = *buflen; written = PERSISTENT_ALL_Marshal(&buffer, &size); } while (size < 66 * 1024); *buflen = written; return ret; } static TPM_RESULT TPM2_VolatileAllStore(unsigned char **buffer, uint32_t *buflen) { TPM_RESULT rc = 0; INT32 size = NV_MEMORY_SIZE; UINT16 written; unsigned char *statebuffer = NULL; *buffer = NULL; statebuffer = malloc(size); if (!statebuffer) { TPMLIB_LogTPM2Error("Could not allocate %u bytes.\n", size); return TPM_SIZE; } /* statebuffer will change */ *buffer = statebuffer; written = VolatileSave(&statebuffer, &size); if (written >= size) { free(*buffer); *buffer = NULL; rc = TPM_FAIL; } else { *buflen = written; } return rc; } static TPM_RESULT TPM2_CancelCommand(void) { _rpc__Signal_CancelOn(); return TPM_SUCCESS; } static TPM_RESULT TPM2_GetTPMProperty(enum TPMLIB_TPMProperty prop, int *result) { switch (prop) { case TPMPROP_TPM_RSA_KEY_LENGTH_MAX: *result = MAX_RSA_KEY_BITS; break; case TPMPROP_TPM_KEY_HANDLES: *result = MAX_HANDLE_NUM; break; /* not supported for TPM 2 */ case TPMPROP_TPM_OWNER_EVICT_KEY_HANDLES: case TPMPROP_TPM_MIN_AUTH_SESSIONS: case TPMPROP_TPM_MIN_TRANS_SESSIONS: case TPMPROP_TPM_MIN_DAA_SESSIONS: case TPMPROP_TPM_MIN_SESSION_LIST: case TPMPROP_TPM_MIN_COUNTERS: case TPMPROP_TPM_NUM_FAMILY_TABLE_ENTRY_MIN: case TPMPROP_TPM_NUM_DELEGATE_TABLE_ENTRY_MIN: case TPMPROP_TPM_SPACE_SAFETY_MARGIN: case TPMPROP_TPM_MAX_NV_SPACE: case TPMPROP_TPM_MAX_SAVESTATE_SPACE: case TPMPROP_TPM_MAX_VOLATILESTATE_SPACE: default: return TPM_FAIL; } return TPM_SUCCESS; } /* * TPM2_GetInfo: * * @flags: logical or of flags that query for information * * Return a JSON document with contents queried for by the user's passed flags */ static char *TPM2_GetInfo(enum TPMLIB_InfoFlags flags) { const char *tpmspec = "\"TPMSpecification\":{" "\"family\":\"2.0\"," "\"level\":" STRINGIFY(SPEC_LEVEL_NUM) "," "\"revision\":" STRINGIFY(SPEC_VERSION) "}"; const char *tpmattrs_temp = "\"TPMAttributes\":{" "\"manufacturer\":\"id:00001014\"," "\"version\":\"id:%08X\"," "\"model\":\"swtpm\"" "}"; const char *tpmfeatures_temp = "\"TPMFeatures\":{" "\"RSAKeySizes\":[%s]," "\"CamelliaKeySizes\":[%s]" "}"; char *fmt = NULL, *buffer; bool printed = false; char *tpmattrs = NULL; char *tpmfeatures = NULL; char rsakeys[32]; char camelliakeys[16]; size_t n; if (!(buffer = strdup("{%s%s%s}"))) return NULL; if ((flags & TPMLIB_INFO_TPMSPECIFICATION)) { fmt = buffer; buffer = NULL; if (asprintf(&buffer, fmt, "", tpmspec, "%s%s%s") < 0) goto error; free(fmt); printed = true; } if ((flags & TPMLIB_INFO_TPMATTRIBUTES)) { fmt = buffer; buffer = NULL; if (asprintf(&tpmattrs, tpmattrs_temp, FIRMWARE_V1) < 0) goto error; if (asprintf(&buffer, fmt, printed ? "," : "", tpmattrs, "%s%s%s") < 0) goto error; free(fmt); printed = true; } if ((flags & TPMLIB_INFO_TPMFEATURES)) { fmt = buffer; buffer = NULL; n = snprintf(rsakeys, sizeof(rsakeys), "%s2048%s%s", RSA_1024 ? "1024," : "", RSA_3072 ? ",3072" : "", RSA_4096 ? ",4096" : ""); if (n >= sizeof(rsakeys)) goto error; n = snprintf(camelliakeys, sizeof(camelliakeys), "%s%s%s", CAMELLIA_128 ? "128" : "", CAMELLIA_192 ? ",192" : "", CAMELLIA_256 ? ",256" : ""); if (n >= sizeof(camelliakeys)) goto error; if (asprintf(&tpmfeatures, tpmfeatures_temp, rsakeys, camelliakeys) < 0) goto error; if (asprintf(&buffer, fmt, printed ? "," : "", tpmfeatures, "%s%s%s") < 0) goto error; free(fmt); printed = true; } /* nothing else to add */ fmt = buffer; buffer = NULL; if (asprintf(&buffer, fmt, "", "", "") < 0) goto error; free(fmt); free(tpmattrs); free(tpmfeatures); return buffer; error: free(fmt); free(buffer); free(tpmattrs); free(tpmfeatures); return NULL; } static uint32_t tpm2_buffersize = TPM_BUFFER_MAX; static uint32_t TPM2_SetBufferSize(uint32_t wanted_size, uint32_t *min_size, uint32_t *max_size) { const uint32_t min = MAX_CONTEXT_SIZE + 128; const uint32_t max = TPM_BUFFER_MAX; if (min_size) *min_size = min; if (max_size) *max_size = max; if (wanted_size == 0) return tpm2_buffersize; if (wanted_size > max) wanted_size = max; else if (wanted_size < min) wanted_size = min; tpm2_buffersize = wanted_size; return tpm2_buffersize; } uint32_t TPM2_GetBufferSize(void) { return TPM2_SetBufferSize(0, NULL, NULL); } /* * Validate the state blobs to check whether they can be * successfully used by a TPM_INIT. */ static TPM_RESULT TPM2_ValidateState(enum TPMLIB_StateType st, unsigned int flags) { TPM_RESULT ret = TPM_SUCCESS; TPM_RC rc = TPM_RC_SUCCESS; unsigned char *data = NULL; uint32_t length; unsigned char bak_NV[NV_MEMORY_SIZE]; INT32 size; BYTE *buffer; BOOL restored; /* make backup of current NvChip memory */ memcpy(bak_NV, s_NV, sizeof(bak_NV)); #ifdef TPM_LIBTPMS_CALLBACKS struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks(); if (cbs->tpm_nvram_init) { ret = cbs->tpm_nvram_init(); if (ret != TPM_SUCCESS) return ret; } #endif if ((rc == TPM_RC_SUCCESS) && (st & (TPMLIB_STATE_PERMANENT | TPMLIB_STATE_SAVE_STATE))) { #ifdef TPM_LIBTPMS_CALLBACKS if (cbs->tpm_nvram_loaddata) { ret = cbs->tpm_nvram_loaddata(&data, &length, 0, TPM_PERMANENT_ALL_NAME); if (ret != TPM_SUCCESS) return ret; } #endif if (!data) return TPM_FAIL; buffer = data; size = length; rc = PERSISTENT_ALL_Unmarshal(&buffer, &size); free(data); } if ((rc == TPM_RC_SUCCESS) && (st & TPMLIB_STATE_VOLATILE)) { rc = VolatileLoad(&restored); } ret = rc; return ret; } /* * Get the state blob of the given type. If the TPM is not running, we * get the cached state blobs, if available, otherwise we try to read * it from files. In case the TPM is running, we get it from the running * TPM. */ static TPM_RESULT TPM2_GetState(enum TPMLIB_StateType st, unsigned char **buffer, uint32_t *buflen) { TPM_RESULT ret = TPM_FAIL; if (!_rpc__Signal_IsPowerOn()) { struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks(); bool is_empty_buffer; ret = CopyCachedState(st, buffer, buflen, &is_empty_buffer); if (ret != TPM_SUCCESS || *buffer != NULL || is_empty_buffer) return ret; if (cbs->tpm_nvram_init) { ret = cbs->tpm_nvram_init(); if (ret != TPM_SUCCESS) return ret; /* we can call the TPM 1.2 function here ... */ ret = TPM_NVRAM_LoadData(buffer, buflen, 0, TPMLIB_StateTypeToName(st)); } else { ret = TPM_FAIL; } return ret; } /* from the running TPM */ switch (st) { case TPMLIB_STATE_PERMANENT: ret = TPM2_PersistentAllStore(buffer, buflen); break; case TPMLIB_STATE_VOLATILE: ret = TPM2_VolatileAllStore(buffer, buflen); break; case TPMLIB_STATE_SAVE_STATE: *buffer = NULL; *buflen = 0; ret = 0; break; } return ret; } /* * Set the state the TPM 2 will use upon next TPM_MainInit(). The TPM 2 * must not have been started, yet, or it must have been terminated for this * function to set the state. * * @st: The TPMLIB_StateType describing the type of blob in the buffer * @buffer: pointer to the buffer containing the state blob; NULL pointer clears * previous state * @buflen: length of the buffer */ static TPM_RESULT TPM2_SetState(enum TPMLIB_StateType st, const unsigned char *buffer, uint32_t buflen) { TPM_RESULT ret = TPM_SUCCESS; TPM_RC rc = TPM_RC_SUCCESS; BYTE *stream = NULL, *orig_stream = NULL; INT32 stream_size = buflen; unsigned char *permanent = NULL, *ptr; INT32 permanent_len; if (buffer == NULL) { SetCachedState(st, NULL, 0); return TPM_SUCCESS; } if (_rpc__Signal_IsPowerOn()) return TPM_INVALID_POSTINIT; if (ret == TPM_SUCCESS) { stream = malloc(buflen); if (!stream) ret = TPM_SIZE; } if (ret == TPM_SUCCESS) { orig_stream = stream; memcpy(stream, buffer, buflen); } /* test whether we can accept the blob */ if (ret == TPM_SUCCESS) { switch (st) { case TPMLIB_STATE_PERMANENT: rc = PERSISTENT_ALL_Unmarshal(&stream, &stream_size); break; case TPMLIB_STATE_VOLATILE: /* load permanent state first */ rc = TPM2_GetState(TPMLIB_STATE_PERMANENT, &permanent, (uint32_t *)&permanent_len); if (rc == TPM_RC_SUCCESS) { ptr = permanent; rc = PERSISTENT_ALL_Unmarshal(&ptr, &permanent_len); if (rc == TPM_RC_SUCCESS) rc = VolatileState_Load(&stream, &stream_size); } break; case TPMLIB_STATE_SAVE_STATE: if (buffer != NULL) rc = TPM_BAD_TYPE; break; } ret = rc; if (ret != TPM_SUCCESS) ClearAllCachedState(); } /* cache the blob for the TPM_MainInit() to pick it up */ if (ret == TPM_SUCCESS) { SetCachedState(st, orig_stream, buflen); } else { free(orig_stream); } free(permanent); return ret; } const struct tpm_interface TPM2Interface = { .MainInit = TPM2_MainInit, .Terminate = TPM2_Terminate, .Process = TPM2_Process, .VolatileAllStore = TPM2_VolatileAllStore, .CancelCommand = TPM2_CancelCommand, .GetTPMProperty = TPM2_GetTPMProperty, .GetInfo = TPM2_GetInfo, .TpmEstablishedGet = TPM2_IO_TpmEstablished_Get, .TpmEstablishedReset = TPM2_IO_TpmEstablished_Reset, .HashStart = TPM2_IO_Hash_Start, .HashData = TPM2_IO_Hash_Data, .HashEnd = TPM2_IO_Hash_End, .SetBufferSize = TPM2_SetBufferSize, .ValidateState = TPM2_ValidateState, .SetState = TPM2_SetState, .GetState = TPM2_GetState, }; libtpms-0.9.3/src/tpm_tpm2_tis.c000066400000000000000000000072771421143571500165710ustar00rootroot00000000000000/********************************************************************************/ /* */ /* TPM TIS I/O */ /* Written by Stefan Berger */ /* IBM Thomas J. Watson Research Center */ /* */ /* (c) Copyright IBM Corporation 2015. */ /* */ /* All rights reserved. */ /* */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions are */ /* met: */ /* */ /* Redistributions of source code must retain the above copyright notice, */ /* this list of conditions and the following disclaimer. */ /* */ /* Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */ /* */ /* Neither the names of the IBM Corporation nor the names of its */ /* contributors may be used to endorse or promote products derived from */ /* this software without specific prior written permission. */ /* */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */ /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */ /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */ /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /********************************************************************************/ #include #include #include "tpm2/Tpm.h" #include "tpm2/TpmTypes.h" #include "tpm2/TpmBuildSwitches.h" #include "tpm2/_TPM_Hash_Start_fp.h" #include "tpm2/_TPM_Hash_Data_fp.h" #include "tpm2/_TPM_Hash_End_fp.h" #include "tpm2/TpmTcpProtocol.h" #include "tpm2/Platform_fp.h" #include "tpm2/Simulator_fp.h" #define TPM_HAVE_TPM2_DECLARATIONS #include "tpm_library_intern.h" #include "tpm_error.h" TPM_RESULT TPM2_IO_TpmEstablished_Get(TPM_BOOL *tpmEstablished) { *tpmEstablished = _rpc__Signal_GetTPMEstablished(); return TPM_SUCCESS; } TPM_RESULT TPM2_IO_TpmEstablished_Reset(void) { TPM_RESULT ret = TPM_SUCCESS; struct libtpms_callbacks *cbs = TPMLIB_GetCallbacks(); TPM_MODIFIER_INDICATOR locality = 0; uint32_t tpm_number = 0; if (cbs->tpm_io_getlocality) { cbs->tpm_io_getlocality(&locality, tpm_number); } _plat__LocalitySet(locality); if (locality == 3 || locality == 4) { _rpc__Signal_ResetTPMEstablished(); } else { ret = TPM_BAD_LOCALITY; } return ret; } TPM_RESULT TPM2_IO_Hash_Start(void) { _TPM_Hash_Start(); _rpc__Signal_SetTPMEstablished(); return TPM_SUCCESS; } TPM_RESULT TPM2_IO_Hash_Data(const unsigned char *data, uint32_t data_length) { _TPM_Hash_Data(data_length, (unsigned char *)data); return TPM_SUCCESS; } TPM_RESULT TPM2_IO_Hash_End(void) { _TPM_Hash_End(); return TPM_SUCCESS; } libtpms-0.9.3/tests/000077500000000000000000000000001421143571500143425ustar00rootroot00000000000000libtpms-0.9.3/tests/Makefile.am000066400000000000000000000034621421143571500164030ustar00rootroot00000000000000# # tests/Makefile.am # # For the license, see the LICENSE file in the root directory. # TESTS_ENVIRONMENT = \ abs_top_testdir=`cd '$(top_srcdir)'/tests; pwd` \ abs_top_builddir=`cd '$(top_builddir)'; pwd` \ abs_top_srcdir=`cd '$(top_srcdir)'; pwd` AM_CFLAGS = -I$(top_srcdir)/include $(SANITIZERS) AM_LDFLAGS = -ltpms -L$(top_builddir)/src/.libs $(SANITIZERS) check_PROGRAMS = \ base64decode TESTS = \ base64decode.sh if WITH_TPM2 check_PROGRAMS += \ nvram_offsets \ tpm2_createprimary \ tpm2_pcr_read \ tpm2_selftest TESTS += \ fuzz.sh \ nvram_offsets \ tpm2_createprimary.sh \ tpm2_pcr_read.sh \ tpm2_selftest.sh endif nvram_offsets_SOURCES = nvram_offsets.c nvram_offsets_CFLAGS = $(AM_CFLAGS) \ -I$(top_srcdir)/include/libtpms \ -I$(top_srcdir)/src \ -I$(top_srcdir)/src/tpm2 \ -I$(top_srcdir)/src/tpm2/crypto \ -I$(top_srcdir)/src/tpm2/crypto/openssl \ -DTPM_POSIX nvram_offsets_LDFLAGS = $(AM_LDFLAGS) if WITH_TPM2 check_PROGRAMS += fuzz endif fuzz_SOURCES = fuzz.cc fuzz_CXXFLAGS = $(FUZZER) $(AM_CFLAGS) fuzz_LDFLAGS = $(FUZZER) $(LIB_FUZZING_ENGINE) $(AM_LDFLAGS) if !WITH_FUZZER if !WITH_FUZZING_ENGINE fuzz_SOURCES += fuzz-main.c endif endif if LIBTPMS_USE_FREEBL check_PROGRAMS += freebl_sha1flattensize TESTS += freebl_sha1flattensize endif freebl_sha1flattensize_SOURCES = \ freebl_sha1flattensize.c freebl_sha1flattensize_CFLAGS = \ $(shell nss-config --cflags) \ $(shell nspr-config --cflags) \ -Wall -Werror freebl_sha1flattensize_LDFLAGS = \ -lfreebl \ $(shell nspr-config --libs) \ $(shell nss-config --libs) EXTRA_DIST = \ freebl_sha1flattensize.c \ base64decode.c \ base64decode.sh \ common \ tpm2_createprimary.c \ tpm2_createprimary.sh \ tpm2_pcr_read.c \ tpm2_pcr_read.sh \ tpm2_selftest.c \ tpm2_selftest.sh \ fuzz.sh CLEANFILES = \ *.gcov \ *.gcda \ *.gcno libtpms-0.9.3/tests/base64decode.c000066400000000000000000000034511421143571500167410ustar00rootroot00000000000000#include #include #include #include #include #include #include static unsigned char *read_file(const char *name, size_t *len) { long sz; unsigned char *res; FILE *f = fopen(name, "rb"); if (!f) { printf("Could not open file %s for reading.", name); exit(EXIT_FAILURE); } fseek(f, 0, SEEK_END); sz = ftell(f); fseek(f, 0, SEEK_SET); res = malloc(sz + 1); if (res != NULL) { *len = fread(res, 1, sz, f); res[sz] = 0; } fclose(f); return res; } int main(int argc, char *argv[]) { int res = EXIT_SUCCESS; TPM_RESULT rc; unsigned char *buf_input = NULL, *buf_cmp = NULL; size_t len_input, len_cmp; unsigned char *result = NULL; size_t result_len; if (argc != 3) { printf("Need 2 files as parameters.\n"); return EXIT_FAILURE; } buf_input = read_file(argv[1], &len_input); buf_cmp = read_file(argv[2], &len_cmp); rc = TPMLIB_DecodeBlob((char *)buf_input, TPMLIB_BLOB_TYPE_INITSTATE, &result, &result_len); if (rc != TPM_SUCCESS) { printf("Decoding of the input file failed.\n"); res = EXIT_FAILURE; goto cleanup; } if (result_len != len_cmp) { printf("Length of decoded blob (%zu) does " "not match length of 2nd file (%zu).\n", result_len, len_cmp); res = EXIT_FAILURE; goto cleanup; } if (memcmp(result, buf_cmp, result_len) != 0) { printf("Decoded blob does not match input from 2nd file.\n"); res = EXIT_FAILURE; goto cleanup; } cleanup: free(result); free(buf_cmp); free(buf_input); return res; } libtpms-0.9.3/tests/base64decode.sh000077500000000000000000000012461421143571500171340ustar00rootroot00000000000000#!/usr/bin/env bash input=$(mktemp) binary=$(mktemp) trap "rm -f $input $binary" EXIT function sseq() { for ((i = $1; i < $2; i=i<<1)); do echo $i done } function do_base64() { if [ -n "$(type -p base64)" ]; then base64 $1 elif [ -n "$(type -p uuencode)" ]; then uuencode -m $1 data | sed 1d | sed '$d' else echo "No tool found for base64 encoding." >&2 exit 1 fi } for i in $(sseq 1 1024) 2048 10240; do echo $i dd if=/dev/urandom of=$binary bs=1 count=$i &>/dev/null echo "-----BEGIN INITSTATE-----" > $input do_base64 $binary >> $input echo "-----END INITSTATE-----" >> $input ./base64decode $input $binary if [ $? -ne 0 ]; then exit 1 fi done libtpms-0.9.3/tests/common000066400000000000000000000002701421143571500155540ustar00rootroot00000000000000 # Get the size of a file in bytes # # @1: filename function get_filesize() { if [[ "$(uname -s)" =~ (Linux|CYGWIN_NT-) ]]; then stat -c%s $1 else # OpenBSD stat -f%z $1 fi } libtpms-0.9.3/tests/corpus-execute-command/000077500000000000000000000000001421143571500207315ustar00rootroot00000000000000libtpms-0.9.3/tests/corpus-execute-command/01288b7552bfaf10ba3e65a18059a54a8bb257d0000066400000000000000000000000141421143571500262050ustar00rootroot00000000000000 zlibtpms-0.9.3/tests/corpus-execute-command/0157ea12e541d38f4ef2a25e302428fa82612667000066400000000000000000000000351421143571500260010ustar00rootroot00000000000000r) @gnnn nnlibtpms-0.9.3/tests/corpus-execute-command/01635a68f629b27540012d097b5591d494e7f1a6000066400000000000000000000000121421143571500256510ustar00rootroot00000000000000 Glibtpms-0.9.3/tests/corpus-execute-command/018987668d5249107dd7b0762420190b010da617000066400000000000000000000000671421143571500255110ustar00rootroot000000000000007X@ @ @ e!2 ^q??? ylibtpms-0.9.3/tests/corpus-execute-command/01a0c50f2aa728173f426c981a08db237478d37d000066400000000000000000000000141421143571500260550ustar00rootroot00000000000000 Wlibtpms-0.9.3/tests/corpus-execute-command/01d2bdf3630d66f77c7c921bad3f3f55cf3c2dc0000066400000000000000000000000141421143571500265150ustar00rootroot00000000000000 libtpms-0.9.3/tests/corpus-execute-command/02623e79f7d581ef174c030449af192796fae549000066400000000000000000000002461421143571500260430ustar00rootroot00000000000000g<#@#`i y%K=7:~ hqEe7r%fɠX#) $'qh :@libtpms-0.9.3/tests/corpus-execute-command/02630a7d049d47191a0f369995b5e4419bcf8fc3000066400000000000000000000000401421143571500261000ustar00rootroot00000000000000 -@ @ libtpms-0.9.3/tests/corpus-execute-command/02a4c7f3b1a0a6ffd40fcd31bac49a00eb779bf6000066400000000000000000000000631421143571500266440ustar00rootroot000000000000003!@ @ ( @ ~libtpms-0.9.3/tests/corpus-execute-command/02ad05b22e8e7cb8ebf2e20bf1422de0039c77d0000066400000000000000000000000241421143571500264200ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/02b3b56a2dd9f053dd5b01b6f8c4cc1720b2a09e000066400000000000000000000002461421143571500264230ustar00rootroot00000000000000g<#@,`i y%K=7:~ hqEe7r%fɠX# @'rN 'qT :@libtpms-0.9.3/tests/corpus-execute-command/032cf0919d6382aea9de278308ffc69b60faece7000066400000000000000000000000141421143571500264640ustar00rootroot00000000000000 olibtpms-0.9.3/tests/corpus-execute-command/037cf899fb8d1c147e21c5e836a4cbe647b4eda9000066400000000000000000000000261421143571500264710ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/03e86d685e5eb50122c5a4c9f700db4e920a9c3c000066400000000000000000000001311421143571500263010ustar00rootroot00000000000000Y< @ < @ )( <@ @%!me libtpms-0.9.3/tests/corpus-execute-command/041c3fa7a9c1b656153f4ece2beda3d2c2a7c4e5000066400000000000000000000002461421143571500265740ustar00rootroot00000000000000g<#@,`i y%K=7:~ hqEe7r%fɠX# '9'rN $'qT :@libtpms-0.9.3/tests/corpus-execute-command/04476f8c92e4c797dd8e20fb69032cfa2c508c88000066400000000000000000000001051421143571500262550ustar00rootroot00000000000000E1@ @ Xme `libtpms-0.9.3/tests/corpus-execute-command/045d4363cf19e6c4b56b6950dc9942781a59658b000066400000000000000000000000121421143571500260340ustar00rootroot00000000000000 0libtpms-0.9.3/tests/corpus-execute-command/04c38ff399dc85ac49eb6cd74e2d9314b163d273000066400000000000000000000000261421143571500263300ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/053a9efeed73544c15ee68bba12a69b320111a22000066400000000000000000000000241421143571500262610ustar00rootroot00000000000000~  libtpms-0.9.3/tests/corpus-execute-command/05ad68bd9a5d0f128dfed21b462a61f8518ad655000066400000000000000000000000201421143571500263620ustar00rootroot00000000000000Blibtpms-0.9.3/tests/corpus-execute-command/05c9745871907e1ee3f95e5df5c3706228c7e0fc000066400000000000000000000002461421143571500262050ustar00rootroot00000000000000g<#@#`i y%K=7:~ hqEe7r%fɠX#) $'qh :@libtpms-0.9.3/tests/corpus-execute-command/060307da694d3c42b27791141deb2a01c52a006d000066400000000000000000000000171421143571500260270ustar00rootroot00000000000000g%libtpms-0.9.3/tests/corpus-execute-command/06727458762c42d650f7efcadeca1cb74bd3da62000066400000000000000000000000231421143571500264440ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/06c29595a604df613bc84aea4ba0ffb58af54b02000066400000000000000000000000531421143571500264350ustar00rootroot00000000000000+v@ @libtpms-0.9.3/tests/corpus-execute-command/06c655ae5b18e3daa3a73a18993b57d5ca56b48d000066400000000000000000000000141421143571500263700ustar00rootroot00000000000000 ^libtpms-0.9.3/tests/corpus-execute-command/06de2e9e2cba4bb467ccc6b88695d92135bbf5b8000066400000000000000000000000161421143571500265430ustar00rootroot00000000000000Plibtpms-0.9.3/tests/corpus-execute-command/06f593a04602ec847f1ee37123c10f58d81ad312000066400000000000000000000000401421143571500260520ustar00rootroot00000000000000 !@ @ libtpms-0.9.3/tests/corpus-execute-command/071aad93edbf3af12056c1d4649bf7e5da254648000066400000000000000000000000331421143571500263640ustar00rootroot00000000000000< @ libtpms-0.9.3/tests/corpus-execute-command/075ddc6690d3238e2c9b96cd3ec4b4c5f64e038f000066400000000000000000000000261421143571500264070ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/07af6f1548b433f23d352d3148f6193cdacb482f000066400000000000000000000000241421143571500262260ustar00rootroot00000000000000~libtpms-0.9.3/tests/corpus-execute-command/07b406ce454996fa5595ad50228ecc92713c7626000066400000000000000000000002461421143571500260330ustar00rootroot00000000000000g<#@,`%K=7:~ hqEe7r%fɠX# @libtpms-0.9.3/tests/corpus-execute-command/09604d3cc3fc15e695abe9c8e41b16331aa63371000066400000000000000000000000121421143571500262130ustar00rootroot00000000000000 Elibtpms-0.9.3/tests/corpus-execute-command/09c7993d9fc88ad7e53320b9e540d229787651eb000066400000000000000000000000141421143571500261250ustar00rootroot00000000000000 ]libtpms-0.9.3/tests/corpus-execute-command/09d08b1770e352fc99d0c83d20c8f97c35dd52e7000066400000000000000000000000321421143571500262450ustar00rootroot00000000000000gglibtpms-0.9.3/tests/corpus-execute-command/0ac2dc4b494f39f36d0b5d9fe9c7238f976203af000066400000000000000000000001111421143571500264040ustar00rootroot00000000000000I1@ @ CE ? `Clibtpms-0.9.3/tests/corpus-execute-command/0b1d3962464f880354f770b192c88794265f49c2000066400000000000000000000007061421143571500256270ustar00rootroot00000000000000g@,`i y%K+=7:~"9Z6> \z kO AeK ҔcJ ";{kG v~E# A3PZȵWAϫad<ɚſ`sd>S;6Wb(-qW[ |•מ) `=-ejTEX6V @libtpms-0.9.3/tests/corpus-execute-command/0b4b00255f1fae86dfa35f62fcee55a53ba05f66000066400000000000000000000000471421143571500265220ustar00rootroot00000000000000':@ @  libtpms-0.9.3/tests/corpus-execute-command/0c42f8d6a159ef06e6c0e4176497250cd343bc66000066400000000000000000000000401421143571500261510ustar00rootroot00000000000000 1@ @ libtpms-0.9.3/tests/corpus-execute-command/0c4a9ae0db7f786075229db6db0814d1a6352a30000066400000000000000000000002461421143571500262160ustar00rootroot00000000000000g<#@,`i y%K+=7:~ X# )pcF$QԆW:t59'rN ij"octP<3$'qT:@libtpms-0.9.3/tests/corpus-execute-command/0cbc2eae447ec793012e090aa48412d63cc50416000066400000000000000000000000631421143571500262020ustar00rootroot0000000000000031@@ @ 5* libtpms-0.9.3/tests/corpus-execute-command/0cdcf1c44ca28d68820abbfa279fcd91d3477f0c000066400000000000000000000000261421143571500266060ustar00rootroot00000000000000libtpms-0.9.3/tests/corpus-execute-command/0cec7fbf0b7dc9bc1aa72ffa6dc6141179a1a52b000066400000000000000000000000671421143571500267330ustar00rootroot0000000000000075e5@NLe75@Ne5@N(g2 libtpms-0.9.3/tests/corpus-execute-command/0d153ecddd05242cd186c4ce869a65dd93a5eb15000066400000000000000000000000221421143571500264420ustar00rootroot00000000000000v@@ libtpms-0.9.3/tests/corpus-execute-command/0d96ea4a5f5bc9e3f5733e00dfde6f57c034a045000066400000000000000000000001111421143571500264440ustar00rootroot00000000000000I1@ @ \E( `Clibtpms-0.9.3/tests/corpus-execute-command/0de02911cd3b9db21923b52616bbc979d00a683a000066400000000000000000000000261421143571500262100ustar00rootroot00000000000000zzlibtpms-0.9.3/tests/corpus-execute-command/0e8853b739b227ea0a2cbfb598ac7227361cd381000066400000000000000000000000261421143571500262270ustar00rootroot00000000000000*@libtpms-0.9.3/tests/corpus-execute-command/0f447663f1849773369cd5caadf033520972eca4000066400000000000000000000000141421143571500261000ustar00rootroot00000000000000 jlibtpms-0.9.3/tests/corpus-execute-command/0f662adcde79403d24452d8347966a3c7f4cf459000066400000000000000000000000321421143571500261710ustar00rootroot00000000000000v@@ libtpms-0.9.3/tests/corpus-execute-command/0fb1b32b6c35d5e1fb7bc71bd2987669ccdaf132000066400000000000000000000001111421143571500265160ustar00rootroot00000000000000I1@ @ \cE, `Clibtpms-0.9.3/tests/corpus-execute-command/0fcf1f27b9a054dbc5acf6ea015635a136cd0ffd000066400000000000000000000000141421143571500266440ustar00rootroot00000000000000 libtpms-0.9.3/tests/corpus-execute-command/1090a39808e0b012def2f866981a564786d041cf000066400000000000000000000000331421143571500260140ustar00rootroot00000000000000$@ @ libtpms-0.9.3/tests/corpus-execute-command/1121e5a8f2e336bbd7ca300fc207d85079331afb000066400000000000000000000000261421143571500262630ustar00rootroot00000000000000 libtpms-0.9.3/tests/corpus-execute-command/113258fb8814749bc30569952277457a972bc3ba000066400000000000000000000000471421143571500256730ustar00rootroot00000000000000'1@ @ \wlibtpms-0.9.3/tests/corpus-execute-command/11b30d1f2c6bc54604ed98380fe413a9ce30333d000066400000000000000000000000431421143571500262070ustar00rootroot00000000000000#(@ @  @libtpms-0.9.3/tests/corpus-execute-command/120203308b2fb29bd00553c9b68ebbefc7e5d612000066400000000000000000000000261421143571500262670ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/128e44224aecafae3701d35ecbbab55691b16aac000066400000000000000000000000221421143571500265510ustar00rootroot00000000000000}@ libtpms-0.9.3/tests/corpus-execute-command/1308d609943b8b39f30e946a0e9b5ff7887caa05000066400000000000000000000000261421143571500261730ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/13e8a2f220447c6ef5e133925ab11215659463bc000066400000000000000000000000121421143571500257710ustar00rootroot00000000000000 2libtpms-0.9.3/tests/corpus-execute-command/13efd83681f51ace37b436050258d456324ee8d3000066400000000000000000000000401421143571500260710ustar00rootroot00000000000000 !@ @ @ libtpms-0.9.3/tests/corpus-execute-command/14050cbb74910c38a6451a0f434f3f3e8db84604000066400000000000000000000007061421143571500260600ustar00rootroot00000000000000g@,`i y%K+=7:~@W[ |•מ) `=-eϫad<ɚſ`sd>S;6Wb(-q@libtpms-0.9.3/tests/corpus-execute-command/144618940d1041a33e6df30b738b1ba12a9c4887000066400000000000000000000000121421143571500257670ustar00rootroot00000000000000 }libtpms-0.9.3/tests/corpus-execute-command/147ef8a5cbb78fad63af9ab469fbfc24fd01c910000066400000000000000000000001311421143571500266720ustar00rootroot00000000000000YX@ @ Y 0@ * Xm ; Xeemlibtpms-0.9.3/tests/corpus-execute-command/148cb0b0ccebec948dff472bb91d11f57c46ec3b000066400000000000000000000000151421143571500266620ustar00rootroot00000000000000 :;libtpms-0.9.3/tests/corpus-execute-command/14d4b01bd22e259c5597dd294c6f5c0c71430745000066400000000000000000000000401421143571500260610ustar00rootroot00000000000000 !@ @ libtpms-0.9.3/tests/corpus-execute-command/15162b142a3a54624c85bef6e0d2576602b28c61000066400000000000000000000000521421143571500257700ustar00rootroot00000000000000*g#@libtpms-0.9.3/tests/corpus-execute-command/155bf7b27185500ded1eb49a5c172071ea127bf3000066400000000000000000000000261421143571500262110ustar00rootroot00000000000000Xzlibtpms-0.9.3/tests/corpus-execute-command/1574197c65abe00b723406a12e2c12a20b5a1d74000066400000000000000000000007061421143571500260320ustar00rootroot00000000000000g@,`i y%K+=7:~@s[ @libtpms-0.9.3/tests/corpus-execute-command/1621b405eaec9120bebf684c462620a4989e2da9000066400000000000000000000000161421143571500262230ustar00rootroot00000000000000slibtpms-0.9.3/tests/corpus-execute-command/16315e46b15c8aec83ef25aeb78a36f31617bf1f000066400000000000000000000001051421143571500263670ustar00rootroot00000000000000E1@ @ Xme `libtpms-0.9.3/tests/corpus-execute-command/16c8d2f1b945a51be8f08fa24338158d2995e7ab000066400000000000000000000000331421143571500262430ustar00rootroot00000000000000%@ @ libtpms-0.9.3/tests/corpus-execute-command/174a2cdf7a49ede39cbe8512927cda9be6538d36000066400000000000000000000000161421143571500264720ustar00rootroot00000000000000?@ libtpms-0.9.3/tests/corpus-execute-command/1777e654486fcc1adb8c86bbecd9d927a226cf10000066400000000000000000000002461421143571500264720ustar00rootroot00000000000000g<#@,`i y%K+=7:~ hqEe7.r%fɠX# QԆW:t59'rN ij"octP<3$'qT:@libtpms-0.9.3/tests/corpus-execute-command/179212de145a3cf9b70f991cfc2d407b0dd65743000066400000000000000000000000261421143571500262320ustar00rootroot00000000000000g ;libtpms-0.9.3/tests/corpus-execute-command/17b5b211c5a6fffa55b3b54204aa6213b1b54fad000066400000000000000000000007061421143571500264140ustar00rootroot00000000000000g@,`i y%K+=7:~"9Z6> \z kO AeK ]ҔcJ ";{kG v~E# A3PZȵWAϫad2ɚſ`sd>S;6Wb(-qvǔSã""("{v3jؐMl'#rƙ$86 nyƁ)&8.t3K1@%TYb]ijfQjl7ʷp=V]$ *A&ʯvvp/1O#I hW%7F޴^d2#+;ݭ|z *@@?FW݉;dLW[ |•מ) `=-ejTEX6V @libtpms-0.9.3/tests/corpus-execute-command/17b7a8bedf7a418eacec1d012019fbcb004919f2000066400000000000000000000001111421143571500265030ustar00rootroot00000000000000I1@ @ CE? `Clibtpms-0.9.3/tests/corpus-execute-command/17c9aad2fde93625e75d40b1c68f902b5b3cb3f3000066400000000000000000000002461421143571500264540ustar00rootroot00000000000000g<#@,`i y%K+=7:~ !X# )pcF$QԆW:t59'rN ij"octP<3$'qT:@libtpms-0.9.3/tests/corpus-execute-command/17e31c9e8a0962ab8fc7d04f9e398cbb85fd3958000066400000000000000000000001111421143571500264220ustar00rootroot00000000000000I1@ @ d? `Clibtpms-0.9.3/tests/corpus-execute-command/18606f9512f8c3cccd97fb26b9ebf3122bd7ec24000066400000000000000000000004521421143571500264640ustar00rootroot00000000000000*gлyO͈V`.+qNx3Ur[n @i(p0|eC> BndjKCn謊_3]5ޒ~,h:7PIPꤌP|,]Py @|Ԝ)-m5 ȕcAW2NMhX.EmHID4~%e/ۘ%|~ـ뜮L8;(]Z%9 @ libtpms-0.9.3/tests/corpus-execute-command/1863ff49e6755ec92440c53db8a261358918cd4e000066400000000000000000000000161421143571500261170ustar00rootroot00000000000000~libtpms-0.9.3/tests/corpus-execute-command/18a31595540d5b785792bb8099d16d9a043b343b000066400000000000000000000000161421143571500257370ustar00rootroot00000000000000Blibtpms-0.9.3/tests/corpus-execute-command/18a68628ac58479294c5f771fbaf0e1512b0e34c000066400000000000000000000002461421143571500261640ustar00rootroot00000000000000g<#@,`i y%K=7:~ hqEe7r%fɠX# '9'rN $'qT :@libtpms-0.9.3/tests/corpus-execute-command/1909a1cac09e2e10237b1723e5a9fdde8219881c000066400000000000000000000001111421143571500262200ustar00rootroot00000000000000I*@ @ !XmerG !libtpms-0.9.3/tests/corpus-execute-command/191eae3a326700c8104b01663510667a6bd1ba29000066400000000000000000000000351421143571500257540ustar00rootroot00000000000000+@ @ libtpms-0.9.3/tests/corpus-execute-command/19bc232253a73299de0c14ef9aeb6bd73aa1256e000066400000000000000000000000121421143571500263530ustar00rootroot00000000000000 libtpms-0.9.3/tests/corpus-execute-command/1a35e3aabb6784d0644c987aad36946d4eaa2f56000066400000000000000000000000261421143571500263730ustar00rootroot00000000000000!libtpms-0.9.3/tests/corpus-execute-command/1bae028a56b8d54a04f481d8e935c57db2c4e208000066400000000000000000000001111421143571500263010ustar00rootroot00000000000000I1@ @ CY? `Clibtpms-0.9.3/tests/corpus-execute-command/1bb2735dc45d3db28c2a500d17f929b9226e7a7b000066400000000000000000000000731421143571500263040ustar00rootroot00000000000000;1@ @ % Clibtpms-0.9.3/tests/corpus-execute-command/1bdd2439e5f146bf980be2c05a2222184e7ebd12000066400000000000000000000000371421143571500262750ustar00rootroot00000000000000-@ @ libtpms-0.9.3/tests/corpus-execute-command/1bec8af0a46023ba2ef2e0766ab51b87149e515d000066400000000000000000000002461421143571500263550ustar00rootroot00000000000000g<#@,`i y%K+=7:~ X# )pcF$QԆW:t59'rN ij"octP<3$'qT:@libtpms-0.9.3/tests/corpus-execute-command/1c25ffe21675e79242fcc9ea1ea70c42287137af000066400000000000000000000000351421143571500263140ustar00rootroot00000000000000^o9jQjlibtpms-0.9.3/tests/corpus-execute-command/1c58de3e5c8a7c7aea5e9d956bf523dd1dd63e42000066400000000000000000000000121421143571500266210ustar00rootroot00000000000000 ;libtpms-0.9.3/tests/corpus-execute-command/1c7e6b1b650812eeeddbfdf17b5a0bf47b3b98f0000066400000000000000000000000241421143571500266620ustar00rootroot00000000000000~  libtpms-0.9.3/tests/corpus-execute-command/1ca8c0ba33835298a3cd82a65f533c982368e072000066400000000000000000000000161421143571500260730ustar00rootroot00000000000000Klibtpms-0.9.3/tests/corpus-execute-command/1cc1a6d575542b942226ce7855d7d1c3f8a10e38000066400000000000000000000001121421143571500261460ustar00rootroot00000000000000JoJHH˥ˆY]Y]YX]IHJH ˆ˥ ˆY]Y] libtpms-0.9.3/tests/corpus-execute-command/1cc8d9f8ce8feabacb89389bcab1b89d578c58a1000066400000000000000000000000161421143571500270010ustar00rootroot00000000000000,@ libtpms-0.9.3/tests/corpus-execute-command/1d023ae4a29efc369790fad71046cbc44baa569c000066400000000000000000000001111421143571500264340ustar00rootroot00000000000000I@ @  * Xme `* C*libtpms-0.9.3/tests/corpus-execute-command/1d81a48de996a1b50fed50e23b4c151e51a45b89000066400000000000000000000002461421143571500263100ustar00rootroot00000000000000g<#@,`i y%K+=7:~ X# )pcF$QԆW:t59'rN ij"octP<3$'qT:@libtpms-0.9.3/tests/corpus-execute-command/1dba0b83c3309cc7c073cfd5c8c60aa40ef0d521000066400000000000000000000000731421143571500264770ustar00rootroot00000000000000;1@ @ %  Clibtpms-0.9.3/tests/corpus-execute-command/1dba507c625b0693d6971e90183f6825fd5a3d81000066400000000000000000000000161421143571500261000ustar00rootroot00000000000000libtpms-0.9.3/tests/corpus-execute-command/1df937b0b6f7aad597b35365dc04b55d819eb238000066400000000000000000000000261421143571500263220ustar00rootroot00000000000000g%libtpms-0.9.3/tests/corpus-execute-command/1e06acc94aad0f32366044ad86b344b2e9e16733000066400000000000000000000000531421143571500262140ustar00rootroot00000000000000+v@ @libtpms-0.9.3/tests/corpus-execute-command/1e0d3d568511b5ba5ccad54395d084ab246e18e1000066400000000000000000000000121421143571500262660ustar00rootroot00000000000000 9libtpms-0.9.3/tests/corpus-execute-command/1e4d0e4b7939177bc414bbfe1c27b55d303acf27000066400000000000000000000000671421143571500263650ustar00rootroot000000000000007gQ BY YB*libtpms-0.9.3/tests/corpus-execute-command/1e88122871537e5e30bde90074c06709d93e4f94000066400000000000000000000000261421143571500257510ustar00rootroot00000000000000libtpms-0.9.3/tests/corpus-execute-command/1efd19aa62ef5d115302070b3b092d557f768c23000066400000000000000000000000261421143571500261360ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/1f25c9c5f06ad1575dda08a58183279969007629000066400000000000000000000001111421143571500257460ustar00rootroot00000000000000I1@ @ CE? `Clibtpms-0.9.3/tests/corpus-execute-command/1f5a6605a01216c7ef13bc2a9e2d056c92658654000066400000000000000000000000261421143571500260620ustar00rootroot00000000000000z2libtpms-0.9.3/tests/corpus-execute-command/1f71ab4b3be2b5c28dec2fb789baf2f0c59f858a000066400000000000000000000001051421143571500266730ustar00rootroot00000000000000E1@ @ e `libtpms-0.9.3/tests/corpus-execute-command/1f74ef335ee188798116dd1d17a8d5efb35083ca000066400000000000000000000000671421143571500263340ustar00rootroot0000000000000071@ @ CF? `libtpms-0.9.3/tests/corpus-execute-command/1feb0553856ab38eba964705906f70efd238ade3000066400000000000000000000002461421143571500263250ustar00rootroot00000000000000g<#@,`i y%K+=7:~ hqEe7.r%fɠX# )pcF$QԆW:t59'rN ij"octP<3$'qT:@libtpms-0.9.3/tests/corpus-execute-command/207596cf258d9e11254bf384e90d2cdb235544bc000066400000000000000000000000141421143571500261520ustar00rootroot00000000000000 tlibtpms-0.9.3/tests/corpus-execute-command/20e3c030c5f2d55de9222971b0e29ef2a5e628c2000066400000000000000000000000261421143571500262170ustar00rootroot000000000000007(libtpms-0.9.3/tests/corpus-execute-command/210a149dc884f9caa6e6e63bc782e1747d5eff60000066400000000000000000000000261421143571500264070ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/217627e1ede534058fb8f1c4691ab38ac0182270000066400000000000000000000000121421143571500260560ustar00rootroot00000000000000 {libtpms-0.9.3/tests/corpus-execute-command/229e01633283f450e49a9bc23abc2ecf81b04da8000066400000000000000000000000261421143571500262740ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/22adbb2594c2adc98d8e9c3ada20495d69b57e2c000066400000000000000000000000201421143571500265270ustar00rootroot00000000000000~libtpms-0.9.3/tests/corpus-execute-command/22ca5a34e7754258ad35e32164f5555d035da47e000066400000000000000000000000671421143571500260730ustar00rootroot000000000000007X@ @  @ e!2 ^q??? ylibtpms-0.9.3/tests/corpus-execute-command/22cb7141259e05dfb2fa1730b4044d5cdf8a9eab000066400000000000000000000001111421143571500264220ustar00rootroot00000000000000I1@ @ C Clibtpms-0.9.3/tests/corpus-execute-command/22ef24147b4be43c3ed6034bf180dc81d03615da000066400000000000000000000001051421143571500262610ustar00rootroot00000000000000E1@ @ Xme `libtpms-0.9.3/tests/corpus-execute-command/22fb4b69e0865ab12c722465bdd9f62614e8e3d9000066400000000000000000000001001421143571500262340ustar00rootroot00000000000000@aZI1 @ @ a; XmC@ :ZXmlibtpms-0.9.3/tests/corpus-execute-command/232059825d5abb08c257c5415c95a19d21881ee3000066400000000000000000000000431421143571500260060ustar00rootroot00000000000000#(@ @ libtpms-0.9.3/tests/corpus-execute-command/234cc3f5406bd58893247e55aa3a2dc36623ffb3000066400000000000000000000000141421143571500262240ustar00rootroot00000000000000 @libtpms-0.9.3/tests/corpus-execute-command/23f43543307a690118bde840aa592316dbf1708f000066400000000000000000000000261421143571500260000ustar00rootroot00000000000000z!!libtpms-0.9.3/tests/corpus-execute-command/23f44560a58b4909ec46a970a4969c01b0d3b7e7000066400000000000000000000000261421143571500260770ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/242e15d325e35b32e46852cb54e2573e98b66ac1000066400000000000000000000000341421143571500260700ustar00rootroot000000000000000@ @ libtpms-0.9.3/tests/corpus-execute-command/242eb44c33a3184a6c97aa297b2f5bd373471966000066400000000000000000000000131421143571500260670ustar00rootroot00000000000000 -libtpms-0.9.3/tests/corpus-execute-command/24597eddfc540f431e2bb20ec7088f86f74c4b8e000066400000000000000000000007061421143571500264150ustar00rootroot00000000000000g@,`i y%K+=7:~"9Z6> \z kO AeK ]ҔcJ ";{kG v~E# A3PZȵWAϫad2ɚſ`sd>S;6Wb(-qvǔSã""("{v3jؐMl'#rƙ$86 nyƁ)&8.t3K1@%TYb]ijfQjl7ʷp=V]$ *A&ʯvvp/1O#I hW%7F޴^d2#+;ݭ|z *@@?FW݉;dLW[ |•מ) `=-ejTEX6V @libtpms-0.9.3/tests/corpus-execute-command/2491c3b250e4fbc5ecccd95f325ba34c6a6bd7e3000066400000000000000000000000321421143571500265750ustar00rootroot00000000000000  libtpms-0.9.3/tests/corpus-execute-command/249af10c0054c504fb0f541dcab45315312ac03b000066400000000000000000000000261421143571500261530ustar00rootroot00000000000000g%glibtpms-0.9.3/tests/corpus-execute-command/24c0f7fb7592326675c08f96c012fefb7e47b7a4000066400000000000000000000000121421143571500262440ustar00rootroot00000000000000 Tlibtpms-0.9.3/tests/corpus-execute-command/24caaac9b752b4d933f797ea3e3bf95fda2e0b25000066400000000000000000000000351421143571500266110ustar00rootroot000000000000008@ @ @ libtpms-0.9.3/tests/corpus-execute-command/250355428243a1513ff81a25a1ba7e6f6f226e51000066400000000000000000000001111421143571500257650ustar00rootroot00000000000000I1@ @ C㓅? `Clibtpms-0.9.3/tests/corpus-execute-command/2570b50abcb9c888512a7cded28bd75f61a3c265000066400000000000000000000000261421143571500263670ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/25e067eba9a9cc3b8bb4e8e27967769d9f77a30b000066400000000000000000000000401421143571500264220ustar00rootroot00000000000000 M@ @libtpms-0.9.3/tests/corpus-execute-command/2618c7302fc70c7f3d629c07866270e038f7cb25000066400000000000000000000000261421143571500260210ustar00rootroot00000000000000RW)libtpms-0.9.3/tests/corpus-execute-command/262fc44e6ef32aa94d2fb1bb1cf84b897a52c249000066400000000000000000000000241421143571500264510ustar00rootroot00000000000000~ libtpms-0.9.3/tests/corpus-execute-command/266a7e27d08b8f1fc6e6551276c966d744919911000066400000000000000000000000671421143571500257740ustar00rootroot000000000000007R@@ @  @e!2 ^q??? ylibtpms-0.9.3/tests/corpus-execute-command/275d90931219944097cb9055c43a3dab96e2cfa7000066400000000000000000000000731421143571500261040ustar00rootroot00000000000000;1@ @ %  Clibtpms-0.9.3/tests/corpus-execute-command/27b20fe4dca29db70663b8d694d91bada08e3e48000066400000000000000000000000261421143571500264540ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/27f27076350ca4b7a7b6294154a3c3061c6f310e000066400000000000000000000000261421143571500257710ustar00rootroot00000000000000z(libtpms-0.9.3/tests/corpus-execute-command/2809e4e29c8a2efca875ba41943aaa992f2ee340000066400000000000000000000000261421143571500263760ustar00rootroot00000000000000g~#libtpms-0.9.3/tests/corpus-execute-command/280df6dbbccd829d7f073143184427499e3075c2000066400000000000000000000003761421143571500261140ustar00rootroot00000000000000a @0$=)?ws 0wX7t(IyGiɪeܻ#Y,ƖTA/ue7t(IsG(B+libtpms-0.9.3/tests/corpus-execute-command/28de493942528a9863750a89f5a9e6abcde26f43000066400000000000000000000000561421143571500262120ustar00rootroot00000000000000.g#@ libtpms-0.9.3/tests/corpus-execute-command/28e32a1a7b6a2048c29a8c922d4604d6377fb4b5000066400000000000000000000000261421143571500261450ustar00rootroot00000000000000 libtpms-0.9.3/tests/corpus-execute-command/28ec3ce50cb399a4d55f664238e329b1c4d233fc000066400000000000000000000000521421143571500263140ustar00rootroot00000000000000*g#@libtpms-0.9.3/tests/corpus-execute-command/28fe0a63dd03b9ab668a0d7ce51b80ddacb4ce21000066400000000000000000000007061421143571500266530ustar00rootroot00000000000000g@,`i y%K+=7:~"9Z6> \z kO AeK ]ҔcJ ";{kG v~E# A3PZȵWAϫad2ɚſ`sd>S;6Wb(-q?vǔSã""("{v3jؐMl'#rƙ$86 nyƁ)&8.t3K1@%TYb]ijfQjl7ʷp=V]$ *A&ʯvvp/1O#I hW%7F޴^d2#+;ݭ|z *@@?FW݉;dLW[ |•מ) `=-ejTEX6V @libtpms-0.9.3/tests/corpus-execute-command/2921392205f2f268d36c4bb63e571fd7a8f33fa9000066400000000000000000000001051421143571500261610ustar00rootroot00000000000000E1@ @ Xme[ `libtpms-0.9.3/tests/corpus-execute-command/29ad3bf5120efa537807ea8b16dd30534c132110000066400000000000000000000000441421143571500261170ustar00rootroot00000000000000$g %3gg @@ B:Blibtpms-0.9.3/tests/corpus-execute-command/29d18b40f5bdd07d38d475ebf70fc93e0051fe38000066400000000000000000000000431421143571500263770ustar00rootroot00000000000000#M@@H@@@@@@@@@@@)libtpms-0.9.3/tests/corpus-execute-command/2a1c4e33bf9a665875bdf963fd773c6c90878d06000066400000000000000000000001111421143571500262600ustar00rootroot00000000000000I1@ @ E? `Clibtpms-0.9.3/tests/corpus-execute-command/2a3c85fa4edb0a9eefa1ba2faa717ddec1eb0e2d000066400000000000000000000000401421143571500272140ustar00rootroot00000000000000 !@ @ @libtpms-0.9.3/tests/corpus-execute-command/2aafad69dac1cff1d3b5ca639706111a4851896e000066400000000000000000000000141421143571500264400ustar00rootroot00000000000000 libtpms-0.9.3/tests/corpus-execute-command/2ae6183a5c91f7e599b8e0b269771682b36e4748000066400000000000000000000000411421143571500260440ustar00rootroot00000000000000!l !k4 libtpms-0.9.3/tests/corpus-execute-command/2aeeeaba43b27bfc919c2e5472f3c29c7ba74a9b000066400000000000000000000000261421143571500266660ustar00rootroot00000000000000ߺlibtpms-0.9.3/tests/corpus-execute-command/2af6d9542459ac2d4e86d1eeaf988cf338269a71000066400000000000000000000001051421143571500263410ustar00rootroot00000000000000E1@ @ Xme `libtpms-0.9.3/tests/corpus-execute-command/2b93cfa9e0dca5b754ddbcd25f32403366e2a4df000066400000000000000000000000771421143571500266050ustar00rootroot00000000000000?X@ @ 'XmXe'NmN'8libtpms-0.9.3/tests/corpus-execute-command/2be52e211c61bf49cfa1cd120178a4aea7116141000066400000000000000000000002461421143571500262530ustar00rootroot00000000000000R@@ @ 7:~ hqEe7.r%fɠXN ij"octP<3$'qT:@libtpms-0.9.3/tests/corpus-execute-command/2c033805322c60215090cf217b8c80b95e72996a000066400000000000000000000000131421143571500256350ustar00rootroot00000000000000 xlibtpms-0.9.3/tests/corpus-execute-command/2c332ad7d4cbaf6896b367b83eb74252615ddc05000066400000000000000000000000121421143571500263040ustar00rootroot00000000000000 Clibtpms-0.9.3/tests/corpus-execute-command/2c829cd903cc9b36b498a6ec3ae77ea063ce1d8a000066400000000000000000000002461421143571500265440ustar00rootroot00000000000000g<#@#`i y%K=7:~ hqEe7r%fɠX#) $'qh :@libtpms-0.9.3/tests/corpus-execute-command/2ca8ebbb702c145979b7d8a364236dee568ae5ba000066400000000000000000000000371421143571500264600ustar00rootroot00000000000000.@ @ libtpms-0.9.3/tests/corpus-execute-command/2d117ad27a92853208a97e5cc61f07bba9fe7885000066400000000000000000000000141421143571500262430ustar00rootroot00000000000000 libtpms-0.9.3/tests/corpus-execute-command/2d20192b5495816a09845f63182e427228add9af000066400000000000000000000000411421143571500257360ustar00rootroot00000000000000!v@@@:qlibtpms-0.9.3/tests/corpus-execute-command/2d9fa0133a77a6ed03a3a24106d22224937a388e000066400000000000000000000000261421143571500260460ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/2ecba8767660001b47a679a3e9df202d939462d2000066400000000000000000000000401421143571500260720ustar00rootroot00000000000000 !@ @ @libtpms-0.9.3/tests/corpus-execute-command/2ed11bf30a3896c233108e0d4223f12f349662ff000066400000000000000000000000731421143571500260570ustar00rootroot00000000000000;1@ @ % Clibtpms-0.9.3/tests/corpus-execute-command/2f479b6d02e51b9120a13c7fccdb1df769d0691c000066400000000000000000000007061421143571500263720ustar00rootroot00000000000000g@,`i y%K+=7:~"9Z6> \z kO AeK ]ҔcJ ";{kG v~E# A3PZȵWAϫad2ɚſ`sd>S;6Wb(-qvǔSã""("{v3jؐMl'#rƙ$86 nyƁ)&8.t3K1@%TYb]ijfQjl7ʷp=V]$ *A&ʯvvp/1O#I hW%7F޴^d2#+;ݭ|z *@@?FW݉;dLW[ |•מ) `=-ejTEX6V @libtpms-0.9.3/tests/corpus-execute-command/2f4e4697981ca3616db8fd9e8a88360a1eb654af000066400000000000000000000000141421143571500263360ustar00rootroot00000000000000 >'libtpms-0.9.3/tests/corpus-execute-command/2f6a9d6d50699ecb737e24b352d703ec04447c23000066400000000000000000000000161421143571500261560ustar00rootroot00000000000000libtpms-0.9.3/tests/corpus-execute-command/2fb15268ea831d40f684b43475dcad01e0cac5dd000066400000000000000000000000161421143571500264310ustar00rootroot000000000000006@ libtpms-0.9.3/tests/corpus-execute-command/2fd0a682c7c121c95674fb88bc5e8d7c693036cd000066400000000000000000000000261421143571500263300ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/2fe073c6d25793c7d63add2d54cfe6a0407f2dbe000066400000000000000000000000551421143571500265330ustar00rootroot00000000000000-*@ @ libtpms-0.9.3/tests/corpus-execute-command/2ff104ba4f68831c13b24b11d1f4747fa41525c0000066400000000000000000000000261421143571500261220ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/2ff7bf5a62c63511377b07c4a46b42f54797d2e1000066400000000000000000000000441421143571500261550ustar00rootroot00000000000000$g # #gg libtpms-0.9.3/tests/corpus-execute-command/3048f6a37813e073c32164df1e54a4f6adc0367c000066400000000000000000000007061421143571500261470ustar00rootroot00000000000000g@`i y%K+=:~"9cJ ";{kG v|}# A1PZȵW'A:ϫad2ɐſ`sdW'A:ϫad4ɐſ`ds>S;6Wb(-q@""("{v0jؐMl'#rƙ$86 n#rcƙ$86 nyƁ)5&ҋ̮1@%TYb]ijfQjl3ʷp=ZFjCAeK ]ҔcJ ";{kG v~E# A3PZȵWAϫad4ɚſ`݉;dLW[ |•מ) `=-ejTEX6V @libtpms-0.9.3/tests/corpus-execute-command/30ba63527b572dc27d20c4cce5b79b98f1f00bf6000066400000000000000000000000341421143571500263620ustar00rootroot00000000000000v@@@v Alibtpms-0.9.3/tests/corpus-execute-command/30d71a3d0039d7b947b94709c38fe94bd0384d86000066400000000000000000000000631421143571500261120ustar00rootroot000000000000003g3933g3@libtpms-0.9.3/tests/corpus-execute-command/3110b7ca4651483b193a6fdbed5a3ac50637ee43000066400000000000000000000001111421143571500262630ustar00rootroot00000000000000I1@ @ [E, `Clibtpms-0.9.3/tests/corpus-execute-command/314c4241080a0399bbdf036a41250977b9498379000066400000000000000000000000261421143571500255730ustar00rootroot00000000000000B libtpms-0.9.3/tests/corpus-execute-command/31698b8a6080821e21d8e3a2d5e8b73851a47890000066400000000000000000000000401421143571500257400ustar00rootroot00000000000000 .@ @ libtpms-0.9.3/tests/corpus-execute-command/319a7a97896846450a1a4248e0f0ae76b0fc7901000066400000000000000000000007061421143571500260250ustar00rootroot00000000000000g@`i y%K+=:~ L0cJ ";{kG }|v# A1PZȵW'A:ϫad2ɐſ`sdW'A6ϫad4ɐſ`ds>S;3Wb(-q ""("{v0jؐMl'#rƙ$66 n?rcƙ$86 nyƁ))&ҋ̮1@Ӓ%TYb]ijfQjl3ʷv=ZFjCGAeK ]ҔcJ ";{kG v~E# A3PZȵWAɵϫad4ɚſ`݉;dLW[ =:~"9cJjTEX6V @ libtpms-0.9.3/tests/corpus-execute-command/3218158d8da0496af12ef244a31a4c9425fcef07000066400000000000000000000000671421143571500262310ustar00rootroot000000000000007R@@ @  @e!2 ^q??? ylibtpms-0.9.3/tests/corpus-execute-command/32276ea99db2cd3ff816011f1ce4d8b452b79031000066400000000000000000000000161421143571500262250ustar00rootroot00000000000000libtpms-0.9.3/tests/corpus-execute-command/3260b6f7199eb5c57dc2c83db6a53101238629b7000066400000000000000000000001111421143571500260670ustar00rootroot00000000000000I1@ @ \cE, `Clibtpms-0.9.3/tests/corpus-execute-command/32b1ceb783530b44cd443244703620432ffb45e9000066400000000000000000000000621421143571500257730ustar00rootroot000000000000002*@ @ libtpms-0.9.3/tests/corpus-execute-command/32bf6055e6aea231a398d01cf3d810f8a6fce399000066400000000000000000000002461421143571500263750ustar00rootroot00000000000000v@@v@@v@@:m;A<Ը{:m;A<Ը{v@@:m;A<Ը{:m;A<Ը{ libtpms-0.9.3/tests/corpus-execute-command/333e317ffa18ddf706ad9256ad23ba86b81621b7000066400000000000000000000000731421143571500263100ustar00rootroot00000000000000;1@ @ % Clibtpms-0.9.3/tests/corpus-execute-command/336b72c52dae38d52ac67c3b98161f20c0f588a8000066400000000000000000000000341421143571500262320ustar00rootroot000000000000000@ @ libtpms-0.9.3/tests/corpus-execute-command/33aa45db3ec49cea8f74ba59d301bd2992cf82af000066400000000000000000000000261421143571500266110ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/33ab19699776080082ce5ca839b48337c1bdb522000066400000000000000000000001051421143571500260150ustar00rootroot00000000000000E1@ @ Xbe `libtpms-0.9.3/tests/corpus-execute-command/33bd2b7a88fc61a31eef32d29bfaab1e940d3125000066400000000000000000000000261421143571500265100ustar00rootroot00000000000000z@libtpms-0.9.3/tests/corpus-execute-command/3434a16448d844195af345085f3260e5cd22da62000066400000000000000000000001051421143571500257230ustar00rootroot00000000000000E1@ @ Xme `libtpms-0.9.3/tests/corpus-execute-command/3435a0c1613a1759cf9ebf1db885cc3abde3370d000066400000000000000000000001051421143571500264350ustar00rootroot00000000000000E1@ @ Xm `libtpms-0.9.3/tests/corpus-execute-command/343a95177a894c143bb74c25d660a631298e1898000066400000000000000000000001051421143571500256660ustar00rootroot00000000000000E1@ @ Xme `libtpms-0.9.3/tests/corpus-execute-command/344e87bea4a67f17b75e605816b40ba24e58a460000066400000000000000000000000371421143571500261530ustar00rootroot00000000000000}@ @ @) @)libtpms-0.9.3/tests/corpus-execute-command/3484c980b10580bc8ff81245605e61f9bd671f31000066400000000000000000000001111421143571500260140ustar00rootroot00000000000000I1@ @ CE? `Clibtpms-0.9.3/tests/corpus-execute-command/34ad54e08bd0154146227546b68efe70a6784270000066400000000000000000000001051421143571500257300ustar00rootroot00000000000000E1@ @ Xmed `libtpms-0.9.3/tests/corpus-execute-command/35737451818b4141050931f6aa0e62f0cd968a72000066400000000000000000000002461421143571500256500ustar00rootroot00000000000000g<#@,`i y%K+=7:~ e7.r%fɠX# )pcF$QԆW:t59'rN ij"octP<3$'qT:@libtpms-0.9.3/tests/corpus-execute-command/35ccb1f9272560435f2fe1a03c52eefc31e49b85000066400000000000000000000000201421143571500262770ustar00rootroot00000000000000elibtpms-0.9.3/tests/corpus-execute-command/363f4f3ad5dd1c2a482edd54ef8d89867708d273000066400000000000000000000001051421143571500263370ustar00rootroot00000000000000E1@ @ Xm:e `libtpms-0.9.3/tests/corpus-execute-command/36dfa0d61c99bcaafdc5c06c1e2950cb507f6fbe000066400000000000000000000007061421143571500267470ustar00rootroot00000000000000g@,`i y%K+=7:~"9Z6> \z kO AeK ]ҔcJ ";{kG v~E# A3PZȵWAϫad2ɚſ`sd>S;6Wb(-q@vǔSã""("{v3jؐMl'#rƙ$86 nyƁ)&8.t3K1@%TYb]ijfQjl7ʷp=V]$ *A&ʯvvp/1O#I hW%7F޴^d2#+;ݭ|z *@@?FW݉;dLW[ |•מ) `=-ejTEX6V @libtpms-0.9.3/tests/corpus-execute-command/36ebf409db1845d7202965e71c88e8a1ce0de1de000066400000000000000000000000141421143571500263760ustar00rootroot00000000000000 Vlibtpms-0.9.3/tests/corpus-execute-command/370ffad9f2ee0a1e2e61546d86325e2ec6f699e4000066400000000000000000000001051421143571500264110ustar00rootroot00000000000000E1@ @ X `libtpms-0.9.3/tests/corpus-execute-command/37b93641d3a77161309f86f730f88c08fbb75bc3000066400000000000000000000010371421143571500261140ustar00rootroot00000000000000FmjZ|X# ` J;1jWIu;?CE6- M8d KtCW%V픘e8!oRg|X# ` J;1jWIu;?'E6- M8d KtCW%VCse8!oRg򀓊 ;'"N?u"b.2뙊ϵ7=.A^ J;1jWIu;?CE6- M8d KtCW%VCse8!oRg򀓊 ;'"N?u"b.0뙊ϵ7=.A^|mtemmDˡYsVQ_^T|*ϵ8=D@ XmetQ<mjZ?CE6- M8d6libtpms-0.9.3/tests/corpus-execute-command/37e5249cc379c2d7546599f00e6cfc58abd5a131000066400000000000000000000000471421143571500262520ustar00rootroot00000000000000'`H!libtpms-0.9.3/tests/corpus-execute-command/37efdff022af1ac5e6430ecc5092c710c539aa8e000066400000000000000000000007061421143571500265230ustar00rootroot00000000000000}@`i y%K+=:~"9cJ ";{kG v|}# A1PZȵW'A:ϫad2ɐſ`sdW'A:ϫad4ɐſ`ds>S;6Wb(-q@""("{v0jؐMl'#rƙ$86 n#rcƙ$86 nyƁ)5&ҋ̮1@%TYb]ijfQjl3ʷp=ZFjCAeK ]ҔcJ ";{kG v~E# A3PZȵWAϫad4ɚſ`݉;dLW[ |•מ) `=-ejTEX6V @libtpms-0.9.3/tests/corpus-execute-command/38380ad244dde431603022271e4e1033636aac02000066400000000000000000000001441421143571500256660ustar00rootroot00000000000000dg,%@,`i y K+=7:~&%CL:-n. Ran@libtpms-0.9.3/tests/corpus-execute-command/385bfb1ece295b2206c48ed081e8a4b3b28e5ea8000066400000000000000000000007061421143571500264560ustar00rootroot00000000000000g@,`i y%K+=7:~@@W[ |•מ) `=-eϫad<ɚſ`sd>S;6Wb(-qW[ |•מ) `=-ejTE6V @libtpms-0.9.3/tests/corpus-execute-command/38c7e6fa0b45ae83334dc60c2f4b9075131f6b0b000066400000000000000000000000341421143571500262750ustar00rootroot00000000000000X@ @ libtpms-0.9.3/tests/corpus-execute-command/38d3924de72074552e4631c01eb5e91a8f6b6eb5000066400000000000000000000000421421143571500261540ustar00rootroot00000000000000"}qZ2JI @libtpms-0.9.3/tests/corpus-execute-command/38dc1840277bda85759a0cd2fd4ea1dd01acc8be000066400000000000000000000000261421143571500265770ustar00rootroot00000000000000z*;;libtpms-0.9.3/tests/corpus-execute-command/38e2c0ad9d58cc5f1f4659b2b905f28c067aba8f000066400000000000000000000000261421143571500264630ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/3915e72594cf89fb32172fee25a14c83ce2b3833000066400000000000000000000001271421143571500261660ustar00rootroot00000000000000W @  ibj#7(\3 묗%p`6NDOǡ !Xlibtpms-0.9.3/tests/corpus-execute-command/3956a4758e63ea268bc910dc28204ed7c080a814000066400000000000000000000000261421143571500260740ustar00rootroot00000000000000z&(libtpms-0.9.3/tests/corpus-execute-command/395ded4725fc973831db14550aa6c1de34da701b000066400000000000000000000001111421143571500262740ustar00rootroot00000000000000I@@ @  A@@  I@@ libtpms-0.9.3/tests/corpus-execute-command/39e13a659b34bc7cb2de9323e9247d8b84c5e676000066400000000000000000000001051421143571500262540ustar00rootroot00000000000000E1@ @ Xme libtpms-0.9.3/tests/corpus-execute-command/39e2d7a8a24aa9f490ac263e18df29a4ca04b052000066400000000000000000000001311421143571500263520ustar00rootroot00000000000000Y1@ @ Xme`Cv ˆJI}libtpms-0.9.3/tests/corpus-execute-command/3a8e0c5b3e284c95df76ee516d7c51270104b695000066400000000000000000000001521421143571500261600ustar00rootroot00000000000000jgX# )pcF$QԆW:t59'rN ij"octP<3$'qT:@libtpms-0.9.3/tests/corpus-execute-command/3ac6e710d8bad16fefeac6255293ef4058118caf000066400000000000000000000000261421143571500265270ustar00rootroot00000000000000z libtpms-0.9.3/tests/corpus-execute-command/3ac8503c6bdef1389592cf40aca80db4e23082fb000066400000000000000000000000261421143571500264370ustar00rootroot00000000000000} libtpms-0.9.3/tests/corpus-execute-command/3b0eb1c5870ef581ac4ffd47c6e35ef28fe496c8000066400000000000000000000000141421143571500265520ustar00rootroot00000000000000 elibtpms-0.9.3/tests/corpus-execute-command/3b1ea8f218822ef1d9a4fdd0cfb96e3413df13b7000066400000000000000000000000261421143571500265270ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/3b27c5aedefa3c82e5153828df87145b4a1e5256000066400000000000000000000000631421143571500263150ustar00rootroot000000000000003*@ @ 33* @libtpms-0.9.3/tests/corpus-execute-command/3b60c7948451ac0d46545d354815a717c971cf29000066400000000000000000000000261421143571500257430ustar00rootroot00000000000000zzlibtpms-0.9.3/tests/corpus-execute-command/3b780c4d37ccb4dff2f506d371ed911ab2579043000066400000000000000000000000351421143571500263050ustar00rootroot000000000000002@ @ libtpms-0.9.3/tests/corpus-execute-command/3b974ba20ae765f5210e5fdb03de36e3e4e825c1000066400000000000000000000000261421143571500263610ustar00rootroot00000000000000z<libtpms-0.9.3/tests/corpus-execute-command/3d17ed586cc4e80d82391d767ebaefce1584632c000066400000000000000000000000261421143571500264110ustar00rootroot00000000000000z3libtpms-0.9.3/tests/corpus-execute-command/3d9776c708b25a36d1e00a0c181ec2b86d2aacc1000066400000000000000000000000671421143571500263500ustar00rootroot000000000000007 @ e @N;libtpms-0.9.3/tests/corpus-execute-command/3e7be3305d134d9f6ffafd88414d0013204069ab000066400000000000000000000000351421143571500262170ustar00rootroot000000000000000@ @ libtpms-0.9.3/tests/corpus-execute-command/3ea1c45cfa2b60a55f615635eff056e1b7576c40000066400000000000000000000001311421143571500262770ustar00rootroot00000000000000Y= @ < < @ )( <@ @%!me libtpms-0.9.3/tests/corpus-execute-command/3f0446bd3b48e31f4bfed2635d6f8d787fbb40e0000066400000000000000000000000241421143571500264560ustar00rootroot00000000000000~  libtpms-0.9.3/tests/corpus-execute-command/3f32842ee741b0dd7a8e3ce84ffef79e161fb2f5000066400000000000000000000000261421143571500265520ustar00rootroot00000000000000z libtpms-0.9.3/tests/corpus-execute-command/3f99ee114c85eba9781636c443ccebd2d2a6ee1a000066400000000000000000000000261421143571500265360ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/3fc7744a2821b4bf4fa4d775d8a534d49863beb0000066400000000000000000000000141421143571500263160ustar00rootroot00000000000000 \libtpms-0.9.3/tests/corpus-execute-command/4051591a5ee0f6dd1f0cd32fd7ce665119612000000066400000000000000000000000671421143571500261340ustar00rootroot0000000000000071@ @ !k8 !k4 libtpms-0.9.3/tests/corpus-execute-command/407a2ac4d9a476f5c1ae6b304052722fd5b278dd000066400000000000000000000002461421143571500263020ustar00rootroot00000000000000g<#@,`i y%K=7:~ hqEe7.r%ɠX# t59'rN  $'qT :@libtpms-0.9.3/tests/corpus-execute-command/40f0b96fcc8981d2d50fc8109e4af94aef8487e6000066400000000000000000000001521421143571500264230ustar00rootroot00000000000000jgX#  )pcF$QԆW:t$2'rN i"oct̤P<5$F'qT:@libtpms-0.9.3/tests/corpus-execute-command/40f3b107e263f15d4b3b28c0b3078b2fc704f3ee000066400000000000000000000000151421143571500262650ustar00rootroot00000000000000 'libtpms-0.9.3/tests/corpus-execute-command/410c9383907f0046445c345dcf55760983197e1f000066400000000000000000000000321421143571500256060ustar00rootroot00000000000000~ libtpms-0.9.3/tests/corpus-execute-command/4119d335ecc2d406865937525a87f9f1fe05eb5a000066400000000000000000000000241421143571500261650ustar00rootroot00000000000000]libtpms-0.9.3/tests/corpus-execute-command/415cd8fb8874cb828e6fe060b93211d67b02ede3000066400000000000000000000002461421143571500263240ustar00rootroot00000000000000g<#@,`i y%K+=7:~ X# )pcF$QԆW:t59'rN ij"octP<3$'qT:@libtpms-0.9.3/tests/corpus-execute-command/4161cf1f90fab2a5ad3ef4436acdb72da508b19b000066400000000000000000000000141421143571500265630ustar00rootroot00000000000000 pdlibtpms-0.9.3/tests/corpus-execute-command/42425b67e94330db14c38f71bfbeb4666ee0162c000066400000000000000000000001271421143571500262270ustar00rootroot00000000000000W @  ibj#7(\3 묗%p`6NDOǡ !Xlibtpms-0.9.3/tests/corpus-execute-command/42a5b77a6be55a21711aae3bfb06c2af20191a24000066400000000000000000000000351421143571500263240ustar00rootroot00000000000000*@ @  libtpms-0.9.3/tests/corpus-execute-command/42fa40b344a2a0af429596a3ee0f398d8ee4dbd6000066400000000000000000000000261421143571500264470ustar00rootroot00000000000000U @;libtpms-0.9.3/tests/corpus-execute-command/4301c2b9b81d18771b07c17925bffe826de64277000066400000000000000000000000351421143571500261020ustar00rootroot00000000000000 @nnnnnn libtpms-0.9.3/tests/corpus-execute-command/4333d96b866cc07a05c51e8050b788a5fd0aaf0d000066400000000000000000000000261421143571500263020ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/434c3a5ee6648945e62b3b1f1104d0b5d6ed97ca000066400000000000000000000000351421143571500263070ustar00rootroot00000000000000)@ @ =libtpms-0.9.3/tests/corpus-execute-command/43af13bb683f7fded0b6753b1d84da96770c9925000066400000000000000000000000141421143571500263250ustar00rootroot00000000000000 vlibtpms-0.9.3/tests/corpus-execute-command/43b933b72a1958da154f954e8e600b9752611176000066400000000000000000000000631421143571500256630ustar00rootroot000000000000003.@ @  4libtpms-0.9.3/tests/corpus-execute-command/445194417722018c5fc4797362712cca14788334000066400000000000000000000000561421143571500254450ustar00rootroot00000000000000.g#@libtpms-0.9.3/tests/corpus-execute-command/447d03383e9f913fcc7e3634640d4a71e5cfe019000066400000000000000000000000261421143571500261630ustar00rootroot00000000000000K*J'libtpms-0.9.3/tests/corpus-execute-command/4499019026bb25d8de9bbaf7d55370d763acb9ed000066400000000000000000000000261421143571500264040ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/45311153c7ee8017b2daa3b1bcd848d8ec505776000066400000000000000000000000261421143571500262230ustar00rootroot00000000000000z>libtpms-0.9.3/tests/corpus-execute-command/45322f0cee9e3c4d89b8d0cec5eb9273ad412bc3000066400000000000000000000002461421143571500265330ustar00rootroot00000000000000g<#@,`i y%K+=7:~ X# )pcF$QԆW:t59'rN ij"octP<3$'qT:@libtpms-0.9.3/tests/corpus-execute-command/453911ced2c34ba70d10374301da69ce7dc49579000066400000000000000000000000121421143571500261400ustar00rootroot00000000000000 (libtpms-0.9.3/tests/corpus-execute-command/455b8a2390bbe28bb5c66957829fc88873f1e746000066400000000000000000000000161421143571500261320ustar00rootroot00000000000000~libtpms-0.9.3/tests/corpus-execute-command/4566e45fa27de944c7274fe68e9af8ff00abacc4000066400000000000000000000001441421143571500265560ustar00rootroot00000000000000dg,%@,`i y K+=7:~&%CL:-n. Ran@libtpms-0.9.3/tests/corpus-execute-command/4568fcebf36d77975eb5f961dcab6d9de88f6d9e000066400000000000000000000000631421143571500266750ustar00rootroot000000000000003@@ @ G libtpms-0.9.3/tests/corpus-execute-command/457772775d5b0496a9b6ec281386b2459dfa9694000066400000000000000000000001051421143571500257730ustar00rootroot00000000000000E1@ @  `libtpms-0.9.3/tests/corpus-execute-command/457f4373d9caa2dace1b183aed2088584512e16b000066400000000000000000000000161421143571500263020ustar00rootroot00000000000000elibtpms-0.9.3/tests/corpus-execute-command/45c21e5610fa98cf6b4551b3911953cd75b82e2e000066400000000000000000000000321421143571500261520ustar00rootroot00000000000000~ libtpms-0.9.3/tests/corpus-execute-command/45f95ad6ef305f7fd3d10ba803064aa58e2565e8000066400000000000000000000000121421143571500263110ustar00rootroot00000000000000 +libtpms-0.9.3/tests/corpus-execute-command/4627c3ef9dc68f2bb0a203b0bdda56dd3af87d98000066400000000000000000000000261421143571500266130ustar00rootroot00000000000000g!zlibtpms-0.9.3/tests/corpus-execute-command/4675c8414b9badd5b5e0416324ccf416d1e929f9000066400000000000000000000000671421143571500262470ustar00rootroot000000000000007v@@ @ @e2 ^q??? ylibtpms-0.9.3/tests/corpus-execute-command/46be562248b4acc16ac7891c6c536f6820db6cbe000066400000000000000000000000731421143571500263760ustar00rootroot00000000000000;,@ @  (@@ ()!mlibtpms-0.9.3/tests/corpus-execute-command/473f1aadcee949f6b8caef770e900c1681b8b465000066400000000000000000000001521421143571500264660ustar00rootroot00000000000000jgX#   )>FpcQ$ԆW:t$1'rN i"oct̤P<5$F'qT:@libtpms-0.9.3/tests/corpus-execute-command/47454f7eaa21b3c84e73a5d347b75e0bada32665000066400000000000000000000001111421143571500262770ustar00rootroot00000000000000I@@ @  A@4@@@  libtpms-0.9.3/tests/corpus-execute-command/476e9247c6aef8922f7a12380ba2262f95f3ba33000066400000000000000000000002461421143571500261640ustar00rootroot00000000000000g<#@,`i y%K+=7:~ rFe7X#X# )pcF$QԆW:t59'rN ij"octP<3$'qT:@libtpms-0.9.3/tests/corpus-execute-command/4786ba05817862d5b9df5f7940ca619a9a5a8518000066400000000000000000000002461421143571500261260ustar00rootroot00000000000000g<#@,`i y%K+=7:~ X# )pcF$QԆW:t59'rN ij"octP<3$'qT:@libtpms-0.9.3/tests/corpus-execute-command/4788711a949cd681d3374eb3d596511ee01e106e000066400000000000000000000000571421143571500260300ustar00rootroot00000000000000/v@@ :m;A=>Ը:{libtpms-0.9.3/tests/corpus-execute-command/47c665b7be710a452f78b68189f6834447184d79000066400000000000000000000000261421143571500257160ustar00rootroot00000000000000R*J'libtpms-0.9.3/tests/corpus-execute-command/47e1ff1c7b9c72c5956e935c5bf36ffcb6e77cd1000066400000000000000000000001051421143571500265630ustar00rootroot00000000000000E1@ @ Xm@e `libtpms-0.9.3/tests/corpus-execute-command/47f707565eded434ff2d280a58d5000154963b4c000066400000000000000000000000331421143571500260730ustar00rootroot00000000000000&@ @ libtpms-0.9.3/tests/corpus-execute-command/4815be6a98707ee2786c415fe7c26c8b54528553000066400000000000000000000001111421143571500260400ustar00rootroot00000000000000I1@ @ bE? `Clibtpms-0.9.3/tests/corpus-execute-command/4894278ee98aedd3eea9618c347803ea5ba4a4e2000066400000000000000000000001111421143571500264070ustar00rootroot00000000000000I1@ @ C㓀? `Clibtpms-0.9.3/tests/corpus-execute-command/48a2707de1fd1a9104078d927f985e35964631a7000066400000000000000000000001051421143571500257530ustar00rootroot00000000000000E1@ @ Xm"e `libtpms-0.9.3/tests/corpus-execute-command/48aa04f7c312ac6fe81e85661d0be781df54f47c000066400000000000000000000000551421143571500264020ustar00rootroot00000000000000-*@ @ @libtpms-0.9.3/tests/corpus-execute-command/48c9ff3f0c7ab69f5518a9f81af436ae3538143f000066400000000000000000000003761421143571500263470ustar00rootroot00000000000000a @0$=)?ws 0wX7t(IyGiɪeܻ#Y,ƖTA/ue7t(IsG(B+libtpms-0.9.3/tests/corpus-execute-command/49256dfb8ad612356bde0cf68611d521c9c9d6c0000066400000000000000000000000671421143571500263230ustar00rootroot000000000000007R@@ @  @e!2 ^q??? ylibtpms-0.9.3/tests/corpus-execute-command/493170748ed96cc77695f6133bb5ae9c363305fe000066400000000000000000000001051421143571500261170ustar00rootroot00000000000000E1@ @ Xme `libtpms-0.9.3/tests/corpus-execute-command/494afbc627f79fa6772baebfcd1cc9921d8727f8000066400000000000000000000000261421143571500265650ustar00rootroot00000000000000z zlibtpms-0.9.3/tests/corpus-execute-command/49a7dad304c73240432b4eceb0668ba02282bce4000066400000000000000000000000321421143571500262570ustar00rootroot00000000000000~ libtpms-0.9.3/tests/corpus-execute-command/49b94557054d91b9921d4e34cc4ab58b95287461000066400000000000000000000000161421143571500257550ustar00rootroot00000000000000libtpms-0.9.3/tests/corpus-execute-command/49c5971526067ac7bcf3284a26b0dafa58073050000066400000000000000000000000261421143571500260630ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/49d2d0e63a7235c8be134a91aefb9604f850d18c000066400000000000000000000000571421143571500263150ustar00rootroot00000000000000/v@@ :m;A=>Ը:{libtpms-0.9.3/tests/corpus-execute-command/49fa32f6084c07b0311d41b498be51abc6e5273f000066400000000000000000000001111421143571500262130ustar00rootroot00000000000000I1@ @ #E? `Clibtpms-0.9.3/tests/corpus-execute-command/4a26e2e0e22bb6fbfe23b9a3791e87884aa12c84000066400000000000000000000002461421143571500263750ustar00rootroot00000000000000g<#@,`i y%K+=7:~ 7X#X# )pcF$QԆW:t59'rN ij"octP<3$'qT:@libtpms-0.9.3/tests/corpus-execute-command/4aa360ea0539de2604ae52d6274bc1706a863b82000066400000000000000000000000261421143571500261310ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/4adf2cdb08df7f10a5bc4634571e81095d7ecd0c000066400000000000000000000000401421143571500265160ustar00rootroot00000000000000 )@ @ libtpms-0.9.3/tests/corpus-execute-command/4b809b038ff209bdcc0a873a9055b87d3a61b6d5000066400000000000000000000000141421143571500263050ustar00rootroot00000000000000 xlibtpms-0.9.3/tests/corpus-execute-command/4d05fe8b30afe2a7d412de87f26623007e4d52be000066400000000000000000000000631421143571500263630ustar00rootroot000000000000003*@ @  blibtpms-0.9.3/tests/corpus-execute-command/4d2b23e99d0b080d706c6e5fade0f083c1680b36000066400000000000000000000000141421143571500262760ustar00rootroot00000000000000 libtpms-0.9.3/tests/corpus-execute-command/4d8035b63ff74dc3b6e3268e06a808c733b39c80000066400000000000000000000000631421143571500261630ustar00rootroot000000000000003.@ @ libtpms-0.9.3/tests/corpus-execute-command/4dc629de7cc453ee2ec1160d6ccc0ae288051f4a000066400000000000000000000000671421143571500265240ustar00rootroot000000000000007R@@ @ @e!2 ^q??? ylibtpms-0.9.3/tests/corpus-execute-command/4dcc0143fdc93cdb8ee5b335ebdd87f19c80e57b000066400000000000000000000001051421143571500266770ustar00rootroot00000000000000E1@ @ XmQ `libtpms-0.9.3/tests/corpus-execute-command/4dd46b1038d7e4514c017b8ddbdc9313841c338c000066400000000000000000000000261421143571500262220ustar00rootroot00000000000000szzlibtpms-0.9.3/tests/corpus-execute-command/4df4e79edc40c0dfa4e9a7e20c9a37b9d0e335b5000066400000000000000000000000671421143571500266210ustar00rootroot0000000000000077 ;-e: X-elibtpms-0.9.3/tests/corpus-execute-command/4dfbe91dd8a81e4b9cf4084bf5599d6bf78a5da8000066400000000000000000000001111421143571500266420ustar00rootroot00000000000000I-@ @ @ @  I@@ libtpms-0.9.3/tests/corpus-execute-command/4e0f2cffc294a4c9b1528126e7f5fb71769294ec000066400000000000000000000000351421143571500263330ustar00rootroot00000000000000cKjlibtpms-0.9.3/tests/corpus-execute-command/4e5c6bb0d1af1376e07435a1af425b92f02c38ea000066400000000000000000000000671421143571500263530ustar00rootroot000000000000007)@ @  :  @libtpms-0.9.3/tests/corpus-execute-command/4e875d85655988b6f200495f86973bb9f9e4f32f000066400000000000000000000000261421143571500260770ustar00rootroot00000000000000%@libtpms-0.9.3/tests/corpus-execute-command/4ea9510c9cbbc4e5d2475af5bde8bb01ef85cf34000066400000000000000000000000151421143571500266660ustar00rootroot00000000000000 *;libtpms-0.9.3/tests/corpus-execute-command/4f13cd64e8c39b64369b30f38aba17a62d98dc0c000066400000000000000000000001111421143571500263670ustar00rootroot00000000000000I1@ @ CE? rClibtpms-0.9.3/tests/corpus-execute-command/4f3fe397964060f88859a24d6e6a2f06edcee7be000066400000000000000000000000401421143571500264240ustar00rootroot00000000000000 !@ @ @ libtpms-0.9.3/tests/corpus-execute-command/4f5de11bf1d2fafb8fc743fa18289c435b1136ea000066400000000000000000000000161421143571500265240ustar00rootroot00000000000000 libtpms-0.9.3/tests/corpus-execute-command/50261f9bb0031f5ed0b30cbfb92d093ad1857749000066400000000000000000000001311421143571500262120ustar00rootroot00000000000000Y1@ @ Xme`Cv ˆJI}libtpms-0.9.3/tests/corpus-execute-command/5081dda6d7ca2e52124d6812bd0b3dbb6b57f1c8000066400000000000000000000000141421143571500264250ustar00rootroot00000000000000 libtpms-0.9.3/tests/corpus-execute-command/510aaf1135dd7846e10542166d89a96ff2107fe0000066400000000000000000000000161421143571500260650ustar00rootroot00000000000000libtpms-0.9.3/tests/corpus-execute-command/5120f67645c7616fed4ab48b323be26421911dca000066400000000000000000000000141421143571500261340ustar00rootroot00000000000000 libtpms-0.9.3/tests/corpus-execute-command/51bafd57af44f84a58a5eae51a6c3377614f2d69000066400000000000000000000000261421143571500264020ustar00rootroot00000000000000z@4libtpms-0.9.3/tests/corpus-execute-command/51fcf3eeb8ea0b998cbc7cc574adae974f04123f000066400000000000000000000002461421143571500267050ustar00rootroot00000000000000g<#@,`i y%K+=7:~ X# )pcF$QԆW:t59'rN ij"octP<3$'qT:@libtpms-0.9.3/tests/corpus-execute-command/5214dc1410f864cbc5316317c5896754e6ef125f000066400000000000000000000001111421143571500260120ustar00rootroot00000000000000I1@ @ \E( bClibtpms-0.9.3/tests/corpus-execute-command/525b75c80d6412656e48fec15e63f9164297f965000066400000000000000000000000371421143571500257730ustar00rootroot00000000000000 @ libtpms-0.9.3/tests/corpus-execute-command/526a040273fc180a23abf672f9c93b5a66267ec2000066400000000000000000000000141421143571500261370ustar00rootroot00000000000000 S!libtpms-0.9.3/tests/corpus-execute-command/52a75b2c865bd6dc1e288090157df974c91a2917000066400000000000000000000000351421143571500261070ustar00rootroot00000000000000!@ @  @ libtpms-0.9.3/tests/corpus-execute-command/52ac5e6bcb640708f7d508bd625841c62c334d55000066400000000000000000000001311421143571500261450ustar00rootroot00000000000000Y< @ @< @ )( <@ @%!me libtpms-0.9.3/tests/corpus-execute-command/530e328256c6684cb9bb223169fa4e8b74288e55000066400000000000000000000001111421143571500260250ustar00rootroot00000000000000I1@ @ UE? `Clibtpms-0.9.3/tests/corpus-execute-command/5312eb9754533476f91903aac8a430694c228e0a000066400000000000000000000000121421143571500257240ustar00rootroot00000000000000 libtpms-0.9.3/tests/corpus-execute-command/53ce8a10fd14e6f4b8adc6e000182b3ebd7f7753000066400000000000000000000000261421143571500264420ustar00rootroot00000000000000z;;libtpms-0.9.3/tests/corpus-execute-command/53eb5b265d74524d3ca7bd01096498a5dadd81af000066400000000000000000000001111421143571500263610ustar00rootroot00000000000000I1@ @ Y `Clibtpms-0.9.3/tests/corpus-execute-command/53f3f1f228532941f46a71103314e5fe2f9afd0b000066400000000000000000000001111421143571500261360ustar00rootroot00000000000000I1@ @ C  `Clibtpms-0.9.3/tests/corpus-execute-command/5403c5233d7a316345ddd5c446c4ff7ae253097b000066400000000000000000000000121421143571500261400ustar00rootroot00000000000000 libtpms-0.9.3/tests/corpus-execute-command/5433c78f5cd3f08e846a168c0cacc144c32c84a4000066400000000000000000000000141421143571500263030ustar00rootroot00000000000000 dlibtpms-0.9.3/tests/corpus-execute-command/545635f8ec026987a2e5592a89bef19eda517b4e000066400000000000000000000000161421143571500262620ustar00rootroot00000000000000"@ libtpms-0.9.3/tests/corpus-execute-command/54f4d3c2d9c8210d4ffddcd6f11f93c1f60cb5e9000066400000000000000000000000161421143571500266150ustar00rootroot00000000000000Qlibtpms-0.9.3/tests/corpus-execute-command/55559472bb892490eb755f0cd4c4c5a9ec3d182b000066400000000000000000000000411421143571500262420ustar00rootroot00000000000000!#f#"""""""""(libtpms-0.9.3/tests/corpus-execute-command/5563fb9f80549952a4764a4bec670f1922d693b1000066400000000000000000000000671421143571500260410ustar00rootroot000000000000007B -e: @ X-elibtpms-0.9.3/tests/corpus-execute-command/5590806d4b4fed25f92b112f0989096ccc4312eb000066400000000000000000000000261421143571500261560ustar00rootroot00000000000000M@ libtpms-0.9.3/tests/corpus-execute-command/55f91ef5defeba4aa006c3178fee723545615956000066400000000000000000000001111421143571500263210ustar00rootroot00000000000000I<@ @ `Clibtpms-0.9.3/tests/corpus-execute-command/56a42414e535212338fbdcb2d69bb37e1281221e000066400000000000000000000000331421143571500260460ustar00rootroot00000000000000'@ @ libtpms-0.9.3/tests/corpus-execute-command/57161736fd76d7d47ed4ce639c4d7bd46eb7a0ad000066400000000000000000000000141421143571500264700ustar00rootroot00000000000000 Ylibtpms-0.9.3/tests/corpus-execute-command/5720fb7a0b34b1f83f35b02d0e18d3112ceecf8f000066400000000000000000000000261421143571500264270ustar00rootroot00000000000000z?libtpms-0.9.3/tests/corpus-execute-command/572862bcbf86159ededb2e960f0bea372942a7bd000066400000000000000000000001051421143571500264600ustar00rootroot00000000000000ER@@ @   libtpms-0.9.3/tests/corpus-execute-command/57688f92b63f377d3d2b9a19524377b1c41a9cb8000066400000000000000000000002461421143571500261230ustar00rootroot00000000000000g<#@,`i y%K+=7:~ X# )pcF$QԆW:t59'rN ij"octP<3$'qT:@libtpms-0.9.3/tests/corpus-execute-command/57c86150e502515a11f81ca6ab28c272f3ff5957000066400000000000000000000000631421143571500260720ustar00rootroot000000000000003a'F=@48.@libtpms-0.9.3/tests/corpus-execute-command/57c94aaf69128b335d60b06f8588b642cde527a8000066400000000000000000000000671421143571500261770ustar00rootroot000000000000007R@@ @  @e!2 ^q??? ylibtpms-0.9.3/tests/corpus-execute-command/580751c24f5b10628d6eb8cddff1216cdac6f184000066400000000000000000000000161421143571500263670ustar00rootroot000000000000000libtpms-0.9.3/tests/corpus-execute-command/58291cfadb242118da02fb2d99a58113d9bb476d000066400000000000000000000000141421143571500263010ustar00rootroot00000000000000 ~libtpms-0.9.3/tests/corpus-execute-command/5896e73078142f2a22c496b63060b46983c0edaa000066400000000000000000000000221421143571500260100ustar00rootroot00000000000000~libtpms-0.9.3/tests/corpus-execute-command/58a7ea12f693bc7f2cfb6ad7811c1e9561fa943b000066400000000000000000000007061421143571500264660ustar00rootroot00000000000000g@`i y%K+=:~"9cJ ";{kG v|}# A1PZȵW'A:ϫad2ɐſ`sdW'A:ϫad4ɐſ`ds>S;6Wb(-q@""("{v0jؐMl'#rƙ$86 n#rcƙ$86 nyƁ)5&ҋ̮1@%TYb]ijfQjl3ʷp=ZFjCAeK ]ҔcJ ";{kG v~E# A3PZȵWAϫad4ɚſ`݉;dLW[ |•מ) `=-ejTEX6V @libtpms-0.9.3/tests/corpus-execute-command/58c393210ba9a94b16c30adb637382382412dda7000066400000000000000000000007061421143571500260610ustar00rootroot00000000000000g@,`i y%K+=7:~"9Z6> \z kO AeK ]ҔcJ ";{kG v~E# A3PZȵWAϫad2ɚſ`sd>S;6Wb(-qvǔSã""("{v3jؐMl'#rƙ$86 nyƁ)&8.t3K1@%TYb]ijfQjl7ʷp=V]$ *A&vvp/1O#I hW%7F޴^d2#);ݭ|z *@%TYb]ijfW[ |•מ) `=-ejTEX6V @libtpms-0.9.3/tests/corpus-execute-command/5914c6db1cf54c84b11df0b35ab88aab287d9e2b000066400000000000000000000002461421143571500265270ustar00rootroot00000000000000}<#@,`i y%K+=7:~ hqEe7.r%fɠX# )pcF$QԆW:t59'rN ij"octP<3$'qT:@libtpms-0.9.3/tests/corpus-execute-command/5927a54cb16d764b2d272e0d5fd7ca8c8b88e3c6000066400000000000000000000001311421143571500264040ustar00rootroot00000000000000Y1@ @ Xme`CˆJI}libtpms-0.9.3/tests/corpus-execute-command/595811216863d39200fd26ad91bdee183370677b000066400000000000000000000000161421143571500257360ustar00rootroot000000000000008@ libtpms-0.9.3/tests/corpus-execute-command/59c65373b0002c7f21393f695526698db2f75af7000066400000000000000000000001121421143571500257520ustar00rootroot00000000000000J\SH ˆ˧Y]YX~]X*eeH ˆ'Y]YYX]Y*libtpms-0.9.3/tests/corpus-execute-command/59ce919611e4319e3e7dbf88ecb8ac45e8f1cbca000066400000000000000000000000261421143571500266340ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/5a5171b81bb22c3b9da0342dd8bb35566087de42000066400000000000000000000000261421143571500262120ustar00rootroot00000000000000g#libtpms-0.9.3/tests/corpus-execute-command/5a51ab5e7df4a44f2372f3f8619889774c018b1f000066400000000000000000000000261421143571500261730ustar00rootroot00000000000000g libtpms-0.9.3/tests/corpus-execute-command/5ab8302cab994acdedd5a1381a20ad5d6b18109c000066400000000000000000000000401421143571500264750ustar00rootroot00000000000000 0@ @ libtpms-0.9.3/tests/corpus-execute-command/5ac0430f71998bed3050d043c88afa9acc642f51000066400000000000000000000000261421143571500263020ustar00rootroot00000000000000z0libtpms-0.9.3/tests/corpus-execute-command/5aecb66b98e67feb121e776a2c90cd835c8ea387000066400000000000000000000000771421143571500265030ustar00rootroot00000000000000?ggNe7@Ne77@g1 libtpms-0.9.3/tests/corpus-execute-command/5b019fd64e7127ca849f167a03f2e416acccf5d1000066400000000000000000000000631421143571500263700ustar00rootroot000000000000003*@ @ GDlibtpms-0.9.3/tests/corpus-execute-command/5b21e17edd991dd364b9ee366e5149690f3436d4000066400000000000000000000000261421143571500261760ustar00rootroot00000000000000Tzlibtpms-0.9.3/tests/corpus-execute-command/5b460d7ae0aa22cfcf931bc8d6b75c97d0f8f013000066400000000000000000000000261421143571500265240ustar00rootroot00000000000000z@'!!libtpms-0.9.3/tests/corpus-execute-command/5b4f827f588c518aec3decf2c2fe04389a1cc11a000066400000000000000000000000341421143571500265310ustar00rootroot00000000000000)D@ * libtpms-0.9.3/tests/corpus-execute-command/5b59f37e3f05d3a64cfa9cb65214b68355e5e7f7000066400000000000000000000001051421143571500263330ustar00rootroot00000000000000E1@ @ Xm `libtpms-0.9.3/tests/corpus-execute-command/5c0f47635a61a2ff441fd675202f73776e89c364000066400000000000000000000000141421143571500260270ustar00rootroot00000000000000 Nlibtpms-0.9.3/tests/corpus-execute-command/5c17a5bbbd61c9d6ddf6edba44524918173b46a5000066400000000000000000000000241421143571500264460ustar00rootroot00000000000000m 0jlibtpms-0.9.3/tests/corpus-execute-command/5c3ef3afc98217b013bace174d815a6604503def000066400000000000000000000000531421143571500263560ustar00rootroot00000000000000+v@ @libtpms-0.9.3/tests/corpus-execute-command/5caf347e082cccb0e3b688f19165afa38f435e95000066400000000000000000000001521421143571500264040ustar00rootroot00000000000000jgX#  )pcF$QԆW:;t$4'rN i-ݐctP<5$F'qT:@libtpms-0.9.3/tests/corpus-execute-command/5d2e81ac88ba9b20a8de80d6f3902be5fc43c6cd000066400000000000000000000000361421143571500266130ustar00rootroot00000000000000VJIulibtpms-0.9.3/tests/corpus-execute-command/5d766f62c8779b46f101ad6aa25a5ac32ad26b68000066400000000000000000000001421421143571500263100ustar00rootroot00000000000000bg,@,`i y%K+=7:~ޭޭޭޭ$ L:-n. Ran@libtpms-0.9.3/tests/corpus-execute-command/5d894c4ae224494d31242bf86531e4c649a90ac8000066400000000000000000000000141421143571500260760ustar00rootroot00000000000000 klibtpms-0.9.3/tests/corpus-execute-command/5d98746565f153ecc48f65a620834a746e308431000066400000000000000000000002461421143571500257010ustar00rootroot00000000000000g<#@,`i y%K+=7:~ X# )pcF$QԆW:t59'rN ij"octP<3$'qT:@libtpms-0.9.3/tests/corpus-execute-command/5e0bd273babca3f80af5a3b7935d6924da39bc45000066400000000000000000000001111421143571500265140ustar00rootroot00000000000000I1@ @ \bE( `Clibtpms-0.9.3/tests/corpus-execute-command/5e4b0cac0830d66fe85178e8bc9ca193cd9c3c7d000066400000000000000000000000521421143571500265420ustar00rootroot00000000000000*g#@libtpms-0.9.3/tests/corpus-execute-command/5e6eb2a268691f7b9aea5af3f0332ad91014f9ef000066400000000000000000000000261421143571500264550ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/5e71a06063ac254e01b452b525c15028f590389b000066400000000000000000000000471421143571500257130ustar00rootroot00000000000000'9@ @  libtpms-0.9.3/tests/corpus-execute-command/5e8d8473786bf7c30d7b79d7bf5085584840b493000066400000000000000000000000351421143571500260600ustar00rootroot00000000000000!@   libtpms-0.9.3/tests/corpus-execute-command/5ee4e54003c26b65ffdd15f9f91898ba4a00fe57000066400000000000000000000000161421143571500264050ustar00rootroot00000000000000G:libtpms-0.9.3/tests/corpus-execute-command/5f25cfe3af965ec58c7f15c56fbcf8c0c71e6856000066400000000000000000000000121421143571500265600ustar00rootroot00000000000000 libtpms-0.9.3/tests/corpus-execute-command/5fa3faadcf6576763cb1fdd0abff92e7d176ab72000066400000000000000000000000411421143571500267520ustar00rootroot00000000000000!gX#libtpms-0.9.3/tests/corpus-execute-command/5fc384693d44ba7ed5af940715b307526ff07c48000066400000000000000000000000261421143571500261700ustar00rootroot00000000000000z=libtpms-0.9.3/tests/corpus-execute-command/6013d490eada8cc1994e6b4c3bcaf5198eb98b7f000066400000000000000000000000631421143571500265460ustar00rootroot000000000000003.@ @ libtpms-0.9.3/tests/corpus-execute-command/606d8835c439251874db6756244b79bb7e2ba978000066400000000000000000000000321421143571500257630ustar00rootroot00000000000000~ libtpms-0.9.3/tests/corpus-execute-command/60c02440e4b6b532898efb95c11ffc22a0fae08d000066400000000000000000000001441421143571500263570ustar00rootroot00000000000000dg,%@,`i y( K+=7:~&% CL:-n. Ran@libtpms-0.9.3/tests/corpus-execute-command/60ca51e367778dad6ed4355a2c0890f7831a7c53000066400000000000000000000000161421143571500261570ustar00rootroot000000000000001Qlibtpms-0.9.3/tests/corpus-execute-command/6173f7c3cf579ee610f8401d567c76004d01beee000066400000000000000000000001111421143571500262320ustar00rootroot00000000000000I1@ @ ? `Clibtpms-0.9.3/tests/corpus-execute-command/61be29f1a4b1ae15dcf067eba10c4efa975a57cf000066400000000000000000000000401421143571500266520ustar00rootroot00000000000000 )@ @ libtpms-0.9.3/tests/corpus-execute-command/61d5fc54dd7c4fec8b93bdabb9e9894c43471d9c000066400000000000000000000000261421143571500266420ustar00rootroot00000000000000z<libtpms-0.9.3/tests/corpus-execute-command/62813ba7fc4b3aad499720fe35b2ac6c9eedd700000066400000000000000000000000141421143571500265210ustar00rootroot00000000000000 `libtpms-0.9.3/tests/corpus-execute-command/63d1d74703fa61bef3e7af664366ee2566db5f9b000066400000000000000000000000371421143571500264130ustar00rootroot00000000000000 @ libtpms-0.9.3/tests/corpus-execute-command/63d6ba79d077aa460fb454c7229539bfacf1b314000066400000000000000000000000551421143571500263110ustar00rootroot00000000000000-*@ @ (libtpms-0.9.3/tests/corpus-execute-command/63e5a2f8fdeeb24c0dced76abc2881c40a2137cc000066400000000000000000000003761421143571500266650ustar00rootroot00000000000000a @0$=)?ws 0wX7t(IyGiɪeܻ#Y,ƖTA/ue7t(IsG(B+libtpms-0.9.3/tests/corpus-execute-command/63e8a5037b74ea77ca1f44adfb0b469e3fc56c26000066400000000000000000000000401421143571500264500ustar00rootroot00000000000000 :@ @ @libtpms-0.9.3/tests/corpus-execute-command/6413f200ae76824682964f436d3dcfa48f46bafe000066400000000000000000000001521421143571500262450ustar00rootroot00000000000000jgX# )>FpcQ$ԆW:t$1'rN i"oct̤P<5$F'qT:@libtpms-0.9.3/tests/corpus-execute-command/645071c1d47785ef4849fe1a62c6d668e8abcb55000066400000000000000000000002461421143571500262640ustar00rootroot00000000000000g<#@,`i y%K+=7:~ X# )pcF$QԆW:t59'rN ij"octP<3$'qT:@libtpms-0.9.3/tests/corpus-execute-command/6453f2612801c1be31457c9588111742d6dc1cd2000066400000000000000000000007061421143571500257250ustar00rootroot00000000000000g@,`i y%K+=7:~Z6> \z kO AeK ҔcJ @;{kG v~E# A3PZȵWAɚſ`sd>S;6Wb(-qZ6> \z kO AeK ҔcJ @;{kG v~E# @W[ |•מ) `=-ejTEX6V @libtpms-0.9.3/tests/corpus-execute-command/648158264e0ae4f6b7389e1ec09d8a0d4c1692f0000066400000000000000000000000141421143571500261610ustar00rootroot00000000000000 Ulibtpms-0.9.3/tests/corpus-execute-command/656a8b634348c132e1aa3c24968781b3b651cd67000066400000000000000000000001011421143571500260060ustar00rootroot00000000000000A1@ @ CE? `Clibtpms-0.9.3/tests/corpus-execute-command/65e167bc7071f387c03eb5d065714430a2413840000066400000000000000000000001111421143571500256310ustar00rootroot00000000000000I1@ @ CE? `Clibtpms-0.9.3/tests/corpus-execute-command/65f691bfe0dcd55611446cb7f0ba3dfb29a24a6d000066400000000000000000000000141421143571500265200ustar00rootroot00000000000000 libtpms-0.9.3/tests/corpus-execute-command/66a4e7249152b89c8f3c6b12926c182cf283fa1b000066400000000000000000000002461421143571500261650ustar00rootroot00000000000000g<#@,`i y%K+=7:~ hqEe7.r%fɠX# )pcF$QԆW:t59'rN ij"octP<3$'qT:@libtpms-0.9.3/tests/corpus-execute-command/66ae225aac1b2b69c8736522b0a31331100b12dd000066400000000000000000000001111421143571500260720ustar00rootroot00000000000000I1@ @ CsE? `Clibtpms-0.9.3/tests/corpus-execute-command/66b427ffc1dcc38deb3b38b3617379ea9bc14941000066400000000000000000000000261421143571500264010ustar00rootroot00000000000000plibtpms-0.9.3/tests/corpus-execute-command/66cee08532b8a0450dc4d00709e2da9dc43f0391000066400000000000000000000000261421143571500262150ustar00rootroot00000000000000BBlibtpms-0.9.3/tests/corpus-execute-command/6768033e216468247bd031a0a2d9876d79818f8f000066400000000000000000000000241421143571500256760ustar00rootroot00000000000000libtpms-0.9.3/tests/corpus-execute-command/67811e5170250613fbd2096b612c813b00da397e000066400000000000000000000000671421143571500257160ustar00rootroot000000000000007*@ @  @ XmNe2 libtpms-0.9.3/tests/corpus-execute-command/67ae701d52d0331b2cb09a222990a2e1cd4a5cd1000066400000000000000000000000261421143571500262470ustar00rootroot00000000000000Olibtpms-0.9.3/tests/corpus-execute-command/67d705bf60c9100ad0db75f9da72220024074af6000066400000000000000000000000371421143571500261310ustar00rootroot00000000000000 @  )libtpms-0.9.3/tests/corpus-execute-command/684258aed17de5774e6e062ed73209c4893ced7a000066400000000000000000000000261421143571500262610ustar00rootroot00000000000000B libtpms-0.9.3/tests/corpus-execute-command/69009cf9776d5dfbf86cf1d6ba36b1a61503b6d0000066400000000000000000000000261421143571500263770ustar00rootroot00000000000000z@4libtpms-0.9.3/tests/corpus-execute-command/6984b78609ff2db6745763cd4b8e92b788c300e1000066400000000000000000000001111421143571500261230ustar00rootroot00000000000000I@@ @ @ @  I@@ libtpms-0.9.3/tests/corpus-execute-command/69d3fa3446900f650c2acabe1f7d12893d80c895000066400000000000000000000000671421143571500262450ustar00rootroot000000000000007< @ e @N; libtpms-0.9.3/tests/corpus-execute-command/69e1b7723a83e905afddf0e3b7b5abe384b5d1db000066400000000000000000000007061421143571500266150ustar00rootroot00000000000000g@,`i y%K+=7:~@s[ |•מ) `=-cejTEX6V @libtpms-0.9.3/tests/corpus-execute-command/69f3b9ed03efb9e7ce6dc91133b55ed725507a43000066400000000000000000000000261421143571500264070ustar00rootroot00000000000000GP~libtpms-0.9.3/tests/corpus-execute-command/6af7eddb3a7228d9e9b8a6f3c3dda1224ac6440c000066400000000000000000000000161421143571500266040ustar00rootroot00000000000000libtpms-0.9.3/tests/corpus-execute-command/6b14212a2e00309c652930ff49d41c8c796a9f60000066400000000000000000000000141421143571500260040ustar00rootroot00000000000000 wlibtpms-0.9.3/tests/corpus-execute-command/6b2a1d522ab7a12a78706606581b030152c1e4b7000066400000000000000000000000261421143571500257520ustar00rootroot00000000000000z>libtpms-0.9.3/tests/corpus-execute-command/6b3438997b24876a38682fdec91a984c59908333000066400000000000000000000000141421143571500257170ustar00rootroot00000000000000 llibtpms-0.9.3/tests/corpus-execute-command/6b34ccaaea52359a717fb14260980a0b491ce814000066400000000000000000000000201421143571500262040ustar00rootroot00000000000000libtpms-0.9.3/tests/corpus-execute-command/6bbf441a1da32d144a1aeb238c0aff4a174b0a31000066400000000000000000000001271421143571500264540ustar00rootroot00000000000000W @ i @ ibj#9(や i !Xlibtpms-0.9.3/tests/corpus-execute-command/6c1ae389b3ae78e70c34734c70661e89e1c3ad33000066400000000000000000000000351421143571500262370ustar00rootroot00000000000000'nnn nn @gnnn nnlibtpms-0.9.3/tests/corpus-execute-command/6c98df1b76a86bcd353aed6652cf7d80cc168a1e000066400000000000000000000000401421143571500265410ustar00rootroot00000000000000 ?@ @ libtpms-0.9.3/tests/corpus-execute-command/6d139946db7161a89a15d55103f8fa6958331479000066400000000000000000000000261421143571500256770ustar00rootroot00000000000000zzlibtpms-0.9.3/tests/corpus-execute-command/6d4f735aa8e8cbf1c81d8fe964c73b9f9f5dbd07000066400000000000000000000000141421143571500266450ustar00rootroot00000000000000 #libtpms-0.9.3/tests/corpus-execute-command/6d7f805472a4c1f1cb6dfb3ed2417070d6f289b6000066400000000000000000000000401421143571500263110ustar00rootroot00000000000000 L@ Q@libtpms-0.9.3/tests/corpus-execute-command/6ddd82b52941ada997a93fab65def8a10c74bfcc000066400000000000000000000001051421143571500266770ustar00rootroot00000000000000E1@ @ XmH `libtpms-0.9.3/tests/corpus-execute-command/6e624dd674571003dda8c1625f3b3bb38bb337b4000066400000000000000000000001271421143571500262210ustar00rootroot00000000000000W@ @ ibj#8(\3 묗%p`0NDO !Xlibtpms-0.9.3/tests/corpus-execute-command/6e92569b4c5be63396df1d55eba2fe118de5c173000066400000000000000000000000161421143571500264060ustar00rootroot00000000000000libtpms-0.9.3/tests/corpus-execute-command/6ec10fa80849b00ba14d667bebaffc60cad57994000066400000000000000000000001051421143571500265240ustar00rootroot00000000000000E1@ @ Yme `libtpms-0.9.3/tests/corpus-execute-command/6ecce0802fda247ba15b736f5dfc403df4c54419000066400000000000000000000000261421143571500264430ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/6edf91c8804db7586d294fdc84a349f4721e35b2000066400000000000000000000001051421143571500262570ustar00rootroot00000000000000E1@ @ XmQ `libtpms-0.9.3/tests/corpus-execute-command/6ef6f44dde4b1978bc00b30948f25c440ef24e02000066400000000000000000000001051421143571500263070ustar00rootroot00000000000000E1@ @ Yme `libtpms-0.9.3/tests/corpus-execute-command/6efdc0ecb0fffae82d30f6402426511ae670cfd1000066400000000000000000000001051421143571500265700ustar00rootroot00000000000000E1@ @ XXe `libtpms-0.9.3/tests/corpus-execute-command/6f3fee7cca8eae439d38bd7827a539e0add97ce2000066400000000000000000000000341421143571500267170ustar00rootroot00000000000000'@ @ libtpms-0.9.3/tests/corpus-execute-command/6fe65a6503233eb40bff82b0a0ab140d83fea3d0000066400000000000000000000000261421143571500264140ustar00rootroot00000000000000z libtpms-0.9.3/tests/corpus-execute-command/70330edb9c62dbbe93d85e5cc9ec7380fb0ef484000066400000000000000000000000261421143571500265450ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/70416dc7af589dd1952d6d2d2bbcd57429ba3bad000066400000000000000000000000371421143571500265320ustar00rootroot00000000000000 @ libtpms-0.9.3/tests/corpus-execute-command/704465f74d24b87b197f197178670dcfb0ac3945000066400000000000000000000000321421143571500260330ustar00rootroot00000000000000~  libtpms-0.9.3/tests/corpus-execute-command/70665432f77a1389af57083d911b22a479610988000066400000000000000000000000161421143571500255330ustar00rootroot00000000000000~libtpms-0.9.3/tests/corpus-execute-command/706e2bd17f8a21bc9fece45b974db24a543bbcdc000066400000000000000000000000321421143571500266610ustar00rootroot00000000000000g]libtpms-0.9.3/tests/corpus-execute-command/70d05eddbe3e524fcc4d926da5ad28ce77eaed82000066400000000000000000000000241421143571500267530ustar00rootroot00000000000000~libtpms-0.9.3/tests/corpus-execute-command/70df1c9f88dce296d97e4ccb90f9cd84f0e83d71000066400000000000000000000000121421143571500265670ustar00rootroot00000000000000 Ilibtpms-0.9.3/tests/corpus-execute-command/71f4bf3a19f2687fe3b7c71e696e235100d17453000066400000000000000000000001421421143571500261010ustar00rootroot00000000000000bg,@,`i y%K+=7:~ޭޭޭޭ$L:-n. Ran@libtpms-0.9.3/tests/corpus-execute-command/720c2391bea09078cefaaa7135d145f96936942b000066400000000000000000000001111421143571500261460ustar00rootroot00000000000000I1@ @ E? `Clibtpms-0.9.3/tests/corpus-execute-command/72e0a87fad6b9d0721ec3e867e0c3134c07ab3f1000066400000000000000000000000261421143571500263600ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/732bec36c4d98e284a8d206d2eb70104a9cd0655000066400000000000000000000000371421143571500262300ustar00rootroot00000000000000+@ @ libtpms-0.9.3/tests/corpus-execute-command/736e8678804cee0ca1a1077513b5d231a6b9b869000066400000000000000000000000141421143571500260730ustar00rootroot00000000000000 Xlibtpms-0.9.3/tests/corpus-execute-command/7371f32f41d8b4ad3188df2a0b43662f3719cf4a000066400000000000000000000000671421143571500262350ustar00rootroot000000000000007R@@ @  @e!2 ^q??? ylibtpms-0.9.3/tests/corpus-execute-command/745e3ad530c0759990767a2e8063d83b4a53c9ce000066400000000000000000000000261421143571500261070ustar00rootroot00000000000000} libtpms-0.9.3/tests/corpus-execute-command/74cedb05446bf31abfd0064080e33ddc7f3702a2000066400000000000000000000000261421143571500263420ustar00rootroot00000000000000z@libtpms-0.9.3/tests/corpus-execute-command/75640f08144288652c901b44f087b381afcabf6a000066400000000000000000000001271421143571500260730ustar00rootroot00000000000000W @  @ ibj#9(やi !Xlibtpms-0.9.3/tests/corpus-execute-command/756e1f9059f310638006b87a580d9a545c944929000066400000000000000000000000261421143571500256220ustar00rootroot00000000000000z@ libtpms-0.9.3/tests/corpus-execute-command/75faa54fd581c2a5af8bef27b91de6c3137ed8af000066400000000000000000000000631421143571500267030ustar00rootroot000000000000003%@ @ 3)@ @libtpms-0.9.3/tests/corpus-execute-command/7620bc73ddd32340e3dac53c5b7a877fb04cce02000066400000000000000000000000141421143571500264250ustar00rootroot00000000000000 libtpms-0.9.3/tests/corpus-execute-command/7621326c88962f61692ce79a7bee4487fa9d7881000066400000000000000000000000261421143571500260650ustar00rootroot00000000000000z!zlibtpms-0.9.3/tests/corpus-execute-command/7647b9d75371781c32d21819d4ee1435d5ca2878000066400000000000000000000000161421143571500257540ustar00rootroot00000000000000Olibtpms-0.9.3/tests/corpus-execute-command/76826c439b26cf43ebd34ae745184c5c0599b67a000066400000000000000000000000121421143571500261650ustar00rootroot00000000000000 7libtpms-0.9.3/tests/corpus-execute-command/76db0248f0d1da42b1772ea5f441170d70083244000066400000000000000000000000411421143571500257620ustar00rootroot00000000000000!v@@ v@@ libtpms-0.9.3/tests/corpus-execute-command/76dc50c6feb3be158b2acadbb72f771870b31b30000066400000000000000000000000161421143571500265100ustar00rootroot00000000000000libtpms-0.9.3/tests/corpus-execute-command/76e13d0b5d6355ffa411e066f2efcdfe7e8a6eb5000066400000000000000000000007061421143571500266260ustar00rootroot00000000000000g@,`i y%K+=7:~"9Z6> \z kO AeK ]ҔcJ ";{kG v~E# A3PZȵWAϫad2ɚſ`sd>S;6Wb(-qvǔSã""("{v3jؐMl'#rƙ$86 nyƁ)&8.t3K1@%TYb]ijfQjl7ʷp=V]$ *A&ʯvvp/1O#I hW%7F޴^d2#+;ݭ|z *@@?FW݉;dLW[ |•מ) `=-ejTEX6V @libtpms-0.9.3/tests/corpus-execute-command/770c8c23d252abb9cbc772abeb3688cfe4d46647000066400000000000000000000000171421143571500264610ustar00rootroot00000000000000v'(!rlibtpms-0.9.3/tests/corpus-execute-command/776148bded655080a13a77aa33f4e1d25aa4271a000066400000000000000000000000261421143571500262110ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/77b82608b3cb24c61e67c40843e30a3197b56e55000066400000000000000000000000201421143571500260060ustar00rootroot00000000000000libtpms-0.9.3/tests/corpus-execute-command/782ca6268ce9e5ec4b3e0299c563385be995d640000066400000000000000000000000261421143571500262060ustar00rootroot00000000000000z;libtpms-0.9.3/tests/corpus-execute-command/783cfbf41f294a41cd77b60119ff9d8b547c69ec000066400000000000000000000000261421143571500264210ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/78a614381a4f3f5b1c72d5836a219a815cdc6f22000066400000000000000000000001111421143571500261430ustar00rootroot00000000000000I1@ @ 'E? `Clibtpms-0.9.3/tests/corpus-execute-command/78c0ba155504a373cab11f2b46762573f8e4f5d0000066400000000000000000000000671421143571500261450ustar00rootroot000000000000007<@ @  @ e!2 ^q??? ylibtpms-0.9.3/tests/corpus-execute-command/792726d0f7e00f110fc9f2be84d7e0a66ccceddd000066400000000000000000000026461421143571500266260ustar00rootroot00000000000000a@@ 1?籄ۘzɷ_0W \ ڱOTf?slm bLح\̪m2AtÊ~}P.GM@D@F¢@W {F"88@ӯ)՚dc>3mXqT<6\ܡj˅:88#Q~Xnn{i񁷜iD2,%i*R㶖C| FX 7<PMpzY ,b%W{^)\SHo:kTpzY]k~ a1:)4tO[(I?lB;lՖP-f|DEbӗ`m'eӳ^> ~y>ap[3LcFX3~Io{6@\̤fs沢\ 5i7oDc|qSIOSհ4,+m+,@3>7mV)J*@4VDD =H2E{r{SYRR+Ij˼ sS r%&$rs7x\2h:k=vlH% #y8]uP:+MW5 (f%3`d{R@쫱!ZR -n4ցEEi9[X㒶:E?aˈjES{v9۔u:g=6k @ڲ)AnM3mwux[ /ʣ&^Ɍ/SWoEM&(EC \z kO AeK ]ҔcJ ";{kG v~E# A3PZȵWAϫad2ɚſ`sd>S;6Wb(-qvǔSã""("{v3jؐMl'#rƙ$86 nyƁ)&8.t3K1@%TYb]ijfQjl7ʷp=V]$ *A&ʯvvp/1O#I hW%7F޴^d2#+;ݭ|z *@@?FW݉;dLW[ |•מ) `=-ejTEX6V @libtpms-0.9.3/tests/corpus-execute-command/8175082d40e973824deb8ec66a31bf80ef600dbe000066400000000000000000000000141421143571500263130ustar00rootroot00000000000000 Flibtpms-0.9.3/tests/corpus-execute-command/8199baf3111ff6cbd1104fce731ca649c3681176000066400000000000000000000000151421143571500262250ustar00rootroot00000000000000 FClibtpms-0.9.3/tests/corpus-execute-command/81c05810865dfe8cdc3f7307ede6e7308f2b0562000066400000000000000000000000261421143571500262430ustar00rootroot00000000000000d*K;;libtpms-0.9.3/tests/corpus-execute-command/8232a5eb708bb4affe1551dd7f875af6e9918620000066400000000000000000000001111421143571500263230ustar00rootroot00000000000000IX@ @ ;'`Xlibtpms-0.9.3/tests/corpus-execute-command/82839efe3da4d0bc216547b2fd8d78e4afd06c47000066400000000000000000000000161421143571500264650ustar00rootroot00000000000000elibtpms-0.9.3/tests/corpus-execute-command/82a2a036de3a67df1dcb62ed462db0d38bca6f97000066400000000000000000000000321421143571500265770ustar00rootroot00000000000000 "libtpms-0.9.3/tests/corpus-execute-command/82e2d08c01eab889e8f3772f5b79324d3cd25192000066400000000000000000000000321421143571500261650ustar00rootroot00000000000000v@@  libtpms-0.9.3/tests/corpus-execute-command/82e8247c01c78fc50485467ca3dd20eb11e1b6a8000066400000000000000000000000401421143571500262200ustar00rootroot00000000000000 R@@ @ libtpms-0.9.3/tests/corpus-execute-command/831bbfc02ed0578fdc284aa0286797946e7b841e000066400000000000000000000001001421143571500262410ustar00rootroot00000000000000@a@ $ @));@@<X@libtpms-0.9.3/tests/corpus-execute-command/8341755237905889bb3a991e32e173036b3eeed4000066400000000000000000000000431421143571500257460ustar00rootroot00000000000000#@ @  libtpms-0.9.3/tests/corpus-execute-command/834d3f22a5ff3cab3c44754cccfc563aff2cfaf4000066400000000000000000000002461421143571500267510ustar00rootroot00000000000000g<#@,`i y%K=7:~ hqEe7r%fɠX# rN $'qT :@libtpms-0.9.3/tests/corpus-execute-command/834e28ebe1939cc85539b282f35f6028b9a95594000066400000000000000000000000261421143571500260530ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/835e042c078157023255bc18d5dea26a4bf44e3e000066400000000000000000000000261421143571500261370ustar00rootroot00000000000000%libtpms-0.9.3/tests/corpus-execute-command/83879417eb18277a57d8076a20afcbcf9194c3c4000066400000000000000000000000261421143571500261720ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/83b1a0c85ac855aaf8400198dfd631d83f6703ac000066400000000000000000000000151421143571500263030ustar00rootroot00000000000000 b;libtpms-0.9.3/tests/corpus-execute-command/8422683fb77b70fcb67f85ef9115edfe9b3174be000066400000000000000000000000531421143571500264240ustar00rootroot00000000000000+v@@)P8ۅvUԄcmplibtpms-0.9.3/tests/corpus-execute-command/843d0c115b50a19cb63735dcb684cd55af1c40c4000066400000000000000000000001441421143571500262700ustar00rootroot00000000000000dg,%*@,`i y K+=7:~&%CL:-n. Ran@libtpms-0.9.3/tests/corpus-execute-command/8473f8181c27e2dc3c3e42621c533e594f87f900000066400000000000000000000000261421143571500260270ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/848ceda2b1e6d03bd3188d46191219bec18b2001000066400000000000000000000000361421143571500262110ustar00rootroot000000000000008JIulibtpms-0.9.3/tests/corpus-execute-command/849895d3d01e029b31ca5c11284fb15baf7f5e45000066400000000000000000000000631421143571500262320ustar00rootroot0000000000000031@@ @ 5* libtpms-0.9.3/tests/corpus-execute-command/8525f32449a185aa7d6d8e23efcad01c123709f9000066400000000000000000000000551421143571500262370ustar00rootroot00000000000000-*@ @ libtpms-0.9.3/tests/corpus-execute-command/855fedea080ec6195404616b3b566f56e848c2eb000066400000000000000000000000631421143571500262510ustar00rootroot000000000000003*@ @ Xmelibtpms-0.9.3/tests/corpus-execute-command/859755835f7ed86b35f2e4d28e1212cd76634d10000066400000000000000000000000161421143571500260350ustar00rootroot00000000000000libtpms-0.9.3/tests/corpus-execute-command/85b96a0a92dacc0d67aec0d81b1e968373210229000066400000000000000000000000141421143571500262170ustar00rootroot00000000000000 xlibtpms-0.9.3/tests/corpus-execute-command/85c2583e9695d6f35a08b94cbe793e78f23dacc5000066400000000000000000000000061421143571500263470ustar00rootroot00000000000000libtpms-0.9.3/tests/corpus-execute-command/86308ad12ef1502add797ff50b3d4bb440236ced000066400000000000000000000000411421143571500263530ustar00rootroot00000000000000!q !k4 libtpms-0.9.3/tests/corpus-execute-command/867c8957affacb02fd8e72406fed8109c0eb574c000066400000000000000000000000261421143571500264730ustar00rootroot00000000000000glibtpms-0.9.3/tests/corpus-execute-command/8718c612b14dfe4296dfe89b68325e4253a53ee3000066400000000000000000000001111421143571500261660ustar00rootroot00000000000000I1@ @ C=? `Clibtpms-0.9.3/tests/corpus-execute-command/8763d7fce4efe0d39e229cbd44424cd9e99dd0ce000066400000000000000000000000561421143571500266450ustar00rootroot00000000000000.g#@libtpms-0.9.3/tests/corpus-execute-command/876ac91a8b20fe6ec7f349fc45b6394489e51956000066400000000000000000000001051421143571500262130ustar00rootroot00000000000000E1@ @ Xve`libtpms-0.9.3/tests/corpus-execute-command/87842f51de0e11e4b904eb43818c1b241070d742000066400000000000000000000000261421143571500257760ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/87abd177107ff2a3082ae823f5d69ff661f62d89000066400000000000000000000000261421143571500262570ustar00rootroot00000000000000; rlibtpms-0.9.3/tests/corpus-execute-command/87ae39b4d5d4d79219b4b33c285d7de69bd399af000066400000000000000000000000261421143571500264260ustar00rootroot00000000000000z7libtpms-0.9.3/tests/corpus-execute-command/886bc7e545728b1069c76d37bd2a2b560753a894000066400000000000000000000001001421143571500260250ustar00rootroot00000000000000@1@ @ \E( libtpms-0.9.3/tests/corpus-execute-command/8880f518552927159665d2ec76d013c86d6038c8000066400000000000000000000000411421143571500256240ustar00rootroot00000000000000!v@@  libtpms-0.9.3/tests/corpus-execute-command/88b5afaa08768e4878841d6965c8e11b967a9971000066400000000000000000000000121421143571500260610ustar00rootroot00000000000000 Rlibtpms-0.9.3/tests/corpus-execute-command/88e6a1b0926799a32789f840247b5a64ade64e3b000066400000000000000000000000141421143571500261140ustar00rootroot00000000000000 rlibtpms-0.9.3/tests/corpus-execute-command/88f4b42fb8e876e10f1707fb98357aa52ab9ed7b000066400000000000000000000000161421143571500264160ustar00rootroot000000000000004@ libtpms-0.9.3/tests/corpus-execute-command/890ddc98c0db5de70fdcd455b3472921d46cad93000066400000000000000000000000521421143571500264620ustar00rootroot00000000000000*g#:@libtpms-0.9.3/tests/corpus-execute-command/89216af272539b26bb7d5b55a84c00218be9f0ce000066400000000000000000000001421421143571500262300ustar00rootroot00000000000000bg,@,`i y%K+=7:~ޭޭޭޭ$L:-n. Ran@libtpms-0.9.3/tests/corpus-execute-command/8935482dd184004584ac1663cf488e8ffa5dbb9f000066400000000000000000000000121421143571500262540ustar00rootroot00000000000000 "libtpms-0.9.3/tests/corpus-execute-command/89383d1442c5f589e141af7c1a897689be5eac26000066400000000000000000000000161421143571500262040ustar00rootroot00000000000000Hlibtpms-0.9.3/tests/corpus-execute-command/898f88d4f2bcc1c29178952dda42b9cebec24c4b000066400000000000000000000000161421143571500265510ustar00rootroot00000000000000<libtpms-0.9.3/tests/corpus-execute-command/8ae4c390c9c6cc893cdf256e8d2c0bc4db6169a4000066400000000000000000000000261421143571500265430ustar00rootroot00000000000000h:libtpms-0.9.3/tests/corpus-execute-command/8bcec5b14dfb7897e8af76e2ab0b3d10d699db0a000066400000000000000000000000341421143571500266740ustar00rootroot000000000000000@ @ libtpms-0.9.3/tests/corpus-execute-command/8bf4f0d9070a6f390840787a4a8bd32859c4cfb2000066400000000000000000000001521421143571500262450ustar00rootroot00000000000000jgX# "octPS;6Wb(-q@""("{v0jؐMl'#rƙ$86 n#rcƙ$86 nyƁ)5&ҋ̮1@%TYb]ijfQjl3ʷp=ZFjCAeK ]ҔcJ ";{kG v~E# A3PZȵWAϫad4ɚſ`݉;dLW[ |•מ) `=-ejTEX6V @libtpms-0.9.3/tests/corpus-execute-command/8f98f7c48a64707af79c818d60673da45559e287000066400000000000000000000001051421143571500260670ustar00rootroot00000000000000E1@ @ X:e `libtpms-0.9.3/tests/corpus-execute-command/8fa2750d4c23b1127ab32b48784463bd2498382d000066400000000000000000000000261421143571500260070ustar00rootroot00000000000000z@libtpms-0.9.3/tests/corpus-execute-command/8ffe07a511a2806d4ae8c294b0f9f579b358bf52000066400000000000000000000000261421143571500263270ustar00rootroot00000000000000n(% libtpms-0.9.3/tests/corpus-execute-command/90288b65b0e74b540437a46eab2dc46514e6378f000066400000000000000000000001521421143571500260770ustar00rootroot00000000000000jgX#  )>FpcQ$ԆW:t$1'rN i"oct̤P<5$F'qT:@libtpms-0.9.3/tests/corpus-execute-command/90cdb6a74e188fa09efea42cb8bc51c34ca2c3ba000066400000000000000000000000261421143571500267330ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/90f9ff438a9422636575384e9dcede7a54cb04b7000066400000000000000000000000261421143571500262630ustar00rootroot00000000000000z@libtpms-0.9.3/tests/corpus-execute-command/910b5ad9ba1be38573fdc316a351c47a35b27a26000066400000000000000000000001111421143571500262640ustar00rootroot00000000000000I@@ @  A@@  I@@ libtpms-0.9.3/tests/corpus-execute-command/912c5058aa5c90d338c878e380353155295aac8b000066400000000000000000000002461421143571500260220ustar00rootroot00000000000000g<#@,`i y%K=7:~ hqEe7r%fɠX#  'qT :@libtpms-0.9.3/tests/corpus-execute-command/9168ab5bcea28f36961c333316f433c154e01c7b000066400000000000000000000001111421143571500261350ustar00rootroot00000000000000I*@ @ +Xme.! Xme.)!; `Clibtpms-0.9.3/tests/corpus-execute-command/9179c0ba690d4980ee46f8540964a204a45bec05000066400000000000000000000002461421143571500261030ustar00rootroot00000000000000g<#@,`i y%K+=7:~ 7X#X# )pcF$QԆW:t59'rN ij"octP<3$'qT:@libtpms-0.9.3/tests/corpus-execute-command/91c4488f0be3324a8d852a3ff2d91d10e829d853000066400000000000000000000000141421143571500261610ustar00rootroot00000000000000 mlibtpms-0.9.3/tests/corpus-execute-command/922621003f0372d37ee37795c45545e360fcf6a1000066400000000000000000000000671421143571500257370ustar00rootroot000000000000007X@ @  @ e!4 ^q??? ylibtpms-0.9.3/tests/corpus-execute-command/926d780731bbeca946ccea7919cf44b4fc91deef000066400000000000000000000000161421143571500266330ustar00rootroot00000000000000}libtpms-0.9.3/tests/corpus-execute-command/92721fcbc7128795d7fe77eb40be401013bc88c1000066400000000000000000000000121421143571500262260ustar00rootroot00000000000000 3libtpms-0.9.3/tests/corpus-execute-command/92b87aea237d81880e90e2189ea1b0099346936e000066400000000000000000000001051421143571500260310ustar00rootroot00000000000000E1@ @ Xm:K `libtpms-0.9.3/tests/corpus-execute-command/92c679bf19e7aff910e68d8340f4a953e972e1e3000066400000000000000000000000631421143571500262720ustar00rootroot000000000000003g%gD*%!Dlibtpms-0.9.3/tests/corpus-execute-command/92f111869bddbd6546831c8404a35c0a8223c7db000066400000000000000000000001111421143571500261370ustar00rootroot00000000000000I1@ @ C  `Clibtpms-0.9.3/tests/corpus-execute-command/930667e1307410a74f8d17380c5d25f76a8c546e000066400000000000000000000003761421143571500257540ustar00rootroot00000000000000a @0$=)?ws 0wX7t(IyGiɪeܻ#Y,ƖTA/ue7t(IsG(B+libtpms-0.9.3/tests/corpus-execute-command/935bc5a21869ab39eba659977516ce83b9b03805000066400000000000000000000007061421143571500261220ustar00rootroot00000000000000g@,`i y%K+=7:~(-q@s[ |•מ) `=-cejTEX6V @libtpms-0.9.3/tests/corpus-execute-command/93a08b41a9c81422626a0f52f2fe5a1d1a0d766c000066400000000000000000000001111421143571500262040ustar00rootroot00000000000000I1@ @ fE? `Clibtpms-0.9.3/tests/corpus-execute-command/940540496f016aea899566b0227e87121eec674a000066400000000000000000000000261421143571500257450ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/944bf230e5e1d8234e09a5dd8e3fbab569bdd521000066400000000000000000000000261421143571500264510ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/949b8e76d474854c8d9ee1bedbb02dd7362a4ef1000066400000000000000000000000261421143571500264760ustar00rootroot00000000000000z(libtpms-0.9.3/tests/corpus-execute-command/94ca785a96a8adfa9c60e109462e36b8bb93e94c000066400000000000000000000001111421143571500264100ustar00rootroot00000000000000I1@ @ CJ? `Clibtpms-0.9.3/tests/corpus-execute-command/9524da5dbfb4c2d7e6bd24f6718addcdcfc67e85000066400000000000000000000000261421143571500267670ustar00rootroot00000000000000gz3libtpms-0.9.3/tests/corpus-execute-command/95ec7643011d0ba5355332c03346b2e487b4f9e7000066400000000000000000000001111421143571500260010ustar00rootroot00000000000000I1@ @ CE^ `Clibtpms-0.9.3/tests/corpus-execute-command/95fb71c002b8b61ab8bdfd63d1fcd27d9fe0eafb000066400000000000000000000001051421143571500270220ustar00rootroot00000000000000E1@ @ Xve `libtpms-0.9.3/tests/corpus-execute-command/961db1a44747a31fbf96dc4632b4e65b400871e5000066400000000000000000000000201421143571500261430ustar00rootroot00000000000000#libtpms-0.9.3/tests/corpus-execute-command/962c8dfe3043bad6bd3361609afab885bd77f8e2000066400000000000000000000001271421143571500264670ustar00rootroot00000000000000W @ ibj#7(\3 묗%p`6NDOǡ !Xlibtpms-0.9.3/tests/corpus-execute-command/9635dfbbd86a038fc2a6e5af67d057b5b9f9eb6b000066400000000000000000000002461421143571500266400ustar00rootroot00000000000000g<#@,`i y%K+=7:~ 0X# )pcF$QԆW:t59'rN ij"octP<3$'qT:@libtpms-0.9.3/tests/corpus-execute-command/96b7431c04d685232a5d8ca30a9f38674f52a9d8000066400000000000000000000000261421143571500261060ustar00rootroot00000000000000L@ libtpms-0.9.3/tests/corpus-execute-command/96ea6f20ad2dcc861f20de1dad961b9920e70816000066400000000000000000000000261421143571500263700ustar00rootroot00000000000000'@ libtpms-0.9.3/tests/corpus-execute-command/977ef7e1ba2c4a40112fbc0fd7ec678367aaf912000066400000000000000000000000261421143571500264520ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/97c29a9df6bcf170c78f39fb8517dcc79058aaac000066400000000000000000000000261421143571500265620ustar00rootroot00000000000000w zlibtpms-0.9.3/tests/corpus-execute-command/98b4dcd5f57b429507c22b71a2aabab7eefcc8cc000066400000000000000000000000161421143571500267440ustar00rootroot00000000000000elibtpms-0.9.3/tests/corpus-execute-command/98e238e08cdfa4de421a8f66f063fa044e9b4941000066400000000000000000000001051421143571500263240ustar00rootroot00000000000000ER@@ @ 0 libtpms-0.9.3/tests/corpus-execute-command/9952956d886218ac1f500b232f9deaf5b9d3434e000066400000000000000000000002461421143571500261760ustar00rootroot00000000000000g<#@,`i y%K+=7:~ @,X#pcF$QԆW:t59'rN ij"octP<3$'qT:@libtpms-0.9.3/tests/corpus-execute-command/999b5f3f5e90536772b7d9422353b97ffb860648000066400000000000000000000001111421143571500257770ustar00rootroot00000000000000I1@ @ CE? `Clibtpms-0.9.3/tests/corpus-execute-command/99d0e014e7eb3f31319b7984dd811fa277c46740000066400000000000000000000001051421143571500261030ustar00rootroot00000000000000E1@ @ Xm2e `libtpms-0.9.3/tests/corpus-execute-command/99db1f5aa894abd14a968feb94906e506b808d65000066400000000000000000000000461421143571500263440ustar00rootroot00000000000000&X@ @ libtpms-0.9.3/tests/corpus-execute-command/9a21d4259ff41223a9040fd6600b45e678a8646f000066400000000000000000000001271421143571500260200ustar00rootroot00000000000000W @  @ ibj#9(やi !Xlibtpms-0.9.3/tests/corpus-execute-command/9a2201aba90f5acfc3d4aa73b855348fe4ef0bf3000066400000000000000000000000351421143571500265740ustar00rootroot000000000000002@ @ libtpms-0.9.3/tests/corpus-execute-command/9a263f4ce53335d26364ee673d11a6b542a1fef5000066400000000000000000000000161421143571500262270ustar00rootroot000000000000005@ libtpms-0.9.3/tests/corpus-execute-command/9a471c7d64386c178907dfd50c6c7b3c0146c23e000066400000000000000000000000201421143571500261530ustar00rootroot00000000000000#libtpms-0.9.3/tests/corpus-execute-command/9a567818c22ed204d9e167916c50d8c0463a2f68000066400000000000000000000001111421143571500260220ustar00rootroot00000000000000I1@ @ ГE- `Clibtpms-0.9.3/tests/corpus-execute-command/9a664a2095e2918c10e15866fc48dfb4dea8586c000066400000000000000000000000261421143571500262550ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/9a7d1eaee211ed6871767e1729c936103683a040000066400000000000000000000000261421143571500260150ustar00rootroot00000000000000libtpms-0.9.3/tests/corpus-execute-command/9af8fd094696feac205785acaab788591de8f41d000066400000000000000000000000121421143571500265000ustar00rootroot00000000000000 Mlibtpms-0.9.3/tests/corpus-execute-command/9bc754bf1eda70c580d20a196552178f2efd864c000066400000000000000000000000131421143571500263140ustar00rootroot00000000000000 8libtpms-0.9.3/tests/corpus-execute-command/9c0a05bd7f32c9b7b35052bbd91d2e6c6a896812000066400000000000000000000001271421143571500263120ustar00rootroot00000000000000W @  ibj#7p`6NDOǡ !XNDOǡ !Xlibtpms-0.9.3/tests/corpus-execute-command/9c228a25fd5d6393ec306713b3c8f1eb800ba3aa000066400000000000000000000000161421143571500263520ustar00rootroot00000000000000aklibtpms-0.9.3/tests/corpus-execute-command/9c57a85859982cd06a591c59ac799726cb90f262000066400000000000000000000000261421143571500260600ustar00rootroot00000000000000Ilibtpms-0.9.3/tests/corpus-execute-command/9cc2f43b7fbfb0f216561f0ee71f89386283bba7000066400000000000000000000000261421143571500264040ustar00rootroot00000000000000K)Vlibtpms-0.9.3/tests/corpus-execute-command/9cd80997ea883576e616156296d64e468a7ae9e7000066400000000000000000000001271421143571500260760ustar00rootroot00000000000000W)@  ibj#7p`6NDOǡ !XNDOǡ !Xlibtpms-0.9.3/tests/corpus-execute-command/9cf46401c7ffa4dc3c7511c2c2127546cfbca91f000066400000000000000000000000261421143571500264420ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/9d458ae4c9b0f6aeda627f4c37b82ecba7a84619000066400000000000000000000002461421143571500265530ustar00rootroot00000000000000g<#@,`i y%K=7:~ hqEe7r%fɠX# 'rN $'qT :@libtpms-0.9.3/tests/corpus-execute-command/9ea5437f1c3fa5ebd32c80fbda93a30b64f5d3c1000066400000000000000000000000351421143571500265760ustar00rootroot00000000000000.@ @)@ libtpms-0.9.3/tests/corpus-execute-command/9ea8a4889b22d26d55d43a83281554798734e130000066400000000000000000000000121421143571500256700ustar00rootroot00000000000000 Plibtpms-0.9.3/tests/corpus-execute-command/9f24a4a2ad82cfd8f568b6ec911a8e3ebab4191a000066400000000000000000000007061421143571500266160ustar00rootroot00000000000000g@,`i y%K+=7:~"9Z6> \z kO AeK ]ҔcJ ";{kG v~E# A3PZȵWAϫad2ɚſ`sd>S;6Wb(-q vǔSã""("{v3jؐMl'#rƙ$86 nyƁ)&8.t3K1@%TYb]ijfQjl7ʷp=V]$ *A&ʯvvp/1O#I hW%7F޴^d2#+;ݭ|z *@@?FW݉;dLW[ |•מ) `=-ejTEX6V @libtpms-0.9.3/tests/corpus-execute-command/9f8f4855f3be0c770ce5ce41b4fa08a8cfc8ba15000066400000000000000000000001311421143571500266170ustar00rootroot00000000000000Y1@ @ Xme`CvˆJI}libtpms-0.9.3/tests/corpus-execute-command/9f93b4b28dc67241be3584e315bdd44469bcd237000066400000000000000000000000401421143571500262400ustar00rootroot00000000000000 0@ @ libtpms-0.9.3/tests/corpus-execute-command/9fd8b1d88df53e8e3075a59a8da5675621c9cf6d000066400000000000000000000001051421143571500264300ustar00rootroot00000000000000E1@ @ XmZe `libtpms-0.9.3/tests/corpus-execute-command/a0c953f1da899c436f4c04111743a32ae76219ee000066400000000000000000000000631421143571500261460ustar00rootroot000000000000003*@ @ Xmelibtpms-0.9.3/tests/corpus-execute-command/a0fd54d2d1794f4dd1b08b102a03cc8d2e4c1c52000066400000000000000000000001001421143571500264060ustar00rootroot00000000000000@a@ $0@));@@<X@libtpms-0.9.3/tests/corpus-execute-command/a107ec0a2369e49e4e9e34756a39948a839eb899000066400000000000000000000000261421143571500261360ustar00rootroot00000000000000zzlibtpms-0.9.3/tests/corpus-execute-command/a1856ce385a807eaf9d1aa4610f8a68e71c7fcdf000066400000000000000000000000151421143571500265420ustar00rootroot00000000000000 Dlibtpms-0.9.3/tests/corpus-execute-command/a2365d774962926f1efe366773bd5b3ce3acb6bc000066400000000000000000000007061421143571500264120ustar00rootroot00000000000000g@`i y%K+=:~"9cJ ";{kG v|}# A1PZȵW'A:ϫad2ɐſ`sdW'A:ϫad4ɐſ`ds>S;6Wb(-q @""("{v0jؐMl'#rƙ$86 n#rcƙ$86 nyƁ)5&ҋ̮1@%TYb]ijfQjl3ʷp=ZFjCAeK ]ҔcJ ";{kG v~E# A3PZȵWAϫad4ɚſ`݉;dLW[ |•מ) `=-ejTEX6V @libtpms-0.9.3/tests/corpus-execute-command/a2859d62efdf3ecef84ddf05a0ecdd8fcbcef880000066400000000000000000000000261421143571500272120ustar00rootroot00000000000000PKlibtpms-0.9.3/tests/corpus-execute-command/a29f981426e66c3f4ef0e6103cd16f531738b344000066400000000000000000000000121421143571500260730ustar00rootroot00000000000000 5libtpms-0.9.3/tests/corpus-execute-command/a2ac34f6bc10f57b64638db1cc02417438fec4b8000066400000000000000000000000341421143571500263550ustar00rootroot00000000000000v@@v@ Alibtpms-0.9.3/tests/corpus-execute-command/a2e61163ba201649f70d46d14175d0cd9571b500000066400000000000000000000001111421143571500257570ustar00rootroot00000000000000I1@ @ cE? `Clibtpms-0.9.3/tests/corpus-execute-command/a309ee348d0c594598225567fe362c4342eda3cd000066400000000000000000000000401421143571500261570ustar00rootroot00000000000000 !@ @ @libtpms-0.9.3/tests/corpus-execute-command/a31a68997ec40e61366cc0066cb4fa95d1b07d8d000066400000000000000000000000141421143571500263100ustar00rootroot00000000000000 libtpms-0.9.3/tests/corpus-execute-command/a32f2190e0d44d0d755f3f40c9209ece86494a9d000066400000000000000000000000261421143571500262370ustar00rootroot00000000000000j!libtpms-0.9.3/tests/corpus-execute-command/a364157bc68af1dc9b13577c83cba16c37c65ef2000066400000000000000000000000621421143571500263730ustar00rootroot000000000000002 @ @libtpms-0.9.3/tests/corpus-execute-command/a3732fd4ceadd6f5ed5169b5097805e0baa1fa0a000066400000000000000000000001051421143571500265730ustar00rootroot00000000000000E1@ @ Xm:g `libtpms-0.9.3/tests/corpus-execute-command/a39aeac51a60651e71990d43cad57b07b2e82bf3000066400000000000000000000001051421143571500263540ustar00rootroot00000000000000E1@ @ dm:e `libtpms-0.9.3/tests/corpus-execute-command/a39e6a2a9930e879ad82fce2f428c03a31791fbf000066400000000000000000000000261421143571500264040ustar00rootroot00000000000000J*J'libtpms-0.9.3/tests/corpus-execute-command/a3ab93648a9968777202df30ec7bb5cbae0608c8000066400000000000000000000000151421143571500263170ustar00rootroot00000000000000 %libtpms-0.9.3/tests/corpus-execute-command/a3f08d2c63e850281d7cfc474e0f87bdc070a695000066400000000000000000000000261421143571500263170ustar00rootroot00000000000000Flibtpms-0.9.3/tests/corpus-execute-command/a445e9bb10e66144129149a2941943317b0ae3bc000066400000000000000000000000141421143571500257670ustar00rootroot00000000000000 Elibtpms-0.9.3/tests/corpus-execute-command/a4736591c16f1f35b1aa00c7368704b219509fc7000066400000000000000000000000431421143571500260020ustar00rootroot00000000000000#(@ @  libtpms-0.9.3/tests/corpus-execute-command/a48bf1b80ab317b4ae99ba78091e232395662c8b000066400000000000000000000007061421143571500262360ustar00rootroot00000000000000g@`i y%K+=:~ "9cJ ";{kG v|}# A1PZȵW'A:ϫad2ɐſ`sdW'A:ϫad4ɐſ`ds>S;6Wb(-q@""("{v0jؐMl'#rƙ$86 n#rcƙ$86 nyƁ)5&ҋ̮1@%TYb]ijfQjl3ʷp=ZFjCAeK ]ҔcJ ";{kG v~E# A3PZȵWAϫad4ɚſ`݉;dLW[ |•מ) `=-ejTEX6V @libtpms-0.9.3/tests/corpus-execute-command/a4dcfff0b801701e95f737a1edd1cc894b9ab878000066400000000000000000000000631421143571500265450ustar00rootroot000000000000003*@ @  libtpms-0.9.3/tests/corpus-execute-command/a4e652f24a9aaa9be4e68767a0322fce1d526038000066400000000000000000000000121421143571500263020ustar00rootroot00000000000000 Flibtpms-0.9.3/tests/corpus-execute-command/a5b00acf67c0388c943d5baf0874363a142d9777000066400000000000000000000000701421143571500261530ustar00rootroot000000000000008g&%CL:-n. Ran@libtpms-0.9.3/tests/corpus-execute-command/a5d66910c3ecfd66ac3413f83ba171fc10680f37000066400000000000000000000007061421143571500263060ustar00rootroot00000000000000g@`i y%K+=:~"9cJ ";{kG v|}# A1PZȵW'A:ϫad2ɐſ`sdW'A:ϫad4ɐſ`ds>S;6Wb(-q""("{v0jؐMl'#rƙ$86 n#rcƙ$86 nyƁ)5&ҋ̮1@%TYb]ijfQjl3ʷp=ZFjCAeK ]ҔcJ ";{kG v~E# A3PZȵWAϫad4ɚſ`݉;dLW[ |•מ) `=-ejTEX6V @libtpms-0.9.3/tests/corpus-execute-command/a60bbaa65fd9d274f7d506af5a42d220d3618236000066400000000000000000000000261421143571500262750ustar00rootroot00000000000000=zzlibtpms-0.9.3/tests/corpus-execute-command/a64a94ca4910998b031680b293ed728cdbe30d4a000066400000000000000000000000141421143571500262230ustar00rootroot00000000000000 Elibtpms-0.9.3/tests/corpus-execute-command/a64e858819de0f6828c0fa736356cef010cc68b6000066400000000000000000000002461421143571500262560ustar00rootroot00000000000000g<#@,`i y%K+=7:~ @,X# )pcF$QԆW:t59'rN ij"octP<3$'qT:@libtpms-0.9.3/tests/corpus-execute-command/a6adbb075ac61050e92aaf5e7f4361f455dbbc2a000066400000000000000000000000421421143571500265620ustar00rootroot00000000000000"g  @libtpms-0.9.3/tests/corpus-execute-command/a6b8fc62c42ed39a1764e242bb2f0abb9e1fb835000066400000000000000000000000141421143571500265160ustar00rootroot00000000000000 libtpms-0.9.3/tests/corpus-execute-command/a73aed2f412da9baad27f3f8478a9c18ff2bc685000066400000000000000000000000141421143571500266170ustar00rootroot00000000000000 libtpms-0.9.3/tests/corpus-execute-command/a74741e07eb1508193ab94982041a2b3f89bd65c000066400000000000000000000007061421143571500260770ustar00rootroot00000000000000g@,`i y%K+=7:~w >S;6Wd (-q>S;6Wd(-q) `=-cejTEX6V @libtpms-0.9.3/tests/corpus-execute-command/a82ec10d5443a315be4d356d916ef0dcc2002472000066400000000000000000000000161421143571500262010ustar00rootroot00000000000000Rlibtpms-0.9.3/tests/corpus-execute-command/a8310e60ec98ba12f60bd4b4b01f831883906b74000066400000000000000000000000261421143571500261400ustar00rootroot00000000000000Blibtpms-0.9.3/tests/corpus-execute-command/a85d5ec579e53b98d259986db571ccab770ce513000066400000000000000000000001271421143571500263450ustar00rootroot00000000000000W @  ibj#7p`6NDOǡ s!XNDOǡ !Xlibtpms-0.9.3/tests/corpus-execute-command/a89a72f8deca23407a785236ca02c5158249f274000066400000000000000000000001111421143571500260710ustar00rootroot00000000000000I1@ @ \E( `Clibtpms-0.9.3/tests/corpus-execute-command/a90ecfcdb55b5bf8eeb559ac9562e0cb3d0cc8f3000066400000000000000000000000261421143571500270340ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/a914436511df463622384731aa7afe4023082d99000066400000000000000000000000731421143571500256470ustar00rootroot00000000000000;<@ @ % Clibtpms-0.9.3/tests/corpus-execute-command/a944f0f8f45ed48c9657403a2bd0ddcdc1a87a1d000066400000000000000000000000341421143571500265310ustar00rootroot00000000000000$@ @ libtpms-0.9.3/tests/corpus-execute-command/a97a59b080c8875fb9c9bda4ca0096c045007f59000066400000000000000000000007061421143571500262510ustar00rootroot00000000000000g@,`i y%K+=7:~>S;6Wd(-q>S;6Wd(-q) `=-cejTEX6V @libtpms-0.9.3/tests/corpus-execute-command/a9c5940b0d188d4c72b911a95783a72edcb401d9000066400000000000000000000000321421143571500262300ustar00rootroot00000000000000~  libtpms-0.9.3/tests/corpus-execute-command/a9e28ed757bf809f3c6e6553ea3e33340ce26606000066400000000000000000000000261421143571500262500ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/aa38ae8b811105a599c3ec03ba93b932d97eacdc000066400000000000000000000000161421143571500265210ustar00rootroot00000000000000}libtpms-0.9.3/tests/corpus-execute-command/aa729fa03696f599e39d9fcf422561fe6720598e000066400000000000000000000001051421143571500262150ustar00rootroot00000000000000ER@@ @  libtpms-0.9.3/tests/corpus-execute-command/aac6366043070d2a98a8013546f923f1392f3b2a000066400000000000000000000000401421143571500257700ustar00rootroot00000000000000 1@ @ libtpms-0.9.3/tests/corpus-execute-command/ab30c403559698bd8e74408fe971a037b1b85a5d000066400000000000000000000000141421143571500261550ustar00rootroot00000000000000 1libtpms-0.9.3/tests/corpus-execute-command/ab72014f1e0b35971ce96bf5bf8cd789e26acc30000066400000000000000000000000671421143571500264600ustar00rootroot000000000000007@@ @  '4+ libtpms-0.9.3/tests/corpus-execute-command/ab9568619a0a007aa45f75346c282a423a092980000066400000000000000000000001111421143571500257140ustar00rootroot00000000000000I1@ @ CE? `Clibtpms-0.9.3/tests/corpus-execute-command/abeb3aae455ef4dd7aab6e2e20f7fa3c95742e1f000066400000000000000000000000571421143571500270260ustar00rootroot00000000000000/v@@:m;A<Ը{ libtpms-0.9.3/tests/corpus-execute-command/ac995a2b6d6d85ddbdd17e54679bc8ead5dac707000066400000000000000000000001111421143571500267050ustar00rootroot00000000000000I1@ @ S;6Wd(-q>S;6Wds[ |•מ) `=-cejTEX6V @libtpms-0.9.3/tests/corpus-execute-command/b10c27c1e5706903ea9225fd5eba5be8cad5ec42000066400000000000000000000000261421143571500265150ustar00rootroot00000000000000z.(libtpms-0.9.3/tests/corpus-execute-command/b17158588402677cefdea80f2375399d042efe5d000066400000000000000000000001051421143571500261750ustar00rootroot00000000000000E1@ @ Xme `libtpms-0.9.3/tests/corpus-execute-command/b18a9210b4efa52513426dc364ef7afa04e6db51000066400000000000000000000000731421143571500263520ustar00rootroot00000000000000;1@ @ % Clibtpms-0.9.3/tests/corpus-execute-command/b239cfeae01100b84a7743349d2ed3a906a3e82d000066400000000000000000000000141421143571500262710ustar00rootroot00000000000000 Qlibtpms-0.9.3/tests/corpus-execute-command/b298d3821574251490dd2758d3357a7eab96098f000066400000000000000000000000261421143571500257570ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/b32a59870e5de6aabf6a1efd0c0692adce20fe3f000066400000000000000000000000401421143571500267330ustar00rootroot00000000000000 1@ @ libtpms-0.9.3/tests/corpus-execute-command/b41e33289a209f8fbe30eec29fe2937814894653000066400000000000000000000000631421143571500261210ustar00rootroot000000000000003*@ @ G 3libtpms-0.9.3/tests/corpus-execute-command/b437766b43dca6140b1993fb78e73bf375ffb9f8000066400000000000000000000000561421143571500263450ustar00rootroot00000000000000.g#@libtpms-0.9.3/tests/corpus-execute-command/b4430e2f8fbf7649109824d22beb709d799d5290000066400000000000000000000000671421143571500261220ustar00rootroot000000000000007R@@ @  @e!2 ^q??? ylibtpms-0.9.3/tests/corpus-execute-command/b48503f6c7bde5fcd14076ff3b0b1c85a3a06ad7000066400000000000000000000000261421143571500265170ustar00rootroot00000000000000z@libtpms-0.9.3/tests/corpus-execute-command/b4f44e89f68fe23a9f596a578f48f914349d1c88000066400000000000000000000000261421143571500262360ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/b4fb5dda992ee74c170104dcb0ebafdb98f10bcc000066400000000000000000000000341421143571500270120ustar00rootroot000000000000000@ @ libtpms-0.9.3/tests/corpus-execute-command/b5807c4547c45236a4c2a136a04133ed21edc641000066400000000000000000000000121421143571500260340ustar00rootroot00000000000000 Olibtpms-0.9.3/tests/corpus-execute-command/b5be9ded44bae5125d2bdb6c934f41316b34334c000066400000000000000000000000141421143571500264310ustar00rootroot00000000000000 libtpms-0.9.3/tests/corpus-execute-command/b5fa7ed1f125641860de44094f20885690931f67000066400000000000000000000000261421143571500257510ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/b68ab523d2f5fdd12ff49e92f1b8287df167a828000066400000000000000000000000531421143571500264160ustar00rootroot00000000000000+v@@ADECNP6;1ܗYlibtpms-0.9.3/tests/corpus-execute-command/b68e48af1a46dd14b84085cc2e0bdba744264af5000066400000000000000000000001111421143571500264350ustar00rootroot00000000000000I1@ @ \E( `Clibtpms-0.9.3/tests/corpus-execute-command/b6fc917641ee55c60f707cc485eb23c642a42487000066400000000000000000000000261421143571500261630ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/b72c2e00ba27731b0dd95738fd27fca392f14bf7000066400000000000000000000000261421143571500263640ustar00rootroot00000000000000zzlibtpms-0.9.3/tests/corpus-execute-command/b735108a58ae9d8db81751994258ce92a55dbc56000066400000000000000000000001271421143571500262010ustar00rootroot00000000000000W<@ @ ibj#9(\3묗%p`6NDO !Xlibtpms-0.9.3/tests/corpus-execute-command/b76b332fb267a9bb8d76b47a124dbfc064ceee75000066400000000000000000000003761421143571500265440ustar00rootroot00000000000000a @0$=)?ws 0wX7t(IyGiɪeܻ#Y,ƖTA/ue7t(IsG(B+libtpms-0.9.3/tests/corpus-execute-command/b7a2b474134f41b0c4b1eec9f9874e2ab9233ef0000066400000000000000000000000371421143571500263650ustar00rootroot00000000000000?@ @ libtpms-0.9.3/tests/corpus-execute-command/b80a48961e6bd659b33c09d9890e52778bae8501000066400000000000000000000000261421143571500261170ustar00rootroot00000000000000%@ libtpms-0.9.3/tests/corpus-execute-command/b84f97d3fc32256ee9aa538fdcbdcf89adc30d30000066400000000000000000000000261421143571500267030ustar00rootroot00000000000000v@ zlibtpms-0.9.3/tests/corpus-execute-command/b883840bba54e55806487cc03c98d199ee308ed3000066400000000000000000000000261421143571500261750ustar00rootroot00000000000000z/libtpms-0.9.3/tests/corpus-execute-command/b8bbcd94b60f836323a24cebc19dc3976b086ae0000066400000000000000000000000621421143571500264460ustar00rootroot000000000000002}@ @ libtpms-0.9.3/tests/corpus-execute-command/b8ef1fd924ad12b60de930aa871b70aa18a47cf7000066400000000000000000000000141421143571500265140ustar00rootroot00000000000000 ilibtpms-0.9.3/tests/corpus-execute-command/b93937b68b4bca4e71197642a9e2cb7cb3a9a1ea000066400000000000000000000000671421143571500264600ustar00rootroot000000000000007X@ @  XmXemN8libtpms-0.9.3/tests/corpus-execute-command/b96472837ada1651de5964e6fb79e058fc8d09f1000066400000000000000000000007061421143571500262740ustar00rootroot00000000000000g@,`i y%K+=7:~"9Z6> \z kO AeK ]ҔcJ ";{kG v~E# A3PZȵWAϫad2ɚſ`sd>S;6Wb(-qvǔSã""("{v3jؐMl'#rƙ$86 nyƁ)&8.t3K1@%TYb]ijfQjl7ʷp=V]$ *A&ʯvvp/1O#I hW%7F޴^d2#+;ݭ|z *@@?FW݉;dLW[ |•מ) `=-ejTEX6V @libtpms-0.9.3/tests/corpus-execute-command/ba15de5a89ca512441de9f90196c650ddada1878000066400000000000000000000000141421143571500263710ustar00rootroot00000000000000 hlibtpms-0.9.3/tests/corpus-execute-command/ba3d9a018df87e290ec09bc4566228154577f060000066400000000000000000000000321421143571500260740ustar00rootroot00000000000000a @libtpms-0.9.3/tests/corpus-execute-command/ba60951dd3b814e4949a66eda2d81fa4ddff4ccf000066400000000000000000000000531421143571500266770ustar00rootroot00000000000000+v@;!!>R:[,VQIlibtpms-0.9.3/tests/corpus-execute-command/ba65f5d70b9d2e6fd3c67a24ab691c1eb7409bf8000066400000000000000000000002461421143571500265430ustar00rootroot00000000000000g<#@,`i y%K+=7:~ rEe7.r%fɠX# )pcF$QԆW:t59'rN ij"octP<3$'qT:@libtpms-0.9.3/tests/corpus-execute-command/ba800105fc85c6f9690ecf4c3651da31452d7b37000066400000000000000000000000731421143571500262300ustar00rootroot00000000000000;1@ @ % Clibtpms-0.9.3/tests/corpus-execute-command/baaafb2a92f6511e3b3d96692b935276d5f1177d000066400000000000000000000001051421143571500263130ustar00rootroot00000000000000E1@ @ Xme `libtpms-0.9.3/tests/corpus-execute-command/bac946269907b72380fe25209722cd6069cf926c000066400000000000000000000000351421143571500260320ustar00rootroot00000000000000< @ libtpms-0.9.3/tests/corpus-execute-command/baf84ace9997a10be8aeeb7c55a624a20862312d000066400000000000000000000000141421143571500264420ustar00rootroot00000000000000 66Dlibtpms-0.9.3/tests/corpus-execute-command/bb0df6afba9701c5dc7c9a2256e9bf92caa544ad000066400000000000000000000000671421143571500267470ustar00rootroot000000000000007R@@ @  @e!2 ^q??? ylibtpms-0.9.3/tests/corpus-execute-command/bb56ea248a943b44986a7f7078e4788a4b85ea98000066400000000000000000000000261421143571500262150ustar00rootroot00000000000000B libtpms-0.9.3/tests/corpus-execute-command/bbbe58d72e718296a4b18c72e77c54b15d92c184000066400000000000000000000007061421143571500262530ustar00rootroot00000000000000g@,`i y%K+=7:~@s[ @libtpms-0.9.3/tests/corpus-execute-command/bc0297bc4fbff36b83a32dc89b83f7131910ad53000066400000000000000000000007061421143571500263740ustar00rootroot00000000000000g@,`i y%K+=7:~"9Z6> \z kO AeK ]ҔcJ ";{kG v~E# A3PZȵWAϫad2ɚſ`sd>S;6Wb(-qvǔSã""("{v3jؐMl'#rƙ$86 nyƁ)&8.t3K1@%TYb]ijfQjl7ʷp=V]$ *A&ʯvvp/1O#I hW%7F޴^d2#+;ݭ|z *@@?FW݉;dLW[ |•מ) `=-ejTEX6V @libtpms-0.9.3/tests/corpus-execute-command/bcb6dfaf0671a9be9d60d30104ed8d9089988b63000066400000000000000000000002461421143571500264140ustar00rootroot00000000000000g<#@,`i y%K+=7:~ X# )pcF$QԆW:t59'rN ij"octP<3$'qT:@libtpms-0.9.3/tests/corpus-execute-command/bcc34a668106d92e29cce5bb97ea5d87607ceda7000066400000000000000000000000321421143571500265430ustar00rootroot00000000000000g!(%A!Blibtpms-0.9.3/tests/corpus-execute-command/bcf235337049a82422eb06cec7c987a0e3cd791c000066400000000000000000000026461421143571500263230ustar00rootroot00000000000000a@@ 1?籄ۘzɷ_0W \ ڱTOf?slm bLح\̪m2AtÊ~}P.GM@D@F¢@W {F"88@ӯ)՚dc>3mXqT<6\ܡj˅:88#Q~Xnn{i񁷜iD1,%i*R㶖C| FX 7<PMpzY ,b%WŶ$ vPW1tE}3ڨ L_A/c(Jw/Vxr%:uY>~y>ap[3LcFX3~Io{6@\̤fs沢\ 5i7oDc|qSIOSհ4,+m+,@3>7mV)J*@4VDD =H2E{r{SYRR+Ij˼ sS r%&$rs7x\2h:k=vlH% #y8]uP:+MW5 (f%3`d{R@쫱!ZR -n4ցEEi9[X㒶:E?aˈjES{v9۔u:g=6k @ڲ)AnM3mwux[ /ʣ&^Ɍ/SWoEM&(EC BndtKCn謊_3]5ޒ~,h:7PIPꤒPC<I$|>|,]Py @|Ԝ)-m3 ȕcAW2NMhX.EmHID4~%e/ۘ%|~ـ뜮Ì8;(]Z%9 @ libtpms-0.9.3/tests/corpus-execute-command/bddbe097a67d8bd4476798f80ec4e8bae85123e7000066400000000000000000000000261421143571500265050ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/be209b00e21d8b6d6d9a2ad8d3d6593af6d55cc2000066400000000000000000000000241421143571500265230ustar00rootroot00000000000000I-1ٿlibtpms-0.9.3/tests/corpus-execute-command/be8a8e749766f5d4c4c24cd414554cc5a92585ad000066400000000000000000000000371421143571500263360ustar00rootroot00000000000000 @ libtpms-0.9.3/tests/corpus-execute-command/bebacefed32270d27c24f12fa832bc8069d1ec8c000066400000000000000000000000141421143571500266540ustar00rootroot00000000000000 qlibtpms-0.9.3/tests/corpus-execute-command/bef054fefd68685fb42da982d7cd94a5cf4b73d2000066400000000000000000000000261421143571500266370ustar00rootroot00000000000000g~#libtpms-0.9.3/tests/corpus-execute-command/bf0192d8e1225739741a7572ae1204180021cd91000066400000000000000000000007061421143571500256340ustar00rootroot00000000000000g@`i y%K+=:~"9cJ ";{kG v|}# A1PZȵW'A:ϫad2ɐſ`sdW'A:ϫad4ɐſ`ds>S;6Wb(-q""("{v0jؐMl'#rƙ$86 n#rcƙ$86 nyƁ)5&ҋ̮1@%TYb]ijfQjl3ʷp=ZFjCAeK ]ҔcJ ";{kG v~E# A3PZȵWAϫad4ɚſ`݉;dLW[ |•מ) `=-ejTEX6V @libtpms-0.9.3/tests/corpus-execute-command/bf22e5d67b02fd22d89d6441d13bfdf9da621b58000066400000000000000000000000261421143571500264520ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/bf3a2599ca3562b0fcf58dac758e0558ce970f25000066400000000000000000000000261421143571500264100ustar00rootroot00000000000000aAlibtpms-0.9.3/tests/corpus-execute-command/bf4778c06a0528b79fc90803f57eb484871c0a2b000066400000000000000000000000401421143571500261600ustar00rootroot00000000000000 '@ @ libtpms-0.9.3/tests/corpus-execute-command/bf7c6584958ecb58b8f0941e68df653228a2ac3c000066400000000000000000000000561421143571500263440ustar00rootroot00000000000000.g#@ libtpms-0.9.3/tests/corpus-execute-command/bff95e35bb240c0afa8e6d5423cfd006dd8e54b7000066400000000000000000000000261421143571500266060ustar00rootroot00000000000000z;libtpms-0.9.3/tests/corpus-execute-command/c00b1f9237b5b18f9f5b4aae388208d592619987000066400000000000000000000000331421143571500261120ustar00rootroot00000000000000 @ libtpms-0.9.3/tests/corpus-execute-command/c0e9a3fd051cd35e38abb93a87a0fbc3fcd02cb7000066400000000000000000000000521421143571500267270ustar00rootroot00000000000000*B#@libtpms-0.9.3/tests/corpus-execute-command/c0f5f960159e9117c35416a7b3549f190773d543000066400000000000000000000000401421143571500256640ustar00rootroot00000000000000 !@ @ @ libtpms-0.9.3/tests/corpus-execute-command/c11ddabc4a0e7ca259c2372030718c761d2ccb0c000066400000000000000000000000431421143571500264060ustar00rootroot00000000000000#@ @ *libtpms-0.9.3/tests/corpus-execute-command/c17af2fab4d3879a828b8b8310ea14efc6cefaeb000066400000000000000000000001111421143571500267440ustar00rootroot00000000000000I1@ @ \E( `Clibtpms-0.9.3/tests/corpus-execute-command/c1aa65a911070110c37c6d4ee51156033af7da5f000066400000000000000000000000261421143571500261750ustar00rootroot00000000000000HJlibtpms-0.9.3/tests/corpus-execute-command/c1baeac9da0c6c8a8b7affb160fd02a510093b7a000066400000000000000000000001111421143571500267070ustar00rootroot00000000000000I@ @ * Xme `Clibtpms-0.9.3/tests/corpus-execute-command/c2264eb0ee1c0bf267898225ab646e5d1836ca2f000066400000000000000000000000261421143571500263070ustar00rootroot00000000000000%libtpms-0.9.3/tests/corpus-execute-command/c30ea0869f973c4ea98d557374a58a2c31bbdaad000066400000000000000000000000161421143571500264530ustar00rootroot00000000000000 libtpms-0.9.3/tests/corpus-execute-command/c36aa74b7faaee98e60bccb67c6a74a667468fa5000066400000000000000000000000141421143571500266240ustar00rootroot00000000000000 ! libtpms-0.9.3/tests/corpus-execute-command/c3806328cc5d3fc584e415d02f403c840ed3ee8d000066400000000000000000000000671421143571500263160ustar00rootroot000000000000007X@ @  XmXemN8libtpms-0.9.3/tests/corpus-execute-command/c388c1b999ac92429b13c8b6a301f6d596acd2c3000066400000000000000000000000161421143571500263170ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/c39b0e9603d0dca595d86a15c07285815f00222d000066400000000000000000000001311421143571500260550ustar00rootroot00000000000000Y<@ @ Xme`Cv ˆJI}libtpms-0.9.3/tests/corpus-execute-command/c419aff393145efa4073f9ccbff585e65e0b3e0b000066400000000000000000000000201421143571500265320ustar00rootroot000000000000003@ @libtpms-0.9.3/tests/corpus-execute-command/c42c350c87426b524cf283bf1731d19e31fa4d48000066400000000000000000000020351421143571500261460ustar00rootroot00000000000000< @ =P`uB2ẇPJ0IhBJ> ^e9V>fsEu#(l閲cH$T-\4׃¢WT+MK t1}Cl`DּP"ƺ1F!YNoԛ {- EEJeFoq ?!y͟^sY Zu{a-Χ }-TŜݞ0VAh%P^m^ xPlibtpms-0.9.3/tests/corpus-execute-command/c43113e5072996b7cff3daacff60df1084ee446f000066400000000000000000000000341421143571500264550ustar00rootroot000000000000009@ @ libtpms-0.9.3/tests/corpus-execute-command/c49bbb3d89557a1e6cc8a96bce4ebec460fe2592000066400000000000000000000000351421143571500266270ustar00rootroot00000000000000@@ @  libtpms-0.9.3/tests/corpus-execute-command/c4a65e3407df7d508902d563ce1ac84f06e22c31000066400000000000000000000000261421143571500262230ustar00rootroot00000000000000z@*libtpms-0.9.3/tests/corpus-execute-command/c4b8134299a7e7e86d2ca0c6a09d5238bb0f4e33000066400000000000000000000000671421143571500263160ustar00rootroot000000000000007R@@ @ @e!2 ^q??? ylibtpms-0.9.3/tests/corpus-execute-command/c4c8ff08231b9f70646fad87c791a2c86bea2b0c000066400000000000000000000001051421143571500264540ustar00rootroot00000000000000E1@ @ im:e `libtpms-0.9.3/tests/corpus-execute-command/c51792c809770eadcae5fde53bfcec748925074c000066400000000000000000000001521421143571500264710ustar00rootroot00000000000000jgX#  D>FpcQ$ԆW:t$1'rN i"oct̤P<5$F'qT:@libtpms-0.9.3/tests/corpus-execute-command/c522494dfc701e361935ac6c4ad5d0bca97dc927000066400000000000000000000000551421143571500263730ustar00rootroot00000000000000-*@ @ @libtpms-0.9.3/tests/corpus-execute-command/c565c10ab9683250c9918335862e49a1106d0c1b000066400000000000000000000000151421143571500257200ustar00rootroot00000000000000 =*libtpms-0.9.3/tests/corpus-execute-command/c56b3da0e904db582c2a8ce236c65eaff39a3476000066400000000000000000000000161421143571500264510ustar00rootroot00000000000000#libtpms-0.9.3/tests/corpus-execute-command/c56b666adb267a3265f40244b6e8aee63e00baab000066400000000000000000000000571421143571500264360ustar00rootroot00000000000000/v@@ :m;A=>Ը:{libtpms-0.9.3/tests/corpus-execute-command/c586b425266e64bdd868e574a60e0982ae1308f1000066400000000000000000000001051421143571500261040ustar00rootroot00000000000000E1@ @ Xme `libtpms-0.9.3/tests/corpus-execute-command/c5c5a63c1495e916e04539c69e140052a5d3d85e000066400000000000000000000000261421143571500260760ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/c5e822cd13db5507aad8b07e7d162d6b3fe46bbd000066400000000000000000000000141421143571500265750ustar00rootroot00000000000000 libtpms-0.9.3/tests/corpus-execute-command/c60ea82d96054d96aea7af038f0429cad9933006000066400000000000000000000000371421143571500262360ustar00rootroot00000000000000}@ @ @) @)libtpms-0.9.3/tests/corpus-execute-command/c63e4e51cc79d88813ecf3f51fc5efa59636861d000066400000000000000000000001111421143571500264210ustar00rootroot00000000000000I@@ @  @@  I@@ libtpms-0.9.3/tests/corpus-execute-command/c72106e189c219083f01d92289877bb4e69e6929000066400000000000000000000000431421143571500257060ustar00rootroot00000000000000#@@ @  libtpms-0.9.3/tests/corpus-execute-command/c73773b80eee07efecc715064d0c9cf486229f81000066400000000000000000000000201421143571500263250ustar00rootroot00000000000000#libtpms-0.9.3/tests/corpus-execute-command/c74c63a4697ebdde735cfcee8f329dc2093b4d23000066400000000000000000000001111421143571500265420ustar00rootroot00000000000000I1@ @ CE? `Clibtpms-0.9.3/tests/corpus-execute-command/c77c644f4105cd9e0be0c764cea76a97e8b0d1c9000066400000000000000000000000161421143571500264610ustar00rootroot0000000000000076 libtpms-0.9.3/tests/corpus-execute-command/c77f7cdd808b836524e60c8013dc02352d8ff5bf000066400000000000000000000000631421143571500263230ustar00rootroot000000000000003Q@ @  libtpms-0.9.3/tests/corpus-execute-command/c78ebd3c85a39a596d9f5cfd2b8d240bc1b9c125000066400000000000000000000000011421143571500265330ustar00rootroot00000000000000libtpms-0.9.3/tests/corpus-execute-command/c81036715c21bc964915f56c061eb92e97d8100c000066400000000000000000000001001421143571500260030ustar00rootroot00000000000000@ @S@@(@libtpms-0.9.3/tests/corpus-execute-command/c8c2b74622e1ad8bc0dbc564e0fa413558e37f6f000066400000000000000000000000621421143571500264470ustar00rootroot000000000000002"@ @  libtpms-0.9.3/tests/corpus-execute-command/c8d7722d7a81a2a41ee88f2ca75acaf19baaac53000066400000000000000000000000261421143571500266570ustar00rootroot00000000000000g%libtpms-0.9.3/tests/corpus-execute-command/c8ea4f0df2f3fa71095a9db19ecbcd3488b7ba62000066400000000000000000000000401421143571500266700ustar00rootroot00000000000000 2@ @ libtpms-0.9.3/tests/corpus-execute-command/c91af251de290f0094fc9f8da6f51f626c7f95e3000066400000000000000000000000351421143571500264150ustar00rootroot00000000000000R@@) libtpms-0.9.3/tests/corpus-execute-command/c929a3dd31af814526310074f0b8189240cd1420000066400000000000000000000000321421143571500257030ustar00rootroot00000000000000 libtpms-0.9.3/tests/corpus-execute-command/c9b3fecee546ff3b82f1e7b64fbb4e1a1bfc7fe8000066400000000000000000000000261421143571500271260ustar00rootroot00000000000000B !libtpms-0.9.3/tests/corpus-execute-command/c9bf95aac998e7065af0082b35abeb255f07d00e000066400000000000000000000000161421143571500264470ustar00rootroot00000000000000`libtpms-0.9.3/tests/corpus-execute-command/c9cfa9363aba5a7348fc86a23c4d105e554f837d000066400000000000000000000000261421143571500264010ustar00rootroot00000000000000z*libtpms-0.9.3/tests/corpus-execute-command/c9fbcb758ba2956b10769dff28b91beeb7563b71000066400000000000000000000000261421143571500264730ustar00rootroot00000000000000zzlibtpms-0.9.3/tests/corpus-execute-command/ca0e0e76149ce213490a67bca9d84dee2fe03f5f000066400000000000000000000001111421143571500265240ustar00rootroot00000000000000I1@ @ \E( `Clibtpms-0.9.3/tests/corpus-execute-command/ca552eb06c32cec5fbecdcea8a5a0f19cc7863ef000066400000000000000000000000261421143571500271030ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/ca8e266512e3de79657e1f5ee41ed90a85c3ab2a000066400000000000000000000000551421143571500264610ustar00rootroot00000000000000-*@ @ N libtpms-0.9.3/tests/corpus-execute-command/caac53b052f1fab51f4cfef425ed2a00a4867257000066400000000000000000000001051421143571500265030ustar00rootroot00000000000000E1@ @ Sme`libtpms-0.9.3/tests/corpus-execute-command/cb52177ddaeffe7ddaf6b0154d0e433b5c3bf71c000066400000000000000000000000241421143571500267340ustar00rootroot00000000000000alibtpms-0.9.3/tests/corpus-execute-command/cb9845edd146b103ec48be60fc24a9f97425d9d2000066400000000000000000000000351421143571500264040ustar00rootroot00000000000000g@(! libtpms-0.9.3/tests/corpus-execute-command/cbd228635f8b8321e35b2085a8428808a000c779000066400000000000000000000000271421143571500257330ustar00rootroot00000000000000YZ:libtpms-0.9.3/tests/corpus-execute-command/cc476f31a8870e6d64dc9febf5bd9ba9f5d973c3000066400000000000000000000004521421143571500266510ustar00rootroot00000000000000*gлWyO͈V`.+qNx3Ur[n @i(p0|eC> BndjKCn謊_3]5ޒ`WL8ӗũ7PIP[ms<I$|>|,]Py @|Ԝ9)-m5 ȕcAW2NMhX.EmHI:D4~%e/ۘ%|~ـ뜮L8;(]Z%9 @libtpms-0.9.3/tests/corpus-execute-command/cc6c0a58127ec37f450944a0cdb83ce5b023eb27000066400000000000000000000000321421143571500263500ustar00rootroot00000000000000~  libtpms-0.9.3/tests/corpus-execute-command/cc7ea476999ce8915614230ef446402f6b08663e000066400000000000000000000000421421143571500260360ustar00rootroot00000000000000"}qZ2JI @libtpms-0.9.3/tests/corpus-execute-command/cc9fa0b0dc106da200d40fae8c53649ae337c6e3000066400000000000000000000000161421143571500265030ustar00rootroot00000000000000libtpms-0.9.3/tests/corpus-execute-command/ccc350faab041e20e3460857d8a76a1911e0f2f8000066400000000000000000000000261421143571500262700ustar00rootroot00000000000000z=libtpms-0.9.3/tests/corpus-execute-command/ccd020caad1f2fce6619d76fe98daa5bf1fa6103000066400000000000000000000000571421143571500267410ustar00rootroot00000000000000/v@:m;A=>Ը:{libtpms-0.9.3/tests/corpus-execute-command/cd234bc40ffccede0bd67539f4e45690ffc9bae8000066400000000000000000000000261421143571500267650ustar00rootroot00000000000000>libtpms-0.9.3/tests/corpus-execute-command/cd4217708673d871d8f2da3904b363cd53bd36e0000066400000000000000000000002461421143571500261570ustar00rootroot00000000000000g<#@,`i y%K+=7:~ X# )pcF$QԆW:t59'rN ij"octP<3$'qT:@libtpms-0.9.3/tests/corpus-execute-command/cd4950c35aea2601164d4c0fe6f728c6e85e5ec9000066400000000000000000000000351421143571500264010ustar00rootroot00000000000000:@ @ libtpms-0.9.3/tests/corpus-execute-command/cd88ad16002277fcf6fe7c170b86fc2fa6c1458e000066400000000000000000000000261421143571500264620ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/cdd2a4b671eb26558b49a534d2b9cedc1fdfd63b000066400000000000000000000000401421143571500266640ustar00rootroot00000000000000 .@ @ libtpms-0.9.3/tests/corpus-execute-command/ce97e79875acd91184926cbc213c70b3f31a3d10000066400000000000000000000000321421143571500262270ustar00rootroot00000000000000Flibtpms-0.9.3/tests/corpus-execute-command/ceca1b24808d01e319549f134f3f3d397c6a95b1000066400000000000000000000001111421143571500262240ustar00rootroot00000000000000I1@ @ CE? `Clibtpms-0.9.3/tests/corpus-execute-command/cee3fce39a124cf71adb151070eadef1421ae162000066400000000000000000000007061421143571500265620ustar00rootroot00000000000000g@,`i y%K+=7:~@W[ |•מ) `=-eϫad<ɚſ`sd>S;6Wb(-qdW[ |•מ) `=-ejT6V @libtpms-0.9.3/tests/corpus-execute-command/cf0ea92e26732be46001bb17e164d8b5a0169e37000066400000000000000000000000261421143571500262150ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/cf461afb3dd5818d72acf81a5805613c09cd81a0000066400000000000000000000001051421143571500263570ustar00rootroot00000000000000E1@ @ Xme `libtpms-0.9.3/tests/corpus-execute-command/cf8082a0f697ec193c2ae0af9a499cd8eed78fb4000066400000000000000000000007061421143571500266450ustar00rootroot00000000000000g@,`i y%K+=7:~"9Z6> \z kO AeK ]ҔcJ ";{kG v~E# A3PZȵWAϫad2ɚſ`sd>S;6Wb(-qvǔSã""("{v3jؐMl'#rƙ$86 nyƁ)&8.t3K1@%TYb]ijfQjl7ʷp=V]$ *A&ʯvvp/1O#I hW%7F޴^d2#+;ݭ|z *@@?FW݉;dLW[ |•מ) `=-ejTEX6V @libtpms-0.9.3/tests/corpus-execute-command/cf995f436443882791f0e33d85b97abc224128cd000066400000000000000000000000161421143571500261150ustar00rootroot00000000000000 @ libtpms-0.9.3/tests/corpus-execute-command/cfa80dfc78af1855d41e16d7869f54ae6f63146c000066400000000000000000000000261421143571500264200ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/cfa9cd6f1ff61d9582fc6aaf4f7ac77b045e2e7a000066400000000000000000000001111421143571500267630ustar00rootroot00000000000000I1@ @ CE? `Clibtpms-0.9.3/tests/corpus-execute-command/cfee3dac8d7bab0997ed52bf9e406ecc7e45dd4b000066400000000000000000000000141421143571500271230ustar00rootroot00000000000000 Blibtpms-0.9.3/tests/corpus-execute-command/d071dceafe7c0041fc74216f459ec75a3ef6481f000066400000000000000000000001051421143571500264530ustar00rootroot00000000000000E1@ @ me `libtpms-0.9.3/tests/corpus-execute-command/d07827d4124dd54518618b33b1bc06d04a894ce4000066400000000000000000000000341421143571500260610ustar00rootroot000000000000005@:* libtpms-0.9.3/tests/corpus-execute-command/d0cf6efbd1ad757b0a02c57decce4abf662e6a56000066400000000000000000000001051421143571500270160ustar00rootroot00000000000000E1@ @ Xm:e `libtpms-0.9.3/tests/corpus-execute-command/d1450d033c2975e8d486e37d26350cf1fff4f163000066400000000000000000000001121421143571500261550ustar00rootroot00000000000000JbJ{ JHH ˆ˧Y]YX]X*eX mmeˆ˧libtpms-0.9.3/tests/corpus-execute-command/d1a4b3e01f2451ddb2bf28b649601221acd7e5a5000066400000000000000000000000261421143571500263360ustar00rootroot00000000000000@libtpms-0.9.3/tests/corpus-execute-command/d1b98228857cc2c27bedbee16935da27f59e6a9f000066400000000000000000000001111421143571500264740ustar00rootroot00000000000000I1@ @ CE- `Clibtpms-0.9.3/tests/corpus-execute-command/d1f1910788e269c27ab556f509e51e0b06cf84d1000066400000000000000000000000261421143571500261610ustar00rootroot00000000000000z@libtpms-0.9.3/tests/corpus-execute-command/d20f5e8345c03001b8f90de7b036f160ecdce2e9000066400000000000000000000000141421143571500263540ustar00rootroot00000000000000 .libtpms-0.9.3/tests/corpus-execute-command/d3a20b04284b851e9c7483d640b00505771e658e000066400000000000000000000000241421143571500257220ustar00rootroot00000000000000@libtpms-0.9.3/tests/corpus-execute-command/d3a237d3910e60a6f2b29bc02c3c3f4956cd7f40000066400000000000000000000000131421143571500262720ustar00rootroot00000000000000 )libtpms-0.9.3/tests/corpus-execute-command/d3baa889e0701c87ef7d14c1f5dd9756866fdf9e000066400000000000000000000000161421143571500265120ustar00rootroot00000000000000Jlibtpms-0.9.3/tests/corpus-execute-command/d3e228e2829baec827fbd569fd10dd559c048591000066400000000000000000000001111421143571500263260ustar00rootroot00000000000000I1@ @ CwE? `Clibtpms-0.9.3/tests/corpus-execute-command/d3f99f10e130653bcf48684fa3ea04513c7f27b8000066400000000000000000000000251421143571500262360ustar00rootroot00000000000000M@ libtpms-0.9.3/tests/corpus-execute-command/d42bc037843fb3d26293870f8002415a660090f0000066400000000000000000000000401421143571500256270ustar00rootroot00000000000000 !@ @ @ libtpms-0.9.3/tests/corpus-execute-command/d4f49adbd49a440993248f38b6cfbd859a90e8f5000066400000000000000000000000351421143571500264300ustar00rootroot00000000000000+)@)@ libtpms-0.9.3/tests/corpus-execute-command/d52bd9a816555ad0ca4ce6eccc7daf8212af8d77000066400000000000000000000002461421143571500266770ustar00rootroot00000000000000g<#@,`i y%K=7:~ hqEe7r%fɠX#  $'qT :@libtpms-0.9.3/tests/corpus-execute-command/d554864c6afec62715b253c2699c128bef76729e000066400000000000000000000000351421143571500262020ustar00rootroot00000000000000@@ @ libtpms-0.9.3/tests/corpus-execute-command/d592f0df818cc98be2bafbe63e4719b130250729000066400000000000000000000007061421143571500263250ustar00rootroot00000000000000g@,`i y%K+=7:~"9Z6> \z kO AeK ҔcJ ";{kG v~E# A3PZȵWAϫad<ɚſ`sd>S;6Wb(-q*A&ʯvvp/1O#I hW%7F޴^d2#+;ݭ|z *@@?FW݉;dLW[ |•מ) `=-ejTEX6V @libtpms-0.9.3/tests/corpus-execute-command/d5e7a9bfeb125f4cdbdb80c3cb0fb3623f9aa744000066400000000000000000000001111421143571500267340ustar00rootroot00000000000000I1@ @ C? `Clibtpms-0.9.3/tests/corpus-execute-command/d60c0181fb920dd6aa228a29c46b388881563b29000066400000000000000000000000421421143571500260670ustar00rootroot00000000000000"}v ˆJI}@libtpms-0.9.3/tests/corpus-execute-command/d61459bba801408261beb3f6b2a60eaaffc16ab7000066400000000000000000000000261421143571500265030ustar00rootroot000000000000003@ libtpms-0.9.3/tests/corpus-execute-command/d632a338e0d67fa60fa9b13307786758f3665db7000066400000000000000000000000261421143571500261120ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/d6f59b637ca675128c2c6a54771daf213933b6c6000066400000000000000000000000141421143571500261570ustar00rootroot00000000000000 Jlibtpms-0.9.3/tests/corpus-execute-command/d704fe71a208f7fe7c08ab5813c758ef09e1bb75000066400000000000000000000000261421143571500264050ustar00rootroot00000000000000~>libtpms-0.9.3/tests/corpus-execute-command/d7813879a62566656ecc6d0bff434f494b54b312000066400000000000000000000000201421143571500261050ustar00rootroot00000000000000 libtpms-0.9.3/tests/corpus-execute-command/d7dea4d610192294afe48d13d530beaf3d9d9b8a000066400000000000000000000000261421143571500265320ustar00rootroot00000000000000z@!!libtpms-0.9.3/tests/corpus-execute-command/d81680fb8951dcdd9dda47399de8bdb42c36290f000066400000000000000000000000261421143571500265000ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/d841850317ec6c428b87527a6bde7fe0b0281bf1000066400000000000000000000000671421143571500262370ustar00rootroot000000000000007H@ @  @e!2 ^q??? ylibtpms-0.9.3/tests/corpus-execute-command/d94e476459cdbf606dcfddac8cad7d93cc6af48c000066400000000000000000000001111421143571500270520ustar00rootroot00000000000000I1@ @ _E( `Clibtpms-0.9.3/tests/corpus-execute-command/d9c62c9a76c81d2d698eafe77ba392ec2c7e7232000066400000000000000000000001271421143571500265010ustar00rootroot00000000000000W<@ @ :ibj#9(\3묗%p`6@NDO !Xlibtpms-0.9.3/tests/corpus-execute-command/d9caa2217d2461ffe52c789a252e5cb1ae018794000066400000000000000000000002461421143571500263140ustar00rootroot00000000000000g<#@,`i y%K+=7:~ X# )pcF$QԆW:t59'rN ij"octP<3$'qT:@libtpms-0.9.3/tests/corpus-execute-command/d9d161cef4fdadb20359418f94070f6c6a4f7748000066400000000000000000000000141421143571500263260ustar00rootroot00000000000000 libtpms-0.9.3/tests/corpus-execute-command/d9df497d81f288bb5996a419dfd2f2513896ba68000066400000000000000000000002461421143571500263060ustar00rootroot00000000000000g<#@,`i y%K+=7:~ X#X# )pcF$QԆW:t59'rN ij"octP<3$'qT:@libtpms-0.9.3/tests/corpus-execute-command/d9ff3b54c6d14e698f9c3797fb7ba0c09d8a48f9000066400000000000000000000001111421143571500265130ustar00rootroot00000000000000I1@ @ \cE, `Clibtpms-0.9.3/tests/corpus-execute-command/da172505f64284aa10240e5898fedadbad51ee85000066400000000000000000000000241421143571500263620ustar00rootroot00000000000000;libtpms-0.9.3/tests/corpus-execute-command/da35507170381bb596e7c757abe7d40f560f4cf7000066400000000000000000000000121421143571500262350ustar00rootroot00000000000000 glibtpms-0.9.3/tests/corpus-execute-command/da3f59b4bc951f2d2a0c61c413a4bba2b52b2e6e000066400000000000000000000000631421143571500265550ustar00rootroot000000000000003*@ @ GDlibtpms-0.9.3/tests/corpus-execute-command/da9d9fec3810fe65b3a7f163cc8742ddb59ab06c000066400000000000000000000003761421143571500266300ustar00rootroot00000000000000a @ 0$=)?ws 0wX7t(IyGiɪeܻ#Y,ƖTA/ue7t(IsG(B+libtpms-0.9.3/tests/corpus-execute-command/db2096d7d005df5a02ba8ecc2f78dfef2af82eea000066400000000000000000000000621421143571500270260ustar00rootroot000000000000002g@ JJ libtpms-0.9.3/tests/corpus-execute-command/db71b452ee521ba89defadecd6ca18755c1198da000066400000000000000000000000671421143571500266760ustar00rootroot000000000000007)@ @ (libtpms-0.9.3/tests/corpus-execute-command/db98bcb595c19620ce7d2dcf56a017a3894cdf50000066400000000000000000000004521421143571500264630ustar00rootroot00000000000000*g лyO͈V`.+qNx2Ur[n @i(p5|eC. BndtKCn謊_3]5ޒ~,h:7PIPꤒPC<I$|>|,]Py @|Ԝ)-m5 ȕcA|>|,]Py @|Ԝ)-m6ۘ%|~ـ뜮L8;(]Z%9 @ libtpms-0.9.3/tests/corpus-execute-command/dc2e18bbef8c631425862bb4e895bcdbf2111d17000066400000000000000000000000431421143571500264430ustar00rootroot00000000000000#@@ @  @libtpms-0.9.3/tests/corpus-execute-command/dc4655912c3df9a3f29e84bc7b0c96ba58a99e46000066400000000000000000000002461421143571500264250ustar00rootroot00000000000000g<#@,`i y%K=7:~ hqEe7r%fɠX# N $'qT :@libtpms-0.9.3/tests/corpus-execute-command/dc5a5b5b82537cc568fbd4365d6bd9396a48a47e000066400000000000000000000000531421143571500264150ustar00rootroot00000000000000+v@@!>R:[,VQIlibtpms-0.9.3/tests/corpus-execute-command/dc9f79ad73ee57f2285a479e2a011428cae50745000066400000000000000000000000141421143571500262430ustar00rootroot00000000000000  libtpms-0.9.3/tests/corpus-execute-command/dd249a9a8171ce6be7a23a5572c9b0152bfaddb4000066400000000000000000000000531421143571500265170ustar00rootroot00000000000000+v@@libtpms-0.9.3/tests/corpus-execute-command/dd33135be31aeb553803b01bb70fd302343b2d3b000066400000000000000000000000141421143571500262340ustar00rootroot00000000000000 clibtpms-0.9.3/tests/corpus-execute-command/dd597b203804c978f3930c62b65ff8f366e8ce43000066400000000000000000000000401421143571500262020ustar00rootroot00000000000000 !@ @ libtpms-0.9.3/tests/corpus-execute-command/dd5a0141ed49741662e535ef62755364724b7024000066400000000000000000000000371421143571500256560ustar00rootroot00000000000000)@ @  libtpms-0.9.3/tests/corpus-execute-command/ddd7cbb405895b451bf0ac89cfe9a2ac3cb549cb000066400000000000000000000001111421143571500267430ustar00rootroot00000000000000Iv@ *@*( Xe(m'` C`libtpms-0.9.3/tests/corpus-execute-command/de712ebd023a518a3b05ad7fd5047b6094f06096000066400000000000000000000000261421143571500262140ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/de88578fe679f0e3babe54c640d6a1fab3a44a9f000066400000000000000000000001311421143571500266230ustar00rootroot00000000000000Y< @ < < @ )( <@ @%!me libtpms-0.9.3/tests/corpus-execute-command/de981d5aa59c132ed88215bb848803b7826bb5cf000066400000000000000000000000341421143571500263240ustar00rootroot00000000000000(@ @ libtpms-0.9.3/tests/corpus-execute-command/deb0d3301556179e9d9f8f16285f83c988628a0f000066400000000000000000000002461421143571500261350ustar00rootroot00000000000000g<#@,`i y%K+=7:~ qEe7.r%fɠX# )pcF$QԆW:t59'rN ij"octP<3$'qT:@libtpms-0.9.3/tests/corpus-execute-command/ded14ea8e1bd05c96cc188a0000fbc383e51933e000066400000000000000000000000671421143571500264410ustar00rootroot000000000000007X@ @   e@ d1 libtpms-0.9.3/tests/corpus-execute-command/df037146daa4bc87a77ccfe442029160f0d80661000066400000000000000000000003761421143571500262310ustar00rootroot00000000000000a @0$=)?ws 0wX7t(IyGiɪeܻ#Y,ƖTA/ue7t(IsG(B+libtpms-0.9.3/tests/corpus-execute-command/df150f679d487c3ec709a2d700db1ff8f53656ad000066400000000000000000000001051421143571500264050ustar00rootroot00000000000000E1@ @ X:e `libtpms-0.9.3/tests/corpus-execute-command/df2397bcadb88985c521d02feb795ca7f9261cb3000066400000000000000000000001111421143571500264630ustar00rootroot00000000000000I1@ @ \E( Clibtpms-0.9.3/tests/corpus-execute-command/df3cb2207df4fe0b4a26342ba7e8521022cae857000066400000000000000000000000771421143571500263550ustar00rootroot00000000000000?v@ @ XwZe'LMN '(7libtpms-0.9.3/tests/corpus-execute-command/df3ec33f95b1c15bad0ddcb9699d53820b207a59000066400000000000000000000000401421143571500264450ustar00rootroot00000000000000 ,@ @ libtpms-0.9.3/tests/corpus-execute-command/df7c4ad08006488875a38c6bef20f7f44388791f000066400000000000000000000000151421143571500262030ustar00rootroot00000000000000 libtpms-0.9.3/tests/corpus-execute-command/df8c10cc2c28e1eba1e483d336bdb23c3743c8d8000066400000000000000000000000261421143571500265170ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/dfd703a6d4d1126efba52744ced847778e3f008a000066400000000000000000000000551421143571500264000ustar00rootroot00000000000000-*@ @ @libtpms-0.9.3/tests/corpus-execute-command/e02938095ca6851a9df89f896b818877f207c84c000066400000000000000000000000401421143571500260620ustar00rootroot00000000000000 .@ @  libtpms-0.9.3/tests/corpus-execute-command/e0edad758ea367514ff21642207e258f1ec5eec1000066400000000000000000000007061421143571500263770ustar00rootroot00000000000000g@,`i y%K+=7:~>S;6Wb(-q@libtpms-0.9.3/tests/corpus-execute-command/e0fd5948caf4a3571c7f5bc618d93b812982402b000066400000000000000000000000261421143571500262420ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/e1d914decf4a86977ff1c4ac60156903905a398b000066400000000000000000000000261421143571500262500ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/e2aa550f18ae9e9ab9e26a2ed7ff62718df5369a000066400000000000000000000000261421143571500265520ustar00rootroot00000000000000zA3libtpms-0.9.3/tests/corpus-execute-command/e2e094400022ecb4e95ebae862193b418b89caf8000066400000000000000000000007061421143571500263160ustar00rootroot00000000000000g@,`i y%K+=7:~@s[ |•מ) `=-cejTEX6V @libtpms-0.9.3/tests/corpus-execute-command/e318b6e4186a6429965fdf428a941f879d4812bd000066400000000000000000000001051421143571500261260ustar00rootroot00000000000000E1@ @ Xm:e `libtpms-0.9.3/tests/corpus-execute-command/e325072ae7ec5486ef88b6c32633cb3d77fbde3e000066400000000000000000000000261421143571500264670ustar00rootroot00000000000000z@ !!libtpms-0.9.3/tests/corpus-execute-command/e344f0da1329e3a7c605cb7819e239404adc7491000066400000000000000000000001111421143571500261420ustar00rootroot00000000000000I1@ @ Ejܬ rClibtpms-0.9.3/tests/corpus-execute-command/e35427fad4a04d0a2d720e58242e4806c378bb32000066400000000000000000000000701421143571500261310ustar00rootroot000000000000008X@ @ ;XmXemNmN8libtpms-0.9.3/tests/corpus-execute-command/e460eb1876ddf784828cf8dd69773d02db44f5fd000066400000000000000000000000261421143571500264320ustar00rootroot00000000000000(@*:;libtpms-0.9.3/tests/corpus-execute-command/e4943c7df3f385f7084d8b726fcd2a267eedbbaa000066400000000000000000000000261421143571500266300ustar00rootroot00000000000000z?libtpms-0.9.3/tests/corpus-execute-command/e4fd10d2026e884ef179a871f30c27dd439d2ce8000066400000000000000000000000261421143571500263240ustar00rootroot00000000000000B@ libtpms-0.9.3/tests/corpus-execute-command/e538a8fb4e9fd47a482e587dd6768e9e1d2963f0000066400000000000000000000007061421143571500263700ustar00rootroot00000000000000g@`i y%K+=:~"9cJ ";{kG v|}# A1PZȵW'A:ϫad2ɐſ`sdW'A:ϫad4ɐſ`ds>S;6Wb(-q ""("{v0jؐMl'#rƙ$86 n#rcƙ$86 nyƁ)5&ҋ̮1@%TYb]ijfQjl3ʷp=ZFjCAeK ]ҔcJ ";{kG v~E# A3PZȵWAϫad4ɚſ`݉;dLW[ |•מ) `=-ejTEX6V @libtpms-0.9.3/tests/corpus-execute-command/e5737f6730a6ef2ddfb8ff4fee919557a77fd914000066400000000000000000000000131421143571500265150ustar00rootroot00000000000000 Clibtpms-0.9.3/tests/corpus-execute-command/e5ddfe92f42a5c3551b13eae038e62f37cae3a66000066400000000000000000000000531421143571500265260ustar00rootroot00000000000000+v@@ ;!!>R:[,VQIlibtpms-0.9.3/tests/corpus-execute-command/e633bcf819f6935ce754901c310bddd48c7abd3f000066400000000000000000000000121421143571500264540ustar00rootroot00000000000000 $libtpms-0.9.3/tests/corpus-execute-command/e7397e9a4496583b1888af2972aa0af2a77e60b0000066400000000000000000000000141421143571500261700ustar00rootroot00000000000000 4libtpms-0.9.3/tests/corpus-execute-command/e7d53f4115a3bbd5fbfb42296d494400ffa5058e000066400000000000000000000000401421143571500263630ustar00rootroot00000000000000 &@ @ libtpms-0.9.3/tests/corpus-execute-command/e7e085c27bdc56d35cff9ffeaf528d654e81cee3000066400000000000000000000000141421143571500267200ustar00rootroot00000000000000 libtpms-0.9.3/tests/corpus-execute-command/e987696c3ed9ef057333ac807e991b73d28181fc000066400000000000000000000000241421143571500262110ustar00rootroot00000000000000~ libtpms-0.9.3/tests/corpus-execute-command/ea1c97fa21aa17cd4d0886799c41222cd55ad8ff000066400000000000000000000000261421143571500264550ustar00rootroot00000000000000z+libtpms-0.9.3/tests/corpus-execute-command/ea9c3a93ae87b5a67a273c4f519923a67b57ec91000066400000000000000000000001111421143571500263250ustar00rootroot00000000000000I1@ @ \E( `Clibtpms-0.9.3/tests/corpus-execute-command/eacb1c9c6f5455bf808ea09fe5b889617f53950b000066400000000000000000000001111421143571500264140ustar00rootroot00000000000000I1@ @ CE?  `Clibtpms-0.9.3/tests/corpus-execute-command/eacc5970513b9cf9a1e85364982bc8943ef06440000066400000000000000000000000261421143571500261720ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/eaedf0198845486881e1e6c40418c7e08355c35a000066400000000000000000000001311421143571500261060ustar00rootroot00000000000000Y?@ :@ Xe)):@ Xe)):@ Xe)ee X0emlibtpms-0.9.3/tests/corpus-execute-command/eb72ad440308cbda350a0f70af2036f0c259f461000066400000000000000000000000411421143571500262520ustar00rootroot00000000000000!v@@  libtpms-0.9.3/tests/corpus-execute-command/eb7602d694faf2be1c55e56af97c3013331447fa000066400000000000000000000000161421143571500263070ustar00rootroot00000000000000N@ libtpms-0.9.3/tests/corpus-execute-command/eb865b9cf2f3afd0e2ba5b087d583c8b77314665000066400000000000000000000000261421143571500264050ustar00rootroot00000000000000z libtpms-0.9.3/tests/corpus-execute-command/eb894d74f3bf773c730c7050716345a84bcced23000066400000000000000000000001111421143571500262320ustar00rootroot00000000000000I1@ @ C?? `Clibtpms-0.9.3/tests/corpus-execute-command/ebb87f0ad4ce59390d6a15de6ccbf62bb44654e3000066400000000000000000000002461421143571500266170ustar00rootroot00000000000000g<#@,`i y%C+=7:~ X# )pcF$QԆW:t59'rN ij"octP<3$'qT:@libtpms-0.9.3/tests/corpus-execute-command/ebdfd199475b3517b88f9a5362b63159d5ad11a9000066400000000000000000000000341421143571500262500ustar00rootroot000000000000001@  Alibtpms-0.9.3/tests/corpus-execute-command/ec4f7f27ef5041c821ba774ff687cd944f05ae2a000066400000000000000000000000201421143571500264600ustar00rootroot00000000000000Blibtpms-0.9.3/tests/corpus-execute-command/ec6222e5895c224d2fd1c6de1efeee165a764b52000066400000000000000000000000631421143571500264560ustar00rootroot000000000000003.@ @ libtpms-0.9.3/tests/corpus-execute-command/ecd4d227244722f9f9d5e96603fe995946e4343e000066400000000000000000000002461421143571500261420ustar00rootroot00000000000000g<#@,`i y%K+=7:~ X# )pcF$QԆW:t59'rN ij"octP<3$'qT:@libtpms-0.9.3/tests/corpus-execute-command/ecf19d01d133886754348fb39b2d56862ae95e41000066400000000000000000000000471421143571500261160ustar00rootroot00000000000000'z @' E^ @$ libtpms-0.9.3/tests/corpus-execute-command/ecf200a1ebf1b4c54729ec8db8822977813e93e9000066400000000000000000000001111421143571500263240ustar00rootroot00000000000000I@@ @  A@@@@@libtpms-0.9.3/tests/corpus-execute-command/ed08a97deebc2baf346a7ba0ffe6fc55af6b37d2000066400000000000000000000000261421143571500271120ustar00rootroot00000000000000BA libtpms-0.9.3/tests/corpus-execute-command/ee39aa5a14bca94b5cef30f459d22efbbb6baae9000066400000000000000000000001051421143571500270760ustar00rootroot00000000000000ER@@ @  libtpms-0.9.3/tests/corpus-execute-command/ee43b6b01331950affc19e49c68cf1a8c1976a05000066400000000000000000000000671421143571500263170ustar00rootroot000000000000007R@@ @  @e!2 ^q??? ylibtpms-0.9.3/tests/corpus-execute-command/eeac81e73a28586dad48a07d249ace55aaf94a4d000066400000000000000000000000141421143571500266130ustar00rootroot00000000000000 Flibtpms-0.9.3/tests/corpus-execute-command/ef05a7312656fc891e8468385431641205bec838000066400000000000000000000002461421143571500256750ustar00rootroot00000000000000g<#@,`i y%K=7:~ hqEe7r%fɠX#  $'qT :@libtpms-0.9.3/tests/corpus-execute-command/ef2c896c8afe5fa83b2724f1d6ceb6c79f99723d000066400000000000000000000000041421143571500265670ustar00rootroot00000000000000libtpms-0.9.3/tests/corpus-execute-command/ef563745f8f6774cbb46e7c14827c357d2cc9d30000066400000000000000000000002461421143571500262660ustar00rootroot00000000000000g<#@,`i y%K=7:~ hqEe7r%fɠX '9'rN $'qT :@libtpms-0.9.3/tests/corpus-execute-command/ef6e8206fa1028d7962234f6343aca25c152fe19000066400000000000000000000000261421143571500261500ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/ef7b047dec7b93e9a9b713e4b803e4dc2d33a7ce000066400000000000000000000000341421143571500266170ustar00rootroot00000000000000k:  }Alibtpms-0.9.3/tests/corpus-execute-command/ef9a762752aee282ca3758588a27800e5d8cef92000066400000000000000000000001111421143571500262560ustar00rootroot00000000000000I1@ @ \E( `Clibtpms-0.9.3/tests/corpus-execute-command/efc5d31e10b19a08e8ac90fe318c400f10248c30000066400000000000000000000001111421143571500262550ustar00rootroot00000000000000I1@ @ \E( `Clibtpms-0.9.3/tests/corpus-execute-command/eff0e1aa7899d7e351075d62fba8991d07437b16000066400000000000000000000001111421143571500262450ustar00rootroot00000000000000I1@ @ CǓE? `Clibtpms-0.9.3/tests/corpus-execute-command/f0331fc109e095725d55e8b985809918e68683cc000066400000000000000000000000121421143571500257650ustar00rootroot00000000000000 ?libtpms-0.9.3/tests/corpus-execute-command/f1a4f98369ffb0c34764aea60508fabce8032dbd000066400000000000000000000001051421143571500265270ustar00rootroot00000000000000E1@ @ Wme `libtpms-0.9.3/tests/corpus-execute-command/f1f9aa87878d951cc968773b4cfd27af3e11087d000066400000000000000000000000121421143571500263430ustar00rootroot00000000000000 <libtpms-0.9.3/tests/corpus-execute-command/f20ab4d3b55fe0d97cb0bc4954866ade367fe8d8000066400000000000000000000000371421143571500265510ustar00rootroot00000000000000}@ @ @) @)libtpms-0.9.3/tests/corpus-execute-command/f21ebc8daa13ce6030e811d38f5c3074bd3bde78000066400000000000000000000000331421143571500265120ustar00rootroot00000000000000 @ libtpms-0.9.3/tests/corpus-execute-command/f241cd87a258ac1c25f2688172fd2830a6dba09e000066400000000000000000000001111421143571500263010ustar00rootroot00000000000000IX@ @ '`Xlibtpms-0.9.3/tests/corpus-execute-command/f2622583bc625aeffa8d9869ac730f33d9264792000066400000000000000000000000261421143571500262010ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/f2e6f357c179e5ef2b56b25a3f242da107dd8426000066400000000000000000000000261421143571500263150ustar00rootroot00000000000000z(libtpms-0.9.3/tests/corpus-execute-command/f34249e56e787bdd10d518762940d6a44a4ca20a000066400000000000000000000000401421143571500261440ustar00rootroot00000000000000 !@ @ @ libtpms-0.9.3/tests/corpus-execute-command/f3c146da8f4b346835ccd7e46655bcd02d479312000066400000000000000000000000141421143571500262340ustar00rootroot00000000000000 {libtpms-0.9.3/tests/corpus-execute-command/f3fad4745c150f668444405561ebdb19cfdaac72000066400000000000000000000002461421143571500263730ustar00rootroot00000000000000g<#@,`i y%K+=7:~ X# )pcF$QԆW:t59'rN ij"octP<3$'qT:@libtpms-0.9.3/tests/corpus-execute-command/f3fd836ed39bb17d5a0d4e6d3a3640478ca04151000066400000000000000000000000261421143571500263020ustar00rootroot00000000000000z;libtpms-0.9.3/tests/corpus-execute-command/f43958712644932e67037f6c02667f83e992cdaa000066400000000000000000000000521421143571500257640ustar00rootroot00000000000000*g# @libtpms-0.9.3/tests/corpus-execute-command/f48a761aceb4be34d49d4f38167a838d38f72c3d000066400000000000000000000000131421143571500264070ustar00rootroot00000000000000 Clibtpms-0.9.3/tests/corpus-execute-command/f4e686e19950d4121fdb5755c99b7912b8a63c09000066400000000000000000000007061421143571500261260ustar00rootroot00000000000000g@,`i y%K+=7:~>S;6Wb(-q @libtpms-0.9.3/tests/corpus-execute-command/f4ed77a878df312dde51d1ff80e7af9faad8569c000066400000000000000000000000321421143571500267220ustar00rootroot00000000000000~  libtpms-0.9.3/tests/corpus-execute-command/f5bfea0369335e633d1a0c397f72b0312c42aa39000066400000000000000000000000261421143571500262120ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/f60ebded74f3aafdacb978fde4c0853d75022ed2000066400000000000000000000000561421143571500267570ustar00rootroot00000000000000.g#"libtpms-0.9.3/tests/corpus-execute-command/f61c7a7f8b08892e4e8ca987d6f1ba664e56febd000066400000000000000000000000631421143571500265730ustar00rootroot0000000000000031@ @ @ 5* libtpms-0.9.3/tests/corpus-execute-command/f680ef93af52da6c9b798ae10f85ed2f511f9aee000066400000000000000000000001051421143571500266350ustar00rootroot00000000000000E1@ @ Xm:E `libtpms-0.9.3/tests/corpus-execute-command/f6813cb09d25a742338c26da89a5e475e836adbf000066400000000000000000000000321421143571500263220ustar00rootroot00000000000000~libtpms-0.9.3/tests/corpus-execute-command/f683f95063afc64019b7789b5b5124a9bb907291000066400000000000000000000000261421143571500260330ustar00rootroot00000000000000zzlibtpms-0.9.3/tests/corpus-execute-command/f6b35baad631159c8dd83455450d86f5510f4c4d000066400000000000000000000001271421143571500262370ustar00rootroot00000000000000W @ ibj#7(\3 묗%p`6NDOǡ !Xlibtpms-0.9.3/tests/corpus-execute-command/f6c929755df6ff95729a0dd9c9fb8b490b189482000066400000000000000000000000331421143571500263060ustar00rootroot00000000000000= @ libtpms-0.9.3/tests/corpus-execute-command/f6d9154a529bc14095da8a2f9b7bea1e92c17371000066400000000000000000000001441421143571500263150ustar00rootroot00000000000000dg,%@,`i y( K+=7:~&% CL:-n. Ran@libtpms-0.9.3/tests/corpus-execute-command/f70c07124cb829b22ba1f36fabf270f4a5fb1612000066400000000000000000000000121421143571500263350ustar00rootroot00000000000000 libtpms-0.9.3/tests/corpus-execute-command/f7233b3e42751229059be569b2301ed9fe777e43000066400000000000000000000000671421143571500260340ustar00rootroot000000000000007X@ @ XmXemN8libtpms-0.9.3/tests/corpus-execute-command/f790f8fedff35100e9e57e74c7d7be0189e5ac7f000066400000000000000000000000351421143571500265710ustar00rootroot000000000000004@)@ @ libtpms-0.9.3/tests/corpus-execute-command/f7c99d04b34b6e5d9fe3abd8b015d9396771b6b0000066400000000000000000000000141421143571500264050ustar00rootroot00000000000000 nlibtpms-0.9.3/tests/corpus-execute-command/f7cceeb10dfbab307cbc6691d5b829d3d0240c36000066400000000000000000000001021421143571500265660ustar00rootroot00000000000000B @ @ Rj\]#! 4ټJlibtpms-0.9.3/tests/corpus-execute-command/f7eee01abc5a1e0569cd5067e95276aa9a8082eb000066400000000000000000000000261421143571500264540ustar00rootroot00000000000000ilibtpms-0.9.3/tests/corpus-execute-command/f80583ca054f21b0e60e6edf69f625b6f693a358000066400000000000000000000000131421143571500262430ustar00rootroot00000000000000 libtpms-0.9.3/tests/corpus-execute-command/f89123447e6ac0989d8e9972ec43d79b2d062e39000066400000000000000000000000121421143571500261310ustar00rootroot00000000000000 |libtpms-0.9.3/tests/corpus-execute-command/f8a0cfdac69e347dbd2c40e6ccfaba6e920b0044000066400000000000000000000002461421143571500267350ustar00rootroot00000000000000g<#@,`i y%K+=7:~ X#X# )pcF$QԆW:t59'rN ij"octP<3$'qT:@libtpms-0.9.3/tests/corpus-execute-command/f8c58da5943cba7597f425266c96402bc15e4d82000066400000000000000000000000261421143571500261740ustar00rootroot00000000000000z*libtpms-0.9.3/tests/corpus-execute-command/f90373a2a63ab5fc3d3cbc25e43777c78dd6ac09000066400000000000000000000000261421143571500264520ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/f90f4a6864cb0d136da0f667da953be36c8f7c90000066400000000000000000000000471421143571500264110ustar00rootroot00000000000000' @': :e^@$ libtpms-0.9.3/tests/corpus-execute-command/f91cc203eefc0280178a81c9b08b62cf7d6db454000066400000000000000000000002461421143571500263740ustar00rootroot00000000000000g<#@,`i y%K+=7:~ #X# )pcF$QԆW:t59'rN ij"octP<3$'qT:@libtpms-0.9.3/tests/corpus-execute-command/f92db18040de478a576975566e70faf1dc5f4cda000066400000000000000000000000261421143571500264120ustar00rootroot00000000000000% libtpms-0.9.3/tests/corpus-execute-command/f97675d3453a55ded6c239e0ea6e4dee5a0e9711000066400000000000000000000000441421143571500264100ustar00rootroot00000000000000$*@ @ 3libtpms-0.9.3/tests/corpus-execute-command/f99859393027feb72ab6664b96bc3eec70714224000066400000000000000000000000161421143571500261160ustar00rootroot00000000000000klibtpms-0.9.3/tests/corpus-execute-command/f9f32b6caebee4b75522406b3ac57df23ed2bd35000066400000000000000000000000671421143571500266070ustar00rootroot000000000000007X@ @  @ e!2 ^q??? ylibtpms-0.9.3/tests/corpus-execute-command/fa21b08a8b4ea19ddbcfb1c30b96a7ac6fca18b0000066400000000000000000000000261421143571500270000ustar00rootroot00000000000000z@libtpms-0.9.3/tests/corpus-execute-command/fa3bbcf24e8e67c2af40edab658450d1a3d33cad000066400000000000000000000000551421143571500267320ustar00rootroot00000000000000-*@ @ @Blibtpms-0.9.3/tests/corpus-execute-command/facc8ab8b84d41c7285cbe5c66caa7fba3e53acd000066400000000000000000000003761421143571500271140ustar00rootroot00000000000000a @0$=)?ws 0wX7t(IyGiɪeܻ#Y,ƖTA/ue7t(IsG(B+libtpms-0.9.3/tests/corpus-execute-command/fb6e47dfdb499b7ccb5a901867efbd7c2c3af9af000066400000000000000000000000511421143571500270530ustar00rootroot00000000000000)@ @ * libtpms-0.9.3/tests/corpus-execute-command/fb9e73310e9493ec07cd83615df8c16a2918d2d1000066400000000000000000000000671421143571500262510ustar00rootroot000000000000007R@@ @ @e!2 ^q??? ylibtpms-0.9.3/tests/corpus-execute-command/fbb7452ff5e0943d1e688d4de7825b6d29b5851b000066400000000000000000000000141421143571500263350ustar00rootroot00000000000000 [libtpms-0.9.3/tests/corpus-execute-command/fbb906a0b44f6e3b439fc237e4e59ee546809c94000066400000000000000000000000621421143571500263360ustar00rootroot0000000000000023@@@ 'libtpms-0.9.3/tests/corpus-execute-command/fbe9a4ee8d4b4fc9e9e16ee562cd7b14a7e75aa1000066400000000000000000000000341421143571500267670ustar00rootroot000000000000000@ @ libtpms-0.9.3/tests/corpus-execute-command/fc5ef1a02d7f0bdff88d883a6cc3e3192c874b40000066400000000000000000000000421421143571500265360ustar00rootroot00000000000000"} ˆJI}@ libtpms-0.9.3/tests/corpus-execute-command/fc7e32232bd74f9a0d2ee0b3755cb8fd91feef8f000066400000000000000000000000671421143571500267130ustar00rootroot000000000000007R@@ @  @e!2 ^q??? ylibtpms-0.9.3/tests/corpus-execute-command/fcc2c84b70368f552a4842dec005ade09857b1d4000066400000000000000000000000431421143571500263070ustar00rootroot00000000000000#@ @  *libtpms-0.9.3/tests/corpus-execute-command/fcc6dd84df1932ff7262ab161baf8fc74f0f1fb1000066400000000000000000000000141421143571500266700ustar00rootroot00000000000000 xlibtpms-0.9.3/tests/corpus-execute-command/fcc9f9018b90ec1fda690c72fcf3374cdcebc931000066400000000000000000000000261421143571500267010ustar00rootroot00000000000000z libtpms-0.9.3/tests/corpus-execute-command/fd28519619ab35b7c57a50662599e1895d1580c3000066400000000000000000000001271421143571500257600ustar00rootroot00000000000000W @ ibjc8(\3 묗%po0NDO !Xlibtpms-0.9.3/tests/corpus-execute-command/fd42b6c647827c1c8809796ca0e95427109907a2000066400000000000000000000002461421143571500257610ustar00rootroot00000000000000g<#@,`i y%K+=7:~ X# )pcF$QԆW:t59'rN ij"octP<3$'qT:@libtpms-0.9.3/tests/corpus-execute-command/fd8828f2a5aab8a7b43a7606e2d09d78c2cf84a2000066400000000000000000000000731421143571500264620ustar00rootroot00000000000000;1@ @ % libtpms-0.9.3/tests/corpus-execute-command/fd947c107ed60fbefc5d3e6ff0ecee9be6dce3f5000066400000000000000000000000261421143571500272140ustar00rootroot00000000000000zlibtpms-0.9.3/tests/corpus-execute-command/fe265ca927449ed7172248f315d379951ca474eb000066400000000000000000000001051421143571500261150ustar00rootroot00000000000000ER@@ @ @e!2 ^q? @ ?? ylibtpms-0.9.3/tests/corpus-execute-command/fe2a94bd43ce5bdf92da7691ebaf8adcca324499000066400000000000000000000000351421143571500267620ustar00rootroot00000000000000S+)@ @ libtpms-0.9.3/tests/corpus-execute-command/ff06e15158084fbfb3731dfd3f260f213117ed96000066400000000000000000000000551421143571500262340ustar00rootroot00000000000000-*@ @ (libtpms-0.9.3/tests/corpus-execute-command/ff7ff0b8a63f38e165b52417d326affc5a7ba13f000066400000000000000000000000141421143571500265310ustar00rootroot00000000000000 glibtpms-0.9.3/tests/corpus-execute-command/ff8e3f668dbec7ff57d077ad12d37ceb356fb66c000066400000000000000000000000261421143571500267230ustar00rootroot00000000000000[libtpms-0.9.3/tests/corpus-execute-command/ffb29ad0b7cd4c30bfd0218d7962e0c710b5a024000066400000000000000000000000241421143571500264200ustar00rootroot00000000000000~ libtpms-0.9.3/tests/freebl_sha1flattensize.c000066400000000000000000000021031421143571500211260ustar00rootroot00000000000000#include #include #include #if defined (__x86_64__) || \ defined (__amd64__) || \ defined (__ia64__) || \ defined (__powerpc64__) || \ defined (__s390x__) || \ (defined (__sparc__) && defined(__arch64__)) || \ defined(__aarch64__) #define EXPECTED_LIB_FLATTENSIZE 248 #elif defined (__i386__) || \ defined (__powerpc__) || \ defined (__s390__) || \ defined (__sparc__) || \ defined (__arm__) #define EXPECTED_LIB_FLATTENSIZE 160 #else #error Undefined architecture type #endif int main(void) { SHA1Context *context; uint32_t libFlattenSize; context = SHA1_NewContext(); if (!context) { printf("Could not create SHA1 context.\n"); return EXIT_FAILURE; } SHA1_Begin(context); libFlattenSize = SHA1_FlattenSize(context); if (libFlattenSize != EXPECTED_LIB_FLATTENSIZE) { printf("SHA1 flatten size is %d, expected %d\n", libFlattenSize, EXPECTED_LIB_FLATTENSIZE); return EXIT_FAILURE; } return EXIT_SUCCESS; } libtpms-0.9.3/tests/fuzz-main.c000066400000000000000000000022251421143571500164270ustar00rootroot00000000000000#include #include #define MIN_NUMBER_OF_RUNS 4 #define EXIT_TEST_SKIP 77 extern int LLVMFuzzerTestOneInput (const unsigned char *data, size_t size); int main(int argc, char **argv) { int i, j; for (i = 1; i < argc; i++) { char *name = argv[i]; ssize_t size; FILE *f = fopen(name, "rb"); char *buf; fprintf(stdout, "%s...\n", name); if (f == NULL) { perror("fopen() failed"); continue; } fseek(f, 0, SEEK_END); size = ftell(f); if (size < 0) { fclose(f); perror("ftell() failed"); continue; } fseek(f, 0, SEEK_SET); buf = malloc(size + 1); if (fread(buf, 1, size, f) != (size_t)size) { fclose(f); perror("fread() failed"); continue; } fclose(f); buf[size] = 0; for (j = 0; j < MIN_NUMBER_OF_RUNS; j++) { if (LLVMFuzzerTestOneInput((void *)buf, size) == EXIT_TEST_SKIP) { return EXIT_TEST_SKIP; } } free(buf); } return EXIT_SUCCESS; } libtpms-0.9.3/tests/fuzz.cc000066400000000000000000000110561421143571500156520ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include static void die(const char *msg) { fprintf(stderr, "%s", msg); assert(false); } static TPM_RESULT mytpm_io_init(void) { return TPM_SUCCESS; } static TPM_RESULT mytpm_io_getlocality(TPM_MODIFIER_INDICATOR *locModif, uint32_t tpm_number) { *locModif = 0; return TPM_SUCCESS; } static TPM_RESULT mytpm_io_getphysicalpresence(TPM_BOOL *phyPres, uint32_t tpm_number) { *phyPres = FALSE; return TPM_SUCCESS; } static unsigned char *permall; static uint32_t permall_length; static TPM_RESULT mytpm_nvram_loaddata(unsigned char **data, uint32_t *length, uint32_t tpm_number, const char *name) { if (!strcmp(name, TPM_PERMANENT_ALL_NAME)) { if (permall) { *data = NULL; assert(TPM_Malloc(data, permall_length) == TPM_SUCCESS); memcpy(*data, permall, permall_length); *length = permall_length; return TPM_SUCCESS; } } return TPM_RETRY; } static TPM_RESULT mytpm_nvram_storedata(const unsigned char *data, uint32_t length, uint32_t tpm_number, const char *name) { if (!strcmp(name, TPM_PERMANENT_ALL_NAME)) { free(permall); permall = NULL; assert(TPM_Malloc(&permall, length) == TPM_SUCCESS); memcpy(permall, data, length); permall_length = length; } return TPM_SUCCESS; } extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { unsigned char *rbuffer = NULL; uint32_t rlength; uint32_t rtotal = 0; TPM_RESULT res; unsigned char *vol_buffer = NULL; uint32_t vol_buffer_len; unsigned char *perm_buffer = NULL; uint32_t perm_buffer_len; unsigned char startup[] = { 0x80, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x01, 0x44, 0x00, 0x00 }; struct libtpms_callbacks cbs = { .sizeOfStruct = sizeof(struct libtpms_callbacks), .tpm_nvram_init = NULL, .tpm_nvram_loaddata = mytpm_nvram_loaddata, .tpm_nvram_storedata = mytpm_nvram_storedata, .tpm_nvram_deletename = NULL, .tpm_io_init = mytpm_io_init, .tpm_io_getlocality = mytpm_io_getlocality, .tpm_io_getphysicalpresence = mytpm_io_getphysicalpresence, }; res = TPMLIB_RegisterCallbacks(&cbs); if (res != TPM_SUCCESS) die("Could not register callbacks\n"); res = TPMLIB_ChooseTPMVersion(TPMLIB_TPM_VERSION_2); if (res != TPM_SUCCESS) die("Could not choose the TPM version\n"); res = TPMLIB_MainInit(); if (res != TPM_SUCCESS) die("Error: TPMLIB_MainInit() failed\n"); res = TPMLIB_Process(&rbuffer, &rlength, &rtotal, startup, sizeof(startup)); if (res != TPM_SUCCESS) die("Error: TPMLIB_Process(Startup) failed\n"); res = TPMLIB_Process(&rbuffer, &rlength, &rtotal, (unsigned char*)data, size); if (res != TPM_SUCCESS) die("Error: TPMLIB_Process(fuzz-command) failed\n"); /* state suspend */ res = TPMLIB_GetState(TPMLIB_STATE_VOLATILE, &vol_buffer, &vol_buffer_len); if (res != TPM_SUCCESS) die("Error: TPMLIB_GetState(TPMLIB_STATE_VOLATILE) failed\n"); res = TPMLIB_GetState(TPMLIB_STATE_PERMANENT, &perm_buffer, &perm_buffer_len); if (res != TPM_SUCCESS) die("Error: TPMLIB_GetState(TPMLIB_STATE_PERMANENT) failed\n"); TPMLIB_Terminate(); /* state resume */ res = TPMLIB_SetState(TPMLIB_STATE_PERMANENT, perm_buffer, perm_buffer_len); if (res != TPM_SUCCESS) die("Error: TPMLIB_SetState(TPMLIB_STATE_PERMANENT) failed\n"); res = TPMLIB_SetState(TPMLIB_STATE_VOLATILE, vol_buffer, vol_buffer_len); if (res != TPM_SUCCESS) die("Error: TPMLIB_SetState(TPMLIB_STATE_VOLATILE) failed\n"); res = TPMLIB_MainInit(); if (res != TPM_SUCCESS) die("Error: TPMLIB_MainInit() to resume with the state failed\n"); TPMLIB_Terminate(); TPM_Free(rbuffer); TPM_Free(vol_buffer); TPM_Free(perm_buffer); TPM_Free(permall); permall = NULL; return 0; } libtpms-0.9.3/tests/fuzz.sh000077500000000000000000000005761421143571500157070ustar00rootroot00000000000000#!/usr/bin/env bash TESTDIR=${abs_top_testdir:-$(dirname "$0")} DIR=${PWD} MAXLINES=128 l=1 corpus=$(ls "$TESTDIR/corpus-execute-command/"*) while :; do echo "Passing test cases $l to $((l + MAXLINES))" tmp=$(echo "${corpus}" | sed -n "${l},$((l + MAXLINES))p") [ -z "${tmp}" ] && exit 0 ${DIR}/fuzz ${tmp} rc=$? [ $rc -ne 0 ] && exit $rc l=$((l + MAXLINES)) done libtpms-0.9.3/tests/nvram_offsets.c000066400000000000000000000066511421143571500173720ustar00rootroot00000000000000#include #include #include "Tpm.h" /* from Global.h */ extern BYTE s_indexOrderlyRam[RAM_INDEX_SPACE]; int main(void) { PERSISTENT_DATA pd; /* Check size of ppList that expands with new commands */ #define PD_PP_LIST_EXP_SIZE 14 if (sizeof(pd.ppList) != PD_PP_LIST_EXP_SIZE) { fprintf(stderr, "sizeof(PERSISTENT_DATA.ppList) does not have expected size " "of %u bytes but %zu bytes\n", PD_PP_LIST_EXP_SIZE, sizeof(pd.ppList)); return EXIT_FAILURE; } /* Check size of auditCommands that expands with new commands */ #define PD_AUDIT_COMMANDS_EXP_SIZE 14 if (sizeof(pd.auditCommands) != PD_AUDIT_COMMANDS_EXP_SIZE) { fprintf(stderr, "sizeof(PERSISTENT_DATA.auditCommands) does not have expected size " "of %u bytes but %zu bytes\n", PD_AUDIT_COMMANDS_EXP_SIZE, sizeof(pd.auditCommands)); return EXIT_FAILURE; } /* ensure that the NVRAM offset of NV_USER_DYNAMIC is at the expected location so that there's enough memory for re-constructing NVRAM indices etc. into the NVRAM */ #define NV_INDEX_RAM_DATA_EXP_OFFSET 5120 if (NV_INDEX_RAM_DATA != NV_INDEX_RAM_DATA_EXP_OFFSET) { /* If this ever changes due to growth of the preceding data * structure, we need to adjust the total NVRAM memory size * for the architecture where this changed (or have all * architectures use the same offset. */ fprintf(stderr, "NV_INDEX_RAM_DATA not at expected offset %u but at %u\n", NV_INDEX_RAM_DATA_EXP_OFFSET, (unsigned int)NV_INDEX_RAM_DATA); return EXIT_FAILURE; } #define NV_USER_DYNAMIC_EXP_OFFSET (5120 + 512) if (NV_USER_DYNAMIC != NV_USER_DYNAMIC_EXP_OFFSET) { fprintf(stderr, "NV_USER_DYNAMIC not at expected offset %u but at %u\n", NV_USER_DYNAMIC_EXP_OFFSET, (unsigned int)NV_USER_DYNAMIC); return EXIT_FAILURE; } /* * OBJECTs are directly written into NVRAM. We have to make sure that the * size of the OBJECT is the same on all architectures so that a full * NVRAM fits on all architectures */ #if RSA_4096 # error Unsupported RSA key size #elif RSA_3072 # define OBJECT_EXP_SIZE 2600 #elif RSA_2048 # define OBJECT_EXP_SIZE 1896 #endif if (sizeof(OBJECT) != OBJECT_EXP_SIZE) { fprintf(stderr, "sizeof(OBJECT) does not have expected size of %u bytes" "but %zu bytes\n", OBJECT_EXP_SIZE, sizeof(OBJECT)); fprintf(stderr, "sizeof(TPMT_PUBLIC) is now %zu bytes;" "was 356/484 bytes for 2048/3072 bit RSA keys\n", sizeof(TPMT_PUBLIC)); fprintf(stderr, "sizeof(TPMT_SENSITIVE) is now %zu bytes;" "was 776/1096 bytes for 2048/3072 bit RSA keys\n", sizeof(TPMT_SENSITIVE)); fprintf(stderr, "sizeof(privateExponent_t) is now %zu bytes;" "was 608/864 bytes for 2048/3072 bit RSA keys\n", sizeof(privateExponent_t)); return EXIT_FAILURE; } /* Same for NV_INDEX */ #define NV_INDEX_EXP_SIZE 148 if (sizeof(NV_INDEX) != NV_INDEX_EXP_SIZE) { fprintf(stderr, "sizeof(NV_INDEX) does not have expected size of %u bytes" "but %zu bytes\n", NV_INDEX_EXP_SIZE, sizeof(NV_INDEX)); return EXIT_FAILURE; } return EXIT_SUCCESS; } libtpms-0.9.3/tests/oss-fuzz.sh000077500000000000000000000010621421143571500165000ustar00rootroot00000000000000#!/bin/bash set -ex export CC=${CC:-clang} export CXX=${CXX:-clang++} export WORK=${WORK:-$(pwd)} export OUT=${OUT:-$(pwd)/out} mkdir -p $OUT build=$WORK/build rm -rf $build mkdir -p $build export LIBTPMS=$(pwd) autoreconf -vfi cd $build $LIBTPMS/configure --disable-shared --enable-static --with-openssl --with-tpm2 make -j$(nproc) && make -C tests fuzz zip -jqr $OUT/fuzz_seed_corpus.zip "$LIBTPMS/tests/corpus-execute-command" find $build -type f -executable -name "fuzz*" -exec mv {} $OUT \; find $build -type f -name "*.options" -exec mv {} $OUT \; libtpms-0.9.3/tests/run-fuzzer.sh000077500000000000000000000004551421143571500170340ustar00rootroot00000000000000#!/usr/bin/env bash # For the license, see the LICENSE file in the root directory. DIR=${PWD}/$(dirname "$0") ROOT=${DIR}/.. WORKDIR=$(mktemp -d) function cleanup() { rm -rf ${WORKDIR} } trap "cleanup" QUIT EXIT pushd $WORKDIR ${DIR}/fuzz $@ ${DIR}/corpus-execute-command rc=$? popd exit $rc libtpms-0.9.3/tests/tpm2_createprimary.c000066400000000000000000000162121421143571500203210ustar00rootroot00000000000000#include #include #include #include #include #include #include int main(void) { unsigned char *rbuffer = NULL; uint32_t rlength; uint32_t rtotal = 0; TPM_RESULT res; int ret = 1; unsigned char *perm = NULL; uint32_t permlen = 0; unsigned char *vol = NULL; uint32_t vollen = 0; unsigned char startup[] = { 0x80, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x01, 0x44, 0x00, 0x00 }; res = TPMLIB_ChooseTPMVersion(TPMLIB_TPM_VERSION_2); if (res) { fprintf(stderr, "TPMLIB_ChooseTPMVersion() failed: 0x%02x\n", res); goto exit; } res = TPMLIB_MainInit(); if (res) { fprintf(stderr, "TPMLIB_MainInit() failed: 0x%02x\n", res); goto exit; } res = TPMLIB_Process(&rbuffer, &rlength, &rtotal, startup, sizeof(startup)); if (res) { fprintf(stderr, "TPMLIB_Process(Startup) failed: 0x%02x\n", res); goto exit; } unsigned char tpm2_createprimary[] = { 0x80, 0x02, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x01, 0x31, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x09, 0x40, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x01, 0x00, 0x0b, 0x00, 0x03, 0x04, 0x72, 0x00, 0x00, 0x00, 0x06, 0x00, 0x80, 0x00, 0x43, 0x00, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; res = TPMLIB_Process(&rbuffer, &rlength, &rtotal, tpm2_createprimary, sizeof(tpm2_createprimary)); if (res) { fprintf(stderr, "TPMLIB_Process(TPM2_CreatePrimary) failed: 0x%02x\n", res); goto exit; } if (rlength != 506) { fprintf(stderr, "Expected response is %u bytes, but got %u.\n", 506, rlength); goto exit; } unsigned char tpm2_evictcontrol[] = { 0x80, 0x02, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x01, 0x20, 0x40, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x40, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00 }; const unsigned char tpm2_evictcontrol_exp_resp[] = { 0x80, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00 }; res = TPMLIB_Process(&rbuffer, &rlength, &rtotal, tpm2_evictcontrol, sizeof(tpm2_evictcontrol)); if (res) { fprintf(stderr, "TPMLIB_Process(TPM2_EvictControl) failed: %02x\n", res); goto exit; } if (rlength != sizeof(tpm2_evictcontrol_exp_resp)) { fprintf(stderr, "Expected TPM2_EvictControl response is %zu bytes, " "but got %u.\n", sizeof(tpm2_evictcontrol_exp_resp), rlength); goto exit; } if (memcmp(rbuffer, tpm2_evictcontrol_exp_resp, rlength)) { fprintf(stderr, "Expected TPM2_EvictControl response is different than " "received one.\n"); goto exit; } /* Expecting a handle 0x81000000 for the persisted key now */ unsigned char tpm2_getcapability[] = { 0x80, 0x01, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x01, 0x7a, 0x00, 0x00, 0x00, 0x01, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40 }; const unsigned char tpm2_getcapability_exp_resp[] = { 0x80, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x81, 0x00, 0x00, 0x00 }; res = TPMLIB_Process(&rbuffer, &rlength, &rtotal, tpm2_getcapability, sizeof(tpm2_getcapability)); if (res) { fprintf(stderr, "TPMLIB_Process(TPM2_GetCapability) failed: 0x%02x\n", res); goto exit; } if (rlength != sizeof(tpm2_getcapability_exp_resp)) { fprintf(stderr, "Expected TPM2_GetCapability response is %zu bytes, " "but got %u.\n", sizeof(tpm2_getcapability_exp_resp), rlength); goto exit; } if (memcmp(rbuffer, tpm2_getcapability_exp_resp, rlength)) { fprintf(stderr, "Expected TPM2_GetCapability response is different than " "received one.\n"); goto exit; } /* save permanent and volatile state */ res = TPMLIB_GetState(TPMLIB_STATE_PERMANENT, &perm, &permlen); if (res) { fprintf(stderr, "TPMLIB_GetState(PERMANENT) failed: 0x%02x\n", res); goto exit; } res = TPMLIB_GetState(TPMLIB_STATE_VOLATILE, &vol, &vollen); if (res) { fprintf(stderr, "TPMLIB_GetState(VOLATILE) failed: 0x%02x\n", res); goto exit; } /* terminate and resume where we left off */ TPMLIB_Terminate(); res = TPMLIB_SetState(TPMLIB_STATE_PERMANENT, perm, permlen); if (res) { fprintf(stderr, "TPMLIB_SetState(PERMANENT) failed: 0x%02x\n", res); goto exit; } res = TPMLIB_SetState(TPMLIB_STATE_VOLATILE, vol, vollen); if (res) { fprintf(stderr, "TPMLIB_SetState(VOLATILE) failed: 0x%02x\n", res); goto exit; } res = TPMLIB_MainInit(); if (res) { fprintf(stderr, "TPMLIB_MainInit() after SetState failed: 0x%02x\n", res); goto exit; } /* Again expecting the handle 0x81000000 for the persisted key */ res = TPMLIB_Process(&rbuffer, &rlength, &rtotal, tpm2_getcapability, sizeof(tpm2_getcapability)); if (res) { fprintf(stderr, "TPMLIB_Process(TPM2_GetCapability) failed: 0x%02x\n", res); goto exit; } if (rlength != sizeof(tpm2_getcapability_exp_resp)) { fprintf(stderr, "Expected TPM2_GetCapability response is %zu bytes," "but got %u.\n", sizeof(tpm2_getcapability_exp_resp), rlength); goto exit; } if (memcmp(rbuffer, tpm2_getcapability_exp_resp, rlength)) { fprintf(stderr, "Expected TPM2_GetCapability response is different than " "received one.\n"); goto exit; } /* Shutdown */ unsigned char tpm2_shutdown[] = { 0x80, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x01, 0x45, 0x00, 0x00 }; res = TPMLIB_Process(&rbuffer, &rlength, &rtotal, tpm2_shutdown, sizeof(tpm2_shutdown)); if (res) { fprintf(stderr, "TPMLIB_Process(Shutdown) after SetState failed: 0x%02x\n", res); goto exit; } unsigned char tpm2_shutdown_resp[] = { 0x80, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00 }; if (memcmp(tpm2_shutdown_resp, rbuffer, rlength)) { fprintf(stderr, "TPM2_PCRRead(Shutdown) after SetState did not return " "expected result\n"); goto exit; } ret = 0; fprintf(stdout, "OK\n"); exit: free(perm); free(vol); TPMLIB_Terminate(); TPM_Free(rbuffer); return ret; } libtpms-0.9.3/tests/tpm2_createprimary.sh000077500000000000000000000010561421143571500205140ustar00rootroot00000000000000#!/usr/bin/env bash # For the license, see the LICENSE file in the root directory. ROOT=${abs_top_builddir:-$(pwd)/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} DIR=${PWD} WORKDIR=$(mktemp -d) . ${TESTDIR}/common function cleanup() { rm -rf ${WORKDIR} } trap "cleanup" QUIT EXIT pushd $WORKDIR &>/dev/null ${DIR}/tpm2_createprimary rc=$? fs=$(get_filesize NVChip) [ $? -ne 0 ] && exit 1 if [ $fs -ne 176832 ]; then echo "Error: Unexpected size of NVChip file." echo "Expected: 131072" echo "Got : $fs" rc=1 fi popd &>/dev/null exit $rc libtpms-0.9.3/tests/tpm2_pcr_read.c000066400000000000000000000242751421143571500172410ustar00rootroot00000000000000#include #include #include #include #include #include #include static void dump_array(const char *h, const unsigned char *d, size_t dlen) { size_t i; fprintf(stderr, "%s\n", h); for (i = 0; i < dlen; i++) { fprintf(stderr, "%02x ", d[i]); if ((i & 0xf) == 0xf) fprintf(stderr, "\n"); } fprintf(stderr, "\n"); } int main(void) { unsigned char *rbuffer = NULL; uint32_t rlength; uint32_t rtotal = 0; TPM_RESULT res; int ret = 1; unsigned char *perm = NULL; uint32_t permlen = 0; unsigned char *vol = NULL; uint32_t vollen = 0; unsigned char startup[] = { 0x80, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x01, 0x44, 0x00, 0x00 }; unsigned char tpm2_pcr_read[] = { 0x80, 0x01, // TPM_ST_NO_SESSIONS 0x00, 0x00, 0x00, 0x26, // command size 0x00, 0x00, 0x01, 0x7e, // TPM_CC_PCR_Read 0x00, 0x00, 0x00, 0x04, // TPML_PCR_SELECTION 0x00, 0x04, // TPMI_ALG_HASH, SHA1=4 0x03, // size of the select 0x01, 0x00, 0x10, // pcrSelect 0x00, 0x0b, // TPMI_ALG_HASH, SHA256=11 0x03, // size of the select 0x01, 0x00, 0x10, // pcrSelect 0x00, 0x0c, // TPMI_ALG_HASH, SHA384=12 0x03, // size of the select 0x01, 0x00, 0x10, // pcrSelect 0x00, 0x0d, // TPMI_ALG_HASH, SHA512=13 0x03, // size of the select 0x01, 0x00, 0x10 // pcrSelect }; const unsigned char tpm2_pcr_read_exp_resp[] = { 0x80, 0x01, 0x00, 0x00, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x03, 0x01, 0x00, 0x10, 0x00, 0x0b, 0x03, 0x01, 0x00, 0x10, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x10, 0x00, 0x0d, 0x03, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; res = TPMLIB_ChooseTPMVersion(TPMLIB_TPM_VERSION_2); if (res) { fprintf(stderr, "TPMLIB_ChooseTPMVersion() failed: 0x%02x\n", res); goto exit; } res = TPMLIB_MainInit(); if (res) { fprintf(stderr, "TPMLIB_MainInit() failed: 0x%02x\n", res); goto exit; } res = TPMLIB_Process(&rbuffer, &rlength, &rtotal, startup, sizeof(startup)); if (res) { fprintf(stderr, "TPMLIB_Process(Startup) failed: 0x%02x\n", res); goto exit; } res = TPMLIB_Process(&rbuffer, &rlength, &rtotal, tpm2_pcr_read, sizeof(tpm2_pcr_read)); if (res) { fprintf(stderr, "TPMLIB_Process(TPM2_PCR_Read) failed: 0x%02x\n", res); goto exit; } if (rlength != sizeof(tpm2_pcr_read_exp_resp)) { fprintf(stderr, "Expected response is %zu bytes, but got %u.\n", sizeof(tpm2_pcr_read_exp_resp), rlength); goto exit; } if (memcmp(rbuffer, tpm2_pcr_read_exp_resp, rlength)) { fprintf(stderr, "Expected response is different than received one.\n"); dump_array("actual:", rbuffer, rlength); dump_array("expected:", tpm2_pcr_read_exp_resp, sizeof(tpm2_pcr_read_exp_resp)); goto exit; } /* Extend PCR 10 with string '1234' */ unsigned char tpm2_pcr_extend[] = { 0x80, 0x02, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x01, 0x82, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x09, 0x40, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0b, 0x31, 0x32, 0x33, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; res = TPMLIB_Process(&rbuffer, &rlength, &rtotal, tpm2_pcr_extend, sizeof(tpm2_pcr_extend)); if (res != TPM_SUCCESS) { fprintf(stderr, "TPMLIB_Process(TPM2_PCR_Extend) failed: 0x%02x\n", res); goto exit; } /* Read value of PCR 10 */ unsigned char tpm2_pcr10_read[] = { 0x80, 0x01, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x01, 0x7e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0b, 0x03, 0x00, 0x04, 0x00 }; res = TPMLIB_Process(&rbuffer, &rlength, &rtotal, tpm2_pcr10_read, sizeof(tpm2_pcr10_read)); if (res) { fprintf(stderr, "TPMLIB_Process(PCR10 Read) failed: 0x%02x\n", res); goto exit; } const unsigned char tpm2_pcr10_read_resp[] = { 0x80, 0x01, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0b, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x20, 0x1f, 0x7f, 0xb1, 0x00, 0xe1, 0xb2, 0xd1, 0x95, 0x19, 0x4b, 0x58, 0xe7, 0xc3, 0x09, 0xa5, 0x86, 0x30, 0x7c, 0x34, 0x64, 0x19, 0xdc, 0xb2, 0xd5, 0x9f, 0x52, 0x2b, 0xe7, 0xf0, 0x94, 0x51, 0x01 }; if (memcmp(tpm2_pcr10_read_resp, rbuffer, rlength)) { fprintf(stderr, "TPM2_PCRRead(PCR10) did not return expected result\n"); dump_array("actual:", rbuffer, rlength); dump_array("expected:", tpm2_pcr10_read_resp, sizeof(tpm2_pcr10_read_resp)); goto exit; } /* save permanent and volatile state */ res = TPMLIB_GetState(TPMLIB_STATE_PERMANENT, &perm, &permlen); if (res) { fprintf(stderr, "TPMLIB_GetState(PERMANENT) failed: 0x%02x\n", res); goto exit; } res = TPMLIB_GetState(TPMLIB_STATE_VOLATILE, &vol, &vollen); if (res) { fprintf(stderr, "TPMLIB_GetState(VOLATILE) failed: 0x%02x\n", res); goto exit; } /* terminate and resume where we left off */ TPMLIB_Terminate(); res = TPMLIB_SetState(TPMLIB_STATE_PERMANENT, perm, permlen); if (res) { fprintf(stderr, "TPMLIB_SetState(PERMANENT) failed: 0x%02x\n", res); goto exit; } res = TPMLIB_SetState(TPMLIB_STATE_VOLATILE, vol, vollen); if (res) { fprintf(stderr, "TPMLIB_SetState(VOLATILE) failed: 0x%02x\n", res); goto exit; } res = TPMLIB_MainInit(); if (res) { fprintf(stderr, "TPMLIB_MainInit() after SetState failed: 0x%02x\n", res); goto exit; } res = TPMLIB_Process(&rbuffer, &rlength, &rtotal, tpm2_pcr10_read, sizeof(tpm2_pcr10_read)); if (res) { fprintf(stderr, "TPMLIB_Process(PCR10 Read) after SetState failedL 0x%02x\n", res); goto exit; } if (memcmp(tpm2_pcr10_read_resp, rbuffer, rlength)) { fprintf(stderr, "TPM2_PCRRead(PCR10) after SetState did not return expected " "result\n"); goto exit; } unsigned char tpm2_shutdown[] = { 0x80, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x01, 0x45, 0x00, 0x00 }; res = TPMLIB_Process(&rbuffer, &rlength, &rtotal, tpm2_shutdown, sizeof(tpm2_shutdown)); if (res) { fprintf(stderr, "TPMLIB_Process(Shutdown) after SetState failed: 0x%02x\n", res); goto exit; } unsigned char tpm2_shutdown_resp[] = { 0x80, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00 }; if (memcmp(tpm2_shutdown_resp, rbuffer, rlength)) { fprintf(stderr, "TPM2_PCRRead(Shutdown) after SetState did not return expected " "result\n"); goto exit; } ret = 0; fprintf(stdout, "OK\n"); exit: free(perm); free(vol); TPMLIB_Terminate(); TPM_Free(rbuffer); return ret; } libtpms-0.9.3/tests/tpm2_pcr_read.sh000077500000000000000000000010511421143571500174170ustar00rootroot00000000000000#!/usr/bin/env bash # For the license, see the LICENSE file in the root directory. ROOT=${abs_top_builddir:-$(pwd)/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} DIR=${PWD} WORKDIR=$(mktemp -d) . ${TESTDIR}/common function cleanup() { rm -rf ${WORKDIR} } trap "cleanup" QUIT EXIT pushd $WORKDIR &>/dev/null ${DIR}/tpm2_pcr_read rc=$? fs=$(get_filesize NVChip) [ $? -ne 0 ] && exit 1 if [ $fs -ne 176832 ]; then echo "Error: Unexpected size of NVChip file." echo "Expected: 131072" echo "Got : $fs" rc=1 fi popd &>/dev/null exit $rc libtpms-0.9.3/tests/tpm2_selftest.c000066400000000000000000000033551421143571500173070ustar00rootroot00000000000000#include #include #include #include #include #include int main(void) { unsigned char *rbuffer = NULL; uint32_t rlength; uint32_t rtotal = 0; TPM_RESULT res; int ret = 1; unsigned char tpm2_startup[] = { 0x80, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x01, 0x44, 0x00, 0x00 }; unsigned char tpm2_selftest[] = { 0x80, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x43, 0x01 }; const unsigned char tpm2_selftest_resp[] = { 0x80, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00 }; res = TPMLIB_ChooseTPMVersion(TPMLIB_TPM_VERSION_2); if (res) { fprintf(stderr, "TPMLIB_ChooseTPMVersion() failed: 0x%02x\n", res); goto exit; } res = TPMLIB_MainInit(); if (res) { fprintf(stderr, "TPMLIB_MainInit() failed: 0x%02x\n", res); goto exit; } res = TPMLIB_Process(&rbuffer, &rlength, &rtotal, tpm2_startup, sizeof(tpm2_startup)); if (res) { fprintf(stderr, "TPMLIB_Process(Startup) failed: 0x%02x\n", res); goto exit; } res = TPMLIB_Process(&rbuffer, &rlength, &rtotal, tpm2_selftest, sizeof(tpm2_selftest)); if (res) { fprintf(stderr, "TPMLIB_Process(TPM2_Self) failed: 0x%02x\n", res); goto exit; } if (memcmp(rbuffer, tpm2_selftest_resp, rlength)) { fprintf(stderr, "Expected response from TPM2_Selftest is different than received one.\n"); goto exit; } fprintf(stdout, "OK\n"); ret = 0; exit: TPMLIB_Terminate(); TPM_Free(rbuffer); return ret; } libtpms-0.9.3/tests/tpm2_selftest.sh000077500000000000000000000010511421143571500174710ustar00rootroot00000000000000#!/usr/bin/env bash # For the license, see the LICENSE file in the root directory. ROOT=${abs_top_builddir:-$(pwd)/..} TESTDIR=${abs_top_testdir:-$(dirname "$0")} DIR=${PWD} WORKDIR=$(mktemp -d) . ${TESTDIR}/common function cleanup() { rm -rf ${WORKDIR} } trap "cleanup" QUIT EXIT pushd $WORKDIR &>/dev/null ${DIR}/tpm2_selftest rc=$? fs=$(get_filesize NVChip) [ $? -ne 0 ] && exit 1 if [ $fs -ne 176832 ]; then echo "Error: Unexpected size of NVChip file." echo "Expected: 131072" echo "Got : $fs" rc=1 fi popd &>/dev/null exit $rc