[
  {
    "path": ".gitignore",
    "content": "build/\n"
  },
  {
    "path": ".travis.yml",
    "content": "env:\n  global:\n    secure: \"J29/ntLw9L6cZwmzz/cuYKs7lZ30zGcAW+3BRys56BcBNGy/h1i/ScKuVNTVeGngYfnpVsifDheZNOv7u+WI6cjOiA3mQaf+vtYy/VPp49GVIKhrt1H8RK0+ZalkOy3V3FAIecH3BxbwAeGhmDmEbSr/Prhy3ijIVF/67j/Qx+GUNkY6AFWO78NUvsrx88RIbGJ6lMVz6RDdtmzwNnIS1cXRkxmeK8tfr1brf2jQoqSzUswmfLAYy/n0RoZww7VzcL5O/9nATon6b36hG8XAU04AINqko19/ZxQWUuX2kHwGe3UTRcHvzJSB+z2I/vumvnfLSoQI9Q4DO/uvd62ap+V/4Rbi2tEvNb/kqHMpB9BswCCJTZkGqRcCvgMjzLbVpbewQmlH4n2zD35uReeIiZibileG5flkVIa3x3Fw/mo0nWa5YKCE49cQsETPRLBdfleyqtFIaEScVxgDIWvxxJq9mCybvIZ9VgsthoKtcspCUcNen8ptNwzuGd2TzHeL5rs1WLJGwSlnIzGlRrbNsDb+HHgDCSZr7AKTE9H+JFbg3gKu8NtoM/M+KPXDUn03Z0RFYildsMh1Q8C58ZeHTPbX/ZMZN8VWRQfKD7YANueOEji37jeSDpWY2Iyq0Q0d65M/slm1jrR+x+C98VBpB/Iw8o1R/qOqFlqL9MXX6mg=\"\nlanguage: c\naddons:\n  apt:\n    packages:\n     - libgmp-dev \n     - linux-kernel-headers\n     - build-essential\n     - kernel-package\n     - libssl-dev \n\nbefore_install:\n  - echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca-\n\naddons:\n  coverity_scan:\n    project:\n      name: \"PeterHuewe/tpm-emulator\"\n      description: \"PeterHuewe/tpm-emulator\"\n    notification_email: peterhuewe@gmx.de\n    build_command_prepend: mkdir -p build && cd build && cmake -DBUILD_DEV=OFF ../\n    build_command: make\n    branch_pattern: master\n\nscript:  mkdir -p build && cd build && cmake -DBUILD_DEV=OFF ../ && make && cd ..\n"
  },
  {
    "path": "AUTHORS",
    "content": "Mario Strasser <mast@gmx.net>\nHeiko Stamer <stamer@gaos.org> [DAA]\n"
  },
  {
    "path": "CMakeLists.txt",
    "content": "# Software-based Trusted Platform Module (TPM) Emulator\n# Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n#\n# $Id: CMakeLists.txt 475 2011-12-20 18:21:19Z mast $\n\nproject(TPM_Emulator C)\n\ncmake_minimum_required(VERSION 2.4)\ninclude(GNUInstallDirs)\nset(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true)\nif(COMMAND cmake_policy)\ncmake_policy(SET CMP0003 NEW)\nendif()\n\n# enforce out of source build\nstring(COMPARE EQUAL \"${CMAKE_SOURCE_DIR}\" \"${CMAKE_BINARY_DIR}\" IS_INSOURCE)\nif(IS_INSOURCE)\n    message(FATAL_ERROR \"${PROJECT_NAME} requires an out of source build.\")\nendif()\n\n# set project and build version\nset(${PROJECT_NAME}_VERSION_MAJOR 0)\nset(${PROJECT_NAME}_VERSION_MINOR 7)\nstring(REGEX REPLACE \".*Revision: ([0-9]+).*\" \"\\\\1\" ${PROJECT_NAME}_VERSION_BUILD \"$Revision: 475 $\")\n\n# create project configuration\nif(WIN32)\nSTRING(REGEX REPLACE \"\\\\\\\\\" \"/\" PROGRAMFILES \"$ENV{PROGRAMFILES}/${PROJECT_NAME}\")\nset(TPM_LOG_FILE \"${PROGRAMFILES}/tpmd.log\")\nset(TPM_STORAGE_NAME \"${PROGRAMFILES}/tpm_emulator-1_2_${${PROJECT_NAME}_VERSION_MAJOR}_${${PROJECT_NAME}_VERSION_MINOR}\")\nset(TPM_DEVICE_NAME \"//./pipe/tpmd:0\")\nelseif(APPLE)\nset(TPM_LOG_FILE \"/private/var/log/tpmd.log\")\nset(TPM_SOCKET_NAME \"/private/var/run/tpm/tpmd_socket:0\")\nset(TPM_STORAGE_NAME \"/private/var/lib/tpm/tpm_emulator-1_2_${${PROJECT_NAME}_VERSION_MAJOR}_${${PROJECT_NAME}_VERSION_MINOR}\")\nset(TPM_DEVICE_NAME \"/dev/tpm\")\nelse()\nset(TPM_LOG_FILE \"/var/log/tpmd.log\")\nset(TPM_SOCKET_NAME \"/var/run/tpm/tpmd_socket:0\")\nset(TPM_STORAGE_NAME \"/var/lib/tpm/tpm_emulator-1_2_${${PROJECT_NAME}_VERSION_MAJOR}_${${PROJECT_NAME}_VERSION_MINOR}\")\nset(TPM_DEVICE_NAME \"/dev/tpm\")\nendif()\nconfigure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)\nadd_definitions(-Wall -Wno-unused-parameter -Wpointer-arith -Wcast-align -Wwrite-strings)\noption(ENABLE_WERROR \"Make warnings into errors\")\nif(ENABLE_WERROR)\n    add_definitions(-Werror)\nendif()\nif(\"${CMAKE_SYSTEM}\" MATCHES \"Linux\")\n    add_definitions(-Wextra)\nendif()\nif(USE_OPENSSL)\n    add_definitions(-DUSE_OPENSSL)\nendif()\ninclude_directories(\"/opt/local/include\")\nlink_directories(\"/opt/local/lib\")\n\n# configure CPack\nset(CPACK_PACKAGE_VERSION_MAJOR ${${PROJECT_NAME}_VERSION_MAJOR})\nset(CPACK_PACKAGE_VERSION_MINOR ${${PROJECT_NAME}_VERSION_MINOR})\nset(CPACK_SOURCE_PACKAGE_FILE_NAME \"tpm_emulator-${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.4\")\nset(CPACK_SOURCE_GENERATOR \"TGZ\")\nset(CPACK_SOURCE_IGNORE_FILES \".svn/\" \"/build/\" \"/.project\" \"/.cproject\")\nset(CPACK_GENERATOR \"ZIP\")\nset(CPACK_SET_DESTDIR ON)\ninclude(CPack)\n\n# include root directories\ninclude_directories(${CMAKE_SOURCE_DIR})\ninclude_directories(${CMAKE_BINARY_DIR})\n\n# add internal libraries\nadd_subdirectory(tpm)\noption(MTM_EMULATOR \"MTM emulator\")\nif(MTM_EMULATOR)\n    add_subdirectory(mtm)\nendif()\nadd_subdirectory(crypto)\n\n# add TDDL\nadd_subdirectory(tddl)\n\n# add kernel modules\noption(BUILD_DEV \"Build linux kernel module\" ON)\nif(BUILD_DEV)\n    add_subdirectory(tpmd_dev)\nendif()\n\n# add executables\nadd_subdirectory(tpmd)\n\n"
  },
  {
    "path": "ChangeLog",
    "content": "2011-11-05  Mario Strasser <mast@gmx.net>\n\t* ChangeLog: ChangeLog updated\n\t* CMakeList.txt: minor version number updated\n\t* tpm_integrity.c: Fixed bug in TPM_Quote2; thanks go to Andreas Steffen\n\n\n2011-11-12  Mario Strasser <mast@gmx.net>\n\t* tpmd_dev/darwin/*: Added support for OS X 10.6; thanks go to Uri Blumenthal\n\t* tpm_counter.c: Bug in TPM_IncrementCounter fixed; thanks go to Charles T\n\n\n2011-11-05  Mario Strasser <mast@gmx.net>\n\t* ChangeLog: ChangeLog updated\n\t* CMakeList.txt: minor version number updated\n\n\n2011-10-25  Mario Strasser <mast@gmx.net>\n\t* tpm_owner.c: set Pubek to false in TakeOwnership\n\n\n2011-09-15  Mario Strasser <mast@gmx.net>\n\t* tpmd_dev.c: fixed byter order conversion bug for aligned memory\n\n\n2011-09-09  Mario Strasser <mast@gmx.net>\n\t* tpm_identity.c: bug fix for MakeIdentity;\n\t\tthanks go to Matthew Fioravante\n\n\n2011-07-19  Mario Strasser <mast@gmx.net>\n\t* tpm_authorization.c, tpm_cmd_handler.c, tpm_structures.h:\n\t\tcopy secret to auth struct\n\n\n2011-07-19  Mario Strasser <mast@gmx.net>\n\t* tpm_owner.c: error codes revised\n\n\n2011-07-19  Mario Strasser <mast@gmx.net>\n\t* tpm_nv_storage.c: bug in NV_DefineSpace fixed; thaks go to Luigi\n\n\n2011-07-09  Mario Strasser <mast@gmx.net>\n\t* CMakeLists.txt, crypto/*: preliminary openssl support added\n\n\n2011-06-08  Mario Strasser <mast@gmx.net>\n\t* tpm_emulator.h, tpm_owner.c, tpmd.c:\n\t\tremoved TPM_CONF_KEEP_PUBEK_READABLE\n\n\n2011-06-04  Mario Strasser <mast@gmx.net>\n\t* tpm_migration.c: bug in TPM_CMK_ApproveMA fixed\n\n\n2011-02-13  Mario Strasser <mast@gmx.net>\n\t* CMakeLists.txt: minor package version updated\n\n\n2011-02-12  Mario Strasser <mast@gmx.net>\n\t* ChangeLog: ChangeLog updated\n\t* CMakeLists.txt: minor package version updated\n\t* tpmd_dev.c: switched to new ioctl function\n\n\n2010-12-30  Mario Strasser <mast@gmx.net>\n\t* build.bat: Missing path for Windows 7 added\n\n\n2010-10-09  Mario Strasser <mast@gmx.net>\n\t* tpm_capability.c: Bug in TPM_SetCapability fixed\n\n\n2010-09-11  Mario Strasser <mast@gmx.net>\n\t* all: Open/FreeBSD compatibility fixes\n\n\n2010-07-19  Mario Strasser <mast@gmx.net>\n\t* tpm_daa.c: Bug in TPM_LoadContext and TPM_DAA_Join/Sign\n\t\tfixed; thanks go toEmanuele Cesena\n\n\n2010-07-05  Mario Strasser <mast@gmx.net>\n\t* ChangeLog: ChangeLog updated\n\t* tpmd_dev/linux/*: missing kernel header file added\n\n\n2010-06-13  Mario Strasser <mast@gmx.net>\n\t* tpm_migration.c, tpm_cmd_handler.c, tpm_crypto.c:\n\t\tbugs in [CMK]MigrationBlob encoding, TPM_MigrateKey(),\n\t\tand TPM_CertifyKey2 fixed; thanks go to S. Tate\n\t* tpm_structures.h: bug in TPM_CERTIFY_INFO fixed;\n\t\tthanks go to S. Tate\n\n\n2010-06-10  Mario Strasser <mast@gmx.net>\n\t* tpm_nv_storage.c: bug in TPM_NV_WriteValue() fixed;\n\t\tthanks go to Luigi Semenzato\n\n\n2010-03-17  Mario Strasser <mast@gmx.net>\n\t* tpm_emulator_extern.[ch]: external functions changed\n\t\tinto function pointers\n\t* tpmd/*/tpmd.c: tpmd functions updated\n\n\n2010-03-12  Mario Strasser <mast@gmx.net>\n\t* tpm_nv_storage.c: bug in TPM_NV_DefineSpace fixed;\n\t\tthanks go to Luigi Semenzato\n\t* README, build.sh: build description updated\n\n\n2010-02-22  Mario Strasser <mast@gmx.net>\n\t* tpmd_dev/darwin/*: darwin module added\n\t* Makefile: installation on Mac OS X enabled\n\t* README: README updated\n\t* ChangeLog: ChangeLog updated\n\n\n2010-02-19  Mario Strasser <mast@gmx.net>\n\t* windows/*: several fixes\n\t* crypto/bn.c: work around for older gmp libs\n\t* tddl/*: platform independent tddl\n\t* README: README updated\n\n\n2010-02-18  Mario Strasser <mast@gmx.net>\n\t* build.sh, buils.bat: build scripts added\n\t* tpmd.c, tpm_emulator_extern.h: log modes independent of syslog\n\t* windows/tpmd.c: tpmd for windows added\n\t* windows/control_tpmd.bat: service control function added\n\n\n2010-02-16  Mario Strasser <mast@gmx.net>\n\t* tpm/*: MTM functions added\n\t* tpmd.c: parameter to set configuration flags added\n\t* README: README updated\n\n\n2010-02-15  Mario Strasser <mast@gmx.net>\n\t* tpm_emulator.h, tpm_cmd_handler.c: startup configuration added\n\t* CMakeLists.txt: build of openbsd module added\n\t* tpm/*: MTM support prepared and MTM hooks added\n\n\n2010-02-13  Mario Strasser <mast@gmx.net>\n\t* all: unused variables removed; free_TPM_DATA added\n\n\n2010-02-12  Mario Strasser <mast@gmx.net>\n\t* tpm_marshalling.[ch]: (un)marshaling_TPM_DATA added\n\n\n2010-02-11  Mario Strasser <mast@gmx.net>\n\t* CMakeLists.txt: installation support added\n\t* README: README updated\n\t* *.h: headers updated\n\n\n2010-02-10  Mario Strasser <mast@gmx.net>\n\t* all: new CMake makefiles added\n\t* README: README updated\n\t* CMakeLists.txt, config.h.in: cpack support added\n\n\n2010-02-09  Mario Strasser <mast@gmx.net>\n\t* crypto/*, tpm/*: BE* conversion functions removed\n\t* tpmd/tpmd.c:  smart startup mode handling\n\t* crypto/*.h, tpm/*.h: tpm_emulator_config.h removed\n\t* tpm_testinc.c: usage of tpm_min/max removed\n\t* tpm_data.c, tpm_emulator_extern.h, tpmd.c:\n\t\t_file -> _storage\n\t* config.h: central config.h added\n\t* all: directory structure changed\n\n\n2009-12-05  Mario Strasser <mast@gmx.net>\n\t* tpmd_dev/Makefile: installation patch added, thanks go to David Anderson\n\n\n2009-10-05  Mario Strasser <mast@gmx.net>\n\t* all: numerous bug fixes to make the trousers test pass\n\n\n2009-10-02  Mario Strasser <mast@gmx.net>\n\t* tpm_delegation.c: delegation support completed\n\n\n2009-09-24  Mario Strasser <mast@gmx.net>\n\t* tpm_crypto.c: internal, deterministic PRNG added (for testing etc.)\n\t* tpm_authorization.c: DSAP verification added\n\n\n2009-09-19  Mario Strasser <mast@gmx.net>\n\t* tpm_capability.c: TPM_SetCapability() added\n\t* tpm_capability.c: TPM_GetCapability() completed\n\t* ChangeLog: changelog updated\n\n\n2009-09-18  Mario Strasser <mast@gmx.net>\n\t* tpm_commands.h: declarations and descriptions of internal\n\t\tfunctions added\n\n\n2009-09-17  Mario Strasser <mast@gmx.net>\n\t* tpm_authorization.c: DSAP support added\n\n\n2009-08-28  Mario Strasser <mast@gmx.net>\n\t* tpm_migration.c: CMK handling completed\n\t* tpm_owner.c: TPM_OwnerClear() updated\n\t* all: code cleanup, obsolete code removed\n\t* tpm_capability.c: capability support revised\n\t* tpm_commands.h: missing parameter added\n\n\n2009-08-27  Mario Strasser <mast@gmx.net>\n\t* tpm_structures.h: structures updated and completed\n\t* all: major revision number incremented to 6 due to changes in the\n\t\tinternal data structure\n\t* ChangeLog: changelog updated\n\n\n2009-08-26  Mario Strasser <mast@gmx.net>\n\t* tpm_migration.c: bugs in CMK functionality fixed, migration support\n\t\tcompleted and enabled\n\t* tpm_storage.c: usage of default exponent in pubkey generation fixed\n\n\n2009-08-25  Mario Strasser <mast@gmx.net>\n\t* tpm_migration.c: bugs in key migration functionality fixed\n\n\n2009-08-19  Mario Strasser <mast@gmx.net>\n\t* tpm_migration.c: TPM_CMK_CreateBlob() and\n\t\tTPM_CMK_ConvertMigration() added\n\n\n2009-08-13  Mario Strasser <mast@gmx.net>\n\t* tpm_migration.c: size_t issue fixed; thanks to E. Fleury\n\n\n2009-08-10  Mario Strasser <mast@gmx.net>\n\t* tpm_storage.c: TPM_CreateWrapKey() updated\n\t* tpm_migration.c: TPM_CMK_CreateKey() added\n\n\n2009-08-09  Mario Strasser <mast@gmx.net>\n\t* tpm_storage.c: tpm_decrypt and tpm_encrypt added\n\t* tpm_migration.c: initial migration support added\n\t* tpm_migration.c: CMK support added\n\n\n2009-08-04  Mario Strasser <mast@gmx.net>\n\t* tpm_deprecated.c, tpm_migration.c: bugs fixed; thanks to M. Schmidt\n\n\n2009-06-05  Mario Strasser <mast@gmx.net>\n\t* tpm_structures.c: bug in rsa key size computation fixed\n\n\n2009-05-30  Mario Strasser <mast@gmx.net>\n\t* tpm_owner.c: set readPubek to false once the TPM is owned\n\n\n2009-04-08  Mario Strasser <mast@gmx.net>\n\t* tpmd.c: missing mkdirs call added\n\n\n2008-10-13  Mario Strasser <mast@gmx.net>\n\t* rsa.[ch]: functions to determine rsa key length added\n\t* tpm_structures.h: sizeof_RSA uses precise vales\n\n\n2008-05-06  Mario Strasser <mast@gmx.net>\n\t* tpm_storage.c: version 1.1 compatibility fixed\n\n\n2008-03-23  Mario Strasser <mast@gmx.net>\n\t* tpm_maintenance.c: management support added\n\t* tpm_maintenance.c: several fixes in the maintenance support\n\t* tpm_storage.c: TPM_Sealx fixed and TPM_UnSeal adapted\n\n\n2008-03-22  Mario Strasser <mast@gmx.net>\n\t* tpm_cmd_handler.c tpm_maintenance.c: maintenance support added\n\n\n2008-03-21  Mario Strasser <mast@gmx.net>\n\t* rsa.[ch], tpm_storage.c: TPM_Sealx added\n\n\n2008-03-13  Mario Strasser <mast@gmx.net>\n\t* tpm_owner.c: memory leak in TPM_OwnerClear fixed\n\n\n2008-03-12  Mario Strasser <mast@gmx.net>\n\t* rsa.c: memory leak fixed\n\t* all: NV support added\n\n\n2008-03-03  Heiko Stamer <stamer@gaos.org>\n\t* tpm_deprecated.c, tpm_marshalling.c: TPM_ChangeAuthAsymFinish() added\n\t* tpm_capability.c: supported commands changed\n\n\n2008-02-21  Heiko Stamer <stamer@gaos.org>\n\t* tpm_deprecated.c, tpm_storage.c: TPM_ChangeAuthAsymStart() added\n\n\n2008-02-12  Mario Strasser <mast@gmx.net>\n\t* ChangeLog: changes updated for release 0.5.1\n\n\n2008-01-07  Mario Strasser <mast@gmx.net>\n\t* tpmd_dev_openbsd/*: OpenBSD module added\n\n\n2007-12-19 Heiko Stamer <stamer@gaos.org> \n\t* tpm_cmd_handler.c, tpm_integrity.c: sig. bug in TPM_Quote2() fixed\n\n\n2007-12-16  Heiko Stamer <stamer@gaos.org>\n\t* tpm_transport.c: missing ptr initialization fixed\n\n\n2007-12-15  Mario Strasser <mast@gmx.net>\n\t* tddl.c, tpm_emulator_config.h: support for FreeBSD/OpenBSD added\n\n\n2007-12-07  Heiko Stamer <stamer@gaos.org>\n\t* tpm_structures.h: session identifier added\n\n\n2007-12-07  Heiko Stamer <stamer@gaos.org>\n\t* tpm_cmd_handler.c, tpm_counter.c: small fixes for counters\n\n\n2007-12-07  Heiko Stamer <stamer@gaos.org>\n\t* tpm_authorization.c, tpm_eviction.c, tpm_handles.c:\n\t\tfixes and debug calls for TSS Test Suite (TrouSerS)\n\n\n2007-12-07  Heiko Stamer <stamer@gaos.org>\n\t* tpm_deprecated.c: fixed DIR index value, according to spec v1.2 rev 103\n\n\n2007-12-05  Mario Strasser <mast@gmx.net> \n\t* tpmd.c: optional creation of missing directories added\n\n\n2007-11-19  Mario Strasser <mast@gmx.net>\n\t* Makefile: make rule for tpmd_dev.rules.in added\n\n\n2007-11-09  Mario Strasser <mast@gmx.net>\n\t* tpm_storage.c, tpm_emulator_config.h: bug in TPMLoadKey fixed\n\n\n2007-09-08  Mario Strasser <mast@gmx.net>\n\t* Makefile: make rules for tpmd_dev.rules added\n\n\n2007-09-05  Heiko Stamer <stamer@gaos.org>\n\t* tpm_deprecated.c: minor bug fixes\n\n\n2007-09-05  Heiko Stamer <stamer@gaos.org>\n\t* tpm_deprecated.c: TPM_ChangeAuthAsymStart() updated\n\n\n2007-09-02  Mario Strasser <mast@gmx.net>\n\t* all Makefiles: some more install fixes\n\n\n2007-08-23  Mario Strasser <mast@gmx.net>\n\t* tpmd.c: bug in tpm_get_ticks fixed\n\n\n2007-08-08  Mario Strasser <mast@gmx.net>\n\t* tpm_integrity.c, tpm_startup.c: bug fixes regarding localityModifier\n\n\n2007-08-07  Mario Strasser <mast@gmx.net>\n\t* tpmd.c: effective user/group can be specified\n\n\n2007-08-06  Mario Strasser <mast@gmx.net>\n\t* all Makefiles: install-tool based installation\n\n\n2007-08-02  Mario Strasser <mast@gmx.net>\n\t* tpm_data.c, tpm_marshalling.c: fixes to make rev 103 changes work\n\t* tpmd_dev.rules: udev rules added  \n\t\n\n2007-08-02  Heiko Stamer <stamer@gaos.org>\n\t* tpm_credentials.c, tpm_crypto.c, tpm_daa.c, tpm_data.c,\n\t\ttpm_marshalling.c, tpm_structures.h: fixes to make rev 103 changes work\n\n\n2007-08-02  Mario Strasser <mast@gmx.net>\n\t* Makefile: soname added\n\n\n2007-08-01  Mario Strasser <mast@gmx.net> \n\t* tddl.c, tpm_storage.c, Makefile, tpmd.c,\n\t\ttpmd_dev.c: default storage directories for state and sockets changed\n\n\n2007-07-28  Heiko Stamer <stamer@gaos.org>\n\t* Makefile: setting soname (FIXME: need version?)\n\n\n2007-07-28  Heiko Stamer <stamer@gaos.org>\n\t* tpm_capability.c, tpm_deprecated.c,\n\t\ttpm_integrity.c: fixes needed for adapting v1.2 rev 103\n\n\n2007-07-27  Heiko Stamer <stamer@gaos.org>\n\t* tpm_capability.c, tpm/tpm_commands.h, tpm_deprecated.c,\n\t\ttpm_structures.h: changes from v1.2 rev 103\n\n\n2007-07-25  Heiko Stamer <stamer@gaos.org>\n\t* tpm_integrity.c: fixing a specification error corrected in v1.2 rev 103\n\n2007-07-05  Mario Strasser <mast@gmx.net>\n\t* tpmd.c: double free fixed, type bug fixed\n\n\n2007-03-23  Mario Strasser <mast@gmx.net>\n\t* tpmd.c: additional tpmd parameters added\n\n\n2006-12-27  Mario Strasser <mast@gmx.net>\n\t* Makefile, tddl.c: gcc 4.1 warnings removed\n\n\n2006-12-03  Mario Strasser <mast@gmx.net>\n\t* Makefile: tpm_dev excluded from standard distribution\n\n\n2006-12-03  Mario Strasser <mast@gmx.net>\n\t* all: tpm daemon and device driver library added\n\n\n2006-11-29  Mario Strasser <mast@gmx.net>\n\t* Makefile: VERSION_SUFFIX added\n\n\n2006-11-14  Mario Strasser <mast@gmx.net>\n\t* gmp_kernel_wrapper.c, tpm_data.c: import and export\n\t\tfunctions simplified\n\t* tpm_emulator_config.h: min/max macros renamed\n\t* tpm_data.c, tpm_cmd_handler.c, tpm_startup.c:\n\t\tstartup/restore behavior adapted according to rev94\n\n\n2006-11-12  Mario Strasser <mast@gmx.net>\n\t* gmp_kernel_wrapper.c: __stack_chk_fail() to GNU MP wrapper added\n\t* tpm_daa.c: size_t vs. uint32_t issue in DAA routines fixed\n\t* rsa.c, tpm_daa.c, tpm_deprecated.c, tpm/tpm_testing.c,\n\t\ttpm_transport.c: pointer signedness warnings fixed\n\n\n2006-11-11  Mario Strasser <mast@gmx.net>\n\t* bn.[ch], rsa.[ch], tpm_daa.c, tpm_storage.c, tpm_testing.c:\n\t\tbn wrapper added\n\t* gmp_kernel_wrapper.c, linux_module.c: printf format for size_t fixed\n\n\n2006-11-10  Mario Strasser <mast@gmx.net>\n\t* all: potential name space conflicts for global symbols solved\n\n\n2006-11-07  Mario Strasser <mast@gmx.net>\n\t* sha1.[ch], tpm_*: some issues related to 64bit architecture\n\t\tand size_t fixed\n\t* rsa.c: potential bug in key generation fixed\n\t* all: advanced compiler warnings and name space collisions fixed\n\n\n2006-10-25  Mario Strasser <mast@gmx.net>\n\t* gmp_kernel_wrapper.c, rsa.c: removed all GNU MP random routines\n\t* linux_module.c, linux_module.h, tpm_emulator_config.h: moved all host\n\t\tspecific functions and configuration parameters from\n\t\tlinux_module.h into tpm_emulator_config.h\n\t* tpm_audit.c, tpm_identity.c, tpm_marshalling.h, tpm_transport.c:\n\t\tfixed some marshalling statements which cause troubles\n\t\tif memory alignment is mandatory\n\n\n2006-10-20  Mario Strasser <mast@gmx.net>\n\t* tpm_capability: inline definition changed due to\n\t\tinteroperability reasons\n\t* tpm_cmd_handler.c: marshalling bug in TPM_Seal[x] fixed\n\n\n2006-10-17  Mario Strasser <mast@gmx.net>\n\t* tpm_cmd_handler.c, tpm_emulator.h: meaning of out/out_size\n\t\tparameter for tpm_handle_command slightly modified\n\t* linux_module.c: support for storage_file parameter added\n\t* linux_module.[ch], tpm_data.c: file storage functions moved\n\t\tinto module\n\t* all: some minor typos/bugs fixed\n\n\n2006-10-11  Mario Strasser <mast@gmx.net>\n\t* all: redundant includes removed\n\n\n2006-09-03  Heiko Stamer <stamer@gaos.org>\n\t* tpm_capability.c: small fixes (TPM_MANUFACTURER)\n\n\n2006-08-14  Mario Strasser <mast@gmx.net>\n\t* tpm_storage.c: required key size fixed\n\n\n2006-08-06  Heiko Stamer <stamer@gaos.org>\n\t* tpm_error.c: DAA error description added\n\n\n2006-08-01  Heiko Stamer <stamer@gaos.org>\n\t* tpm_integrity.c: TPM_Quote2() added\n\n\n2006-06-23  Mario Strasser <mast@gmx.net>\n\t* tpm_startup.c: behaviour of ST_CLEAR and storage of\n\t\tpersistent data adapted\n\n\n2006-06-18  Heiko Stamer <stamer@gaos.org>\n\t* tpm_identity.c: identity creation and activation,\n\t\tthat is TPM_MakeIdentity and TPM_ActivateIdentity added\n\n\n2005-12-24  Mario Strasser <mast@gmx.net>\n\t* tpm_transport.c, tpm_marshalling.c, tpm_structures.h:\n\t\tTransport session functionality added\n\n\n2005-12-16  Mario Strasser <mast@gmx.net>\n\t* linux_module.c: ioctl() support added\n\t* tpm_capability.c: TPM_GetCapability() adapted to make\n\t\tit work with trousers\n\n\n2005-12-09  Heiko Stamer <stamer@gaos.org>\n\t* tpm_marshalling.c, tpm_daa.c, rsa.c: DAA functionality,\n\t\tthat is TPM_DAA_Join and TPM_DAA_Sign added\n\n\n2005-08-15  Mario Strasser <mast@gmx.net>\n\t* all: some typos corrected\n\t* tpm_integrity.c: bug in TPM_Extend fixed\n\n\n2005-05-07  Mario Strasser <mast@gmx.net>\n\t* bug in TPM_SaveContext fixed\n\n\n2005-04-30  Mario Strasser <mast@gmx.net>\n\t* tpm_digest.c: audit functionality added\n \n\n2005-04-29  Mario Strasser  <mast@gmx.net>\n\t* tpm_context.c: TPM_KeyControlOwner, TPM_SaveContext, \n\t\tand TPM_LoadContext added\n\t* tpm_deprecated: TPM_(Save|Load)(Key|Auth)Context added\n\t* rc4.[ch]: RC4 encryption added\n\t* rsa.c: rsa_copy_key added\n\n\n2005-04-27  Mario Strasser  <mast@gmx.net>\n\t* tpm_crypto.c: TPM_CertifyKey and TPM_CertifyKey2 added\n\t* tpm_deprecated: TPM_OwnerReadPubek, TPM_CertifySelfTest,\n\t\tTPM_DirWriteAuth, and TPM_DirRead added\n\n\n2005-04-26  Mario Strasser  <mast@gmx.net>\n\t* tpm_ticks.c: timing ticks functionality added\n\t* tpm_authorization.c: TPM_ChangeAuth and TPM_ChangeAuthOwner added\n\t* tpm_storage, tpm_crypto.c, tpm_integrity.c: authorization \n\t\tverification now considers the value of authDataUsage\n\t* tpm_storage: TPM_UnBind added\n\n\n2004-10-24  Mario Strasser  <mast@gmx.net>\n\t* Makefile: new makefile for Linux kernels > 2.5.0 build system\n\t* tpm_testing.c: replacement of some floating-point calculations \n\t\twith fix-point arithmetic \n\t* all: minor changes int the directory and header file structure\n\t       \tto make the package easier portable and maintainable \n\n\n2004-07-01  Mario Strasser  <mast@gmx.net>  \n\t* Initial release based on my semester thesis\n\n"
  },
  {
    "path": "LICENSE",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 2, June 1991\n\n Copyright (C) 1989, 1991 Free Software Foundation, Inc.,\n 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The licenses for most software are designed to take away your\nfreedom to share and change it.  By contrast, the GNU General Public\nLicense is intended to guarantee your freedom to share and change free\nsoftware--to make sure the software is free for all its users.  This\nGeneral Public License applies to most of the Free Software\nFoundation's software and to any other program whose authors commit to\nusing it.  (Some other Free Software Foundation software is covered by\nthe GNU Lesser General Public License instead.)  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthis service if you wish), that you receive source code or can get it\nif you want it, that you can change the software or use pieces of it\nin new free programs; and that you know you can do these things.\n\n  To protect your rights, we need to make restrictions that forbid\nanyone to deny you these rights or to ask you to surrender the rights.\nThese restrictions translate to certain responsibilities for you if you\ndistribute copies of the software, or if you modify it.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must give the recipients all the rights that\nyou have.  You must make sure that they, too, receive or can get the\nsource code.  And you must show them these terms so they know their\nrights.\n\n  We protect your rights with two steps: (1) copyright the software, and\n(2) offer you this license which gives you legal permission to copy,\ndistribute and/or modify the software.\n\n  Also, for each author's protection and ours, we want to make certain\nthat everyone understands that there is no warranty for this free\nsoftware.  If the software is modified by someone else and passed on, we\nwant its recipients to know that what they have is not the original, so\nthat any problems introduced by others will not reflect on the original\nauthors' reputations.\n\n  Finally, any free program is threatened constantly by software\npatents.  We wish to avoid the danger that redistributors of a free\nprogram will individually obtain patent licenses, in effect making the\nprogram proprietary.  To prevent this, we have made it clear that any\npatent must be licensed for everyone's free use or not licensed at all.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                    GNU GENERAL PUBLIC LICENSE\n   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n\n  0. This License applies to any program or other work which contains\na notice placed by the copyright holder saying it may be distributed\nunder the terms of this General Public License.  The \"Program\", below,\nrefers to any such program or work, and a \"work based on the Program\"\nmeans either the Program or any derivative work under copyright law:\nthat is to say, a work containing the Program or a portion of it,\neither verbatim or with modifications and/or translated into another\nlanguage.  (Hereinafter, translation is included without limitation in\nthe term \"modification\".)  Each licensee is addressed as \"you\".\n\nActivities other than copying, distribution and modification are not\ncovered by this License; they are outside its scope.  The act of\nrunning the Program is not restricted, and the output from the Program\nis covered only if its contents constitute a work based on the\nProgram (independent of having been made by running the Program).\nWhether that is true depends on what the Program does.\n\n  1. You may copy and distribute verbatim copies of the Program's\nsource code as you receive it, in any medium, provided that you\nconspicuously and appropriately publish on each copy an appropriate\ncopyright notice and disclaimer of warranty; keep intact all the\nnotices that refer to this License and to the absence of any warranty;\nand give any other recipients of the Program a copy of this License\nalong with the Program.\n\nYou may charge a fee for the physical act of transferring a copy, and\nyou may at your option offer warranty protection in exchange for a fee.\n\n  2. You may modify your copy or copies of the Program or any portion\nof it, thus forming a work based on the Program, and copy and\ndistribute such modifications or work under the terms of Section 1\nabove, provided that you also meet all of these conditions:\n\n    a) You must cause the modified files to carry prominent notices\n    stating that you changed the files and the date of any change.\n\n    b) You must cause any work that you distribute or publish, that in\n    whole or in part contains or is derived from the Program or any\n    part thereof, to be licensed as a whole at no charge to all third\n    parties under the terms of this License.\n\n    c) If the modified program normally reads commands interactively\n    when run, you must cause it, when started running for such\n    interactive use in the most ordinary way, to print or display an\n    announcement including an appropriate copyright notice and a\n    notice that there is no warranty (or else, saying that you provide\n    a warranty) and that users may redistribute the program under\n    these conditions, and telling the user how to view a copy of this\n    License.  (Exception: if the Program itself is interactive but\n    does not normally print such an announcement, your work based on\n    the Program is not required to print an announcement.)\n\nThese requirements apply to the modified work as a whole.  If\nidentifiable sections of that work are not derived from the Program,\nand can be reasonably considered independent and separate works in\nthemselves, then this License, and its terms, do not apply to those\nsections when you distribute them as separate works.  But when you\ndistribute the same sections as part of a whole which is a work based\non the Program, the distribution of the whole must be on the terms of\nthis License, whose permissions for other licensees extend to the\nentire whole, and thus to each and every part regardless of who wrote it.\n\nThus, it is not the intent of this section to claim rights or contest\nyour rights to work written entirely by you; rather, the intent is to\nexercise the right to control the distribution of derivative or\ncollective works based on the Program.\n\nIn addition, mere aggregation of another work not based on the Program\nwith the Program (or with a work based on the Program) on a volume of\na storage or distribution medium does not bring the other work under\nthe scope of this License.\n\n  3. You may copy and distribute the Program (or a work based on it,\nunder Section 2) in object code or executable form under the terms of\nSections 1 and 2 above provided that you also do one of the following:\n\n    a) Accompany it with the complete corresponding machine-readable\n    source code, which must be distributed under the terms of Sections\n    1 and 2 above on a medium customarily used for software interchange; or,\n\n    b) Accompany it with a written offer, valid for at least three\n    years, to give any third party, for a charge no more than your\n    cost of physically performing source distribution, a complete\n    machine-readable copy of the corresponding source code, to be\n    distributed under the terms of Sections 1 and 2 above on a medium\n    customarily used for software interchange; or,\n\n    c) Accompany it with the information you received as to the offer\n    to distribute corresponding source code.  (This alternative is\n    allowed only for noncommercial distribution and only if you\n    received the program in object code or executable form with such\n    an offer, in accord with Subsection b above.)\n\nThe source code for a work means the preferred form of the work for\nmaking modifications to it.  For an executable work, complete source\ncode means all the source code for all modules it contains, plus any\nassociated interface definition files, plus the scripts used to\ncontrol compilation and installation of the executable.  However, as a\nspecial exception, the source code distributed need not include\nanything that is normally distributed (in either source or binary\nform) with the major components (compiler, kernel, and so on) of the\noperating system on which the executable runs, unless that component\nitself accompanies the executable.\n\nIf distribution of executable or object code is made by offering\naccess to copy from a designated place, then offering equivalent\naccess to copy the source code from the same place counts as\ndistribution of the source code, even though third parties are not\ncompelled to copy the source along with the object code.\n\n  4. You may not copy, modify, sublicense, or distribute the Program\nexcept as expressly provided under this License.  Any attempt\notherwise to copy, modify, sublicense or distribute the Program is\nvoid, and will automatically terminate your rights under this License.\nHowever, parties who have received copies, or rights, from you under\nthis License will not have their licenses terminated so long as such\nparties remain in full compliance.\n\n  5. You are not required to accept this License, since you have not\nsigned it.  However, nothing else grants you permission to modify or\ndistribute the Program or its derivative works.  These actions are\nprohibited by law if you do not accept this License.  Therefore, by\nmodifying or distributing the Program (or any work based on the\nProgram), you indicate your acceptance of this License to do so, and\nall its terms and conditions for copying, distributing or modifying\nthe Program or works based on it.\n\n  6. Each time you redistribute the Program (or any work based on the\nProgram), the recipient automatically receives a license from the\noriginal licensor to copy, distribute or modify the Program subject to\nthese terms and conditions.  You may not impose any further\nrestrictions on the recipients' exercise of the rights granted herein.\nYou are not responsible for enforcing compliance by third parties to\nthis License.\n\n  7. If, as a consequence of a court judgment or allegation of patent\ninfringement or for any other reason (not limited to patent issues),\nconditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot\ndistribute so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you\nmay not distribute the Program at all.  For example, if a patent\nlicense would not permit royalty-free redistribution of the Program by\nall those who receive copies directly or indirectly through you, then\nthe only way you could satisfy both it and this License would be to\nrefrain entirely from distribution of the Program.\n\nIf any portion of this section is held invalid or unenforceable under\nany particular circumstance, the balance of the section is intended to\napply and the section as a whole is intended to apply in other\ncircumstances.\n\nIt is not the purpose of this section to induce you to infringe any\npatents or other property right claims or to contest validity of any\nsuch claims; this section has the sole purpose of protecting the\nintegrity of the free software distribution system, which is\nimplemented by public license practices.  Many people have made\ngenerous contributions to the wide range of software distributed\nthrough that system in reliance on consistent application of that\nsystem; it is up to the author/donor to decide if he or she is willing\nto distribute software through any other system and a licensee cannot\nimpose that choice.\n\nThis section is intended to make thoroughly clear what is believed to\nbe a consequence of the rest of this License.\n\n  8. If the distribution and/or use of the Program is restricted in\ncertain countries either by patents or by copyrighted interfaces, the\noriginal copyright holder who places the Program under this License\nmay add an explicit geographical distribution limitation excluding\nthose countries, so that distribution is permitted only in or among\ncountries not thus excluded.  In such case, this License incorporates\nthe limitation as if written in the body of this License.\n\n  9. The Free Software Foundation may publish revised and/or new versions\nof the General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\nEach version is given a distinguishing version number.  If the Program\nspecifies a version number of this License which applies to it and \"any\nlater version\", you have the option of following the terms and conditions\neither of that version or of any later version published by the Free\nSoftware Foundation.  If the Program does not specify a version number of\nthis License, you may choose any version ever published by the Free Software\nFoundation.\n\n  10. If you wish to incorporate parts of the Program into other free\nprograms whose distribution conditions are different, write to the author\nto ask for permission.  For software which is copyrighted by the Free\nSoftware Foundation, write to the Free Software Foundation; we sometimes\nmake exceptions for this.  Our decision will be guided by the two goals\nof preserving the free status of all derivatives of our free software and\nof promoting the sharing and reuse of software generally.\n\n                            NO WARRANTY\n\n  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\nFOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\nOTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\nPROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\nOR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\nTO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\nPROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\nREPAIR OR CORRECTION.\n\n  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\nREDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\nINCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\nOUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\nTO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\nYOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\nPROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGES.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nconvey the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software; you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License along\n    with this program; if not, write to the Free Software Foundation, Inc.,\n    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n\nAlso add information on how to contact you by electronic and paper mail.\n\nIf the program is interactive, make it output a short notice like this\nwhen it starts in an interactive mode:\n\n    Gnomovision version 69, Copyright (C) year name of author\n    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, the commands you use may\nbe called something other than `show w' and `show c'; they could even be\nmouse-clicks or menu items--whatever suits your program.\n\nYou should also get your employer (if you work as a programmer) or your\nschool, if any, to sign a \"copyright disclaimer\" for the program, if\nnecessary.  Here is a sample; alter the names:\n\n  Yoyodyne, Inc., hereby disclaims all copyright interest in the program\n  `Gnomovision' (which makes passes at compilers) written by James Hacker.\n\n  <signature of Ty Coon>, 1 April 1989\n  Ty Coon, President of Vice\n\nThis General Public License does not permit incorporating your program into\nproprietary programs.  If your program is a subroutine library, you may\nconsider it more useful to permit linking proprietary applications with the\nlibrary.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.\n"
  },
  {
    "path": "README",
    "content": " _____ ____  __  __           _____                 _       _\n|_   _|  _ \\|  \\/  |         | ____|_ __ ___  _   _| | __ _| |_ ___  _ __\n  | | | |_) | |\\/| |  _____  |  _| | '_ ` _ \\| | | | |/ _` | __/ _ \\| '__|\n  | | |  __/| |  | | |_____| | |___| | | | | | |_| | | (_| | || (_) | |\n  |_| |_|   |_|  |_|         |_____|_| |_| |_|\\__,_|_|\\__,_|\\__\\___/|_|\n\n TPM-Emulator v0.7 -\n A Software-based TPM and MTM Emulator.\n--------------------------------------------------------------------------\n\nCopyright\n--------------------------------------------------------------------------\nCopyright (C) 2009-2011 Mario Strasser.\nCopyright (C) 2004-2009 Mario Strasser, ETH Zurich.\n\n\nThis program is free software; you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation; either version 2 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU General Public License for more details.\n\n\nPackage\n--------------------------------------------------------------------------\nThe tpm emulator package comprises four main parts:\n\na) tpmd - a user-space application that implements the actual emulator\n   and can be accessed by means of Unix domain sockets (Unix) or\n   named pipes (Windows).\n\nb) tpmd_dev - a kernel module that provides the device /dev/tpm for\n   backward compatibility and forwards the received commands to tpmd\n   (Unix and Mac OS X only).\n\nc) tddl - a TSS conform device driver library for the emulator.\n\n\nCompilation and Installation\n--------------------------------------------------------------------------\nThe compilation and installation of the TPM emulator package is based on\nthe CMake build environment (version 2.6 or better) and requires that the \nGNU MP library (version 4.0 or better) is properly installed on your\nsystem. A working MinGW compiler suite is further required on Windows\n(see http://www.mingw.org/). To compile and install the package execute:\n\n# tar -xvzf tpm_emulator-X.Y.tar.gz\n# cd tpm_emulator-X.Y\n# mkdir build\n# cd build\n# cmake ../\n# make\n# make install\n\nThe script files build.sh and build.bat automate the compliation process.\n\nOn Windows, the TPM emulator system service has additionally to be\nregistered by calling:\n# control_tpmd.bat install\n\nMTM support can be enabled by replacing\n# cmake ../\nwith\n# cmake ../ -DMTM_EMULATOR=ON\n\n\nStartup\n--------------------------------------------------------------------------\nIn order to use the TPM emulator on Unix or Mac OS X, one has to start the\nTPM emulator daemon and load the TPM device forwarding module. On Linux,\nthis is done by executing:\n\n# modprobe tpmd_dev\n# tpmd\n\nOn Windows, the TPM emulator service can either be started with the\nMicrosoft Management Console or with the control_tpmd.bat script:\n\n# control_tpmd.bat start\n# control_tpmd.bat status\n\nThe startup mode of the TPM (see TPM Spec. Part 1) is defined by the\nstartup mode argument and can either be set to clear, save (default)\nor deactivated. Additionally supported arguments are\n\nusage: tpmd [-d] [-f] [-s storage file] [-u unix socket name]\n            [-o user name] [-g group name] [-h] [startup mode]\n  d : enable debug mode\n  f : forces the application to run in the foreground\n  s : storage file to use (default: /var/lib/tpm/tpm_emulator-1_2_0_7)\n  u : unix socket name to use (default: /var/run/tpm/tpmd_socket:0)\n  o : effective user the application should run as\n  g : effective group the application should run as\n  h : print this help message\n  startup mode : must be 'clear', 'save' (default) or 'deactivated\n\nand\n\nusage: tpmd.exe [-d] [-f] [-s storage file] [-u windows pipe name]\n                [-l log file] [-h] [startup mode]\n  d : enable debug mode\n  f : forces the application to run in the foreground\n  s : storage file to use (default:\n      C:/Program Files/TPM_Emulator/tpm_emulator-1_2_0_7)\n  u : windows named pipe name to use (default: //./pipe/tpmd:0)\n  l : name of the log file (default: C:/Program Files/TPM_Emulator/tpmd.log)\n  h : print this help message\n  startup mode : must be 'clear', 'save' (default) or 'deactivated\n\non Unix and Windows, respectively.\n\nIf the emulator is started in mode save and fails to load a previously\nstored TPM state, it will go into fail-stop mode and has to be reloaded.\nTherefore, the first time the TPM emulator is started, the argument must\nbe set to 'clear'. Recovering a TPM emulator that is in fail-stop mode\nis done by first deactivating it and then reloading it in mode 'clear':\n\n# tpmd deactivated\n# killall tpmd\n# tpmd clear\n\n\nUsage and Backward Compatibility\n--------------------------------------------------------------------------\nThe most correct and convenient way to access the tpm emulator is to use\nthe provided device driver library (tddl). For a comprehensive description\nof its functionality we refer to the official TCG specification (see\nhttps://www.trustedcomputinggroup.org/specs/TSS), an example of use is\ngiven by the test application tddl/test_tddl.\n\nNote that on Windows the tddl is called ifxtpm.dll as many applications\n(e.g., TPM/J) expect this name and do not support alternative drivers.\n\nFor backward compatibility with existing Unix applications, the kernel\nmodule tpmd_dev forwards any command sent to the device /dev/tpm to the\ntpm emulator daemon. In order to access the emulator directly (i.e.,\nwithout using the device driver library or the device dev/tpm) all one\nhas to do is to include the header files sys/socket.h and sys/un.h and\nto replace the open(\"/dev/tpm\") call with something like:\n\nstruct sockaddr_un addr;\nfh = socket(PF_UNIX, SOCK_STREAM, 0);\nif (fh < 0) { /* handle error */ }\naddr.sun_family = AF_UNIX;\nstrncpy(addr.sun_path, \"/var/run/tpm/tpmd_socket:0\", sizeof(addr.sun_path)-1);\nres = connect(fh, (struct sockaddr*)&addr, sizeof(struct sockaddr_un));\nif (res < 0) { /* handle error */ }\n\nAll subsequent calls of read(), write(), and close() should work as\nexpected.\n\n\nUsage Examples for TPM/J\n--------------------------------------------------------------------------\n\n=== Linux\n# modprobe tpmd_dev\n# tpmd -d\n\n# cd <path to tpmj>/lib\n# export CLASSPATH=tpmj.jar:bcprov-jdk15-131.jar:$CLASSPATH\n# java edu.mit.csail.tpmj.tools.TPMInfo\n\n\n=== Mac OS X\n# sudo kextload /System/Library/Extensions/tpm_bridge.kext\n# sudo tpmd -d\n\n# cd <path to tpmj>/lib\n# export CLASSPATH=tpmj.jar:bcprov-jdk15-131.jar:$CLASSPATH\n# sudo java edu.mit.csail.tpmj.tools.TPMInfo\n\n\n=== Windows\n# set PATH=%PROGRAMFILES%\\TPM_Emulator;%PATH%\n# set PATH=%PROGRAMFILES%\\TPM_Emulator\\lib;%PATH%\n# control_tpmd.bat start\n\n# cd <path to tpmj>\\lib\n# set CLASSPATH=tpmj.jar;bcprov-jdk15-131.jar:%CLASSPATH%\n# java edu.mit.csail.tpmj.tools.TPMInfo\n\n\nNotes\n--------------------------------------------------------------------------\n* Since release 0.7 the emulator also runs on Darwin (Mac OS X) and on\n  Windows; thanks go to Amit Singh and Domenic Schröder. In addition,\n  the emulator now also supports MTM emulation; thanks go to Jan-Erik\n  Ekberg and Markku Kylänpää from Nokia.\n* Since release 0.5.1 the emulator supports Free- and OpenBSD; thanks go\n  to Sebastian Schuetz.\n* Since release 0.5 the kernel-based emulator (tpm_dev) is obsolete.\n* The name and format of the persistent-storage file has changed between\n  release 0.2 and 0.3, 0.4 and 0.4.1., 0.5 and 0.6, and 0.6 and 0.7.\n* The DAA support was tested with the IBM DAA Test Suite and should work \n  now as expected. Thanks go to Roger Zimmermann for his kindly help.\n\n\nContact\n--------------------------------------------------------------------------\nAny comments, suggestions and bug reports are welcome. Please, mention\nthe keyword 'TPM emulator' in the subject.\nPeter Huewe <peterhuewe@gmx.de>\nMario Strasser <mast@gmx.net>\n\n"
  },
  {
    "path": "build.bat",
    "content": "@echo off\r\n\r\nset BUILD_DIR=build\r\nset PATH=C:\\MinGW\\bin;C:\\Program Files\\CMake 2.8\\bin;C:\\Program Files (x86)\\CMake 2.8\\bin;%PATH%\r\n\r\nif \"%1\" == \"clean\" rmdir \"%BUILD_DIR%\" /S /Q\r\n\r\nif not exist \"%BUILD_DIR%\" mkdir \"%BUILD_DIR%\"\r\n\r\ncd %BUILD_DIR%\r\ncmake .. -G \"MinGW Makefiles\"\r\n::cmake .. -G \"MinGW Makefiles\" -DMTM_EMULATOR=ON\r\nmingw32-make\r\ncd ..\r\n\r\n"
  },
  {
    "path": "build.sh",
    "content": "#!/bin/sh\n\nBUILD_DIR=\"build\"\n\nif [ \"$1\" = \"clean\" ]; then\n  rm -rf $BUILD_DIR\nfi\n\nif [ ! -d $BUILD_DIR ]; then\n  mkdir $BUILD_DIR || exit 1\nfi\n\ncd build\ncmake ../ #-DMTM_EMULATOR=ON \nmake\ncd ..\n\nexit 0\n\n"
  },
  {
    "path": "config.h.in",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: config.h.in 426 2010-02-22 17:11:58Z mast $\n */\n\n#ifndef _CONFIG_H_\n#define _CONFIG_H_\n\n/* project and build version */\n#define VERSION_MAJOR ${TPM_Emulator_VERSION_MAJOR}\n#define VERSION_MINOR ${TPM_Emulator_VERSION_MINOR}\n#define VERSION_BUILD ${TPM_Emulator_VERSION_BUILD}\n\n/* TDDL and LKM configuration */\n#define TPM_SOCKET_NAME  \"${TPM_SOCKET_NAME}\"\n#define TPM_STORAGE_NAME \"${TPM_STORAGE_NAME}\"\n#define TPM_DEVICE_NAME  \"${TPM_DEVICE_NAME}\"\n#define TPM_LOG_FILE     \"${TPM_LOG_FILE}\"\n#define TPM_CMD_BUF_SIZE 4096\n\n#endif /* _CONFIG_H_ */\n\n"
  },
  {
    "path": "crypto/CMakeLists.txt",
    "content": "# Software-based Trusted Platform Module (TPM) Emulator\n# Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n#\n# $Id: CMakeLists.txt 464 2011-07-09 14:57:41Z mast $\n\nfile(GLOB tpm_crypto_SRCS \"*.[h|c]\")\nfile(GLOB bn_SRCS \"bn_*.c\")\nlist(REMOVE_ITEM tpm_crypto_SRCS ${bn_SRCS})\n\nif(USE_OPENSSL)\nlist(APPEND tpm_crypto_SRCS \"bn_openssl.c\")\nadd_library(tpm_crypto STATIC ${tpm_crypto_SRCS})\ntarget_link_libraries(tpm_crypto crypto)\nelse()\nlist(APPEND tpm_crypto_SRCS \"bn_gmp.c\")\nadd_library(tpm_crypto STATIC ${tpm_crypto_SRCS})\ntarget_link_libraries(tpm_crypto gmp)\nendif()\n\n"
  },
  {
    "path": "crypto/bn.h",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: bn.h 464 2011-07-09 14:57:41Z mast $\n */\n \n#ifndef _BN_H_\n#define _BN_H_\n\n#include <stddef.h>\n#include <stdint.h>\n\n#ifdef USE_OPENSSL\n#include <openssl/bn.h>\ntypedef BIGNUM tpm_bn_t[1];\n#else\n#include <gmp.h>\ntypedef mpz_t tpm_bn_t;\n#endif\n\nvoid tpm_bn_init(tpm_bn_t a);\n\nvoid tpm_bn_init2(tpm_bn_t a, size_t nbits);\n\nvoid tpm_bn_init_set(tpm_bn_t a, tpm_bn_t val);\n\nvoid tpm_bn_init_set_ui(tpm_bn_t a, uint32_t val);\n\nvoid tpm_bn_set_ui(tpm_bn_t a, uint32_t val);\n\nvoid tpm_bn_clear(tpm_bn_t a);\n\nvoid tpm_bn_swap(tpm_bn_t a, tpm_bn_t b);\n\nuint32_t tpm_bn_bitsize(tpm_bn_t a);\n\nvoid tpm_bn_import(tpm_bn_t out, size_t count, int order, const void *in);\n\nvoid tpm_bn_export(void *out, size_t *count, int order, tpm_bn_t in);\n\nint tpm_bn_cmp(tpm_bn_t a, tpm_bn_t b);\n\nint tpm_bn_cmp_ui(tpm_bn_t a, uint32_t b);\n\nint tpm_bn_sgn(tpm_bn_t a);\n\nvoid tpm_bn_setbit(tpm_bn_t res, uint32_t bit);\n\nvoid tpm_bn_add(tpm_bn_t res, tpm_bn_t a, tpm_bn_t b);\n\nvoid tpm_bn_add_ui(tpm_bn_t res, tpm_bn_t a, uint32_t b);\n\nvoid tpm_bn_sub(tpm_bn_t res, tpm_bn_t a, tpm_bn_t b);\n\nvoid tpm_bn_sub_ui(tpm_bn_t res, tpm_bn_t a, uint32_t b);\n\nvoid tpm_bn_mul(tpm_bn_t res, tpm_bn_t a, tpm_bn_t b);\n\nvoid tpm_bn_mod(tpm_bn_t res, tpm_bn_t a, tpm_bn_t mod);\n\nvoid tpm_bn_powm(tpm_bn_t res, tpm_bn_t base, tpm_bn_t exp, tpm_bn_t mod);\n\nvoid tpm_bn_ui_pow_ui(tpm_bn_t res, uint32_t base, uint32_t exp);\n\nvoid tpm_bn_fdiv_q_2exp(tpm_bn_t res, tpm_bn_t n, uint32_t b);\n\nvoid tpm_bn_tdiv_q(tpm_bn_t res, tpm_bn_t a, tpm_bn_t b);\n\nvoid tpm_bn_gcd(tpm_bn_t res, tpm_bn_t a, tpm_bn_t b);\n\nvoid tpm_bn_invert(tpm_bn_t res, tpm_bn_t a, tpm_bn_t b);\n\nvoid tpm_bn_nextprime(tpm_bn_t res, tpm_bn_t a);\n\n#endif /* _BN_H_ */\n"
  },
  {
    "path": "crypto/bn_gmp.c",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: bn_gmp.c 464 2011-07-09 14:57:41Z mast $\n */\n \n#include \"bn.h\"\n\nvoid tpm_bn_init(tpm_bn_t a)\n{\n  mpz_init(a);\n}\n\nvoid tpm_bn_init2(tpm_bn_t a, size_t nbits)\n{\n  mpz_init2(a, nbits + GMP_NUMB_BITS);\n}\n\nvoid tpm_bn_init_set(tpm_bn_t a, tpm_bn_t val)\n{\n  mpz_init_set(a, val);     \n}\n\nvoid tpm_bn_init_set_ui(tpm_bn_t a, uint32_t val)\n{\n  mpz_init_set_ui(a, val);\n}\n\nvoid tpm_bn_set_ui(tpm_bn_t a, uint32_t val)\n{\n  mpz_set_ui(a, val);\n}\n\nvoid tpm_bn_clear(tpm_bn_t a)\n{\n  mpz_clear(a);\n}\n\nvoid tpm_bn_swap(tpm_bn_t a, tpm_bn_t b)\n{\n  mpz_swap(a, b);\n}\n\nuint32_t tpm_bn_bitsize(tpm_bn_t a)\n{\n  return mpz_sizeinbase(a, 2);\n}\n\nvoid tpm_bn_import(tpm_bn_t out, size_t count, int order, const void *in)\n{\n  mpz_import(out, count, order, 1, 0, 0, in);\n}\n\nvoid tpm_bn_export(void *out, size_t *count, int order, tpm_bn_t in)\n{\n  size_t count_out;\n  mpz_export(out, &count_out, order, 1, 0, 0, in);\n  if (count != NULL) *count = count_out;\n}\n\nint tpm_bn_cmp(tpm_bn_t a, tpm_bn_t b)\n{\n  return mpz_cmp(a, b);\n}\n\nint tpm_bn_cmp_ui(tpm_bn_t a, uint32_t b)\n{\n  return mpz_cmp_ui(a, b);\n}\n\nint tpm_bn_sgn(tpm_bn_t a)\n{\n  return mpz_sgn(a);\n}\n\nvoid tpm_bn_setbit(tpm_bn_t res, uint32_t bit)\n{\n  mpz_setbit(res, bit);\n}\n\nvoid tpm_bn_add(tpm_bn_t res, tpm_bn_t a, tpm_bn_t b)\n{\n  mpz_add(res, a, b);\n}\n\nvoid tpm_bn_add_ui(tpm_bn_t res, tpm_bn_t a, uint32_t b)\n{\n  mpz_add_ui(res, a, b);\n}\n\nvoid tpm_bn_sub(tpm_bn_t res, tpm_bn_t a, tpm_bn_t b)\n{\n  mpz_sub(res, a, b);\n}\n\nvoid tpm_bn_sub_ui(tpm_bn_t res, tpm_bn_t a, uint32_t b)\n{\n  mpz_sub_ui(res, a, b);\n}\n\nvoid tpm_bn_mul(tpm_bn_t res, tpm_bn_t a, tpm_bn_t b)\n{\n  mpz_mul(res, a, b);\n}\n\nvoid tpm_bn_mod(tpm_bn_t res, tpm_bn_t a, tpm_bn_t mod)\n{\n  mpz_mod(res, a, mod);\n}\n\nvoid tpm_bn_powm(tpm_bn_t res, tpm_bn_t base, tpm_bn_t exp, tpm_bn_t mod)\n{\n  mpz_powm(res, base, exp, mod);\n}\n\nvoid tpm_bn_ui_pow_ui(tpm_bn_t res, uint32_t base, uint32_t exp)\n{\n  mpz_ui_pow_ui(res, base, exp);\n}\n\nvoid tpm_bn_fdiv_q_2exp(tpm_bn_t res, tpm_bn_t n, uint32_t b)\n{\n  mpz_fdiv_q_2exp(res, n, b);\n}\n\nvoid tpm_bn_tdiv_q(tpm_bn_t res, tpm_bn_t a, tpm_bn_t b)\n{\n  mpz_tdiv_q(res, a, b);\n}\n\nvoid tpm_bn_gcd(tpm_bn_t res, tpm_bn_t a, tpm_bn_t b)\n{\n  mpz_gcd(res, a, b);\n}\n\nvoid tpm_bn_invert(tpm_bn_t res, tpm_bn_t a, tpm_bn_t b)\n{\n  mpz_invert(res, a, b);\n}\n\nvoid tpm_bn_nextprime(tpm_bn_t res, tpm_bn_t a)\n{\n  mpz_nextprime(res, a);\n}\n\n\n"
  },
  {
    "path": "crypto/bn_openssl.c",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2011 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: bn.c 406 2010-02-19 11:08:30Z mast $\n */\n \n#include \"bn.h\"\n\nBN_CTX *bn_ctx = NULL;\n\nvoid tpm_bn_init(tpm_bn_t a)\n{\n  if (bn_ctx == NULL) bn_ctx = BN_CTX_new();\n  BN_init(a);\n}\n\nvoid tpm_bn_init2(tpm_bn_t a, size_t nbits)\n{\n  tpm_bn_init(a);\n  BN_set_bit(a, nbits);\n  BN_clear_bit(a, nbits);\n}\n\nvoid tpm_bn_init_set(tpm_bn_t a, tpm_bn_t val)\n{\n  tpm_bn_init(a);\n  BN_copy(a, val);\n}\n\nvoid tpm_bn_init_set_ui(tpm_bn_t a, uint32_t val)\n{\n  tpm_bn_init(a);\n  BN_set_word(a, val);\n}\n\nvoid tpm_bn_set_ui(tpm_bn_t a, uint32_t val)\n{\n  BN_set_word(a, val);\n}\n\nvoid tpm_bn_clear(tpm_bn_t a)\n{\n  BN_clear_free(a);\n}\n\nvoid tpm_bn_swap(tpm_bn_t a, tpm_bn_t b)\n{\n  BN_swap(a, b);\n}\n\nuint32_t tpm_bn_bitsize(tpm_bn_t a)\n{\n  return BN_num_bits(a);\n}\n\nvoid tpm_bn_import(tpm_bn_t out, size_t count, int order, const void *in)\n{\n  //FIXME: reverse order if order != 1.\n  BN_bin2bn(in, count, out);\n}\n\nvoid tpm_bn_export(void *out, size_t *count, int order, tpm_bn_t in)\n{\n  //FIXME: reverse order if order != 1.\n  BN_bn2bin(in, out);\n  if (count != NULL) *count = BN_num_bytes(in);\n}\n\nint tpm_bn_cmp(tpm_bn_t a, tpm_bn_t b)\n{\n  return BN_cmp(a, b);\n}\n\nint tpm_bn_cmp_ui(tpm_bn_t a, uint32_t b)\n{\n  tpm_bn_t b2;\n  tpm_bn_init_set_ui(b2, b);\n  int res = tpm_bn_cmp(a, b2);\n  tpm_bn_clear(b2);\n  return res;\n}\n\nint tpm_bn_sgn(tpm_bn_t a)\n{\n  if (BN_is_zero(a)) return 0;\n  return BN_is_negative(a) ? -1 : 1;\n}\n\nvoid tpm_bn_setbit(tpm_bn_t res, uint32_t bit)\n{\n  BN_set_bit(res, bit);\n}\n\nvoid tpm_bn_add(tpm_bn_t res, tpm_bn_t a, tpm_bn_t b)\n{\n  BN_add(res, a, b);\n}\n\nvoid tpm_bn_add_ui(tpm_bn_t res, tpm_bn_t a, uint32_t b)\n{\n  BN_copy(res, a);\n  BN_add_word(res, b);\n}\n\nvoid tpm_bn_sub(tpm_bn_t res, tpm_bn_t a, tpm_bn_t b)\n{\n  BN_sub(res, a, b);\n}\n\nvoid tpm_bn_sub_ui(tpm_bn_t res, tpm_bn_t a, uint32_t b)\n{\n  BN_copy(res, a);\n  BN_sub_word(res, b);\n}\n\nvoid tpm_bn_mul(tpm_bn_t res, tpm_bn_t a, tpm_bn_t b)\n{\n  BN_mul(res, a, b, bn_ctx);\n}\n\nvoid tpm_bn_mod(tpm_bn_t res, tpm_bn_t a, tpm_bn_t mod)\n{\n  BN_mod(res, a, mod, bn_ctx);\n}\n\nvoid tpm_bn_powm(tpm_bn_t res, tpm_bn_t base, tpm_bn_t exp, tpm_bn_t mod)\n{\n  BN_mod_exp(res, base, exp, mod, bn_ctx);\n}\n\nvoid tpm_bn_ui_pow_ui(tpm_bn_t res, uint32_t base, uint32_t exp)\n{\n  //FIXME: \n  BIGNUM b, e;\n  BN_init(&b);\n  BN_init(&e);\n  BN_set_word(&b, base);\n  BN_set_word(&e, exp);    \n  BN_exp(res, &b, &e, bn_ctx);\n  BN_clear_free(&b);\n  BN_clear_free(&e);\n}\n\nvoid tpm_bn_fdiv_q_2exp(tpm_bn_t res, tpm_bn_t n, uint32_t b)\n{\n  BN_rshift(res, n, b);\n}\n\nvoid tpm_bn_tdiv_q(tpm_bn_t res, tpm_bn_t a, tpm_bn_t b)\n{\n  BN_div(res, NULL, a, b, bn_ctx);\n}\n\nvoid tpm_bn_gcd(tpm_bn_t res, tpm_bn_t a, tpm_bn_t b)\n{\n  BN_gcd(res, a, b, bn_ctx);\n}\n\nvoid tpm_bn_invert(tpm_bn_t res, tpm_bn_t a, tpm_bn_t b)\n{\n  BN_mod_inverse(res, a, b, bn_ctx);\n}\n\nvoid tpm_bn_nextprime(tpm_bn_t res, tpm_bn_t a)\n{\n  BN_copy(res, a);\n  BN_set_bit(res, 0);\n  while (!BN_is_prime(res, BN_prime_checks, NULL, bn_ctx, NULL)) {\n    BN_add_word(res, 2);\n  }\n}\n\n"
  },
  {
    "path": "crypto/hmac.c",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: hmac.c 364 2010-02-11 10:24:45Z mast $\n */\n\n#include \"hmac.h\"\n#include <string.h>\n\nvoid tpm_hmac_init(tpm_hmac_ctx_t *ctx, const uint8_t *key, size_t key_len)\n{\n  uint8_t tk[SHA1_DIGEST_LENGTH];\n  uint8_t k_ipad[HMAC_PAD_LENGTH];\n  int i;\n\n  /* if the key is longer than 64 bytes reset it to key := hash(key) */\n  if (key_len > HMAC_PAD_LENGTH) {\n    tpm_sha1_init(&ctx->ctx);\n    tpm_sha1_update(&ctx->ctx, key, key_len);\n    tpm_sha1_final(&ctx->ctx, tk);\n    key = tk;\n    key_len = SHA1_DIGEST_LENGTH;\n  }\n  /* start out by storing key in pads */\n  memset(k_ipad, 0, HMAC_PAD_LENGTH);\n  memset(ctx->k_opad, 0, HMAC_PAD_LENGTH);\n  memcpy(k_ipad, key, key_len);\n  memcpy(ctx->k_opad, key, key_len);\n  /* xor key with ipad and opad values */\n  for (i = 0; i < HMAC_PAD_LENGTH; i++) {\n    k_ipad[i] ^= 0x36;\n    ctx->k_opad[i] ^= 0x5C;\n  }\n  /* start inner hash */\n  tpm_sha1_init(&ctx->ctx);\n  tpm_sha1_update(&ctx->ctx, k_ipad, HMAC_PAD_LENGTH);\n}\n\nvoid tpm_hmac_update(tpm_hmac_ctx_t *ctx, const uint8_t *data, size_t length)\n{\n  /* update inner hash */\n  tpm_sha1_update(&ctx->ctx, data, length);\n}\n\nvoid tpm_hmac_final(tpm_hmac_ctx_t *ctx, uint8_t *digest)\n{\n  /* complete inner hash */\n  tpm_sha1_final(&ctx->ctx, digest);\n  /* perform outer hash */\n  tpm_sha1_init(&ctx->ctx);\n  tpm_sha1_update(&ctx->ctx, ctx->k_opad, HMAC_PAD_LENGTH);\n  tpm_sha1_update(&ctx->ctx, digest, SHA1_DIGEST_LENGTH);\n  tpm_sha1_final(&ctx->ctx, digest);\n}\n\n"
  },
  {
    "path": "crypto/hmac.h",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: hmac.h 364 2010-02-11 10:24:45Z mast $\n */\n\n#ifndef _HMAC_H_\n#define _HMAC_H_\n\n#include <stddef.h>\n#include <stdint.h>\n#include \"sha1.h\"\n\n#define HMAC_PAD_LENGTH 64\n\ntypedef struct {\n  tpm_sha1_ctx_t ctx;\n  uint8_t k_opad[HMAC_PAD_LENGTH];\n} tpm_hmac_ctx_t;\n\nvoid tpm_hmac_init(tpm_hmac_ctx_t *ctx, const uint8_t *key, size_t key_len);\n\nvoid tpm_hmac_update(tpm_hmac_ctx_t *ctx, const uint8_t *data, size_t length);\n\nvoid tpm_hmac_final(tpm_hmac_ctx_t *ctx, uint8_t *digest);\n\n#endif /* _HMAC_H_ */\n\n"
  },
  {
    "path": "crypto/rc4.c",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: rc4.c 364 2010-02-11 10:24:45Z mast $\n */\n\n#include \"rc4.h\"\n\nvoid tpm_rc4_init(tpm_rc4_ctx_t *ctx, uint8_t *key, size_t key_len)\n{\n    int i;\n    uint8_t a, j, k;\n    \n    ctx->x = ctx->y = 0;\n    for (i = 0; i < 256; i++) {\n        ctx->state[i] = i;\n    }\n    for (i = j = k = 0; i < 256; i++) {\n        a = ctx->state[i];\n        j += a + key[k++];\n        ctx->state[i] = ctx->state[j];\n        ctx->state[j] = a;\n        if (k >= key_len) k = 0;        \n    }\n    /* to strengthen the algorithm it is recommended to\n       discard the first few (say 256) octets */\n    for (i = 0; i < 16; i++) {\n        uint8_t buf[16];\n        tpm_rc4_crypt(ctx, buf, buf, sizeof(buf));\n    }\n}\n\nvoid tpm_rc4_crypt(tpm_rc4_ctx_t *ctx, uint8_t *in, uint8_t *out, size_t length)\n{\n    uint8_t a, x, y, *state;\n    \n    x = ctx->x;\n    y = ctx->y;\n    state = ctx->state;     \n    while (length--) {\n        x++;\n        y += state[x];\n        a = state[x];\n        state[x] = state[y];\n        state[y] = a;\n        a += state[x];        \n        *out++ = *in++ ^ state[a];\n    }\n    ctx->x = x;\n    ctx->y = y;\n}\n\n"
  },
  {
    "path": "crypto/rc4.h",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: rc4.h 364 2010-02-11 10:24:45Z mast $\n */\n \n#ifndef _RC4_H_\n#define _RC4_H_\n\n#include <stddef.h>\n#include <stdint.h>\n\ntypedef struct {\n    uint8_t state[256];\n    uint8_t x, y;\n} tpm_rc4_ctx_t;\n\nvoid tpm_rc4_init(tpm_rc4_ctx_t *s, uint8_t *key, size_t key_len);\n\nvoid tpm_rc4_crypt(tpm_rc4_ctx_t *s, uint8_t *in, uint8_t *out, size_t length);\n\n#endif /* _RC4_h_ */\n"
  },
  {
    "path": "crypto/rsa.c",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: rsa.c 364 2010-02-11 10:24:45Z mast $\n */\n\n#include \"rsa.h\"\n#include \"sha1.h\"\n#include \"tpm/tpm_commands.h\"\n\nstatic int rsa_public(tpm_rsa_public_key_t *key, \n                      const uint8_t *in, size_t in_len, uint8_t *out)\n{\n  size_t t;\n  tpm_bn_t p, c;\n\n  tpm_bn_init2(p, key->size);\n  tpm_bn_init2(c, key->size);\n  tpm_bn_import(p, in_len, 1, in);\n  /* c = p ^ d mod n */\n  tpm_bn_powm(c, p, key->e, key->n);\n  t = tpm_bn_bitsize(c);\n  if (t > key->size) {\n    tpm_bn_clear(p);\n    tpm_bn_clear(c);\n    return -1;\n  }\n  t = (key->size - t) >> 3;\n  memset(out, 0, t);\n  tpm_bn_export(&out[t], &t, 1, c);\n  tpm_bn_clear(p);\n  tpm_bn_clear(c);\n  return 0;\n}\n\nstatic int rsa_private(tpm_rsa_private_key_t *key,\n                       const uint8_t *in, size_t in_len, uint8_t *out)\n{\n  size_t t;\n  tpm_bn_t p, c, m1, m2, h;\n\n  tpm_bn_init2(p, key->size);\n  tpm_bn_init2(c, key->size);\n  tpm_bn_import(p, in_len, 1, in);\n\n  if (!key->p || !key->q || !key->u) {\n    /* c = p ^ d mod n */\n    tpm_bn_powm(c, p, key->d, key->n);\n  } else {\n    tpm_bn_init2(m1, key->size / 2);\n    tpm_bn_init2(m2, key->size / 2);\n    tpm_bn_init2(h, key->size);\n    /* m1 = p ^ (d mod (p-1)) mod p */\n    tpm_bn_sub_ui(h, key->p, 1);\n    tpm_bn_mod(h, key->d, h);\n    tpm_bn_powm(m1, p, h, key->p);\n    /* m2 = p ^ (d mod (q-1)) mod q */\n    tpm_bn_sub_ui(h, key->q, 1);\n    tpm_bn_mod(h, key->d, h);\n    tpm_bn_powm(m2, p, h, key->q);\n    /* h = u * ( m2 - m1 ) mod q */\n    tpm_bn_sub(h, m2, m1);\n    if (tpm_bn_sgn(h) < 0) tpm_bn_add(h, h, key->q);\n    tpm_bn_mul(h, key->u, h);\n    tpm_bn_mod(h, h, key->q);\n    /* c = m1 + h * p */\n    tpm_bn_mul(h, h, key->p);\n    tpm_bn_add(c, m1, h);\n    tpm_bn_clear(m1);\n    tpm_bn_clear(m2);\n    tpm_bn_clear(h);\n  }\n  t = tpm_bn_bitsize(c);\n  if (t > key->size) {\n    tpm_bn_clear(p);\n    tpm_bn_clear(c);\n    return -1;\n  }\n  t = (key->size - t) >> 3;\n  memset(out, 0, t);\n  tpm_bn_export(&out[t], &t, 1, c);\n  tpm_bn_clear(p);\n  tpm_bn_clear(c);\n  return 0;\n}\n\nstatic int rsa_test_key(tpm_rsa_private_key_t *key)\n{\n  tpm_bn_t a, b, t;\n  int res = 0;\n  \n  tpm_bn_init2(a, key->size);\n  tpm_bn_init2(b, key->size);\n  tpm_bn_init2(t, key->size);\n  tpm_bn_set_ui(t, 0xdeadbeef);\n  tpm_bn_powm(a, t, key->e, key->n);\n  tpm_bn_powm(b, a, key->d, key->n);\n  if (tpm_bn_cmp(t, b) != 0) res = -1;\n  tpm_bn_powm(a, t, key->d, key->n);\n  tpm_bn_powm(b, a, key->e, key->n);\n  if (tpm_bn_cmp(t, b) != 0) res = -1;\n  tpm_bn_clear(a);\n  tpm_bn_clear(b);\n  tpm_bn_clear(t);\n  return res;\n}\n\nint tpm_rsa_import_key(tpm_rsa_private_key_t *key, int endian,\n                       const uint8_t *n, size_t n_len,\n                       const uint8_t *e, size_t e_len,\n                       const uint8_t *p, const uint8_t *q)\n{\n  tpm_bn_t t1, t2, phi;\n  if (n == NULL || n_len == 0 || (p == NULL && q == NULL)) return -1;\n  /* init key */\n  key->size = n_len << 3;\n  if (e == NULL || e_len == 0) {\n    tpm_bn_init_set_ui(key->e, 65537);\n  } else {\n    tpm_bn_init2(key->e, e_len << 3);\n    tpm_bn_import(key->e, e_len, endian, e);\n  }\n  tpm_bn_init2(key->n, key->size);\n  tpm_bn_init2(key->p, key->size / 2);\n  tpm_bn_init2(key->q, key->size / 2);\n  tpm_bn_init2(key->d, key->size);\n  tpm_bn_init2(key->u, key->size / 2); \n  tpm_bn_init2(t1, key->size / 2);\n  tpm_bn_init2(t2, key->size / 2);\n  tpm_bn_init2(phi, key->size);\n  /* import values */\n  tpm_bn_import(key->n, n_len, endian, n);\n  if (p != NULL) tpm_bn_import(key->p, n_len / 2, endian, p);\n  if (q != NULL) tpm_bn_import(key->q, n_len / 2, endian, q);\n  if (p == NULL) tpm_bn_tdiv_q(key->p, key->n, key->q);\n  if (q == NULL) tpm_bn_tdiv_q(key->q, key->n, key->p);\n  /* p shall be smaller than q */\n  if (tpm_bn_cmp(key->p, key->q) > 0) tpm_bn_swap(key->p, key->q);\n  /* calculate missing values */\n  tpm_bn_sub_ui(t1, key->p, 1);\n  tpm_bn_sub_ui(t2, key->q, 1);\n  tpm_bn_mul(phi, t1, t2);\n  tpm_bn_invert(key->d, key->e, phi);\n  tpm_bn_invert(key->u, key->p, key->q);\n  /* release helper variables */\n  tpm_bn_clear(t1);\n  tpm_bn_clear(t2);\n  tpm_bn_clear(phi);\n  /* test key */\n  if (rsa_test_key(key) != 0) {\n    tpm_rsa_release_private_key(key);\n    return -1;\n  }\n  return 0;\n}\n\nvoid tpm_rsa_copy_key(tpm_rsa_private_key_t *dst, tpm_rsa_private_key_t *src)\n{\n  tpm_bn_init_set(dst->n, src->n);\n  tpm_bn_init_set(dst->e, src->e);\n  tpm_bn_init_set(dst->d, src->d);\n  tpm_bn_init_set(dst->p, src->p);\n  tpm_bn_init_set(dst->q, src->q);\n  tpm_bn_init_set(dst->u, src->u);\n  dst->size = src->size;\n}\n\nint tpm_rsa_import_public_key(tpm_rsa_public_key_t *key, int endian,\n                              const uint8_t *n, size_t n_len,\n                              const uint8_t *e, size_t e_len)\n{\n  if (n == NULL || n_len == 0) return -1;\n  /* init key */\n  key->size = n_len << 3;\n  if (e == NULL || e_len == 0) {\n    tpm_bn_init_set_ui(key->e, 65537);\n  } else {\n    tpm_bn_init2(key->e, e_len << 3);\n    tpm_bn_import(key->e, e_len, endian, e);\n  }\n  tpm_bn_init2(key->n, key->size);\n  /* import values */\n  tpm_bn_import(key->n, n_len, endian, n);\n  return 0;\n}\n\nstatic void rsa_tpm_bn_random(tpm_bn_t a, size_t nbits)\n{\n  size_t size = nbits >> 3;\n  uint8_t buf[size];\n  tpm_get_random_bytes(buf, size);\n  tpm_bn_import(a, size, 1, buf);\n}\n\nint tpm_rsa_generate_key(tpm_rsa_private_key_t *key, uint16_t key_size)\n{\n  tpm_bn_t e, p, q, n, t1, t2, phi, d, u;\n\n  /* bit_size must be a multiply of eight */\n  while (key_size & 0x07) key_size++;\n  /* we use e = 65537 */\n  tpm_bn_init_set_ui(e, 65537);\n  tpm_bn_init2(p, key_size / 2);\n  tpm_bn_init2(q, key_size / 2);\n  tpm_bn_init2(n, key_size);\n  tpm_bn_init2(t1, key_size / 2);\n  tpm_bn_init2(t2, key_size / 2);\n  tpm_bn_init2(phi, key_size);\n  tpm_bn_init2(d, key_size);\n  tpm_bn_init2(u, key_size / 2);\n  do {  \n    /* get prime p */\n    rsa_tpm_bn_random(p, key_size / 2);\n    tpm_bn_setbit(p, 0); \n    tpm_bn_setbit(p, key_size / 2 - 1);\n    tpm_bn_setbit(p, key_size / 2 - 2);\n    tpm_bn_nextprime(p, p);\n    tpm_bn_sub_ui(t1, p, 1);\n    tpm_bn_gcd(phi, e, t1);\n    if (tpm_bn_cmp_ui(phi, 1) != 0) continue;\n    /* get prime q */\n    rsa_tpm_bn_random(q, key_size / 2);\n    tpm_bn_setbit(q, 0);\n    tpm_bn_setbit(q, key_size / 2 - 1);\n    tpm_bn_setbit(q, key_size / 2 - 2);\n    tpm_bn_nextprime(q, q);\n    tpm_bn_sub_ui(t2, q, 1); \n    tpm_bn_gcd(phi, e, t1);\n    if (tpm_bn_cmp_ui(phi, 1) != 0) continue;\n    /* p shall be smaller than q */\n    if (tpm_bn_cmp(p, q) > 0) tpm_bn_swap(p, q);\n    /* calculate the modulus */\n    tpm_bn_mul(n, p, q);\n  } while (tpm_bn_bitsize(n) != key_size);\n  /* calculate Euler totient: phi = (p-1)(q-1) */\n  tpm_bn_mul(phi, t1, t2);\n  /* calculate the secret key d = e^(-1) mod phi */\n  tpm_bn_invert(d, e, phi);\n  /* calculate the inverse of p and q (used for chinese remainder theorem) */\n  tpm_bn_invert(u, p, q);\n  /* setup private key */\n  tpm_bn_init_set(key->n, n);\n  tpm_bn_init_set(key->e, e);\n  tpm_bn_init_set(key->p, p);\n  tpm_bn_init_set(key->q, q);\n  tpm_bn_init_set(key->d, d);\n  tpm_bn_init_set(key->u, u);  \n  key->size = key_size;\n  /* release helper variables */\n  tpm_bn_clear(e);\n  tpm_bn_clear(p);\n  tpm_bn_clear(q);\n  tpm_bn_clear(n);\n  tpm_bn_clear(t1);\n  tpm_bn_clear(t2);\n  tpm_bn_clear(phi);\n  tpm_bn_clear(d);\n  tpm_bn_clear(u);\n  /* test key */\n  if (rsa_test_key(key) != 0) {\n    tpm_rsa_release_private_key(key);\n    return -1;\n  }\n  return 0;\n}\n\nvoid tpm_rsa_release_private_key(tpm_rsa_private_key_t *key)\n{\n  tpm_bn_clear(key->n);\n  tpm_bn_clear(key->e);\n  tpm_bn_clear(key->p);\n  tpm_bn_clear(key->q);\n  tpm_bn_clear(key->d);\n  tpm_bn_clear(key->u);\n  memset(key, 0, sizeof(*key));\n}\n\nvoid tpm_rsa_release_public_key(tpm_rsa_public_key_t *key)\n{\n  tpm_bn_clear(key->n);\n  tpm_bn_clear(key->e);\n  memset(key, 0, sizeof(*key));\n}\n\nvoid tpm_rsa_export_modulus(tpm_rsa_private_key_t *key, \n                            uint8_t *modulus, size_t *length)\n{\n  tpm_bn_export(modulus, length, 1, key->n);\n}\n\nvoid tpm_rsa_export_exponent(tpm_rsa_private_key_t *key, \n                             uint8_t *exponent, size_t *length)\n{\n  tpm_bn_export(exponent, length, 1, key->e);\n}\n\nvoid tpm_rsa_export_prime1(tpm_rsa_private_key_t *key, \n                           uint8_t *prime, size_t *length)\n{\n  tpm_bn_export(prime, length, 1, key->p);\n}\n\nvoid tpm_rsa_export_prime2(tpm_rsa_private_key_t *key, \n                           uint8_t *prime, size_t *length)\n{\n  tpm_bn_export(prime, length, 1, key->q);\n}\n\nvoid tpm_rsa_export_public_modulus(tpm_rsa_public_key_t *key,\n                                   uint8_t *modulus, size_t *length)\n{\n  tpm_bn_export(modulus, length, 1, key->n);\n}\n\nvoid tpm_rsa_export_public_exponent(tpm_rsa_public_key_t *key,\n                                    uint8_t *exponent, size_t *length)\n{\n  tpm_bn_export(exponent, length, 1, key->e);\n}\n\nsize_t tpm_rsa_modulus_length(tpm_rsa_private_key_t *key)\n{\n  return (tpm_bn_bitsize(key->n) + 7) >> 3;\n}\n\nsize_t tpm_rsa_exponent_length(tpm_rsa_private_key_t *key)\n{\n  return (tpm_bn_bitsize(key->e) + 7) >> 3;\n}\n\nsize_t tpm_rsa_prime1_length(tpm_rsa_private_key_t *key)\n{\n  return (tpm_bn_bitsize(key->p) + 7) >> 3;\n}\n\nsize_t tpm_rsa_prime2_length(tpm_rsa_private_key_t *key)\n{\n  return (tpm_bn_bitsize(key->q) + 7) >> 3;\n}\n\nsize_t tpm_rsa_public_modulus_length(tpm_rsa_public_key_t *key)\n{\n  return (tpm_bn_bitsize(key->n) + 7) >> 3;\n}\n\nsize_t tpm_rsa_public_exponent_length(tpm_rsa_public_key_t *key)\n{\n  return (tpm_bn_bitsize(key->e) + 7) >> 3;\n}\n\nvoid tpm_rsa_mask_generation(const uint8_t *seed, size_t seed_len, \n                             uint8_t *data, size_t data_len)\n{\n  tpm_sha1_ctx_t ctx;\n  uint8_t mask[SHA1_DIGEST_LENGTH];\n  uint32_t i, len, counter = 0;\n  \n  while (data_len > 0) {\n    tpm_sha1_init(&ctx);\n    tpm_sha1_update(&ctx, seed, seed_len);\n    tpm_sha1_update_be32(&ctx, counter);\n    tpm_sha1_final(&ctx, mask);\n    counter++;\n    len = (data_len < SHA1_DIGEST_LENGTH) ? data_len : SHA1_DIGEST_LENGTH;\n    for (i = 0; i < len; i++) *data++ ^= mask[i];\n    data_len -= len; \n  }\n}\n\nstatic int encode_message(int type, const uint8_t *data, size_t data_len, \n                          uint8_t *msg, size_t msg_len)\n{\n  size_t i;\n  tpm_sha1_ctx_t ctx;\n\n  /* encode message according to type */\n  switch (type) {\n    case RSA_SSA_PKCS1_SHA1:\n      /* EM = 0x00||0x01||0xff-pad||0x00||SHA-1 DER header||SHA-1 digest */\n      if (msg_len < 35 + 11) return -1;\n      msg[0] = 0x00; msg[1] = 0x01;\n      memset(&msg[2], 0xff, msg_len - 38); \n      msg[msg_len - 36] = 0x00;\n      memcpy(&msg[msg_len - 35], \"\\x30\\x21\\x30\\x09\\x06\\x05\\x2b\"\n        \"\\x0e\\x03\\x02\\x1a\\x05\\x00\\x04\\x14\", 15);\n      tpm_sha1_init(&ctx);\n      tpm_sha1_update(&ctx, data, data_len);\n      tpm_sha1_final(&ctx, &msg[msg_len - 20]);\n      break;\n    case RSA_SSA_PKCS1_SHA1_RAW:\n      /* EM = 0x00||0x01||0xff-pad||0x00||SHA-1 DER header||SHA-1 digest */\n      if (msg_len < 35 + 11 || data_len != 20) return -1;\n      msg[0] = 0x00; msg[1] = 0x01;\n      memset(&msg[2], 0xff, msg_len - 38);\n      msg[msg_len - 36] = 0x00;\n      memcpy(&msg[msg_len - 35], \"\\x30\\x21\\x30\\x09\\x06\\x05\\x2b\"\n        \"\\x0e\\x03\\x02\\x1a\\x05\\x00\\x04\\x14\", 15);\n      memcpy(&msg[msg_len - 20], data, data_len);\n      break;\n    case RSA_SSA_PKCS1_DER:\n      /* EM = 0x00||0x01||0xff-pad||0x00||DER encoded data */\n      if (msg_len < data_len + 11) return -1;\n      msg[0] = 0x00; msg[1] = 0x01;\n      memset(&msg[2], 0xff, msg_len - data_len - 3);\n      msg[msg_len - data_len - 1] = 0x00;\n      memcpy(&msg[msg_len - data_len], data, data_len);\n      break;\n    case RSA_ES_PKCSV15:\n      /* EM = 0x00||0x02||nonzero random-pad||0x00||data */\n      if (msg_len < data_len + 11) return -1;\n      msg[0] = 0x00; msg[1] = 0x02;\n      tpm_get_random_bytes(&msg[2], msg_len - data_len - 3);\n      for (i = 2; i < msg_len - data_len; i++)\n        while (!msg[i]) tpm_get_random_bytes(&msg[i], 1);\n      msg[msg_len - data_len - 1] = 0x00;\n      memcpy(&msg[msg_len - data_len], data, data_len);\n      break;\n    case RSA_ES_OAEP_SHA1:\n      /* DB = SHA-1(\"TCPA\")||0x00-pad||0x01||data\n         seed = random value of size SHA1_DIGEST_LENGTH\n         masked-seed = seed xor MFG(seed, seed_len)\n         masked-DB = DB xor MFG(seed, DB_len)\n         EM = 0x00||masked-seed||masked-DB */\n      if (msg_len < data_len + 2 * SHA1_DIGEST_LENGTH + 2) return -1;\n      msg[0] = 0x00;\n      tpm_get_random_bytes(&msg[1], SHA1_DIGEST_LENGTH);\n      tpm_sha1_init(&ctx);\n      tpm_sha1_update(&ctx, (uint8_t*)\"TCPA\", 4);\n      tpm_sha1_final(&ctx, &msg[1 + SHA1_DIGEST_LENGTH]);\n      memset(&msg[1 + 2 * SHA1_DIGEST_LENGTH], 0x00, \n        msg_len - data_len - 2 * SHA1_DIGEST_LENGTH - 2);\n      msg[msg_len - data_len - 1] = 0x01;\n      memcpy(&msg[msg_len - data_len], data, data_len);\n      tpm_rsa_mask_generation(&msg[1], SHA1_DIGEST_LENGTH, \n        &msg[1 + SHA1_DIGEST_LENGTH], msg_len - SHA1_DIGEST_LENGTH - 1);\n      tpm_rsa_mask_generation(&msg[1 + SHA1_DIGEST_LENGTH], \n        msg_len - SHA1_DIGEST_LENGTH - 1, &msg[1], SHA1_DIGEST_LENGTH);\n      break;\n    case RSA_ES_PLAIN:\n        /* EM = data */\n        if (msg_len != data_len) return -1;\n        if (msg != data) memcpy(msg, data, data_len);\n        break;\n    default:\n      /* unsupported encoding method */\n      return -1;\n  }\n  return 0;\n}\n\nstatic int decode_message(int type, uint8_t *msg, size_t msg_len,\n                          uint8_t *data, size_t *data_len)\n{\n  size_t i;\n  tpm_sha1_ctx_t ctx;\n\n  /* decode message according to type */\n  switch (type) {\n    case  RSA_ES_PKCSV15:\n      /* EM = 0x00||0x02||nonzero random-pad||0x00||data */\n      if (msg_len < 11) return -1;\n      if (msg[0] != 0x00 || msg[1] != 0x02) return -1;\n      for (i = 2; i < msg_len && msg[i]; i++);\n      if (i < 10 || i >= msg_len) return -1;\n      *data_len = msg_len - i - 1;\n      memmove(data, &msg[i + 1], *data_len);\n      break;\n    case RSA_ES_OAEP_SHA1:\n      /* DB = SHA-1(\"TCPA\")||0x00-pad||0x01||data\n         seed = random value of size SHA1_DIGEST_LENGTH\n         masked-seed = seed xor MFG(seed, seed_len)\n         masked-DB = DB xor MFG(seed, DB_len)\n         EM = 0x00||masked-seed||masked-DB */\n      if (msg_len < 2 + 2 * SHA1_DIGEST_LENGTH) return -1;\n      if (msg[0] != 0x00) return -1;\n      tpm_rsa_mask_generation(&msg[1 + SHA1_DIGEST_LENGTH],\n        msg_len - SHA1_DIGEST_LENGTH - 1, &msg[1], SHA1_DIGEST_LENGTH);\n      tpm_rsa_mask_generation(&msg[1], SHA1_DIGEST_LENGTH,\n        &msg[1 + SHA1_DIGEST_LENGTH], msg_len - SHA1_DIGEST_LENGTH - 1);\n      tpm_sha1_init(&ctx);\n      tpm_sha1_update(&ctx, (uint8_t*)\"TCPA\", 4);\n      tpm_sha1_final(&ctx, &msg[1]);\n      if (memcmp(&msg[1], &msg[1 + SHA1_DIGEST_LENGTH], \n          SHA1_DIGEST_LENGTH) != 0) return -1;\n      for (i = 1 + 2 * SHA1_DIGEST_LENGTH; i < msg_len && !msg[i]; i++);\n      if (i >= msg_len || msg[i] != 0x01) return -1;\n      *data_len = msg_len - i - 1;\n      memmove(data, &msg[i + 1], *data_len);\n      break;\n    case RSA_ES_PLAIN:\n      /* EM = data */\n      *data_len = msg_len;\n      if (msg != data) memcpy(msg, data, msg_len);\n      break;\n    default:\n      /* unsupported encoding method */\n      return -1;\n  }\n  return 0;\n}\n\nint tpm_rsa_sign(tpm_rsa_private_key_t *key, int type, \n                 const uint8_t *data, size_t data_len, uint8_t *sig)\n{\n  size_t sig_len = key->size >> 3;\n\n  /* encode message */\n  if (encode_message(type, data, data_len, sig, sig_len) != 0) return -1;\n  /* sign encoded message */\n  if (rsa_private(key, sig, sig_len, sig) != 0) return -1;\n  return 0;\n}\n\nint tpm_rsa_verify(tpm_rsa_public_key_t *key, int type,\n                   const uint8_t *data, size_t data_len, uint8_t *sig)\n{\n  size_t sig_len = key->size >> 3;\n  uint8_t msg_a[sig_len];\n  uint8_t msg_b[sig_len];\n\n  /* encode message */\n  if (encode_message(type, data, data_len, msg_a, sig_len) != 0) return -1;\n  /* decrypt signature */\n  if (rsa_public(key, sig, sig_len, msg_b) != 0) return -1;\n  /* compare messages */\n  return (memcmp(msg_a, msg_b, sig_len) == 0) ? 0 : 1;\n}\n\nint tpm_rsa_decrypt(tpm_rsa_private_key_t *key, int type,\n                    const uint8_t *in, size_t in_len,\n                    uint8_t *out, size_t *out_len)\n{\n  *out_len = key->size >> 3;\n  if (in_len != *out_len || in_len < 11) return -1;\n  /* decrypt message */\n  if (rsa_private(key, in, in_len, out) != 0) return -1;\n  /* decode message */\n  if (decode_message(type, out, *out_len, out, out_len) != 0) return -1;\n  return 0;\n}\n\nint tpm_rsa_encrypt(tpm_rsa_public_key_t *key, int type,\n                    const uint8_t *in, size_t in_len,\n                    uint8_t *out, size_t *out_len)\n{\n  *out_len = key->size >> 3;\n  /* encode message */\n  if (encode_message(type, in, in_len, out, *out_len) != 0) return -1;\n  /* encrypt encoded message */\n  if (rsa_public(key, out, *out_len, out) != 0) return -1;\n  return 0;\n}\n\n"
  },
  {
    "path": "crypto/rsa.h",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: rsa.h 364 2010-02-11 10:24:45Z mast $\n */\n\n#ifndef _RSA_H_\n#define _RSA_H_\n\n#include <stddef.h>\n#include <stdint.h>\n#include \"bn.h\"\n\ntypedef struct {\n  tpm_bn_t n;\n  tpm_bn_t e;\n  tpm_bn_t d;\n  tpm_bn_t p;\n  tpm_bn_t q;\n  tpm_bn_t u;\n  uint16_t size;\n} tpm_rsa_private_key_t;\n\ntypedef struct {\n  tpm_bn_t n;\n  tpm_bn_t e;\n  uint16_t size;\n} tpm_rsa_public_key_t;\n\nenum { \n  RSA_ES_PKCSV15,\n  RSA_ES_OAEP_SHA1,\n  RSA_ES_PLAIN,\n  RSA_SSA_PKCS1_SHA1,\n  RSA_SSA_PKCS1_SHA1_RAW,\n  RSA_SSA_PKCS1_DER\n};\n\nenum {\n  RSA_LSB_FIRST = -1, RSA_MSB_FIRST = 1\n};\n\n#define TPM_RSA_EXTRACT_PUBLIC_KEY(priv_key, pub_key) { \\\n  tpm_bn_init_set(pub_key.n, priv_key.n); \\\n  tpm_bn_init_set(pub_key.e, priv_key.e); \\\n  pub_key.size = priv_key.size; }\n\nint tpm_rsa_import_key(tpm_rsa_private_key_t *key, int endian, \n                       const uint8_t *n, size_t n_len,\n                       const uint8_t *e, size_t e_len, \n                       const uint8_t *p, const uint8_t *q);\n\nvoid tpm_rsa_copy_key(tpm_rsa_private_key_t *dst, tpm_rsa_private_key_t *src);\n\nint tpm_rsa_import_public_key(tpm_rsa_public_key_t *key, int endian, \n                              const uint8_t *n, size_t n_len,\n                              const uint8_t *e, size_t e_len);\n\nint tpm_rsa_generate_key(tpm_rsa_private_key_t *key, uint16_t key_size);\n\nvoid tpm_rsa_release_private_key(tpm_rsa_private_key_t *key);\n\nvoid tpm_rsa_release_public_key(tpm_rsa_public_key_t *key);\n\nvoid tpm_rsa_export_modulus(tpm_rsa_private_key_t *key, \n                            uint8_t *modulus, size_t *length);\n\nvoid tpm_rsa_export_exponent(tpm_rsa_private_key_t *key, \n                             uint8_t *exponent, size_t *length);\n\nvoid tpm_rsa_export_prime1(tpm_rsa_private_key_t *key, \n                           uint8_t *prime, size_t *length);\n\nvoid tpm_rsa_export_prime2(tpm_rsa_private_key_t *key, \n                           uint8_t *prime, size_t *length);\n\nsize_t tpm_rsa_modulus_length(tpm_rsa_private_key_t *key);\n\nsize_t tpm_rsa_exponent_length(tpm_rsa_private_key_t *key);\n\nsize_t tpm_rsa_prime1_length(tpm_rsa_private_key_t *key);\n\nsize_t tpm_rsa_prime2_length(tpm_rsa_private_key_t *key);\n\nvoid tpm_rsa_mask_generation(const uint8_t *seed, size_t seed_len, \n                             uint8_t *data, size_t data_len);\n\nvoid tpm_rsa_export_public_modulus(tpm_rsa_public_key_t *key,\n                                   uint8_t *modulus, size_t *length);\n\nvoid tpm_rsa_export_public_exponent(tpm_rsa_public_key_t *key,\n                                    uint8_t *exponent, size_t *length);\n\nsize_t tpm_rsa_public_modulus_length(tpm_rsa_public_key_t *key);\n\nsize_t tpm_rsa_public_exponent_length(tpm_rsa_public_key_t *key);\n\n/* Note: Input and output areas MUST NOT overlap (i.e., one can't \n   use the same buffer for data and sig or in and out). */\n\nint tpm_rsa_sign(tpm_rsa_private_key_t *key, int type,\n                 const uint8_t *data, size_t data_len, uint8_t *sig);\n\nint tpm_rsa_verify(tpm_rsa_public_key_t *key, int type,\n                   const uint8_t *data, size_t data_len, uint8_t *sig);\n\nint tpm_rsa_decrypt(tpm_rsa_private_key_t *key, int type,\n                    const uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len);\n\nint tpm_rsa_encrypt(tpm_rsa_public_key_t *key, int type,\n                    const uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len);\n\n#endif /* _RSA_H_ */\n\n"
  },
  {
    "path": "crypto/sha1.c",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: sha1.c 364 2010-02-11 10:24:45Z mast $\n */\n\n#include \"sha1.h\"\n#include <string.h>\n\n/* This code is based on Steve Reid's <steve@edmweb.com> \n   public domain implementation. */ \n\n#define rol(v,b) (((v) << (b)) | ((v) >> (32 - (b))))\n#ifdef __BIG_ENDIAN__\n#define B0(i) (buf[i] = buf[i])\n#else\n#define B0(i) (buf[i] = (((buf[i] & 0xff000000) >> 24) \\\n                       | ((buf[i] & 0x00ff0000) >> 8) \\\n                       | ((buf[i] & 0x0000ff00) << 8) \\\n                       | ((buf[i] & 0x000000ff) << 24)))\n\n#endif\n#define B1(i) (buf[i & 15] = rol(buf[i & 15] ^ buf[(i-14) & 15] \\\n                                 ^ buf[(i-8) & 15] ^ buf[(i-3) & 15], 1))\n#define F0(x,y,z) ((x & (y ^ z)) ^ z)\n#define F1(x,y,z) (x ^ y ^ z)\n#define F2(x,y,z) (((x | y) & z) | (x & y))\n#define R0(a,b,c,d,e,i) e += F0(b,c,d) + B0(i) + 0x5A827999 + rol(a,5); b = rol(b,30);\n#define R1(a,b,c,d,e,i) e += F0(b,c,d) + B1(i) + 0x5A827999 + rol(a,5); b = rol(b,30);\n#define R2(a,b,c,d,e,i) e += F1(b,c,d) + B1(i) + 0x6ED9EBA1 + rol(a,5); b = rol(b,30);\n#define R3(a,b,c,d,e,i) e += F2(b,c,d) + B1(i) + 0x8F1BBCDC + rol(a,5); b = rol(b,30);\n#define R4(a,b,c,d,e,i) e += F1(b,c,d) + B1(i) + 0xCA62C1D6 + rol(a,5); b = rol(b,30);\n\nstatic void tpm_sha1_transform(uint32_t h[5], const uint8_t data[64])\n{\n  uint32_t a, b, c, d, e;\n  uint32_t buf[16];\n\n  /* copy state and data*/\n  a = h[0];\n  b = h[1];\n  c = h[2];\n  d = h[3];\n  e = h[4];\n  memcpy(buf, data, 64);\n  /* unrolled sha-1 rounds */\n  R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);\n  R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);\n  R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);\n  R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);\n  R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);\n  R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);\n  R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);\n  R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);\n  R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);\n  R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);\n  R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);\n  R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);\n  R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);\n  R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);\n  R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);\n  R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);\n  R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);\n  R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);\n  R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);\n  R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);\n  /* update state */\n  h[0] += a;\n  h[1] += b;\n  h[2] += c;\n  h[3] += d;\n  h[4] += e;\n  /* overwrite all used variables */\n  a = b = c = d = e = 0;\n  memset(buf, 0, 64);\n}\n\n\nvoid tpm_sha1_init(tpm_sha1_ctx_t *ctx)\n{\n  /* initialise with sha-1 constants */\n  ctx->h[0] = 0x67452301;\n  ctx->h[1] = 0xEFCDAB89;\n  ctx->h[2] = 0x98BADCFE;\n  ctx->h[3] = 0x10325476;\n  ctx->h[4] = 0xC3D2E1F0;\n  ctx->count_lo = ctx->count_hi = 0;\n}\n\nvoid tpm_sha1_update(tpm_sha1_ctx_t *ctx, const uint8_t *data, size_t length)\n{\n  size_t buf_off = (ctx->count_lo >> 3) & 63;\n  size_t data_off = 0;\n\n  /* add data */\n  if (length + buf_off >= 64) {\n    data_off = 64 - buf_off;\n    memcpy(&ctx->buf[buf_off], data, data_off);\n    tpm_sha1_transform(ctx->h, ctx->buf);\n    while (data_off + 64 <= length) { \n      tpm_sha1_transform(ctx->h, &data[data_off]);\n      data_off += 64;\n    }\n    buf_off = 0;\n  }\n  memcpy(&ctx->buf[buf_off], &data[data_off], length - data_off);\n  /* update counter */\n  buf_off = ctx->count_lo;\n  ctx->count_lo += length << 3;\n  if (ctx->count_lo < buf_off) ctx->count_hi++;\n  ctx->count_hi += length >> 29;\n}\n\nvoid tpm_sha1_update_be32(tpm_sha1_ctx_t *ctx, uint32_t data)\n{\n  uint8_t buf[4];\n\n  buf[0] = (data >> 24) & 0xff;\n  buf[1] = (data >> 16) & 0xff;\n  buf[2] = (data >>  8) & 0xff;\n  buf[3] = (data >>  0) & 0xff;\n  tpm_sha1_update(ctx, buf, 4);\n}\n\nvoid tpm_sha1_final(tpm_sha1_ctx_t *ctx, uint8_t digest[SHA1_DIGEST_LENGTH])\n{\n  uint8_t d, counter[8];\n\n  /* setup counter */\n  for (d = 0; d < 4; d++) {\n    counter[d    ] = (ctx->count_hi >> (24 - d * 8)) & 0xff;\n    counter[d + 4] = (ctx->count_lo >> (24 - d * 8)) & 0xff;\n  }\n  /* add padding */\n  d = 0x80;\n  tpm_sha1_update(ctx, &d, 1);\n  d = 0x00;\n  while ((ctx->count_lo & (63 * 8)) != (56 * 8)) tpm_sha1_update(ctx, &d, 1);\n  /* add counter */\n  tpm_sha1_update(ctx, counter, 8);\n  for (d = 0; d < SHA1_DIGEST_LENGTH; d++) \n    digest[d] = (uint8_t)(ctx->h[d >> 2] >> (8 * (3 - (d & 3))) & 0xff);\n  /* overwrite all used variables */\n  memset(ctx, 0, sizeof(*ctx));\n  memset(counter, 0, sizeof(counter));\n}\n"
  },
  {
    "path": "crypto/sha1.h",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: sha1.h 364 2010-02-11 10:24:45Z mast $\n */\n\n#ifndef _SHA1_H_\n#define _SHA1_H_\n\n#include <stddef.h>\n#include <stdint.h>\n\n#define SHA1_DIGEST_LENGTH 20\n\ntypedef struct {\n  uint32_t h[5];\n  uint32_t count_lo, count_hi;\n  uint8_t buf[64];\n} tpm_sha1_ctx_t;\n\nvoid tpm_sha1_init(tpm_sha1_ctx_t *ctx);\n\nvoid tpm_sha1_update(tpm_sha1_ctx_t *ctx, const uint8_t *data, size_t length);\n\nvoid tpm_sha1_update_be32(tpm_sha1_ctx_t *ctx, uint32_t data);\n\nvoid tpm_sha1_final(tpm_sha1_ctx_t *ctx, uint8_t digest[SHA1_DIGEST_LENGTH]);\n\n#endif /* _SHA1_H_ */\n"
  },
  {
    "path": "mtm/CMakeLists.txt",
    "content": "# Software-based Trusted Platform Module (TPM) Emulator\n# Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n#\n# $Id: CMakeLists.txt 376 2010-02-16 14:51:42Z mast $\n\nadd_definitions(-DMTM_EMULATOR)\nfile(GLOB tpm_SRCS ../tpm/tpm_cmd_handler.c ../tpm/tpm_data.c)\nfile(GLOB mtm_SRCS \"*.[h|c]\")\nadd_library(mtm STATIC ${mtm_SRCS} ${tpm_SRCS})\n\n"
  },
  {
    "path": "mtm/mtm_capability.c",
    "content": "/* Software-based Mobile Trusted Module (MTM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id$\n */\n\n#include \"mtm_structures.h\"\n#include \"mtm_marshalling.h\"\n#include \"mtm_data.h\"\n#include \"tpm/tpm_data.h\"\n#include \"tpm/tpm_commands.h\"\n\nstatic inline TPM_RESULT return_UINT32(UINT32 *respSize, BYTE **resp, UINT32 value)\n{\n  UINT32 len = *respSize = 4;\n  BYTE *ptr = *resp = tpm_malloc(*respSize);\n  if (ptr == NULL || tpm_marshal_UINT32(&ptr, &len, value)) {\n    tpm_free(*resp);\n    return TPM_FAIL;\n  }\n  return TPM_SUCCESS;\n}\n\nstatic inline TPM_RESULT return_BOOL(UINT32 *respSize, BYTE **resp, BOOL value)\n{\n  UINT32 len = *respSize = 1;\n  BYTE *ptr = *resp = tpm_malloc(*respSize);\n  if (ptr == NULL || tpm_marshal_BOOL(&ptr, &len, value)) {\n    tpm_free(*resp);\n    return TPM_FAIL;\n  }\n  return TPM_SUCCESS;\n}\n\n#define return_BYTE return_BOOL\n\nstatic TPM_RESULT cap_ord(UINT32 subCapSize, BYTE *subCap,\n                          UINT32 *respSize, BYTE **resp)\n{\n  TPM_COMMAND_CODE ord;\n  if (tpm_unmarshal_TPM_COMMAND_CODE(&subCap, &subCapSize, &ord))\n    return TPM_BAD_MODE;\n  switch (ord) {\n    case MTM_ORD_InstallRIM:\n    case MTM_ORD_LoadVerificationKey:\n    case MTM_ORD_LoadVerificationRootKeyDisable:\n    case MTM_ORD_VerifyRIMCert:\n    case MTM_ORD_VerifyRIMCertAndExtend:\n    case MTM_ORD_IncrementBootstrapCounter:\n    case MTM_ORD_SetVerifiedPCRSelection:\n      return return_BOOL(respSize, resp, TRUE);\n    default:\n      return return_BOOL(respSize, resp, FALSE);\n  }\n}\n\nstatic TPM_RESULT cap_mtm_permanent_data(UINT32 subCapSize, BYTE *subCap,\n                                         UINT32 *respSize, BYTE **resp)\n{\n  UINT32 subCapVal, len;\n  BYTE* ptr;\n\n/* unmarshal subCap */\n  if (tpm_unmarshal_UINT32(&subCap, &subCapSize, &subCapVal) != 0)\n    return TPM_BAD_PARAMETER;\n  switch (subCapVal) {\n\n    case 1:\n      return TPM_FAIL;\n      break;\n\n    case 2:\n      *respSize = len = sizeof_TPM_PCR_SELECTION(mtmData.permanent.data.verifiedPCRs);\n      *resp = ptr = tpm_malloc(*respSize);\n      if (*resp == NULL \n          || tpm_marshal_TPM_PCR_SELECTION(&ptr, &len, &mtmData.permanent.data.verifiedPCRs)) {\n        tpm_free(*resp);\n        return TPM_FAIL;\n      }\n      error(\"[TPM_CAP_MTM_PERMANENT_DATA] SubCap 2 not Implemented\");\n      return TPM_FAIL; // TODO not implemented.\n\n    case 3:\n      return return_UINT32(respSize, resp,\n        tpmData.permanent.data.counters[MTM_COUNTER_SELECT_BOOTSTRAP].counter);\n\n    case 4:\n      return return_UINT32(respSize, resp, mtmData.permanent.data.counterRimProtectId);\n\n    case 5:\n      return return_UINT32(respSize, resp, mtmData.permanent.data.counterStorageProtectId);\n\n    case 6:\n      return return_BYTE(respSize, resp, mtmData.permanent.data.specMajor);\n\n    case 7:\n      return return_BYTE(respSize, resp, mtmData.permanent.data.specMinor);\n\n    case 8:\n      return return_BYTE(respSize, resp, mtmData.permanent.data.loadVerificationKeyMethods);\n\n    default:\n      return TPM_BAD_PARAMETER;\n\n  }\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT MTM_GetCapability(TPM_CAPABILITY_AREA capArea, UINT32 subCapSize,\n                             BYTE *subCap, UINT32 *respSize, BYTE **resp)\n{\n  info(\"MTM_GetCapability()\");\n  switch (capArea) {\n\n    case TPM_CAP_ORD:\n      debug(\"[MTM_CAP_ORD]\");\n      TPM_RESULT res = cap_ord(subCapSize, subCap, respSize, resp);\n      if (res == TPM_SUCCESS && resp[0] == FALSE) {\n        res = TPM_GetCapability(capArea, subCapSize, subCap, respSize, resp);\n      }\n      return res;\n\n    case TPM_CAP_MTM_PERMANENT_DATA:\n      debug(\"[TPM_CAP_MTM_PERMANENT_DATA]\");\n      return cap_mtm_permanent_data(subCapSize, subCap, respSize, resp);\n\n    default:\n      return TPM_GetCapability(capArea, subCapSize, subCap, respSize, resp);\n\n  }\n}\n\n"
  },
  {
    "path": "mtm/mtm_cmd_handler.c",
    "content": "/* Software-based Mobile Trusted Module (MTM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n * Copyright (C) 2007 Jan-Erik Ekberg <jan-erik.ekberg@nokia.com>,\n *                    Nokia Corporation and/or its subsidiary(-ies)\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id$\n */\n\n#include \"mtm_commands.h\"\n#include \"mtm_marshalling.h\"\n\nextern void tpm_compute_in_param_digest(TPM_REQUEST *req);\n\nstatic TPM_RESULT execute_MTM_InstallRIM(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  UINT32 rimCertSize;\n  TPM_RIM_CERTIFICATE rimCertIn;\n  TPM_RIM_CERTIFICATE rimCertOut;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_UINT32(&ptr, &len, &rimCertSize)\n      || tpm_unmarshal_TPM_RIM_CERTIFICATE(&ptr, &len, &rimCertIn)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = MTM_InstallRIM(&rimCertIn, &req->auth1, &rimCertOut);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 4 + sizeof_TPM_RIM_CERTIFICATE(rimCertOut);\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_UINT32(&ptr, &len, sizeof_TPM_RIM_CERTIFICATE(rimCertOut))\n      || tpm_marshal_TPM_RIM_CERTIFICATE(&ptr, &len, &rimCertOut)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  free_TPM_RIM_CERTIFICATE(rimCertOut);\n  return res;\n}\n\nstatic TPM_RESULT execute_MTM_LoadVerificationKey(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_VERIFICATION_KEY_HANDLE parentKey;\n  UINT32 verificationKeySize;\n  TPM_VERIFICATION_KEY verificationKey;\n  TPM_VERIFICATION_KEY_HANDLE verificationKeyHandle;\n  BYTE loadMethod;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_VERIFICATION_KEY_HANDLE(&ptr, &len, &parentKey)\n      || tpm_unmarshal_UINT32(&ptr, &len, &verificationKeySize)\n      || tpm_unmarshal_TPM_VERIFICATION_KEY(&ptr, &len, &verificationKey)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command  */\n  res = MTM_LoadVerificationKey(parentKey, &verificationKey, &req->auth1,\n    &verificationKeyHandle, &loadMethod);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 4 + 1;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_VERIFICATION_KEY_HANDLE(&ptr, &len, verificationKeyHandle)\n      || tpm_marshal_BYTE(&ptr, &len, loadMethod)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  return res;\n}\n\nstatic TPM_RESULT execute_MTM_LoadVerificationRootKeyDisable(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* execute command */\n  res = MTM_LoadVerificationRootKeyDisable();\n  /* marshal output */\n  rsp->paramSize = 0;\n  rsp->param = NULL;\n  return res;\n}\n\nstatic TPM_RESULT execute_MTM_VerifyRIMCert(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  UINT32 rimCertSize;\n  TPM_RIM_CERTIFICATE rimCert;\n  TPM_VERIFICATION_KEY_HANDLE rimKey;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_UINT32(&ptr, &len, &rimCertSize)\n      || tpm_unmarshal_TPM_RIM_CERTIFICATE(&ptr, &len, &rimCert)\n      || tpm_unmarshal_TPM_VERIFICATION_KEY_HANDLE(&ptr, &len, &rimKey)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = MTM_VerifyRIMCert(&rimCert, rimKey);\n  /* marshal output */\n  rsp->paramSize = len = 0;\n  rsp->param = ptr = NULL;\n  return res;\n}\n\nstatic TPM_RESULT execute_MTM_VerifyRIMCertAndExtend(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  UINT32 rimCertSize;\n  TPM_RIM_CERTIFICATE rimCert;\n  TPM_VERIFICATION_KEY_HANDLE rimKey;\n  TPM_PCRVALUE outDigest;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_UINT32(&ptr, &len, &rimCertSize)\n      || tpm_unmarshal_TPM_RIM_CERTIFICATE(&ptr, &len, &rimCert)\n      || tpm_unmarshal_TPM_VERIFICATION_KEY_HANDLE(&ptr, &len, &rimKey)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = MTM_VerifyRIMCertAndExtend(&rimCert, rimKey, &outDigest);\n  /* marshal output */\n  rsp->paramSize = len = 20;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_PCRVALUE(&ptr, &len, &outDigest)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  return res;\n}\n\nstatic TPM_RESULT execute_MTM_IncrementBootstrapCounter(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  UINT32 rimCertSize;\n  TPM_RIM_CERTIFICATE rimCert;\n  TPM_VERIFICATION_KEY_HANDLE rimKey;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_UINT32(&ptr, &len, &rimCertSize)\n      || tpm_unmarshal_TPM_RIM_CERTIFICATE(&ptr, &len, &rimCert)\n      || tpm_unmarshal_TPM_VERIFICATION_KEY_HANDLE(&ptr, &len, &rimKey)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = MTM_IncrementBootstrapCounter(&rimCert, rimKey);\n  /* marshal output */\n  rsp->paramSize = len = 0;\n  rsp->param = ptr = NULL;\n  return res;\n}\n\nstatic TPM_RESULT execute_MTM_SetVerifiedPCRSelection(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_PCR_SELECTION verifiedSelection;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_PCR_SELECTION(&ptr, &len, &verifiedSelection)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = MTM_SetVerifiedPCRSelection(&verifiedSelection, &req->auth1);\n  /* marshal output */\n  rsp->paramSize = len = 0;\n  rsp->param = ptr = NULL;\n  return res;\n}\n\n\nTPM_RESULT mtm_execute_command(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  TPM_RESULT res;\n\n  /* handle command ordinal */\n  switch (req->ordinal) {\n    case MTM_ORD_InstallRIM:\n      debug(\"[MTM_ORD_InstallRIM]\");\n      res = execute_MTM_InstallRIM(req, rsp);\n      break;\n\n    case MTM_ORD_LoadVerificationKey:\n      debug(\"[MTM_ORD_LoadVerificationKey]\");\n      res = execute_MTM_LoadVerificationKey(req, rsp);\n      break;\n\n    case MTM_ORD_LoadVerificationRootKeyDisable:\n      debug(\"[MTM_ORD_LoadVerificationRootKeyDisable]\");\n      res = execute_MTM_LoadVerificationRootKeyDisable(req, rsp);\n      break;\n\n    case MTM_ORD_VerifyRIMCert:\n      debug(\"[MTM_ORD_VerifyRIMCert]\");\n      res = execute_MTM_VerifyRIMCert(req, rsp);\n      break;\n\n    case MTM_ORD_VerifyRIMCertAndExtend:\n      debug(\"[MTM_ORD_VerifyRIMCertAndExtend]\");\n      res = execute_MTM_VerifyRIMCertAndExtend(req, rsp);\n      break;\n\n    case MTM_ORD_IncrementBootstrapCounter:\n      debug(\"[MTM_ORD_IncrementBootstrapCounter]\");\n      res = execute_MTM_IncrementBootstrapCounter(req, rsp);\n      break;\n\n    case MTM_ORD_SetVerifiedPCRSelection:\n      debug(\"[MTM_ORD_SetVerifiedPCRSelection]\");\n      res = execute_MTM_SetVerifiedPCRSelection(req, rsp);\n      break;\n\n    default:\n      res = TPM_BAD_ORDINAL;\n      break;\n  }\n  return res;\n}\n"
  },
  {
    "path": "mtm/mtm_commands.h",
    "content": "/* Software-based Mobile Trusted Module (MTM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n * Copyright (C) 2007 Jan-Erik Ekberg <jan-erik.ekberg@nokia.com>,\n *                    Nokia Corporation and/or its subsidiary(-ies)\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id$\n */\n\n#ifndef _MTM_COMMANDS_H_\n#define _MTM_COMMANDS_H_\n\n#include \"mtm_structures.h\"\n\n/*\n * Modified TPM commands\n */\n\n/**\n * MTM_Extend - adds a new measurement to a PCR\n * @pcrNum: [in] The PCR to be updated\n * @inDigest: [in] The 160 bit value representing the event to be recorded\n * @outDigest: [out] The PCR value after execution of the command\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n */\nTPM_RESULT MTM_Extend(\n  TPM_PCRINDEX pcrNum,\n  TPM_DIGEST *inDigest,\n  TPM_PCRVALUE *outDigest\n);\n\n/**\n * MTM_PCR_Reset - resets the indicated PCRs\n * @pcrSelection: [in] The PCRs to reset\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n */\nTPM_RESULT MTM_PCR_Reset(\n  TPM_PCR_SELECTION *pcrSelection\n);\n\n/**\n * MTM_GetCapability - provides current information regarding the TPM\n * @capArea: [in] Partition of capabilities to be interrogated\n * @subCapSize: [in] Size of subCap parameter\n * @subCap: [in] Further definition of information\n * @respSize: [out] The length of the returned capability response\n * @resp: [out] The capability response\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n */\nTPM_RESULT MTM_GetCapability(\n  TPM_CAPABILITY_AREA capArea,\n  UINT32 subCapSize,\n  BYTE *subCap,\n  UINT32 *respSize,\n  BYTE **resp\n);\n\n/**\n * MTM_ReleaseCounter - releases a counter\n * @countID: [in] ID value of the counter\n * @auth1: [in, out] Authorization protocol parameters\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n */\nTPM_RESULT MTM_ReleaseCounter(\n  TPM_COUNT_ID countID,\n  TPM_AUTH *auth1\n);\n\n/**\n * MTM_ReleaseCounterOwner - releases a counter\n * @countID: [in] ID value of the counter\n * @auth1: [in, out] Authorization protocol parameters\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n */\nTPM_RESULT MTM_ReleaseCounterOwner(\n  TPM_COUNT_ID countID,\n  TPM_AUTH *auth1\n);\n\n/**\n * MTM_FlushSpecific - flushes a specific handle\n * @handle: [in] Handle of the item to flush\n * @resourceType: [in] The type of resource that is being flushed\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n */\nTPM_RESULT MTM_FlushSpecific(\n  TPM_HANDLE handle,\n  TPM_RESOURCE_TYPE resourceType\n);\n\n/*\n * Additional, MTM specific commands\n */\n\n/**\n * MTM_InstallRIM - generates internal RIM certificates.\n * @rimCertIn: [in] Data to be used for internal RIM certificate\n * @auth1: [in, out] Authorization protocol parameters\n * @rimCertOut: [out] An internal RIM certificate\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n *\n * Description: ([MTM_spec, v1.0], Section 7.2)\n */\nTPM_RESULT MTM_InstallRIM(\n  TPM_RIM_CERTIFICATE *rimCertIn,\n  TPM_AUTH *auth1,\n  TPM_RIM_CERTIFICATE *rimCertOut\n);\n\n/**\n * MTM_LoadVerificationKey - load one Verification Key into the MTM\n * @parentKey: [in] Parent key used to verify this key\n * @auth1: [in, out] Authorization protocol parameters\n * @verificationKeyHandle: [out] Handle for the key that was loaded\n * @loadMethod: [out] which method was used to load this verification key\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n *\n * Description: ([MTM_spec, v1.0], Section 7.3)\n */\nTPM_RESULT MTM_LoadVerificationKey(\n  TPM_VERIFICATION_KEY_HANDLE parentKey,\n  TPM_VERIFICATION_KEY *verificationKey,\n  TPM_AUTH *auth1,\n  TPM_VERIFICATION_KEY_HANDLE *verificationKeyHandle,\n  BYTE *loadMethod\n);\n\n/**\n * MTM_LoadVerificationRootKeyDisable - disables the functionality to load Verification Root Keys.\n * Returns: TPM_SUCCESS\n *\n * Description: ([MTM_spec, v1.0], Section 7.4)\n */\nTPM_RESULT MTM_LoadVerificationRootKeyDisable();\n\n/**\n * MTM_VerifyRIMCert - verify an internal or external RIM certificate.\n * @rimCert: [in] RIM certificate to be validated\n * @rimKey: [in] Key handle for the verification. NULL if internal verification key is used.\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n *\n * Description: ([MTM_spec, v1.0], Section 7.5)\n */\nTPM_RESULT MTM_VerifyRIMCert(\n  TPM_RIM_CERTIFICATE* rimCert,\n  TPM_VERIFICATION_KEY_HANDLE rimKey\n);\n\n/**\n * MTM_VerifyRIMCertAndExtend - verify an internal or external RIM certificate and extend PCR given in RIM certificate.\n * @rimCert: [in] RIM certificate to be validated\n * @rimKey: [in] Key handle for the verification key. NULL if internal verification key is used.\n * @outDigest: [out] The PCR value after the execution of the command\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n *\n * Description: ([MTM_spec, v1.0], Section 7.6)\n */\nTPM_RESULT MTM_VerifyRIMCertAndExtend(\n  TPM_RIM_CERTIFICATE *rimCert,\n  TPM_VERIFICATION_KEY_HANDLE rimKey,\n  TPM_PCRVALUE *outDigest\n);\n\n/**\n * MTM_IncrementBootstrapCounter - increment bootstrap counter in MTM permanent data.\n * @rimCert: [in] A RIM certificate\n * @rimKey: [in] Key handle for the verification key to be used\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n *\n * Description: ([MTM_spec, v1.0], Section 7.7)\n */\nTPM_RESULT MTM_IncrementBootstrapCounter(\n  TPM_RIM_CERTIFICATE *rimCert,\n  TPM_VERIFICATION_KEY_HANDLE rimKey\n);\n\n/**\n * MTM_SetVerifiedPCRSelection - Set verifiedPCRs field in MTM_PERMANENT_DATA\n * @verifiedSelection: [in] Set of PCRs that can only be extended with this function\n * @auth1: [in, out]  Authorization protocol parameters\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n *\n * Description: ([MTM_spec, v1.0], Section 7.8)\n */\nTPM_RESULT MTM_SetVerifiedPCRSelection(\n  TPM_PCR_SELECTION *verifiedSelection,\n  TPM_AUTH *auth1\n);\n\nTPM_RESULT mtm_execute_command(TPM_REQUEST *req, TPM_RESPONSE *rsp);\n\n#endif /* _MTM_COMMANDS_H_ */\n"
  },
  {
    "path": "mtm/mtm_counter.c",
    "content": "/* Software-based Mobile Trusted Module (MTM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id$\n */\n\n#include \"mtm_commands.h\"\n#include \"tpm/tpm_handles.h\"\n#include \"tpm/tpm_commands.h\"\n\nTPM_RESULT MTM_ReleaseCounter(TPM_COUNT_ID countID, TPM_AUTH *auth1)\n{\n  int i = HANDLE_TO_INDEX(countID);\n  info(\"MTM_ReleaseCounter()\");\n  if (i == MTM_COUNTER_SELECT_BOOTSTRAP\n      || i == MTM_COUNTER_SELECT_RIMPROTECT\n      || i == MTM_COUNTER_SELECT_STORAGEPROTECT) {\n    debug(\"MTM counters cannot be released\");\n    return TPM_FAIL;\n  }\n  return TPM_ReleaseCounter(countID, auth1);\n}\n\nTPM_RESULT MTM_ReleaseCounterOwner(TPM_COUNT_ID countID, TPM_AUTH *auth1)\n{\n  int i = HANDLE_TO_INDEX(countID);\n  info(\"MTM_ReleaseCounterOwner()\");\n  if (i == MTM_COUNTER_SELECT_BOOTSTRAP\n      || i == MTM_COUNTER_SELECT_RIMPROTECT\n      || i == MTM_COUNTER_SELECT_STORAGEPROTECT) {\n    debug(\"MTM counters cannot be released\");\n    return TPM_FAIL;\n  }\n  return TPM_ReleaseCounterOwner(countID, auth1);\n}\n\n\n"
  },
  {
    "path": "mtm/mtm_data.c",
    "content": "/* Software-based Mobile Trusted Module (MTM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id$\n */\n\n#include \"mtm_data.h\"\n#include \"tpm/tpm_data.h\"\n\nMTM_DATA mtmData;\n\nstatic void set_counter(unsigned int num, const char *label)\n{\n  TPM_COUNTER_VALUE *counter = &tpmData.permanent.data.counters[num];\n  counter->valid = TRUE;\n  counter->tag = TPM_TAG_COUNTER_VALUE;\n  memcpy(counter->label, label, sizeof(counter->label));\n  counter->counter = 1;\n  memset(counter->usageAuth, 0, sizeof(TPM_SECRET));\n}\n\nvoid mtm_init_data(void)\n{\n  int i;\n  info(\"initializing MTM data to default values\");\n  /* reset all data to NULL, FALSE or 0 */\n  memset(&mtmData, 0, sizeof(mtmData));\n  mtmData.permanent.data.tag = MTM_TAG_PERMANENT_DATA;\n  /* set specification version */\n  mtmData.permanent.data.specMajor = 0x01;\n  mtmData.permanent.data.specMinor = 0x00;\n  /* define verified PCRs */\n  mtmData.permanent.data.verifiedPCRs.sizeOfSelect = TPM_NUM_PCR / 8;\n  for (i = 0; i < TPM_NUM_PCR / 8; i++) {\n    mtmData.permanent.data.verifiedPCRs.pcrSelect[i] = 0x00;\n  }\n  /* map MTM counters to TPM counters */\n  set_counter(MTM_COUNTER_SELECT_BOOTSTRAP, \"MTM1\");\n  set_counter(MTM_COUNTER_SELECT_RIMPROTECT, \"MTM2\");\n  set_counter(MTM_COUNTER_SELECT_STORAGEPROTECT, \"MTM3\");\n  /* the field integrityCheckRootData is filled when the first verification key is loaded */\n  memset(mtmData.permanent.data.integrityCheckRootData, 0xff,\n         sizeof(mtmData.permanent.data.integrityCheckRootData));\n  /* set internal verification key */\n  memcpy(mtmData.permanent.data.internalVerificationKey,\n         \"\\x77\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n         \"\\x00\\x00\\x00\\x77\", sizeof(TPM_SECRET));\n  /* init flags */\n  mtmData.stany.flags.tag = MTM_TAG_STANY_FLAGS;\n  mtmData.stany.flags.loadVerificationRootKeyEnabled = TRUE;\n}\n\n"
  },
  {
    "path": "mtm/mtm_data.h",
    "content": "/* Software-based Mobile Trusted Module (MTM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id$\n */\n\n#ifndef _MTM_DATA_H_\n#define _MTM_DATA_H_\n\n#include \"mtm_structures.h\"\n\nextern MTM_DATA mtmData;\n\nvoid mtm_init_data(void);\n\n#endif /* _MTM_DATA_H_ */\n\n"
  },
  {
    "path": "mtm/mtm_eviction.c",
    "content": "/* Software-based Mobile Trusted Module (MTM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id$\n */\n\n#include \"mtm_commands.h\"\n#include \"mtm_handles.h\"\n#include \"tpm/tpm_commands.h\"\n\nTPM_RESULT MTM_FlushSpecific(TPM_HANDLE handle, \n                             TPM_RESOURCE_TYPE resourceType)\n{\n  MTM_KEY_DATA *key;\n  \n  info(\"MTM_FlushSpecific()\");\n  debug(\"handle = %08x, resourceType = %08x\", handle, resourceType);\n  if (resourceType == TPM_RT_KEY) {\n    key = mtm_get_key(handle);\n    if (key != NULL) {\n      free_MTM_KEY_DATA((*key)); \n      memset(key, 0, sizeof(*key));\n      tpm_invalidate_sessions(handle);\n      return TPM_SUCCESS;\n    } \n  }\n  return TPM_FlushSpecific(handle, resourceType);\n}\n\n"
  },
  {
    "path": "mtm/mtm_handles.c",
    "content": "/* Software-based Mobile Trusted Module (MTM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id$\n */\n\n#include \"mtm_handles.h\"\n#include \"mtm_data.h\"\n\nMTM_KEY_DATA *mtm_get_key_slot(TPM_VERIFICATION_KEY_HANDLE handle)\n{\n  if (handle == TPM_INVALID_HANDLE) return NULL;\n  handle &= 0x00ffffff;\n  if (handle < TPM_MAX_KEYS) return NULL;\n  handle -= TPM_MAX_KEYS;\n  if (handle >= MTM_MAX_KEYS) return NULL;\n  return &mtmData.permanent.data.keys[handle];\n}\n\nMTM_KEY_DATA *mtm_get_key(TPM_VERIFICATION_KEY_HANDLE handle)\n{\n  if (handle == TPM_INVALID_HANDLE\n      || (handle >> 24) != TPM_RT_KEY) return NULL;\n  handle &= 0x00ffffff;\n  if (handle < TPM_MAX_KEYS) return NULL;\n  handle -= TPM_MAX_KEYS;\n  if (handle >= MTM_MAX_KEYS\n      || !mtmData.permanent.data.keys[handle].valid) return NULL;\n  return &mtmData.permanent.data.keys[handle]; \n}\n\nMTM_KEY_DATA *mtm_get_key_by_id(TPM_VERIFICATION_KEY_ID id)\n{\n  int i;\n  for (i = 0; i < MTM_MAX_KEYS; i++) {\n    if (mtmData.permanent.data.keys[i].valid\n        && mtmData.permanent.data.keys[i].myId == id)\n      return &mtmData.permanent.data.keys[i];\n  }\n  return NULL;\n}\n\n"
  },
  {
    "path": "mtm/mtm_handles.h",
    "content": "/* Software-based Mobile Trusted Module (MTM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id$\n */\n\n#include \"mtm_structures.h\"\n#include \"tpm/tpm_handles.h\"\n\nMTM_KEY_DATA *mtm_get_key_slot(TPM_VERIFICATION_KEY_HANDLE handle);\n\nMTM_KEY_DATA *mtm_get_key(TPM_VERIFICATION_KEY_HANDLE handle);\n\nMTM_KEY_DATA *mtm_get_key_by_id(TPM_VERIFICATION_KEY_ID id); \n\n"
  },
  {
    "path": "mtm/mtm_integrity.c",
    "content": "/* Software-based Mobile Trusted Module (MTM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id$\n */\n\n#include \"mtm_structures.h\"\n#include \"mtm_data.h\"\n#include \"tpm/tpm_commands.h\"\n\nTPM_RESULT MTM_Extend(TPM_PCRINDEX pcrNum, TPM_DIGEST *inDigest, \n                      TPM_PCRVALUE *outDigest)\n{\n  info(\"MTM_Extend()\");\n  if (mtmData.permanent.data.verifiedPCRs.pcrSelect[pcrNum >> 3] & (1 << (pcrNum & 7))) {\n    return TPM_BAD_LOCALITY;\n  }\n  return TPM_Extend(pcrNum, inDigest, outDigest);\n}\n\nTPM_RESULT MTM_PCR_Reset(TPM_PCR_SELECTION *pcrSelection)\n{\n  int i;\n  info(\"MTM_PCR_Reset()\");\n  for (i = 0; i < pcrSelection->sizeOfSelect * 8; i++) {\n    if ((pcrSelection->pcrSelect[i >> 3] & (1 << (i & 7)))\n        && (mtmData.permanent.data.verifiedPCRs.pcrSelect[i >> 3] & (1 << (i & 7)))) {\n      return TPM_FAIL;\n    }\n  }\n  return TPM_PCR_Reset(pcrSelection);\n}\n\n"
  },
  {
    "path": "mtm/mtm_marshalling.c",
    "content": "/* Software-based Mobile Trusted Module (MTM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id$\n */\n\n#include \"mtm_marshalling.h\"\n\nint tpm_marshal_MTM_PERMANENT_DATA(BYTE **ptr, UINT32 *length, MTM_PERMANENT_DATA *v)\n{\n  int i;\n  if (tpm_marshal_TPM_STRUCTURE_TAG(ptr, length, v->tag)\n      || tpm_marshal_BYTE(ptr, length, v->specMajor)\n      || tpm_marshal_BYTE(ptr, length, v->specMinor)\n      || tpm_marshal_TPM_PCR_SELECTION(ptr, length, &v->verifiedPCRs)\n      || tpm_marshal_TPM_COUNT_ID(ptr, length, v->counterRimProtectId)\n      || tpm_marshal_TPM_COUNT_ID(ptr, length, v->counterStorageProtectId)\n      || tpm_marshal_BYTE(ptr, length, v->loadVerificationKeyMethods)\n      || tpm_marshal_BOOL(ptr, length, v->integrityCheckRootValid)\n      || tpm_marshal_BYTE_ARRAY(ptr, length, v->integrityCheckRootData,\n                                sizeof(v->integrityCheckRootData))\n      || tpm_marshal_TPM_SECRET(ptr, length, &v->internalVerificationKey)) return -1;\n  for (i = 0; i < MTM_MAX_KEYS; i++) {\n    if (tpm_marshal_MTM_KEY_DATA(ptr, length, &v->keys[i])) return -1;\n  }\n  return 0;\n}\n\nint tpm_unmarshal_MTM_PERMANENT_DATA(BYTE **ptr, UINT32 *length, MTM_PERMANENT_DATA *v)\n{\n  int i;\n  if (tpm_unmarshal_TPM_STRUCTURE_TAG(ptr, length, &v->tag)\n      || tpm_unmarshal_BYTE(ptr, length, &v->specMajor)\n      || tpm_unmarshal_BYTE(ptr, length, &v->specMinor)\n      || tpm_unmarshal_TPM_PCR_SELECTION(ptr, length, &v->verifiedPCRs)\n      || tpm_unmarshal_TPM_COUNT_ID(ptr, length, &v->counterRimProtectId)\n      || tpm_unmarshal_TPM_COUNT_ID(ptr, length, &v->counterStorageProtectId)\n      || tpm_unmarshal_BYTE(ptr, length, &v->loadVerificationKeyMethods)\n      || tpm_unmarshal_BOOL(ptr, length, &v->integrityCheckRootValid)\n      || tpm_unmarshal_BYTE_ARRAY(ptr, length, v->integrityCheckRootData,\n                                  sizeof(v->integrityCheckRootData))\n      || tpm_unmarshal_TPM_SECRET(ptr, length, &v->internalVerificationKey)) return -1;\n  for (i = 0; i < MTM_MAX_KEYS; i++) {\n    if (tpm_unmarshal_MTM_KEY_DATA(ptr, length, &v->keys[i])) return -1;\n  }\n  return 0;\n}\n\nint tpm_marshal_MTM_STANY_FLAGS(BYTE **ptr, UINT32 *length, MTM_STANY_FLAGS *v)\n{\n  if (tpm_marshal_TPM_TAG(ptr, length, v->tag)\n      || tpm_marshal_BOOL(ptr, length, v->loadVerificationRootKeyEnabled)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_MTM_STANY_FLAGS(BYTE **ptr, UINT32 *length, MTM_STANY_FLAGS *v)\n{\n  if (tpm_unmarshal_TPM_TAG(ptr, length, &v->tag)\n      || tpm_unmarshal_BOOL(ptr, length, &v->loadVerificationRootKeyEnabled)) return -1;\n  return 0;\n}\n\nint tpm_marshal_MTM_COUNTER_REFERENCE(BYTE **ptr, UINT32 *length, MTM_COUNTER_REFERENCE *v)\n{\n  if (tpm_marshal_BYTE(ptr, length, v->counterSelection)\n      || tpm_marshal_TPM_ACTUAL_COUNT(ptr, length, v->counterValue)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_MTM_COUNTER_REFERENCE(BYTE **ptr, UINT32 *length, MTM_COUNTER_REFERENCE *v)\n{\n  if (tpm_unmarshal_BYTE(ptr, length, &v->counterSelection)\n      || tpm_unmarshal_TPM_ACTUAL_COUNT(ptr, length, &v->counterValue)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_RIM_CERTIFICATE(BYTE **ptr, UINT32 *length, TPM_RIM_CERTIFICATE *v)\n{\n  if (tpm_marshal_TPM_STRUCTURE_TAG(ptr, length, v->tag)\n      || tpm_marshal_BYTE_ARRAY(ptr, length, v->label, 8)\n      || tpm_marshal_UINT32(ptr, length, v->rimVersion)\n      || tpm_marshal_MTM_COUNTER_REFERENCE(ptr, length, &v->referenceCounter)\n      || tpm_marshal_TPM_PCR_INFO_SHORT(ptr, length, &v->state)\n      || tpm_marshal_UINT32(ptr, length, v->measurementPcrIndex)\n      || tpm_marshal_TPM_PCRVALUE(ptr, length, &v->measurementValue)\n      || tpm_marshal_TPM_VERIFICATION_KEY_ID(ptr, length, v->parentId)\n      || tpm_marshal_BYTE(ptr, length, v->extensionDigestSize)\n      || (v->extensionDigestSize > 0\n          && tpm_marshal_BLOB(ptr, length, v->extensionDigestData, v->extensionDigestSize))\n      || tpm_marshal_UINT32(ptr, length, v->integrityCheckSize)\n      || (v->integrityCheckSize > 0\n          && tpm_marshal_BLOB(ptr, length, v->integrityCheckData, v->integrityCheckSize))) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_RIM_CERTIFICATE(BYTE **ptr, UINT32 *length, TPM_RIM_CERTIFICATE *v)\n{\n  if (tpm_unmarshal_TPM_STRUCTURE_TAG(ptr, length, &v->tag)\n      || tpm_unmarshal_BYTE_ARRAY(ptr, length, v->label, 8)\n      || tpm_unmarshal_UINT32(ptr, length, &v->rimVersion)\n      || tpm_unmarshal_MTM_COUNTER_REFERENCE(ptr, length, &v->referenceCounter)\n      || tpm_unmarshal_TPM_PCR_INFO_SHORT(ptr, length, &v->state)\n      || tpm_unmarshal_UINT32(ptr, length, &v->measurementPcrIndex)\n      || tpm_unmarshal_TPM_PCRVALUE(ptr, length, &v->measurementValue)\n      || tpm_unmarshal_TPM_VERIFICATION_KEY_ID(ptr, length, &v->parentId)\n      || tpm_unmarshal_BYTE(ptr, length, &v->extensionDigestSize)\n      || (v->extensionDigestSize > 0\n          && tpm_unmarshal_BLOB(ptr, length, &v->extensionDigestData, v->extensionDigestSize))\n      || tpm_unmarshal_UINT32(ptr, length, &v->integrityCheckSize)\n      || (v->integrityCheckSize > 0\n          && tpm_unmarshal_BLOB(ptr, length, &v->integrityCheckData, v->integrityCheckSize))) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_VERIFICATION_KEY(BYTE **ptr, UINT32 *length, TPM_VERIFICATION_KEY *v)\n{\n  if (tpm_marshal_TPM_STRUCTURE_TAG(ptr, length, v->tag)\n      || tpm_marshal_UINT16(ptr, length, v->usageFlags)\n      || tpm_marshal_TPM_VERIFICATION_KEY_ID(ptr, length, v->parentId)\n      || tpm_marshal_TPM_VERIFICATION_KEY_ID(ptr, length, v->myId)\n      || tpm_marshal_MTM_COUNTER_REFERENCE(ptr, length, &v->referenceCounter)\n      || tpm_marshal_TPM_ALGORITHM_ID(ptr, length, v->keyAlgorithm)\n      || tpm_marshal_TPM_SIG_SCHEME(ptr, length, v->keyScheme)\n      || tpm_marshal_BYTE(ptr, length, v->extensionDigestSize)\n      || (v->extensionDigestSize > 0\n          && tpm_marshal_BLOB(ptr, length, v->extensionDigestData, v->extensionDigestSize))\n      || tpm_marshal_UINT32(ptr, length, v->keySize)\n      || (v->keySize > 0 && tpm_marshal_BLOB(ptr, length, v->keyData, v->keySize))\n      || tpm_marshal_UINT32(ptr, length, v->integrityCheckSize)\n      || (v->integrityCheckSize > 0\n          && tpm_marshal_BLOB(ptr, length, v->integrityCheckData, v->integrityCheckSize))) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_VERIFICATION_KEY(BYTE **ptr, UINT32 *length, TPM_VERIFICATION_KEY *v)\n{\n  if (tpm_unmarshal_TPM_STRUCTURE_TAG(ptr, length, &v->tag)\n      || tpm_unmarshal_UINT16(ptr, length, &v->usageFlags)\n      || tpm_unmarshal_TPM_VERIFICATION_KEY_ID(ptr, length, &v->parentId)\n      || tpm_unmarshal_TPM_VERIFICATION_KEY_ID(ptr, length, &v->myId)\n      || tpm_unmarshal_MTM_COUNTER_REFERENCE(ptr, length, &v->referenceCounter)\n      || tpm_unmarshal_TPM_ALGORITHM_ID(ptr, length, &v->keyAlgorithm)\n      || tpm_unmarshal_TPM_SIG_SCHEME(ptr, length, &v->keyScheme)\n      || tpm_unmarshal_BYTE(ptr, length, &v->extensionDigestSize)\n      || (v->extensionDigestSize > 0\n          && tpm_unmarshal_BLOB(ptr, length, &v->extensionDigestData, v->extensionDigestSize))\n      || tpm_unmarshal_UINT32(ptr, length, &v->keySize)\n      || (v->keySize > 0 && tpm_unmarshal_BLOB(ptr, length, &v->keyData, v->keySize))\n      || tpm_unmarshal_UINT32(ptr, length, &v->integrityCheckSize)\n      || (v->integrityCheckSize > 0\n          && tpm_unmarshal_BLOB(ptr, length, &v->integrityCheckData, v->integrityCheckSize))) return -1;\n  return 0;\n}\n\nint tpm_marshal_MTM_KEY_DATA(BYTE **ptr, UINT32 *length, MTM_KEY_DATA *v)\n{\n  if (tpm_marshal_BOOL(ptr, length, v->valid)) return -1;\n  if (v->valid) {\n    if (tpm_marshal_UINT16(ptr, length, v->usageFlags)\n        || tpm_marshal_TPM_VERIFICATION_KEY_ID(ptr, length, v->parentId)\n        || tpm_marshal_TPM_VERIFICATION_KEY_ID(ptr, length, v->myId)\n        || tpm_marshal_TPM_ALGORITHM_ID(ptr, length, v->keyAlgorithm)\n        || tpm_marshal_TPM_SIG_SCHEME(ptr, length, v->keyScheme)\n        || tpm_marshal_RSAPub(ptr, length, &v->key)) return -1;\n  }\n  return 0;\n}\n\nint tpm_unmarshal_MTM_KEY_DATA(BYTE **ptr, UINT32 *length, MTM_KEY_DATA *v)\n{\n  if (tpm_unmarshal_BOOL(ptr, length, &v->valid)) return -1;\n  if (v->valid) {\n    if (tpm_unmarshal_UINT16(ptr, length, &v->usageFlags)\n        || tpm_unmarshal_TPM_VERIFICATION_KEY_ID(ptr, length, &v->parentId)\n        || tpm_unmarshal_TPM_VERIFICATION_KEY_ID(ptr, length, &v->myId)\n        || tpm_unmarshal_TPM_ALGORITHM_ID(ptr, length, &v->keyAlgorithm)\n        || tpm_unmarshal_TPM_SIG_SCHEME(ptr, length, &v->keyScheme)\n        || tpm_unmarshal_RSAPub(ptr, length, &v->key)) return -1;\n  }\n  return 0;\n}\n\nint tpm_marshal_MTM_DATA(BYTE **ptr, UINT32 *length, MTM_DATA *v)\n{\n  if (tpm_marshal_MTM_PERMANENT_DATA(ptr, length, &v->permanent.data)\n      || tpm_marshal_MTM_STANY_FLAGS(ptr, length, &v->stany.flags)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_MTM_DATA(BYTE **ptr, UINT32 *length, MTM_DATA *v)\n{\n  if (tpm_unmarshal_MTM_PERMANENT_DATA(ptr, length, &v->permanent.data)\n      || tpm_unmarshal_MTM_STANY_FLAGS(ptr, length, &v->stany.flags)) return -1;\n  return 0;\n}\n\n"
  },
  {
    "path": "mtm/mtm_marshalling.h",
    "content": "/* Software-based Mobile Trusted Module (MTM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id$\n */\n\n#ifndef _MTM_MARSHALLING_H_\n#define _MTM_MARSHALLING_H_\n\n#include \"mtm_structures.h\"\n#include \"tpm/tpm_marshalling.h\"\n\n#define tpm_marshal_TPM_VERIFICATION_KEY_ID        tpm_marshal_UINT32\n#define tpm_unmarshal_TPM_VERIFICATION_KEY_ID      tpm_unmarshal_UINT32\n#define tpm_marshal_TPM_VERIFICATION_KEY_HANDLE    tpm_marshal_UINT32\n#define tpm_unmarshal_TPM_VERIFICATION_KEY_HANDLE  tpm_unmarshal_UINT32\n\nint tpm_marshal_MTM_PERMANENT_DATA(BYTE **ptr, UINT32 *length, MTM_PERMANENT_DATA *v);\nint tpm_unmarshal_MTM_PERMANENT_DATA(BYTE **ptr, UINT32 *length, MTM_PERMANENT_DATA *v);\n\nint tpm_marshal_MTM_STANY_FLAGS(BYTE **ptr, UINT32 *length, MTM_STANY_FLAGS *v);\nint tpm_unmarshal_MTM_STANY_FLAGS(BYTE **ptr, UINT32 *length, MTM_STANY_FLAGS *v);\n\nint tpm_marshal_MTM_COUNTER_REFERENCE(BYTE **ptr, UINT32 *length, MTM_COUNTER_REFERENCE *v);\nint tpm_unmarshal_MTM_COUNTER_REFERENCE(BYTE **ptr, UINT32 *length, MTM_COUNTER_REFERENCE *v);\n\nint tpm_marshal_TPM_RIM_CERTIFICATE(BYTE **ptr, UINT32 *length, TPM_RIM_CERTIFICATE *v);\nint tpm_unmarshal_TPM_RIM_CERTIFICATE(BYTE **ptr, UINT32 *length, TPM_RIM_CERTIFICATE *v);\n\nint tpm_marshal_TPM_VERIFICATION_KEY(BYTE **ptr, UINT32 *length, TPM_VERIFICATION_KEY *v);\nint tpm_unmarshal_TPM_VERIFICATION_KEY(BYTE **ptr, UINT32 *length, TPM_VERIFICATION_KEY *v);\n\nint tpm_marshal_MTM_KEY_DATA(BYTE **ptr, UINT32 *length, MTM_KEY_DATA *v);\nint tpm_unmarshal_MTM_KEY_DATA(BYTE **ptr, UINT32 *length, MTM_KEY_DATA *v);\n\nint tpm_marshal_MTM_DATA(BYTE **ptr, UINT32 *length, MTM_DATA *v);\nint tpm_unmarshal_MTM_DATA(BYTE **ptr, UINT32 *length, MTM_DATA *v);\n\n#endif /* _MTM_MARSHALLING_H_ */\n\n"
  },
  {
    "path": "mtm/mtm_structures.h",
    "content": "/* Software-based Mobile Trusted Module (MTM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id$\n */\n\n#ifndef _MTM_STRUCTURES_H_\n#define _MTM_STRUCTURES_H_\n\n#include \"tpm/tpm_structures.h\"\n#include \"crypto/sha1.h\"\n\n/*\n * Ordinals\n * The command ordinals provide the index value for each command.\n */\n#define MTM_ORD_InstallRIM                      (66 + TPM_PROTECTED_COMMAND)\n#define MTM_ORD_LoadVerificationKey             (67 + TPM_PROTECTED_COMMAND)\n#define MTM_ORD_LoadVerificationRootKeyDisable  (68 + TPM_PROTECTED_COMMAND)\n#define MTM_ORD_VerifyRIMCert                   (69 + TPM_PROTECTED_COMMAND)\n#define MTM_ORD_VerifyRIMCertAndExtend          (72 + TPM_PROTECTED_COMMAND)\n#define MTM_ORD_IncrementBootstrapCounter       (73 + TPM_PROTECTED_COMMAND)\n#define MTM_ORD_SetVerifiedPCRSelection         (74 + TPM_PROTECTED_COMMAND)\n\n/*\n * TPM_CAPABILITY_AREA Values for TPM_GetCapability\n */\n#define TPM_CAP_MTM_PERMANENT_DATA        0x0000000A\n\n/*\n * MTM_COUNTER_REFERENCE ([MTM], Section 5.1)\n * MTM counter reference structure\n */\n#define MTM_COUNTER_SELECT_NONE           0\n#define MTM_COUNTER_SELECT_BOOTSTRAP      1\n#define MTM_COUNTER_SELECT_RIMPROTECT     2\n#define MTM_COUNTER_SELECT_STORAGEPROTECT 3\n#define MTM_COUNTER_SELECT_MAX            3\ntypedef struct MTM_COUNTER_REFERENCE_STRUCT {\n  BYTE counterSelection;\n  TPM_ACTUAL_COUNT counterValue;\n} MTM_COUNTER_REFERENCE;\n#define sizeof_MTM_COUNTER_REFERENCE(s) (1 + 4)\n\n/*\n * TPM_VERIFICATION_KEY_ID ([MTM], Section 5.3)\n */\ntypedef UINT32 TPM_VERIFICATION_KEY_ID;\n#define TPM_VERIFICATION_KEY_ID_NONE     0xFFFFFFFF\n#define TPM_VERIFICATION_KEY_ID_INTERNAL 0xFFFFFFFE\n\n/*\n * TPM_VERIFICATION_KEY_USAGE ([MTM], Section 5.3)\n */\n#define TPM_VERIFICATION_KEY_USAGE_MTM_MASK            0x00ff\n#define TPM_VERIFICATION_KEY_USAGE_AGENT_MASK          0x0f00\n#define TPM_VERIFICATION_KEY_USAGE_VENDOR_MASK         0xf000\n#define TPM_VERIFICATION_KEY_USAGE_SIGN_RIMCERT        0x0001\n#define TPM_VERIFICATION_KEY_USAGE_SIGN_RIMAUTH        0x0002\n#define TPM_VERIFICATION_KEY_USAGE_INCREMENT_BOOTSTRAP 0x0004\n\n/*\n * TPM_VERIFICATION_KEY_HANDLE ([MTM], Section 5.3)\n * Handle used to refer to TPM_VERIFICATION_KEY structures\n */\ntypedef UINT32 TPM_VERIFICATION_KEY_HANDLE;\n\n/*\n * TPM_VERIFICATION_KEY ([MTM], Section 5.3)\n * The TPM_VERIFICATION_KEY structure is used for representing keys in\n * the authorization hierarchy used to authorize RIM_Certs for a MTM.\n */\n#define TPM_TAG_VERIFICATION_KEY 0x0301\ntypedef struct TPM_VERIFICATION_KEY_STRUCT {\n  TPM_STRUCTURE_TAG tag;\n  UINT16 usageFlags;\n  TPM_VERIFICATION_KEY_ID parentId;\n  TPM_VERIFICATION_KEY_ID myId;\n  MTM_COUNTER_REFERENCE referenceCounter;\n  TPM_ALGORITHM_ID keyAlgorithm;\n  TPM_SIG_SCHEME keyScheme;\n  BYTE extensionDigestSize;\n  BYTE* extensionDigestData;\n  UINT32 keySize;\n  BYTE* keyData;\n  UINT32 integrityCheckSize;\n  BYTE* integrityCheckData;\n} TPM_VERIFICATION_KEY;\n#define sizeof_TPM_VERIFICATION_KEY(s) (2 + 2 + 4 + 4 \\\n  + sizeof_MTM_COUNTER_REFERENCE(s.referenceCounter) + 4 + 2 + 1 \\\n  + s.extensionDigestSize + 4 + s.keySize + 4 + s.integrityCheckSize)\n#define free_TPM_VERIFICATION_KEY(s) { \\\n  if (s.extensionDigestSize > 0) tpm_free(s.extensionDigestData); \\\n  if (s.keySize > 0) tpm_free(s.keyData); \\\n  if (s.integrityCheckSize > 0) tpm_free(s.integrityCheckData); }\n\n/*\n * TPM_RIM_CERTIFICATE ([MTM], Section 5.2)\n * A RIM Certificate is a structure authorizing a measurement value\n * that is extended using MTM_VerifyRIMCertAndExtend into a PCR\n * defined in the RIM Certificate.\n */\n#define TPM_TAG_RIM_CERTIFICATE 0x0302\ntypedef struct TPM_RIM_CERTIFICATE_STRUCT {\n  TPM_STRUCTURE_TAG tag;\n  BYTE label[8];\n  UINT32 rimVersion;\n  MTM_COUNTER_REFERENCE referenceCounter;\n  TPM_PCR_INFO_SHORT state;\n  UINT32 measurementPcrIndex;\n  TPM_PCRVALUE measurementValue;\n  TPM_VERIFICATION_KEY_ID parentId;\n  BYTE extensionDigestSize;\n  BYTE *extensionDigestData;\n  UINT32 integrityCheckSize;\n  BYTE *integrityCheckData;\n} TPM_RIM_CERTIFICATE;\n#define sizeof_TPM_RIM_CERTIFICATE(s) (2 + 8 + 4 \\\n  + sizeof_MTM_COUNTER_REFERENCE(s.referenceCounter) \\\n  + sizeof_TPM_PCR_INFO_SHORT(s.state) \\\n  + 4 + 20 + 4 + 1 + s.extensionDigestSize \\\n  + 4 + s.integrityCheckSize)\n#define free_TPM_RIM_CERTIFICATE(s) { \\\n  if (s.extensionDigestSize > 0) tpm_free(s.extensionDigestData); \\\n  if (s.integrityCheckSize > 0) tpm_free(s.integrityCheckData); }\n\n/*\n * TPM_VERIFICATION_KEY_LOAD_METHODS ([MTM], Section 5.4)\n * Methods to load a TPM_VERIFICATION_KEY\n */\ntypedef BYTE TPM_VERIFICATION_KEY_LOAD_METHODS;\n#define TPM_VERIFICATION_KEY_ROOT_LOAD                      0x01\n#define TPM_VERIFICATION_KEY_INTEGRITY_CHECK_ROOT_DATA_LOAD 0x02\n#define TPM_VERIFICATION_KEY_OWNER_AUTHORIZED_LOAD          0x04\n#define TPM_VERIFICATION_KEY_CHAIN_AUTHORIZED_LOAD          0x08\n\n/*\n * MTM_KEY_DATA\n * This structure contains the data for stored MTM verification keys.\n */\ntypedef struct MTM_KEY_DATA_STRUCT {\n  BOOL valid;\n  UINT16 usageFlags;\n  TPM_VERIFICATION_KEY_ID parentId;\n  TPM_VERIFICATION_KEY_ID myId;\n  TPM_ALGORITHM_ID keyAlgorithm;\n  TPM_SIG_SCHEME keyScheme;\n  tpm_rsa_public_key_t key;\n} MTM_KEY_DATA;\n#define sizeof_MTM_KEY_DATA(s) ( \\\n  1 + 2 + 4 + 4 + 4 + 2 + sizeof_RSAPub(s.key))\n#define free_MTM_KEY_DATA(s) { tpm_rsa_release_public_key(&s.key); }\n\n/* \n * MTM_PERMANENT_DATA ([MTM], Section 5.4)\n * The MTM_PERMANENT_DATA structure contains the permanent data associated\n * with a MTM that are used by the MTM commands. Note that there is an\n * alternative where there is only AIK but no EK defined.\n */\n#define MTM_TAG_PERMANENT_DATA        0x0303\n#define MTM_MAX_KEYS                  10\ntypedef struct MTM_PERMANENT_DATA_STRUCT {\n  TPM_STRUCTURE_TAG tag;\n  BYTE specMajor;\n  BYTE specMinor;\n  /* TPM_KEY aik; - not needed as the EK is always present */\n  TPM_PCR_SELECTION verifiedPCRs;\n  TPM_COUNT_ID counterRimProtectId;\n  TPM_COUNT_ID counterStorageProtectId;\n  TPM_VERIFICATION_KEY_LOAD_METHODS loadVerificationKeyMethods;\n  BOOL integrityCheckRootValid;\n  BYTE integrityCheckRootData[SHA1_DIGEST_LENGTH];\n  TPM_SECRET internalVerificationKey;\n  /* TPM_SECRET verificationAuth; - is a mirror of the ownerAuth */\n  MTM_KEY_DATA keys[MTM_MAX_KEYS];\n} MTM_PERMANENT_DATA;\n\nstatic inline int sizeof_MTM_PERMANENT_DATA(MTM_PERMANENT_DATA *s)\n{\n  int i, size = 2 + 1 + 1 + 4 + 4 + 1 + 1 + 20;\n  size += sizeof_TPM_PCR_SELECTION(s->verifiedPCRs);\n  size += sizeof(s->integrityCheckRootData);\n  for (i = 0; i < MTM_MAX_KEYS; i++) {\n    if (s->keys[i].valid) {\n      size += sizeof_MTM_KEY_DATA(s->keys[i]);\n    } else {\n      size += 1;\n    }\n  }\n  return size;\n}\n\nstatic inline void free_MTM_PERMANENT_DATA(MTM_PERMANENT_DATA *s)\n{\n  int i;\n  for (i = 0; i < MTM_MAX_KEYS; i++) {\n    if (s->keys[i].valid) free_MTM_KEY_DATA(s->keys[i]);\n  }\n}\n\n/*\n * The MTM_STANY_FLAGS structure houses additional flags that are\n * initialized by TPM_Init when the MTM boots.\n */\n#define MTM_TAG_STANY_FLAGS 0x0304\ntypedef struct MTM_STANY_FLAGS_STRUCT {\n  TPM_TAG tag;\n  BOOL loadVerificationRootKeyEnabled;\n} MTM_STANY_FLAGS;\n#define sizeof_MTM_STANY_FLAGS(s) (2 + 1)\n\n/*\n * MTM_DATA\n * Internal data of the MTM\n */\ntypedef struct tdMTM_DATA {\n  struct {\n    MTM_PERMANENT_DATA data;\n  } permanent;\n  // struct {\n  // } stclear;\n  struct {\n    MTM_STANY_FLAGS flags;\n  } stany;\n} MTM_DATA;\n#define sizeof_MTM_DATA(s) (sizeof_MTM_PERMANENT_DATA(&s.permanent.data) \\\n  + sizeof_MTM_STANY_FLAGS(s.stany.flags))\n#define free_MTM_DATA(s) { free_MTM_PERMANENT_DATA(&s.permanent.data); }\n \n#endif /* _MTM_STRUCTURES_H */\n\n"
  },
  {
    "path": "mtm/mtm_verification.c",
    "content": "/* Software-based Mobile Trusted Module (MTM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n * Copyright (C) 2007 Jan-Erik Ekberg <jan-erik.ekberg@nokia.com>,\n *                    Nokia Corporation and/or its subsidiary(-ies)\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id$\n */\n\n#include \"mtm_structures.h\"\n#include \"mtm_commands.h\"\n#include \"tpm/tpm_commands.h\"\n#include \"mtm_data.h\"\n#include \"tpm/tpm_data.h\"\n#include \"mtm_handles.h\"\n#include \"mtm_marshalling.h\"\n#include \"crypto/hmac.h\"\n#include \"crypto/rsa.h\"\n#include \"crypto/sha1.h\"\n\nstatic int copy_TPM_RIM_CERTIFICATE(TPM_RIM_CERTIFICATE* src, TPM_RIM_CERTIFICATE* dst)\n{\n  memcpy(dst, src, sizeof(TPM_RIM_CERTIFICATE));\n  if (dst->extensionDigestSize > 0) {\n    dst->extensionDigestData = tpm_malloc(dst->extensionDigestSize);\n    if (dst->extensionDigestData == NULL) return -1;\n    memcpy(dst->extensionDigestData, src->extensionDigestData,\n           dst->extensionDigestSize);\n  } else {\n    dst->extensionDigestData = NULL;\n  }\n  if (dst->integrityCheckSize > 0) {\n    dst->integrityCheckData = tpm_malloc(dst->integrityCheckSize);\n    if (dst->integrityCheckData == NULL) {\n      tpm_free(dst->extensionDigestData);\n      return -1;\n    }\n    memcpy(dst->integrityCheckData, src->integrityCheckData,\n           dst->integrityCheckSize);\n  } else {\n    dst->integrityCheckData = NULL;\n  }\n  return 0;\n}\n\nstatic int compute_rim_certificate_digest(TPM_RIM_CERTIFICATE* rimCert, BYTE *digest)\n{\n  tpm_sha1_ctx_t sha1_ctx;\n  BYTE *buf, *ptr;\n  UINT32 buf_len, len;\n  UINT32 integrityCheckSize;\n\n  /* marshal certificate */\n  integrityCheckSize = rimCert->integrityCheckSize;\n  rimCert->integrityCheckSize = 0;\n  buf_len = len = sizeof_TPM_RIM_CERTIFICATE((*rimCert));\n  buf = ptr = tpm_malloc(buf_len);\n  if (buf == NULL || tpm_marshal_TPM_RIM_CERTIFICATE(&ptr, &len, rimCert)) {\n    rimCert->integrityCheckSize = integrityCheckSize;\n    tpm_free(buf);\n    return -1;\n  }\n  rimCert->integrityCheckSize = integrityCheckSize;\n  /* compute hmac */\n  tpm_sha1_init(&sha1_ctx);\n  tpm_sha1_update(&sha1_ctx, buf, buf_len);\n  tpm_sha1_final(&sha1_ctx, digest);\n  tpm_free(buf);\n  return 0;\n}\n\nstatic int compute_rim_certificate_hmac(TPM_RIM_CERTIFICATE* rimCert, BYTE *digest)\n{\n  tpm_hmac_ctx_t hmac_ctx;\n  BYTE *buf, *ptr;\n  UINT32 buf_len, len;\n  UINT32 integrityCheckSize;\n\n  /* marshal certificate */\n  integrityCheckSize = rimCert->integrityCheckSize;\n  rimCert->integrityCheckSize = 0;\n  buf_len = len = sizeof_TPM_RIM_CERTIFICATE((*rimCert));\n  buf = ptr = tpm_malloc(buf_len);\n  if (buf == NULL || tpm_marshal_TPM_RIM_CERTIFICATE(&ptr, &len, rimCert)) {\n    rimCert->integrityCheckSize = integrityCheckSize;\n    tpm_free(buf);\n    return -1;\n  }\n  rimCert->integrityCheckSize = integrityCheckSize;\n  /* compute hmac */\n  tpm_hmac_init(&hmac_ctx, mtmData.permanent.data.internalVerificationKey,\n                sizeof(TPM_SECRET));\n  tpm_hmac_update(&hmac_ctx, buf, buf_len);\n  tpm_hmac_final(&hmac_ctx, digest);\n  tpm_free(buf);\n  return 0;\n}\n\nstatic TPM_RESULT verify_rim_certificate(TPM_RIM_CERTIFICATE *rimCert)\n{\n  /* check parrentID */\n  debug(\"parentId = %08x\", rimCert->parentId);\n  if (rimCert->parentId == TPM_VERIFICATION_KEY_ID_NONE) return TPM_KEYNOTFOUND;\n  /* verify certificate with appropiate key */\n  if (rimCert->parentId == TPM_VERIFICATION_KEY_ID_INTERNAL) {\n    BYTE digest[SHA1_DIGEST_LENGTH];\n    debug(\"internal verification\");\n    if (compute_rim_certificate_hmac(rimCert, digest) != 0) {\n      debug(\"compute_rim_certificate_hmac() failed\");\n      return TPM_FAIL;\n    }\n    /* check hmac */\n    if (memcmp(digest, rimCert->integrityCheckData, SHA1_DIGEST_LENGTH) != 0) {\n      debug(\"verification failed\");\n      return TPM_AUTHFAIL;\n    } else {\n      debug(\"verification succeeded\");\n      return TPM_SUCCESS;\n    }\n  } else {\n    BYTE digest[SHA1_DIGEST_LENGTH];\n    /* get verification key */\n    MTM_KEY_DATA *key = mtm_get_key_by_id(rimCert->parentId);\n    if (key == NULL) {\n      return TPM_KEYNOTFOUND;\n    }\n    /* compute digest */\n    if (compute_rim_certificate_digest(rimCert, digest) != 0) {\n      debug(\"compute_rim_certificate_digest() failed\");\n      return TPM_FAIL;\n    }\n    /* check key properties */\n    if (key->keyAlgorithm != TPM_ALG_RSA \n        || key->keyScheme != TPM_SS_RSASSAPKCS1v15_SHA1) {\n      debug(\"invalid signature scheme\");\n      return TPM_BAD_SCHEME;\n    }\n    /* verify signature */\n    if (tpm_rsa_verify(&key->key, RSA_SSA_PKCS1_SHA1_RAW, digest, sizeof(digest),\n                       rimCert->integrityCheckData) != 0) {\n      debug(\"verification failed\");\n      return TPM_AUTHFAIL;\n    } else {\n      debug(\"verification succeeded\");\n      return TPM_SUCCESS;\n    }\n  }\n}\n\nstatic int compute_verification_key_digest(TPM_VERIFICATION_KEY *key, BYTE *digest)\n{\n  tpm_sha1_ctx_t sha1_ctx;\n  BYTE *buf, *ptr;\n  UINT32 buf_len, len;\n  UINT32 integrityCheckSize;\n\n  /* marshal certificate */\n  integrityCheckSize = key->integrityCheckSize;\n  key->integrityCheckSize = 0;\n  buf_len = len = sizeof_TPM_VERIFICATION_KEY((*key));\n  buf = ptr = tpm_malloc(buf_len);\n  if (buf == NULL || tpm_marshal_TPM_VERIFICATION_KEY(&ptr, &len, key)) {\n    key->integrityCheckSize = integrityCheckSize;\n    tpm_free(buf);\n    return -1;\n  }\n  key->integrityCheckSize = integrityCheckSize;\n  /* compute sha1 */\n  tpm_sha1_init(&sha1_ctx);\n  tpm_sha1_update(&sha1_ctx, buf, buf_len);\n  tpm_sha1_final(&sha1_ctx, digest);\n  tpm_free(buf);\n  return 0;\n\n}\n\nstatic TPM_RESULT verify_verification_key(TPM_VERIFICATION_KEY *key, MTM_KEY_DATA *parentKey)\n{\n  BYTE digest[SHA1_DIGEST_LENGTH];\n\n  /* compute digest */\n  if (compute_verification_key_digest(key, digest) != 0) {\n    debug(\"compute_verification_key_digest() failed\");\n    return TPM_FAIL;\n  }\n  /* check key properties */\n  if (parentKey->keyAlgorithm != TPM_ALG_RSA\n      || parentKey->keyScheme != TPM_SS_RSASSAPKCS1v15_SHA1) {\n    debug(\"invalid signature scheme\");\n    return TPM_BAD_SCHEME;\n  }\n  /* verify signature */\n  if (tpm_rsa_verify(&parentKey->key, RSA_SSA_PKCS1_SHA1_RAW, digest, sizeof(digest),\n                     key->integrityCheckData) != 0) {\n    debug(\"verification failed\");\n    return TPM_AUTHFAIL;\n  } else {\n    debug(\"verification succeeded\");\n    return TPM_SUCCESS;\n  }\n}\n\nstatic int store_verification_key(TPM_VERIFICATION_KEY *inKey, MTM_KEY_DATA *outKey)\n{\n  outKey->usageFlags = inKey->usageFlags;\n  outKey->parentId = inKey->parentId;\n  outKey->myId = inKey->myId;\n  outKey->keyAlgorithm = inKey->keyAlgorithm;\n  outKey->keyScheme = inKey->keyScheme;\n  BYTE *ptr = inKey->keyData;\n  UINT32 len = inKey->keySize;\n  if (tpm_unmarshal_RSAPub(&ptr, &len, &outKey->key) != 0) return -1;\n  return 0;\n}\n\nTPM_RESULT MTM_InstallRIM(TPM_RIM_CERTIFICATE *rimCertIn, TPM_AUTH *auth1,\n                          TPM_RIM_CERTIFICATE *rimCertOut)\n{\n  TPM_RESULT res;\n  TPM_ACTUAL_COUNT cntProtect;\n\n  info(\"MTM_InstallRIM()\");\n  /* 1 */\n  if (rimCertIn == NULL || rimCertIn->tag != TPM_TAG_RIM_CERTIFICATE)\n    return TPM_BAD_PARAMETER;\n  /* 2 */\n  res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, auth1->authHandle);\n  if (res != TPM_SUCCESS) return res;\n  /* 3 */\n  cntProtect = tpmData.permanent.data.counters[MTM_COUNTER_SELECT_RIMPROTECT].counter;\n  /* 5 */\n  rimCertIn->integrityCheckSize = SHA1_DIGEST_LENGTH;\n  if (copy_TPM_RIM_CERTIFICATE(rimCertIn, rimCertOut) != 0) {\n    debug(\"copy_TPM_RIM_CERTIFICATE() failed\");\n    return TPM_FAIL;\n  }\n  /* 6, 7 */\n  if (rimCertIn->referenceCounter.counterSelection != MTM_COUNTER_SELECT_NONE) {\n    rimCertOut->referenceCounter.counterValue = cntProtect + 1;\n    rimCertOut->referenceCounter.counterSelection = MTM_COUNTER_SELECT_RIMPROTECT;\n  } else {\n    rimCertOut->referenceCounter.counterValue = 0;\n  }\n  /* 8 */\n  rimCertOut->parentId = TPM_VERIFICATION_KEY_ID_INTERNAL;\n  /* 10, 11, 12 */\n  if (compute_rim_certificate_hmac(rimCertOut, rimCertOut->integrityCheckData) != 0) {\n    debug(\"compute_rim_certificate_hmac() failed\");\n    free_TPM_RIM_CERTIFICATE((*rimCertOut));\n    return TPM_FAIL;\n  }\n  /* 13 */\n  return TPM_SUCCESS;\n}\n\nstatic TPM_VERIFICATION_KEY_HANDLE mtm_get_free_key(void)\n{\n  int i;\n  for (i = 0; i < TPM_MAX_KEYS; i++) {\n    if (!mtmData.permanent.data.keys[i].valid) {\n      mtmData.permanent.data.keys[i].valid = TRUE;\n      return INDEX_TO_KEY_HANDLE(i);\n    }\n  }\n  return TPM_INVALID_HANDLE;\n}\n\n\nTPM_RESULT MTM_LoadVerificationKey(TPM_VERIFICATION_KEY_HANDLE parentKeyHandle,\n                                   TPM_VERIFICATION_KEY *verificationKey, TPM_AUTH *auth1,\n                                   TPM_VERIFICATION_KEY_HANDLE *verificationKeyHandle,\n                             \t     BYTE *loadMethod)\n{\n  TPM_RESULT res;\n  MTM_KEY_DATA *key;\n\n  /* 1 */\n  if (verificationKey == NULL || verificationKey->tag != TPM_TAG_VERIFICATION_KEY)\n    return TPM_BAD_PARAMETER;\n  /* 2 */\n  *verificationKeyHandle = mtm_get_free_key();\n  key = mtm_get_key(*verificationKeyHandle);\n  if (key == NULL) {\n    debug(\"no free key slot available\");\n    return TPM_NOSPACE;\n  }\n  *loadMethod = 0;\n  /* 3 */\n  if (mtmData.stany.flags.loadVerificationRootKeyEnabled) {\n    debug(\"TPM_VERIFICATION_KEY_ROOT_LOAD\");\n    /* set integrityCheckRootData */\n    if (!mtmData.permanent.data.integrityCheckRootValid) {\n      if (compute_verification_key_digest(verificationKey,\n            mtmData.permanent.data.integrityCheckRootData) != 0) {\n        debug(\"compute_verification_key_digest() failed\");\n        memset(key, 0, sizeof(*key));\n        return TPM_FAIL;\n      }\n      mtmData.permanent.data.integrityCheckRootValid = TRUE;\n    }\n    *loadMethod = TPM_VERIFICATION_KEY_ROOT_LOAD;\n  }\n  /* 4 */\n  if (*loadMethod == 0\n      && mtmData.permanent.data.integrityCheckRootValid) {\n    BYTE digest[SHA1_DIGEST_LENGTH];\n    if (compute_verification_key_digest(verificationKey, digest) != 0) {\n      debug(\"compute_verification_key_digest() failed\");\n      memset(key, 0, sizeof(*key));\n      return TPM_FAIL;\n    }\n    if (memcmp(mtmData.permanent.data.integrityCheckRootData,\n               digest, SHA1_DIGEST_LENGTH) == 0) {\n      debug(\"TPM_VERIFICATION_KEY_INTEGRITY_CHECK_ROOT_DATA_LOAD\");\n      *loadMethod = TPM_VERIFICATION_KEY_INTEGRITY_CHECK_ROOT_DATA_LOAD;\n    }\n  }\n  /* 5 */\n  if (*loadMethod == 0\n      && tpmData.permanent.flags.owned && auth1->authHandle != TPM_INVALID_HANDLE) {\n    TPM_RESULT res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);\n    if (res != TPM_SUCCESS) {\n      memset(key, 0, sizeof(*key));\n      return res;\n    }\n    debug(\"TPM_VERIFICATION_KEY_OWNER_AUTHORIZED_LOAD\");\n    *loadMethod = TPM_VERIFICATION_KEY_OWNER_AUTHORIZED_LOAD;\n  }\n  /* 6 */\n  if (*loadMethod == 0) {\n    MTM_KEY_DATA *parentKey = mtm_get_key(parentKeyHandle);\n    if (parentKey == NULL) {\n      debug(\"invalid parent key handle %08x\", parentKeyHandle);\n      memset(key, 0, sizeof(*key));\n      return TPM_KEYNOTFOUND;\n    }\n    /* 7a-c */\n    if (!(parentKey->usageFlags & TPM_VERIFICATION_KEY_USAGE_SIGN_RIMAUTH)) {\n      memset(key, 0, sizeof(*key));\n      return TPM_INVALID_KEYUSAGE;\n    }\n    if ((verificationKey->usageFlags & TPM_VERIFICATION_KEY_USAGE_INCREMENT_BOOTSTRAP)\n        && !(parentKey->usageFlags & TPM_VERIFICATION_KEY_USAGE_INCREMENT_BOOTSTRAP)) {\n      memset(key, 0, sizeof(*key));\n      return TPM_INVALID_KEYUSAGE;\n    }\n    if (key->parentId != parentKey->myId) {\n      debug(\"id mismatch: parentId = %08x keyId = %08x\", key->parentId, parentKey->myId);\n      memset(key, 0, sizeof(*key));  \n      return TPM_AUTHFAIL;  \n    }\n    /* 7d */\n    res = verify_verification_key(verificationKey, parentKey);\n    if (res != TPM_SUCCESS) {\n      memset(key, 0, sizeof(*key));\n      return res;\n    }\n    /* 7e-g */\n    if (verificationKey->referenceCounter.counterSelection > MTM_COUNTER_SELECT_MAX)\n      return TPM_BAD_COUNTER;\n    if (verificationKey->referenceCounter.counterSelection == MTM_COUNTER_SELECT_BOOTSTRAP) {\n      if (verificationKey->referenceCounter.counterValue\n          < tpmData.permanent.data.counters[MTM_COUNTER_SELECT_BOOTSTRAP].counter)\n        return TPM_BAD_COUNTER;\n    }\n    if (verificationKey->referenceCounter.counterSelection == MTM_COUNTER_SELECT_RIMPROTECT) {\n      if (verificationKey->referenceCounter.counterValue\n          < tpmData.permanent.data.counters[MTM_COUNTER_SELECT_RIMPROTECT].counter)\n        return TPM_BAD_COUNTER;\n    }\n    /* 7j */\n    debug(\"TPM_VERIFICATION_KEY_CHAIN_AUTHORIZED_LOAD\");\n    *loadMethod = TPM_VERIFICATION_KEY_CHAIN_AUTHORIZED_LOAD;\n  }\n  /* store verification key */\n  if (store_verification_key(verificationKey, key) != 0) {\n    debug(\"store_verification_key() failed\");\n    memset(key, 0, sizeof(*key));\n    return TPM_FAIL;\n  }\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT MTM_LoadVerificationRootKeyDisable()\n{\n  info(\"MTM_LoadVerificationRootKeyDisable()\");\n  mtmData.stany.flags.loadVerificationRootKeyEnabled = FALSE;\n  mtmData.permanent.data.loadVerificationKeyMethods |= TPM_VERIFICATION_KEY_ROOT_LOAD;\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT MTM_VerifyRIMCert(TPM_RIM_CERTIFICATE* rimCert,\n                             TPM_VERIFICATION_KEY_HANDLE rimKeyHandle)\n{\n  TPM_RESULT res;\n  \n  info(\"MTM_VerifyRIMCert()\");\n  debug(\"key handle = %08x\", rimKeyHandle);\n  /* 1 */\n  if (rimCert ==  NULL || rimCert->tag != TPM_TAG_RIM_CERTIFICATE)\n    return TPM_BAD_PARAMETER;\n  /* 2 */\n  if (rimCert->parentId == TPM_VERIFICATION_KEY_ID_NONE)\n    return TPM_AUTHFAIL;\n  /* 3 */\n  if (rimCert->parentId == TPM_VERIFICATION_KEY_ID_INTERNAL) {\n    return verify_rim_certificate(rimCert);\n  } else {\n    /* 4 */\n    MTM_KEY_DATA *rimKey = mtm_get_key(rimKeyHandle);\n    if (rimKey == NULL) return TPM_KEYNOTFOUND;\n    if ((rimKey->usageFlags & TPM_VERIFICATION_KEY_USAGE_SIGN_RIMCERT) == 0)\n      return TPM_INVALID_KEYUSAGE;\n    if (rimCert->parentId != rimKey->myId) {\n      debug(\"id mismatch: parentId = %08x keyId = %08x\", rimCert->parentId, rimKey->myId);\n      return TPM_AUTHFAIL;\n    }\n    res = verify_rim_certificate(rimCert);\n    if (res != TPM_SUCCESS) return res;\n  }\n  /* 5 */\n  if (rimCert->referenceCounter.counterSelection > MTM_COUNTER_SELECT_MAX)\n    return TPM_BAD_COUNTER;\n  /* 6 */\n  if (rimCert->referenceCounter.counterSelection == MTM_COUNTER_SELECT_BOOTSTRAP) {\n    if (rimCert->referenceCounter.counterValue\n        < tpmData.permanent.data.counters[MTM_COUNTER_SELECT_BOOTSTRAP].counter)\n      return TPM_BAD_COUNTER;\n  }\n  /* 7 */\n  if (rimCert->referenceCounter.counterSelection == MTM_COUNTER_SELECT_RIMPROTECT) {\n    if (rimCert->referenceCounter.counterValue\n        < tpmData.permanent.data.counters[MTM_COUNTER_SELECT_RIMPROTECT].counter)\n      return TPM_BAD_COUNTER;\n  }\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT MTM_VerifyRIMCertAndExtend(TPM_RIM_CERTIFICATE *rimCert,\n                                      TPM_VERIFICATION_KEY_HANDLE rimKey,\n                                      TPM_PCRVALUE *outDigest)\n{\n  int i;\n  TPM_RESULT res;\n\n  info(\"MTM_VerifyRIMCertAndExtend()\");\n  /* 1-7 */\n  res = MTM_VerifyRIMCert(rimCert, rimKey);\n  if (res != TPM_SUCCESS) return res;\n  /* 8 */\n  for (i = 0; i < TPM_NUM_PCR / 8; i++) {\n    if (rimCert->state.pcrSelection.pcrSelect[i] != 0) break;\n  }\n  if (i < TPM_NUM_PCR / 8) {\n    TPM_COMPOSITE_HASH digest;\n    if (tpm_compute_pcr_digest(&rimCert->state.pcrSelection, &digest, NULL) != TPM_SUCCESS) {\n      debug(\"tpm_compute_pcr_digest() failed\");\n      return TPM_FAIL;\n    }\n    if (memcmp(&digest, &rimCert->state.digestAtRelease, sizeof(TPM_COMPOSITE_HASH)) != 0)\n      return TPM_WRONGPCRVAL;\n  }\n  /* 9, 10 */\n  return TPM_Extend(rimCert->measurementPcrIndex, &rimCert->measurementValue, outDigest);\n}\n\nTPM_RESULT MTM_IncrementBootstrapCounter(TPM_RIM_CERTIFICATE *rimCert,\n                                         TPM_VERIFICATION_KEY_HANDLE rimKeyHandle)\n{\n  TPM_RESULT res;\n  MTM_KEY_DATA* rimKey;\n \n  info(\"MTM_IncrementBootstrapCounter()\");\n  /* 1 */\n  if (rimCert == NULL || rimCert->tag != TPM_TAG_RIM_CERTIFICATE)\n    return TPM_BAD_PARAMETER;\n  /* 2 */\n  debug(\"rimKeyHandle = %08x\", rimKeyHandle);\n  rimKey = mtm_get_key(rimKeyHandle);\n  if (rimKey == NULL) return TPM_KEYNOTFOUND;\n  /* 3 */\n  if ((rimKey->usageFlags & TPM_VERIFICATION_KEY_USAGE_SIGN_RIMCERT) == 0\n      ||(rimKey->usageFlags & TPM_VERIFICATION_KEY_USAGE_INCREMENT_BOOTSTRAP) == 0)\n    return TPM_INVALID_KEYUSAGE;\n  /* 4 */\n  if (rimCert->parentId != rimKey->myId) return TPM_AUTHFAIL;\n  /* 5 */\n  res = verify_rim_certificate(rimCert);\n  if (res != TPM_SUCCESS) return res;\n  /* 6 */\n  if (rimCert->referenceCounter.counterSelection > MTM_COUNTER_SELECT_MAX)\n    return TPM_BAD_COUNTER;\n  /* 7 */\n  if (rimCert->referenceCounter.counterSelection == MTM_COUNTER_SELECT_BOOTSTRAP) {\n    if (rimCert->referenceCounter.counterValue\n        < tpmData.permanent.data.counters[MTM_COUNTER_SELECT_BOOTSTRAP].counter)\n      return TPM_BAD_COUNTER;\n    tpmData.permanent.data.counters[MTM_COUNTER_SELECT_BOOTSTRAP].counter\n      = rimCert->referenceCounter.counterValue;\n  }\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT MTM_SetVerifiedPCRSelection(TPM_PCR_SELECTION *verifiedSelection,\n                                       TPM_AUTH *auth1)\n{\n  int i;\n  TPM_RESULT res;\n\n  info(\"MTM_SetVerifiedPCRSelection()\");\n  /* verify permission */\n  if (tpmData.permanent.flags.owned) {\n    res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);\n  } else {\n    res = FALSE;\n  }\n  if (!res && !mtmData.stany.flags.loadVerificationRootKeyEnabled) {\n    return TPM_FAIL;\n  }\n  /* echeck if a localityModifier is set */\n  for (i = 0; i < TPM_NUM_PCR; i++) {\n    if (verifiedSelection->pcrSelect[i >> 3] & (1 << (i & 7))) {\n\t    if (tpmData.permanent.data.pcrAttrib[i].pcrResetLocal) return TPM_FAIL;\n\t  }\n  }\n  /* copy selection */\n  memcpy(&mtmData.permanent.data.verifiedPCRs,\n         verifiedSelection, sizeof(TPM_PCR_SELECTION));\n  return TPM_SUCCESS;\n}\n\n"
  },
  {
    "path": "tddl/CMakeLists.txt",
    "content": "# Software-based Trusted Platform Module (TPM) Emulator\n# Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n#\n# $Id: CMakeLists.txt 455 2010-09-17 18:34:04Z mast $\n\nset(tddl-tpm-emulator_SRCS \"tddl.c\" \"tddl-tpm-emulator.h\")\nadd_library(tddl-tpm-emulator SHARED ${tddl-tpm-emulator_SRCS})\nadd_library(tddl-tpm-emulator_static STATIC ${tddl-tpm-emulator_SRCS})\nif(UNIX)\n  set_target_properties(tddl-tpm-emulator PROPERTIES SOVERSION \"1.2\"\n    VERSION \"1.2.${${PROJECT_NAME}_VERSION_MAJOR}.${${PROJECT_NAME}_VERSION_MINOR}\")\n  set_target_properties(tddl-tpm-emulator_static PROPERTIES OUTPUT_NAME tddl-tpm-emulator)\nelseif(WIN32)\n  set_target_properties(tddl-tpm-emulator PROPERTIES OUTPUT_NAME ifxtpm)\n  set_target_properties(tddl-tpm-emulator PROPERTIES PREFIX \"\")\nendif()\n\ninstall(TARGETS tddl-tpm-emulator DESTINATION ${CMAKE_INSTALL_LIBDIR})\ninstall(TARGETS tddl-tpm-emulator_static DESTINATION ${CMAKE_INSTALL_LIBDIR})\ninstall(FILES \"tddl-tpm-emulator.h\" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})\n\ninclude_directories(${CMAKE_CURRENT_SOURCE_DIR})\nadd_executable(test_tddl test_tddl.c)\ntarget_link_libraries(test_tddl tddl-tpm-emulator_static)\n\n"
  },
  {
    "path": "tddl/tddl-tpm-emulator.h",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: tddl.h 364 2010-02-11 10:24:45Z mast $\n */\n\n#ifndef _TDDL_H_\n#define _TDDL_H_\n\n#include <stdint.h>\n\n/*\n * The following types and functions are specified in the\n * TCPA Software Stack (TSS) Specification [TSS_Spec].\n */\n\n/*\n * Basic Data Types\n */\ntypedef uint8_t  BYTE;\ntypedef uint8_t  TSS_BOOL;\ntypedef uint32_t UINT32;\ntypedef uint32_t TSS_RESULT;\n\n/*\n * TDDL Return Codes\n */\n#define TSS_E_BASE                     0x00000000\n#define TDDL_SUCCESS                   (TSS_E_BASE + 0x00)\n#define TDDL_E_FAIL                    (TSS_E_BASE + 0x02)\n#define TDDL_E_BAD_PARAMETER           (TSS_E_BASE + 0x03)\n#define TDDL_E_NOTIMPL                 (TSS_E_BASE + 0x06)\n#define TDDL_E_TIMEOUT                 (TSS_E_BASE + 0x12)\n#define TDDL_E_ALREADY_OPENED          (TSS_E_BASE + 0x81)\n#define TDDL_E_ALREADY_CLOSED          (TSS_E_BASE + 0x82)\n#define TDDL_E_INSUFFICIENT_BUFFER     (TSS_E_BASE + 0x83)\n#define TDDL_E_COMMAND_COMPLETED       (TSS_E_BASE + 0x84)\n#define TDDL_E_COMMAND_ABORTED         (TSS_E_BASE + 0x85)\n#define TDDL_E_IOERROR                 (TSS_E_BASE + 0x87)\n#define TDDL_E_BADTAG                  (TSS_E_BASE + 0x88)\n#define TDDL_E_COMPONENT_NOT_FOUND     (TSS_E_BASE + 0x89)\n\n/*\n * Capability Flag Definitions\n */\n#define TDDL_CAP_VERSION               0x0100 \n#define TDDL_CAP_VER_DRV               0x0101 \n#define TDDL_CAP_VER_FW                0x0102 \n#define TDDL_CAP_VER_FW_DATE           0x0103 \n#define TDDL_CAP_PROPERTY              0x0200 \n#define TDDL_CAP_PROP_MANUFACTURER     0x0201 \n#define TDDL_CAP_PROP_MODULE_TYPE      0x0202 \n#define TDDL_CAP_PROP_GLOBAL_STATE     0x0203\n\n/*\n * Driver and Device Status Codes\n */\n#define TDDL_DRIVER_STATUS             0x0010\n#define TDDL_DRIVER_OK                 0x0010\n#define TDDL_DRIVER_FAILED             0x0011\n#define TDDL_DRIVER_NOT_OPENED         0x0012\n#define TDDL_DEVICE_STATUS             0x0020\n#define TDDL_DEVICE_OK                 0x0020\n#define TDDL_DEVICE_UNRECOVERABLE      0x0021\n#define TDDL_DEVICE_RECOVERABLE        0x0022 \n#define TDDL_DEVICE_NOT_FOUND          0x0023\n\n/*\n * TDDL Interface Functions\n */\n#ifdef __cplusplus \nextern \"C\" {\n#endif \n\n/**\n * Tddli_Open - establish a connection to the TPM device driver\n *\n * This function establishes a connection with the TPM device driver. The \n * application utilizing the TPM DDL is guaranteed to  have exclusive access \n * to the TPM device. This function must be called before calling GetStatus, \n * GetCapability, SetCapability, or TransmitData.\n */\nTSS_RESULT Tddli_Open(void); \n\n/**\n * Tddli_Close - close a open connection to the TPM device driver\n *\n * This function closes a connection with the TPM device driver. Following \n * a successful response to this function, the TPM device driver can clean \n * up any resources used to maintain a connection with the TPM device driver \n * library. \n */\nTSS_RESULT Tddli_Close(void); \n\n/**\n * Tddli_Cancel - cancels the last outstanding TPM command\n * \n * This function cancels an outstanding TPM command. An application can call \n * this function, in a separate context, to interrupt a TPM command that has \n * not completed.  The TPM device driver must acknowledge this function if \n * it has not returned from a previous TPM command and return \n * TDDL_COMMAND_ABORTED for the call in process. \n */\nTSS_RESULT Tddli_Cancel(void); \n\n/**\n * Tddli_GetCapability - read the attributes returned by the TPM\n *\n * @CapArea: [in] Partition of capabilities to be interrogated.\n * @SubCap: [in] Subcode of the requested capabilities.\n * @pCapBuf: [out] Pointer to a buffer containing the received attribute data.\n * @puntCapBufLen: [in] Size of the receive buffer in bytes. \n                   [out] Number of written bytes.\n *\n * This function queries the TPM hardware, firmware and device driver \n * attributes such as firmware version, driver version, etc.  \n */ \nTSS_RESULT Tddli_GetCapability(UINT32 CapArea, UINT32 SubCap, \n                               BYTE* pCapBuf, UINT32* puntCapBufLen);\n\n/**\n * Tddli_SetCapability - set parameters to the TPM\n *\n * @CapArea: [in] Partition of capabilities to be set.\n * @SubCap: [in] Subcode of the capabilities to be set.\n * @pCapBuf: [in] Pointer to a buffer containing the capability data to set.\n * @puntCapBufLen: [in] Size of the request buffer in bytes.\n *\n * This function sets parameters in the TPM hardware, firmware and device\n * driver attributes. An application can set TPM device driver and operating\n * parameters that may be defined by the TPM vendor. For now, the parameter\n * definitions are vendor-defined.\n */ \nTSS_RESULT Tddli_SetCapability(UINT32 CapArea, UINT32 SubCap, \n                               BYTE* pCapBuf, UINT32* puntCapBufLen); \n\n/**\n * Tddli_GetStatus - get status of the TPM driver and device TDDLI\n *\n * @ReqStatusType: [in] Requested type of status information.\n * @puntStatus: [out] Requested status.\n *\n * This function queries the status the TPM driver and device. An application \n * can determine the health of the TPM subsystem by utilizing this function.\n */ \nTSS_RESULT Tddli_GetStatus(UINT32 ReqStatusType, UINT32* puntStatus); \n\n/** \n * Tddli_TransmitData - send any data to the TPM module TDDLI\n *\n * @pTransmitBuf: [in] Pointer to a buffer containing TPM transmit data. \n * @TransmitBufLen: [in] Size of TPM transmit data in bytes. \n * @pReceiveBuf: [out] Pointer to a buffer containing TPM receive data \n * @puntReceiveBufLen: [in] Size of TPM receive buffer in bytes. \n *                     [out] Number of written bytes.\n *\n * The function sends a TPM command directly to a TPM device driver, causing \n * the TPM to perform the corresponding operation.\n */ \nTSS_RESULT Tddli_TransmitData(BYTE* pTransmitBuf, UINT32 TransmitBufLen, \n                              BYTE* pReceiveBuf, UINT32* puntReceiveBufLen);\n\n\n/**\n * Tddli_SetPowerManagement - sets and queries the TPM's power states\n *\n * @SendSaveStateCommand: [in]\n * @QuerySetNewTPMPowerState: [in] \n *                            [out]\n *\n * This function sets and queries the TPM’s power states.\n */\nTSS_RESULT Tddli_SetPowerManagement(TSS_BOOL SendSaveStateCommand,\n                                    UINT32 *QuerySetNewTPMPowerState);\n\n/**\n * Tddli_PowerManagementControl - gets and sets the power state management\n *\n * @SendPowerManager: [in]\n * @DriverManagesPowerStates: [out]\n *\n * This command determines and sets which component, TCS or the Driver,\n * receives and handles the platform’s OS power state management signals.\n */\nTSS_RESULT Tddli_PowerManagementControl(TSS_BOOL SendPowerManager,\n                                        UINT32 DriverManagesPowerStates);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* _TDDL_H_ */\n\n"
  },
  {
    "path": "tddl/tddl.c",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: tddl.c 364 2010-02-11 10:24:45Z mast $\n */\n\n#include <unistd.h>\n#include <string.h>\n#include <config.h>\n#include \"tddl-tpm-emulator.h\"\n\n/* device and socket names */\nstatic const char *tpm_device_name = TPM_DEVICE_NAME;\nstatic const char *tpmd_socket_name = TPM_SOCKET_NAME;\n\n/* TPM device handle */\nstatic int tddli_dh = -1;\n\n/* status of the TPM device driver and the TPM itself */\nstatic TSS_RESULT tddli_driver_status = TDDL_DRIVER_FAILED;\nstatic TSS_RESULT tddli_device_status = TDDL_DEVICE_NOT_FOUND;\n\n#if defined(_WIN32) || defined(_WIN64)\n#include \"tddl_windows.h\"\n#else\n#include \"tddl_unix.h\"\n#endif\n\nTSS_RESULT Tddli_Open()\n{\n  TSS_RESULT res;\n  tddli_mutex_lock(&tddli_lock);\n  if (tddli_dh != -1) {\n    res = TDDL_E_ALREADY_OPENED;\n  } else {\n    res = open_socket(tpmd_socket_name);\n    if (res != TDDL_SUCCESS) {\n      res = open_device(tpm_device_name);\n    }\n  }\n  tddli_mutex_unlock(&tddli_lock);\n  return res;\n} \n\nTSS_RESULT Tddli_Close()\n{\n  TSS_RESULT res = TDDL_SUCCESS;\n  tddli_mutex_lock(&tddli_lock);\n  if (tddli_dh >= 0) {\n    close(tddli_dh);\n    tddli_dh = -1;\n  } else {\n    res = TDDL_E_ALREADY_CLOSED;\n  }\n  tddli_mutex_unlock(&tddli_lock); \n  return res;\n}\n \nTSS_RESULT Tddli_Cancel()\n{\n  /* this is not supported by the TPM emulator */\n  return TDDL_E_NOTIMPL;\n}\n\nstatic TSS_RESULT send_to_tpm(BYTE* pTransmitBuf, UINT32 TransmitBufLen)\n{\n  ssize_t res;\n  res = write(tddli_dh, pTransmitBuf, TransmitBufLen);\n  if (res < 0 || (UINT32)res != TransmitBufLen) return TDDL_E_IOERROR;\n  return TDDL_SUCCESS;\n}\n\nstatic TSS_RESULT receive_from_tpm(BYTE* pReceiveBuf, UINT32* puntReceiveBufLen)\n{\n  ssize_t res;\n  uint32_t len;\n  if (*puntReceiveBufLen < 10) return TDDL_E_INSUFFICIENT_BUFFER;\n  res = read(tddli_dh, pReceiveBuf, *puntReceiveBufLen);\n  if (res < 10) return TDDL_E_IOERROR;\n  *puntReceiveBufLen = res;\n  len = ((uint32_t)pReceiveBuf[2] << 24) | ((uint32_t)pReceiveBuf[3] << 16)\n        | ((uint32_t)pReceiveBuf[4] << 8) | (uint32_t)pReceiveBuf[5];\n  if (len != *puntReceiveBufLen) return TDDL_E_INSUFFICIENT_BUFFER;\n  return TDDL_SUCCESS;\n}\n\nTSS_RESULT Tddli_TransmitData(BYTE* pTransmitBuf, UINT32 TransmitBufLen,\n                              BYTE* pReceiveBuf, UINT32* puntReceiveBufLen)\n{\n  TSS_RESULT res;\n  tddli_mutex_lock(&tddli_lock);\n  if (tddli_dh >= 0) {\n    res = send_to_tpm(pTransmitBuf, TransmitBufLen);\n    if (res == TDDL_SUCCESS)\n      res = receive_from_tpm(pReceiveBuf, puntReceiveBufLen);\n  } else {\n    res = TDDL_E_FAIL;\n  }\n  tddli_mutex_unlock(&tddli_lock);\n  return res;\n}\n\nstatic TSS_RESULT cap_version(UINT32 SubCap, BYTE* pCapBuf,\n                              UINT32* puntCapBufLen)\n{\n  TSS_RESULT res;\n  UINT32 len = 18;\n  BYTE buf[18];\n\n  switch (SubCap) {\n    case TDDL_CAP_VER_DRV:\n      if (*puntCapBufLen < 4) return TDDL_E_INSUFFICIENT_BUFFER;\n      *puntCapBufLen = 4;\n      memcpy(pCapBuf, \"\\x01\\x05\\x00\\x00\", 4);\n      return TDDL_SUCCESS;\n\n    case TDDL_CAP_VER_FW:\n      if (*puntCapBufLen < 4) return TDDL_E_INSUFFICIENT_BUFFER;\n      *puntCapBufLen = 4;\n      res = send_to_tpm((uint8_t*)\"\\x00\\xc1\\x00\\x00\\x00\\x12\\x00\\x00\\x00\\x65\"\n        \"\\x00\\x00\\x00\\x06\\x00\\x00\\x00\\x00\", 18);\n      if (res != TDDL_SUCCESS) return res;\n      res = receive_from_tpm(buf, &len);\n      if (res != TDDL_SUCCESS) return res;\n      if (len != 18 || (buf[6] | buf[7] | buf[8] | buf[9]) != 0) return TDDL_E_FAIL;\n      memcpy(pCapBuf, &buf[14], 4);\n      return TDDL_SUCCESS;\n\n    case TDDL_CAP_VER_FW_DATE:\n      /* this is not yet supported by the TPM emulator */\n      return TDDL_E_NOTIMPL;\n\n    default:\n      return TDDL_E_BAD_PARAMETER;\n  }\n}\n\nstatic TSS_RESULT cap_property(UINT32 SubCap, BYTE* pCapBuf,\n                               UINT32* puntCapBufLen)\n{\n  static const char *manufacturer = \"Mario Strasser, ETH Zurich\";\n  static const char *type = \"Software-based TPM Emulator\";\n\n  switch (SubCap) {\n    case TDDL_CAP_PROP_MANUFACTURER:\n      if (*puntCapBufLen < strlen(manufacturer))\n        return TDDL_E_INSUFFICIENT_BUFFER;\n      *puntCapBufLen = strlen(manufacturer);\n      memcpy(pCapBuf, manufacturer, *puntCapBufLen);\n      return TDDL_SUCCESS;\n\n    case TDDL_CAP_PROP_MODULE_TYPE:\n      if (*puntCapBufLen < strlen(type)) return TDDL_E_INSUFFICIENT_BUFFER;\n      *puntCapBufLen = strlen(type);\n      memcpy(pCapBuf, type, *puntCapBufLen);\n      return TDDL_SUCCESS;\n\n    default:\n      return TDDL_E_BAD_PARAMETER;\n  }\n}\n\nTSS_RESULT Tddli_GetCapability(UINT32 CapArea, UINT32 SubCap, \n                               BYTE* pCapBuf, UINT32* puntCapBufLen)\n{\n  TSS_RESULT res = TDDL_SUCCESS;\n  if (tddli_dh < 0) return TDDL_E_FAIL;\n  tddli_mutex_lock(&tddli_lock);\n  switch (CapArea) {\n    case TDDL_CAP_VERSION:\n      res = cap_version(SubCap, pCapBuf, puntCapBufLen);    \n      break;\n    case TDDL_CAP_PROPERTY:\n      res = cap_property(SubCap, pCapBuf, puntCapBufLen);\n      break;\n    default:\n      res = TDDL_E_BAD_PARAMETER;\n  }\n  tddli_mutex_unlock(&tddli_lock);\n  return res;\n}\n\nTSS_RESULT Tddli_SetCapability(UINT32 CapArea, UINT32 SubCap, \n                               BYTE* pCapBuf, UINT32* puntCapBufLen) \n{\n  /* no vendor-specific capabilities available, yet */\n  return TDDL_E_BAD_PARAMETER;\n}\n\nTSS_RESULT Tddli_GetStatus(UINT32 ReqStatusType, UINT32* puntStatus) \n{\n  TSS_RESULT res = TDDL_SUCCESS;\n  tddli_mutex_lock(&tddli_lock);\n  switch (ReqStatusType) {\n    case TDDL_DRIVER_STATUS:\n      *puntStatus = tddli_driver_status;\n      break;\n    case TDDL_DEVICE_STATUS:\n      *puntStatus = tddli_device_status;\n      break;\n    default:\n      res = TDDL_E_BAD_PARAMETER;\n  }\n  tddli_mutex_unlock(&tddli_lock);\n  return res;\n}\n\nTSS_RESULT Tddli_SetPowerManagement(TSS_BOOL SendSaveStateCommand,\n                                    UINT32 *QuerySetNewTPMPowerState)\n{\n  return TDDL_E_NOTIMPL;\n}\n\nTSS_RESULT Tddli_PowerManagementControl(TSS_BOOL SendPowerManager,\n                                        UINT32 DriverManagesPowerStates)\n{\n  return TDDL_E_NOTIMPL;\n}\n\n/* \n * Export also TDDL_* function aliases as they are\n * used by some non standard-conform applications.\n */\n\nTSS_RESULT TDDL_Open()\n{\n  return Tddli_Open();\n}\n\n\nTSS_RESULT TDDL_Close()\n{\n  return Tddli_Close();\n}\n \nTSS_RESULT TDDL_Cancel()\n{\n  return Tddli_Cancel();\n}\n\nTSS_RESULT TDDL_TransmitData(BYTE* pTransmitBuf, UINT32 TransmitBufLen,\n                              BYTE* pReceiveBuf, UINT32* puntReceiveBufLen)\n{\n  return Tddli_TransmitData(pTransmitBuf, TransmitBufLen,\n                            pReceiveBuf, puntReceiveBufLen);\n}\n\nTSS_RESULT TDDL_GetCapability(UINT32 CapArea, UINT32 SubCap, \n                              BYTE* pCapBuf, UINT32* puntCapBufLen)\n{\n  return Tddli_GetCapability(CapArea, SubCap, pCapBuf, puntCapBufLen);\n}\n\nTSS_RESULT TDDL_SetCapability(UINT32 CapArea, UINT32 SubCap, \n                              BYTE* pCapBuf, UINT32* puntCapBufLen)\n{\n  return Tddli_SetCapability(CapArea, SubCap, pCapBuf, puntCapBufLen);\n}\n\nTSS_RESULT TDDL_GetStatus(UINT32 ReqStatusType, UINT32* puntStatus)\n{\n  return Tddli_GetStatus(ReqStatusType, puntStatus);\n}\n\nTSS_RESULT TDDL_SetPowerManagement(TSS_BOOL SendSaveStateCommand,\n                                    UINT32 *QuerySetNewTPMPowerState)\n{\n  return Tddli_SetPowerManagement(SendSaveStateCommand, QuerySetNewTPMPowerState);\n}\n\nTSS_RESULT TDDL_PowerManagementControl(TSS_BOOL SendPowerManager,\n                                        UINT32 DriverManagesPowerStates)\n{\n  return Tddli_PowerManagementControl(SendPowerManager, DriverManagesPowerStates);\n}\n\n"
  },
  {
    "path": "tddl/tddl_unix.h",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: tddl.c 364 2010-02-11 10:24:45Z mast $\n */\n\n#include <sys/types.h>\n#include <sys/socket.h>\n#include <sys/un.h>\n#include <fcntl.h>\n#include <unistd.h>\n#include <string.h>\n#include <errno.h>\n#include <pthread.h>\n\n/* library lock */\nstatic pthread_mutex_t tddli_lock = PTHREAD_MUTEX_INITIALIZER;\n\n#define tddli_mutex_lock(a)   pthread_mutex_lock(a)\n#define tddli_mutex_unlock(a) pthread_mutex_unlock(a)\n\nstatic TSS_RESULT open_device(const char *device_name)\n{\n  tddli_dh = open(device_name, O_RDWR);\n  if (tddli_dh < 0) {\n    if (errno == ENOENT || errno == ENXIO) {\n      tddli_driver_status = TDDL_DRIVER_FAILED;\n      tddli_device_status = TDDL_DEVICE_NOT_FOUND;\n    } else {\n      tddli_driver_status = TDDL_DRIVER_NOT_OPENED;\n      tddli_device_status = TDDL_DEVICE_RECOVERABLE;\n    }\n    return TDDL_E_FAIL;\n  } else {\n    tddli_driver_status = TDDL_DRIVER_OK;\n    tddli_device_status = TDDL_DEVICE_OK;\n    return TDDL_SUCCESS;\n  }\n}\n\nstatic TSS_RESULT open_socket(const char *socket_name)\n{\n  struct sockaddr_un addr;\n  tddli_dh = socket(AF_UNIX, SOCK_STREAM, 0);\n  if (tddli_dh < 0) {\n    tddli_driver_status = TDDL_DRIVER_FAILED;\n    tddli_device_status = TDDL_DEVICE_NOT_FOUND;\n    return TDDL_E_FAIL;\n  }\n  addr.sun_family = AF_UNIX;\n  strncpy(addr.sun_path, socket_name, sizeof(addr.sun_path)-1);\n  if (connect(tddli_dh, (struct sockaddr*)&addr, sizeof(struct sockaddr_un)) < 0) {\n    tddli_driver_status = TDDL_DRIVER_FAILED;\n    tddli_device_status = TDDL_DEVICE_NOT_FOUND;\n    return TDDL_E_FAIL;\n  }\n  tddli_driver_status = TDDL_DRIVER_OK;\n  tddli_device_status = TDDL_DEVICE_OK;\n  return TDDL_SUCCESS;\n}\n\n"
  },
  {
    "path": "tddl/tddl_windows.h",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: tddl.c 364 2010-02-11 10:24:45Z mast $\n */\n\n#include <fcntl.h>\n#include <unistd.h>\n#include <errno.h>\n#include <windows.h>\n#include <config.h>\n#include \"tddl.h\"\n\n/* library lock */\nstatic CRITICAL_SECTION tddli_lock;\n\n#define tddli_mutex_lock(a)   EnterCriticalSection(a)\n#define tddli_mutex_unlock(a) LeaveCriticalSection(a)\n\nBOOL APIENTRY DllMain(HANDLE hModule, DWORD reason, LPVOID lpReserved)\n{\n  switch(reason) {\n    case DLL_PROCESS_ATTACH:\n      InitializeCriticalSection(&tddli_lock);\n      break;\n    case DLL_PROCESS_DETACH:\n      DeleteCriticalSection(&tddli_lock);\n      break;\n    default:\n      break;\n  }\n  return TRUE;\n}\n\nstatic TSS_RESULT open_device(const char *device_name)\n{\n  /* open the named pipe and generate a posix file handle */\n  DWORD mode = PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE;\n  HANDLE ph = CreateFile(device_name, GENERIC_READ | GENERIC_WRITE,\n    0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);\n  SetNamedPipeHandleState(ph, &mode, NULL, NULL);\n  tddli_dh = _open_osfhandle((DWORD)ph, O_RDWR | O_BINARY);\n  if (tddli_dh < 0) {\n    if (errno == ENOENT || errno == ENXIO) {\n      tddli_driver_status = TDDL_DRIVER_FAILED;\n      tddli_device_status = TDDL_DEVICE_NOT_FOUND;\n    } else {\n      tddli_driver_status = TDDL_DRIVER_NOT_OPENED;\n      tddli_device_status = TDDL_DEVICE_RECOVERABLE;\n    }\n    return TDDL_E_FAIL;\n  } else {\n    tddli_driver_status = TDDL_DRIVER_OK;\n    tddli_device_status = TDDL_DEVICE_OK;\n\n    return TDDL_SUCCESS;\n  }\n}\n\nstatic TSS_RESULT open_socket(const char *socket_name)\n{\n  return TDDL_E_FAIL;\n}\n\n"
  },
  {
    "path": "tddl/test_tddl.c",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: test_tddl.c 364 2010-02-11 10:24:45Z mast $\n */\n\n#include <stdio.h>\n#include <tddl-tpm-emulator.h>\n\nconst char *get_error(TSS_RESULT res)\n{\n  switch (res) {\n    case TDDL_SUCCESS:\n      return \"success\";\n    case TDDL_E_FAIL:\n      return \"operation failed\";\n    case TDDL_E_BAD_PARAMETER:\n      return \"bad patameter\";\n    case TDDL_E_TIMEOUT:\n      return \"timeout\";\n    case TDDL_E_ALREADY_OPENED:\n      return \"already opened\";\n    case TDDL_E_ALREADY_CLOSED:\n      return \"already closed\";\n    case TDDL_E_INSUFFICIENT_BUFFER:\n      return \"insufficient buffer\";\n    case TDDL_E_COMMAND_COMPLETED:\n      return \"comand completed\";\n    case TDDL_E_COMMAND_ABORTED:\n      return \"command aborted\";\n    case TDDL_E_IOERROR:\n      return \"IO error\";\n    case TDDL_E_BADTAG:\n      return \"bad tag\";\n    case TDDL_E_COMPONENT_NOT_FOUND:\n      return \"component not found\";\n    default:\n      return \"unknown error\";\n   }\n}\n\nconst char *get_status(UINT32 status)\n{\n  switch (status) {\n    case TDDL_DRIVER_OK: return \"DRIVER OK\";\n    case TDDL_DRIVER_FAILED: return \"DRIVER FAILED\"; \n    case TDDL_DRIVER_NOT_OPENED: return \"DRIVER NOT OPENED\";\n    case TDDL_DEVICE_OK: return \"DEVICE OK\"; \n    case TDDL_DEVICE_UNRECOVERABLE: return \"DEVICE UNRECOVERABLE\";\n    case TDDL_DEVICE_RECOVERABLE: return \"DEVICE RECOVERABLE\";\n    case TDDL_DEVICE_NOT_FOUND: return \"DEVICE NOT FOUND\";\n    default: return \"\";\n  }\n}\n\nint main()\n{\n  TSS_RESULT res;\n  UINT32 status;\n  BYTE buf[256];\n  UINT32 buf_size = sizeof(buf);\n  BYTE reset[] = {0, 193, 0, 0, 0, 10, 0, 0, 0, 90};\n  unsigned int i;\n  \n  res = Tddli_Open();\n  if (res != TDDL_SUCCESS) {\n    printf(\"Error: Tddli_Open() failed: %s (%04x)\\n\", get_error(res), res);\n    return -1;\n  }\n\n  /* get driver and device status */\n  res = Tddli_GetStatus(TDDL_DRIVER_STATUS, &status);\n  if (res != TDDL_SUCCESS) {\n    printf(\"Error: Tddli_GetStatus() failed: %s (%04x)\\n\", get_error(res), res);\n    Tddli_Close();\n    return -1;\n  }\n  printf(\"Driver status: %s\\n\", get_status(status));\n  res = Tddli_GetStatus(TDDL_DEVICE_STATUS, &status);\n  if (res != TDDL_SUCCESS) {\n    printf(\"Error: Tddli_GetStatus() failed: %s (%04x)\\n\", get_error(res), res);\n    Tddli_Close();\n    return -1;\n  }\n  printf(\"Device status: %s\\n\", get_status(status));\n  /* get version */\n  buf_size = sizeof(buf);\n  res = Tddli_GetCapability(TDDL_CAP_VERSION, TDDL_CAP_VER_DRV, buf, &buf_size);\n  if (res != TDDL_SUCCESS) {\n    printf(\"Error: Tddli_GetCapability() failed: %s (%04x)\\n\", get_error(res), res);\n    Tddli_Close();\n    return -1;\n  }\n  printf(\"DRV version: %d.%d.%d.%d\\n\", buf[0], buf[1], buf[2], buf[3]);\n  buf_size = sizeof(buf);\n  res = Tddli_GetCapability(TDDL_CAP_VERSION, TDDL_CAP_VER_FW, buf, &buf_size);\n  if (res != TDDL_SUCCESS) {\n    printf(\"Error: Tddli_GetCapability() failed: %s (%04x)\\n\", get_error(res), res);\n    Tddli_Close();\n    return -1;\n  }\n  printf(\"TPM Version: %d.%d.%d.%d\\n\", buf[0], buf[1], buf[2], buf[3]);\n  /* get properties */\n  buf_size = sizeof(buf);\n  res = Tddli_GetCapability(TDDL_CAP_PROPERTY, TDDL_CAP_PROP_MANUFACTURER, buf, &buf_size);\n  if (res != TDDL_SUCCESS) {\n    printf(\"Error: Tddli_GetCapability() failed: %s (%04x)\\n\", get_error(res), res);\n    Tddli_Close();\n    return -1;\n  }\n  buf[buf_size] = 0;\n  printf(\"Manufacturer: %s\\n\", buf);\n  buf_size = sizeof(buf);\n  res = Tddli_GetCapability(TDDL_CAP_PROPERTY, TDDL_CAP_PROP_MODULE_TYPE, buf, &buf_size);\n  if (res != TDDL_SUCCESS) {\n    printf(\"Error: Tddli_GetCapability() failed: %s (%04x)\\n\", get_error(res), res);\n    Tddli_Close();\n    return -1;\n  }\n  buf[buf_size] = 0;\n  printf(\"Module type: %s\\n\", buf);\n  /* reset tpm */\n  printf(\"Transmit: \");\n  for (i = 0; i < sizeof(reset); i++) printf(\"%02x \", reset[i]);\n  printf(\"\\n\");\n  buf_size = sizeof(buf);\n  res = Tddli_TransmitData(reset, sizeof(reset), buf, &buf_size);\n  if (res != TDDL_SUCCESS) {\n    printf(\"Error: Tddli_TransmitData() failed: %s (%04x)\\n\", get_error(res), res);\n    Tddli_Close();\n    return -1;\n  }\n  printf(\"Result:   \");\n  for (i = 0; i < buf_size; i++) printf(\"%02x \", buf[i]);\n  printf(\"\\n\");\n\n  res = Tddli_Close();\n  if (res != TDDL_SUCCESS) {\n    printf(\"Error: Tddli_Close() failed: %s (%04x)\\n\", get_error(res), res);\n    return -1;\n  }\n  return 0;\n}\n"
  },
  {
    "path": "tpm/CMakeLists.txt",
    "content": "# Software-based Trusted Platform Module (TPM) Emulator\n# Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n#\n# $Id: CMakeLists.txt 364 2010-02-11 10:24:45Z mast $\n\nfile(GLOB tpm_SRCS \"*.[h|c]\")\nadd_library(tpm STATIC ${tpm_SRCS})\n\n"
  },
  {
    "path": "tpm/tpm_audit.c",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: tpm_audit.c 385 2010-02-17 15:41:28Z mast $\n */\n\n#include \"tpm_emulator.h\"\n#include \"tpm_commands.h\"\n#include \"tpm_data.h\"\n#include \"tpm_marshalling.h\"\n#include \"tpm_handles.h\"\n#include <crypto/sha1.h>\n\n/*\n * Auditing ([TPM_Part3], Section 8)\n * The TPM generates an audit event in response to the TPM executing a \n * function that has the audit flag set to TRUE for that function. The \n * TPM maintains an extended value for all audited operations. \n */\n \n#define AUDIT_STATUS tpmData.permanent.data.ordinalAuditStatus\n\nvoid tpm_audit_request(TPM_COMMAND_CODE ordinal, TPM_REQUEST *req)\n{\n  tpm_sha1_ctx_t sha1_ctx;\n  BYTE buf[sizeof_TPM_AUDIT_EVENT_IN(x)], *ptr;\n  UINT32 len;\n  TPM_COMMAND_CODE ord = ordinal & TPM_ORD_INDEX_MASK;\n  if (ord < TPM_ORD_MAX\n      && (AUDIT_STATUS[ord / 8] & (1 << (ord & 0x07)))) {\n    info(\"tpm_audit_request()\");\n    /* is there already an audit session running? */\n    if (!tpmData.stany.data.auditSession) {       \n      tpmData.stany.data.auditSession = TRUE;\n      tpmData.permanent.data.auditMonotonicCounter++;\n    }\n    /* update audit digest */\n    ptr = buf; len = sizeof(buf);\n    tpm_marshal_TPM_TAG(&ptr, &len, TPM_TAG_AUDIT_EVENT_IN);\n    tpm_marshal_TPM_COMMAND_CODE(&ptr, &len, ordinal);\n    tpm_sha1_init(&sha1_ctx);\n    tpm_sha1_update(&sha1_ctx, req->param, req->paramSize);\n    tpm_sha1_final(&sha1_ctx, ptr);\n    ptr += 20; len -= 20;\n    tpm_marshal_TPM_TAG(&ptr, &len, TPM_TAG_COUNTER_VALUE);\n    tpm_marshal_UINT32(&ptr, &len, 0);\n    tpm_marshal_UINT32(&ptr, &len, tpmData.permanent.data.auditMonotonicCounter);\n    tpm_sha1_init(&sha1_ctx);\n    tpm_sha1_update(&sha1_ctx, tpmData.stany.data.auditDigest.digest, sizeof(TPM_DIGEST));\n    tpm_sha1_update(&sha1_ctx, buf, sizeof(buf));\n    tpm_sha1_final(&sha1_ctx, tpmData.stany.data.auditDigest.digest);\n  }\n}\n\nvoid tpm_audit_response(TPM_COMMAND_CODE ordinal, TPM_RESPONSE *rsp)\n{\n  tpm_sha1_ctx_t sha1_ctx;\n  BYTE buf[sizeof_TPM_AUDIT_EVENT_OUT(x)], *ptr;\n  UINT32 len;\n  TPM_COMMAND_CODE ord = ordinal & TPM_ORD_INDEX_MASK;\n  if (ord < TPM_ORD_MAX\n      && (AUDIT_STATUS[ord / 8] & (1 << (ord & 0x07)))) {\n    info(\"tpm_audit_response()\");\n    /* update audit digest */\n    ptr = buf; len = sizeof(buf);\n    tpm_marshal_TPM_TAG(&ptr, &len, TPM_TAG_AUDIT_EVENT_OUT);\n    tpm_marshal_TPM_COMMAND_CODE(&ptr, &len, ordinal);\n    tpm_sha1_init(&sha1_ctx);\n    tpm_sha1_update(&sha1_ctx, rsp->param, rsp->paramSize);\n    tpm_sha1_final(&sha1_ctx, ptr);\n    ptr += 20; len -= 20;\n    tpm_marshal_TPM_TAG(&ptr, &len, TPM_TAG_COUNTER_VALUE);\n    tpm_marshal_UINT32(&ptr, &len, 0);\n    tpm_marshal_UINT32(&ptr, &len, tpmData.permanent.data.auditMonotonicCounter);\n    tpm_marshal_TPM_RESULT(&ptr, &len, rsp->result);\n    tpm_sha1_init(&sha1_ctx);\n    tpm_sha1_update(&sha1_ctx, tpmData.stany.data.auditDigest.digest, sizeof(TPM_DIGEST));\n    tpm_sha1_update(&sha1_ctx, buf, sizeof(buf));\n    tpm_sha1_final(&sha1_ctx, tpmData.stany.data.auditDigest.digest);\n  }\n}\n\n/* number of bits to represent 0, 1, 2, 3 ... */\nstatic uint8_t bits[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 }; \n\nTPM_RESULT TPM_GetAuditDigest(UINT32 startOrdinal, \n                              TPM_COUNTER_VALUE *counterValue, \n                              TPM_DIGEST *auditDigest, BOOL *more,\n                              UINT32 *ordSize, UINT32 **ordList)\n{\n  UINT32 i, j, len, *ptr;\n  info(\"TPM_GetAuditDigest()\");\n  /* compute (maximal) size of the ordinal list */\n  for (len = 0, i = startOrdinal/8; i < TPM_ORD_MAX/8; i++) {\n    len += bits[AUDIT_STATUS[i] & 0x0f];\n    len += bits[(AUDIT_STATUS[i] >> 4) & 0x0f];  \n  }\n  /* setup ordinal list */\n  ptr = *ordList = tpm_malloc(len);\n  if (ptr == NULL) return TPM_FAIL;\n  for (*ordSize = 0, i = startOrdinal/8; i < TPM_ORD_MAX/8; i++) {\n    if (AUDIT_STATUS[i]) for (j = 0; j < 8; j++) {\n      if ((AUDIT_STATUS[i] & (1 << j)) && i * 8 + j > startOrdinal) {\n        *ptr++ = i * 8 + j;\n        *ordSize += 4;\n      }      \n    } \n  }\n  counterValue->tag = TPM_TAG_COUNTER_VALUE;\n  memset(counterValue->label, 0, sizeof(counterValue->label));\n  counterValue->counter = tpmData.permanent.data.auditMonotonicCounter;\n  memcpy(auditDigest, &tpmData.stany.data.auditDigest, sizeof(TPM_DIGEST));\n  if (more != NULL) *more = FALSE;\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_GetAuditDigestSigned(TPM_KEY_HANDLE keyHandle, \n                                    BOOL closeAudit, TPM_NONCE *antiReplay,\n                                    TPM_AUTH *auth1,\n                                    TPM_COUNTER_VALUE *counterValue,\n                                    TPM_DIGEST *auditDigest,\n                                    TPM_DIGEST *ordinalDigest,\n                                    UINT32 *sigSize, BYTE **sig)\n{\n  TPM_RESULT res;\n  TPM_KEY_DATA *key;\n  UINT32 ordSize;\n  UINT32 *ordList;\n  BYTE buf[TPM_ORD_MAX * 4];\n  BYTE *ptr;\n  UINT32 len;\n  tpm_sha1_ctx_t ctx;\n  info(\"TPM_GetAuditDigestSigned()\");\n  /* get key */\n  key = tpm_get_key(keyHandle);\n  if (key == NULL) return TPM_INVALID_KEYHANDLE;\n  if (key->keyUsage != TPM_KEY_SIGNING && key->keyUsage != TPM_KEY_IDENTITY\n      && key->keyUsage != TPM_KEY_LEGACY) return TPM_INVALID_KEYUSAGE;\n  /* verify authorization */ \n  if (auth1->authHandle != TPM_INVALID_HANDLE\n      || key->authDataUsage != TPM_AUTH_NEVER) {\n    res = tpm_verify_auth(auth1, key->usageAuth, keyHandle);\n    if (res != TPM_SUCCESS) return res;\n  }\n  /* get audit digest */    \n  res = TPM_GetAuditDigest(0, counterValue, auditDigest, NULL,\n                           &ordSize, &ordList);\n  if (res != TPM_SUCCESS) return res;\n  /* allocate buffer memory */\n  len = sizeof(buf);\n  ptr = buf;\n  if (tpm_marshal_UINT32_ARRAY(&ptr, &len, ordList, ordSize/4) != 0) {\n    debug(\"tpm_marshal_UINT32_ARRAY() failed.\");\n    tpm_free(ordList);\n    return TPM_FAIL;\n  }\n  tpm_free(ordList);\n  /* compute ordinal digest */\n  tpm_sha1_init(&ctx);\n  tpm_sha1_update(&ctx, buf, ordSize);\n  tpm_sha1_final(&ctx, ordinalDigest->digest);\n  /* setup a TPM_SIGN_INFO structure */\n  memset(buf, 0, sizeof(buf));\n  memcpy(&buf[0], \"\\x00\\x05\", 2);\n  memcpy(&buf[2], \"ADIG\", 4);\n  memcpy(&buf[6], antiReplay->nonce, 20);\n  len = sizeof(buf) - 26;\n  ptr = &buf[26];\n  if (tpm_marshal_UINT32(&ptr, &len,\n        20 + sizeof_TPM_COUNTER_VALUE((*counterValue)) + 20) != 0) {\n    debug(\"tpm_marshal_UINT32() failed.\");\n    return TPM_FAIL;\n  }\n  memcpy(ptr, auditDigest->digest, 20);\n  len -= 20;\n  ptr += 20;\n  if (tpm_marshal_TPM_COUNTER_VALUE(&ptr, &len, counterValue) != 0) {\n    debug(\"tpm_marshal_TPM_COUNTER_VALUE() failed.\");\n    return TPM_FAIL;\n  }\n  memcpy(ptr, ordinalDigest->digest, 20);\n  /* check key usage */\n  if (closeAudit) {\n    if (key->keyUsage == TPM_KEY_IDENTITY) {\n      memset(&tpmData.stany.data.auditDigest, 0, sizeof(TPM_DIGEST));\n    } else {\n      return TPM_INVALID_KEYUSAGE;\n    }\n  }\n  /* sign data */\n  if (key->sigScheme == TPM_SS_RSASSAPKCS1v15_SHA1) {\n    debug(\"TPM_SS_RSASSAPKCS1v15_SHA1\");\n    len = 30 + 20 + sizeof_TPM_COUNTER_VALUE((*counterValue)) + 20;\n    tpm_sha1_init(&ctx);\n    tpm_sha1_update(&ctx, buf, len);\n    tpm_sha1_final(&ctx, buf);\n    res = tpm_sign(key, auth1, FALSE, buf, SHA1_DIGEST_LENGTH, sig, sigSize);\n  } else if (key->sigScheme == TPM_SS_RSASSAPKCS1v15_INFO) {\n    debug(\"TPM_SS_RSASSAPKCS1v15_INFO\");\n    res = tpm_sign(key, auth1, TRUE, buf, sizeof(buf), sig, sigSize);\n  } else {\n    debug(\"unsupported signature scheme: %02x\", key->sigScheme);\n    res = TPM_INVALID_KEYUSAGE;\n  }\n  return res;\n}\n\nTPM_RESULT TPM_SetOrdinalAuditStatus(TPM_COMMAND_CODE ordinalToAudit,\n                                     BOOL auditState, TPM_AUTH *auth1)\n{\n  TPM_RESULT res;\n  info(\"TPM_SetOrdinalAuditStatus()\");\n  /* verify authorization */\n  res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);\n  if (res != TPM_SUCCESS) return res;\n  /* set ordinal's audit status */\n  if (ordinalToAudit > TPM_ORD_MAX) return TPM_BADINDEX;\n  ordinalToAudit &= TPM_ORD_INDEX_MASK;\n  if (auditState) {\n    AUDIT_STATUS[ordinalToAudit / 8] |= (1 << (ordinalToAudit & 0x07));\n  } else {\n    AUDIT_STATUS[ordinalToAudit / 8] &= ~(1 << (ordinalToAudit & 0x07)); \n  }\n  return TPM_SUCCESS;\n}\n\n"
  },
  {
    "path": "tpm/tpm_authorization.c",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: tpm_authorization.c 467 2011-07-19 17:36:12Z mast $\n */\n\n#include \"tpm_emulator.h\"\n#include \"tpm_commands.h\"\n#include \"tpm_handles.h\"\n#include \"tpm_data.h\"\n#include \"tpm_marshalling.h\"\n#include \"crypto/hmac.h\"\n#include \"crypto/sha1.h\"\n\n/*\n * Authorization Changing ([TPM_Part3], Section 17)\n */\n\nTPM_RESULT TPM_ChangeAuth(TPM_KEY_HANDLE parentHandle,\n                          TPM_PROTOCOL_ID protocolID, TPM_ENCAUTH *newAuth,\n                          TPM_ENTITY_TYPE entityType, UINT32 encDataSize,\n                          BYTE *encData, TPM_AUTH *auth1, TPM_AUTH *auth2,\n                          UINT32 *outDataSize, BYTE **outData)\n{\n  TPM_RESULT res;\n  TPM_KEY_DATA *parent;\n  TPM_SESSION_DATA *session;\n  TPM_SECRET plainAuth;\n  info(\"TPM_ChangeAuth()\");\n  /* get parent key */\n  parent = tpm_get_key(parentHandle);\n  if (parent == NULL) return TPM_INVALID_KEYHANDLE;\n  /* verify entity authorization */ \n  auth2->continueAuthSession = FALSE;\n  session = tpm_get_auth(auth2->authHandle);\n  if (session->type != TPM_ST_OIAP) return TPM_BAD_MODE; \n  /* verify parent authorization */\n  res = tpm_verify_auth(auth1, parent->usageAuth, parentHandle);\n  if (res != TPM_SUCCESS) return res;\n  auth1->continueAuthSession = FALSE;\n  session = tpm_get_auth(auth1->authHandle);\n  if (session->type != TPM_ST_OSAP) return TPM_BAD_MODE;  \n  /* decrypt auth */\n  tpm_decrypt_auth_secret(*newAuth, session->sharedSecret,\n                          &session->lastNonceEven, plainAuth);\n  /* decrypt the entity, replace authData, and encrypt it again */\n  if (entityType == TPM_ET_DATA) {\n    TPM_SEALED_DATA seal;\n    BYTE *seal_buf;\n    /* decrypt entity */\n    if (tpm_decrypt_sealed_data(parent, encData, encDataSize,\n        &seal, &seal_buf)) return TPM_DECRYPT_ERROR;\n    /* verify auth2 */\n    res = tpm_verify_auth(auth2, seal.authData, TPM_INVALID_HANDLE);\n    if (res != TPM_SUCCESS) return (res == TPM_AUTHFAIL) ? TPM_AUTH2FAIL : res;\n    /* change authData and use it also for auth2 */\n    memcpy(seal.authData, plainAuth, sizeof(TPM_SECRET));    \n    /* encrypt entity */\n    *outDataSize = parent->key.size >> 3;\n    *outData = tpm_malloc(*outDataSize);\n    if (tpm_encrypt_sealed_data(parent, &seal, *outData, outDataSize)) {\n      tpm_free(encData);\n      tpm_free(seal_buf);      \n      return TPM_ENCRYPT_ERROR;\n    }                    \n    tpm_free(seal_buf); \n  } else if (entityType == TPM_ET_KEY) {\n    TPM_STORE_ASYMKEY store;\n    BYTE *store_buf;\n    /* decrypt entity */\n    if (tpm_decrypt_private_key(parent, encData, encDataSize,\n        &store, &store_buf, NULL)) return TPM_DECRYPT_ERROR;\n    /* verify auth2 */\n    res = tpm_verify_auth(auth2, store.usageAuth, TPM_INVALID_HANDLE);\n    if (res != TPM_SUCCESS) return (res == TPM_AUTHFAIL) ? TPM_AUTH2FAIL : res;\n    /* change usageAuth and use it also for auth2 */\n    memcpy(store.usageAuth, plainAuth, sizeof(TPM_SECRET));  \n    /* encrypt entity */\n    *outDataSize = parent->key.size >> 3;\n    *outData = tpm_malloc(*outDataSize);\n    if (tpm_encrypt_private_key(parent, &store, *outData, outDataSize)) {\n      tpm_free(encData);\n      tpm_free(store_buf);      \n      return TPM_ENCRYPT_ERROR;\n    }                    \n    tpm_free(store_buf); \n  } else {\n    return TPM_WRONG_ENTITYTYPE;\n  }\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_ChangeAuthOwner(TPM_PROTOCOL_ID protocolID, \n                               TPM_ENCAUTH *newAuth, \n                               TPM_ENTITY_TYPE entityType, TPM_AUTH *auth1)\n{\n  TPM_RESULT res;\n  TPM_SESSION_DATA *session;\n  TPM_SECRET plainAuth;\n  int i;\n  info(\"TPM_ChangeAuthOwner()\");\n  /* verify authorization */\n  res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);\n  if (res != TPM_SUCCESS) return res;\n  auth1->continueAuthSession = FALSE;\n  session = tpm_get_auth(auth1->authHandle);\n  if (session->type != TPM_ST_OSAP) return TPM_AUTHFAIL;\n  /* decrypt auth */\n  tpm_decrypt_auth_secret(*newAuth, session->sharedSecret,\n                          &session->lastNonceEven, plainAuth);\n  /* change authorization data */\n  if (entityType == TPM_ET_OWNER) {\n    memcpy(tpmData.permanent.data.ownerAuth, plainAuth, sizeof(TPM_SECRET));\n    /* invalidate all associated sessions but the current one */\n    for (i = 0; i < TPM_MAX_SESSIONS; i++) {\n      if (tpmData.stany.data.sessions[i].handle == TPM_KH_OWNER\n          && &tpmData.stany.data.sessions[i] != session) {\n          memset(&tpmData.stany.data.sessions[i], 0, sizeof(TPM_SESSION_DATA));\n      }\n    }\n  } else if (entityType == TPM_ET_SRK) {\n    memcpy(tpmData.permanent.data.srk.usageAuth, plainAuth, sizeof(TPM_SECRET));\n/* probably not correct; spec. v1.2 rev94 says nothing about authDataUsage\n    tpmData.permanent.data.srk.authDataUsage = TPM_AUTH_ALWAYS;\n*/\n    /* invalidate all associated sessions but the current one */\n    for (i = 0; i < TPM_MAX_SESSIONS; i++) {\n      if (tpmData.stany.data.sessions[i].handle == TPM_KH_SRK\n          && &tpmData.stany.data.sessions[i] != session) {\n          memset(&tpmData.stany.data.sessions[i], 0, sizeof(TPM_SESSION_DATA));\n      }\n    }\n  } else {\n    return TPM_WRONG_ENTITYTYPE;\n  }\n  return TPM_SUCCESS;\n}\n\n/*\n * Authorization Sessions ([TPM_Part3], Section 18)\n */\n\nTPM_RESULT TPM_OIAP(TPM_AUTHHANDLE *authHandle, TPM_NONCE *nonceEven)\n{\n  TPM_SESSION_DATA *session;\n  info(\"TPM_OIAP()\");\n  /* get a free session if any is left */\n  *authHandle = tpm_get_free_session(TPM_ST_OIAP);\n  session = tpm_get_auth(*authHandle);\n  if (session == NULL) return TPM_RESOURCES;\n  /* setup session */\n  tpm_get_random_bytes(nonceEven->nonce, sizeof(nonceEven->nonce));\n  memcpy(&session->nonceEven, nonceEven, sizeof(TPM_NONCE));\n  debug(\"handle = %08x\", *authHandle);\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_OSAP(TPM_ENTITY_TYPE entityType, UINT32 entityValue, \n                    TPM_NONCE *nonceOddOSAP, TPM_AUTHHANDLE *authHandle,\n                    TPM_NONCE *nonceEven, TPM_NONCE *nonceEvenOSAP)\n{\n  tpm_hmac_ctx_t ctx;\n  TPM_SESSION_DATA *session;\n  TPM_SECRET *secret = NULL;\n  info(\"TPM_OSAP()\");\n  /* get a free session if any is left */\n  *authHandle = tpm_get_free_session(TPM_ST_OSAP);\n  session = tpm_get_auth(*authHandle);\n  if (session == NULL) return TPM_RESOURCES;\n  debug(\"entityType = %04x, entityValue = %04x\", entityType, entityValue);\n  /* check whether ADIP encryption scheme is supported */\n  switch (entityType & 0xFF00) {\n    case TPM_ET_XOR:\n      break;\n    default:\n      return TPM_INAPPROPRIATE_ENC;\n  }\n  /* get resource handle and the respective secret */\n  switch (entityType & 0x00FF) {\n    case TPM_ET_KEYHANDLE:\n      session->handle = entityValue;\n      if (session->handle == TPM_KH_OPERATOR) return TPM_BAD_HANDLE;\n      if (tpm_get_key(session->handle) != NULL)\n        secret = &tpm_get_key(session->handle)->usageAuth;\n      else\n        debug(\"TPM_OSAP failed(): tpm_get_key(handle) == NULL\");\n      break;\n    case TPM_ET_OWNER:\n    case TPM_ET_VERIFICATION_AUTH:\n      session->handle = TPM_KH_OWNER;\n      if (tpmData.permanent.flags.owned)\n        secret = &tpmData.permanent.data.ownerAuth;\n      break;\n    case TPM_ET_SRK:\n      session->handle = TPM_KH_SRK;\n      if (tpmData.permanent.data.srk.payload)\n        secret = &tpmData.permanent.data.srk.usageAuth;\n      break;\n    case TPM_ET_COUNTER:\n      session->handle = entityValue;\n      if (tpm_get_counter(session->handle) != NULL)\n        secret = &tpm_get_counter(session->handle)->usageAuth;\n      break;\n    case TPM_ET_NV:\n      session->handle = entityValue;\n      if (tpm_get_nvs(session->handle) != NULL)\n        secret = &tpm_get_nvs(session->handle)->authValue;\n      break;\n    default:\n      return TPM_BAD_PARAMETER;\n  }\n  if (secret == NULL) {\n    debug(\"TPM_OSAP failed(): secret == NULL\");\n    memset(session, 0, sizeof(*session));\n    return TPM_BAD_PARAMETER;\n  }\n  /* save entity type */\n  session->entityType = entityType;\n  /* generate nonces */\n  tpm_get_random_bytes(nonceEven->nonce, sizeof(nonceEven->nonce));\n  memcpy(&session->nonceEven, nonceEven, sizeof(TPM_NONCE));\n  tpm_get_random_bytes(nonceEvenOSAP->nonce, sizeof(nonceEvenOSAP->nonce));\n  /* compute shared secret */\n  tpm_hmac_init(&ctx, *secret, sizeof(*secret));\n  tpm_hmac_update(&ctx, nonceEvenOSAP->nonce, sizeof(nonceEvenOSAP->nonce));\n  tpm_hmac_update(&ctx, nonceOddOSAP->nonce, sizeof(nonceOddOSAP->nonce));\n  tpm_hmac_final(&ctx, session->sharedSecret);\n  debug(\"handle = %08x\", *authHandle);\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_DSAP(TPM_ENTITY_TYPE entityType, TPM_KEY_HANDLE keyHandle,\n                    TPM_NONCE *nonceOddDSAP, UINT32 entityValueSize,\n                    BYTE *entityValue, TPM_AUTHHANDLE *authHandle,\n                    TPM_NONCE *nonceEven, TPM_NONCE *nonceEvenDSAP)\n{\n  tpm_hmac_ctx_t ctx;\n  TPM_SESSION_DATA *session;\n  TPM_SECRET secret;\n  TPM_FAMILY_TABLE_ENTRY *fr;\n  info(\"TPM_DSAP()\");\n  /* get a free session if any is left */\n  *authHandle = tpm_get_free_session(TPM_ST_DSAP);\n  session = tpm_get_auth(*authHandle);\n  if (session == NULL) return TPM_RESOURCES;\n  debug(\"entityType = %04x, entityValueSize = %04x\", entityType, entityValueSize);\n  /* decode entity value and get respective secret */\n  if (entityType == TPM_ET_DEL_OWNER_BLOB) {\n    TPM_DELEGATE_OWNER_BLOB blob;\n    TPM_DELEGATE_SENSITIVE sens;\n    BYTE *sens_buf;\n    TPM_DIGEST blobDigest;\n    /* unmarshal the entity value */\n    if (tpm_unmarshal_TPM_DELEGATE_OWNER_BLOB(&entityValue,\n                                              &entityValueSize, &blob)\n        || blob.tag != TPM_TAG_DELEGATE_OWNER_BLOB) return TPM_WRONG_ENTITYTYPE;\n    /* validate the integrity of the blob */\n    tpm_compute_owner_blob_digest(&blob, &blobDigest);\n    if (memcmp(&blob.integrityDigest, &blobDigest, sizeof(TPM_DIGEST)) != 0)\n      return TPM_AUTHFAIL;\n    /* get family table row */\n    debug(\"family id = %d\", blob.pub.familyID);\n    fr = tpm_get_family_row(blob.pub.familyID);\n    if (fr == NULL) return TPM_BADINDEX;\n    if (!(fr->flags & TPM_FAMFLAG_ENABLED)) return TPM_DISABLED_CMD;\n    if (fr->verificationCount != blob.pub.verificationCount) return TPM_FAIL;\n    /* decrypt sensitive data */\n    if (tpm_decrypt_sensitive(blob.additionalArea, blob.additionalSize,\n          blob.sensitiveArea, blob.sensitiveSize, &sens, &sens_buf)) {\n      debug(\"tpm_decrypt_sensitive() failed\");\n      return TPM_DECRYPT_ERROR;\n    }\n    if (sens.tag != TPM_TAG_DELEGATE_SENSITIVE) {\n      tpm_free(sens_buf);\n      return TPM_BAD_DELEGATE;\n    }\n    memcpy(&secret, &sens.authValue, sizeof(TPM_SECRET));\n    memcpy(&session->permissions, &blob.pub.permissions, sizeof(TPM_DELEGATIONS));\n    session->handle = TPM_KH_OWNER;\n    session->familyID = blob.pub.familyID;\n    tpm_free(sens_buf);\n  } else if (entityType == TPM_ET_DEL_ROW) {\n    UINT32 row;\n    TPM_DELEGATE_TABLE_ROW *dr;\n    if (tpm_unmarshal_UINT32(&entityValue, &entityValueSize, &row))\n      return TPM_WRONG_ENTITYTYPE;\n    debug(\"row number = %d\", row);\n    dr = tpm_get_delegate_row(row);\n    if (dr == NULL) return TPM_BADINDEX;\n    fr = tpm_get_family_row(dr->pub.familyID);\n    if (fr == NULL) return TPM_BADINDEX;\n    if (!(fr->flags & TPM_FAMFLAG_ENABLED)) return TPM_DISABLED_CMD;\n    if (fr->verificationCount != dr->pub.verificationCount) return TPM_FAIL;\n    memcpy(&secret, dr->authValue, sizeof(TPM_SECRET));\n    memcpy(&session->permissions, &dr->pub.permissions, sizeof(TPM_DELEGATIONS));\n    session->handle = keyHandle;\n    session->familyID = dr->pub.familyID;\n  } else if (entityType == TPM_ET_DEL_KEY_BLOB) {\n    TPM_DELEGATE_KEY_BLOB blob;\n    TPM_DELEGATE_SENSITIVE sens;\n    BYTE *sens_buf;\n    TPM_DIGEST blobDigest;\n    TPM_KEY_DATA *key;\n    TPM_PUBKEY pubKey;\n    /* unmarshal the entity value */\n    if (tpm_unmarshal_TPM_DELEGATE_KEY_BLOB(&entityValue,\n                                            &entityValueSize, &blob)\n        || blob.tag != TPM_TAG_DELEGATE_KEY_BLOB) return TPM_WRONG_ENTITYTYPE;\n    /* validate the integrity of the blob */\n    tpm_compute_key_blob_digest(&blob, &blobDigest);\n    if (memcmp(&blob.integrityDigest, &blobDigest, sizeof(TPM_DIGEST)) != 0)\n      return TPM_AUTHFAIL;\n    /* validate key digest */\n    key = tpm_get_key(keyHandle);\n    if (key == NULL) return TPM_KEYNOTFOUND;\n    if (tpm_extract_pubkey(key, &pubKey) != 0) {\n      debug(\"tpm_extract_pubkey() failed.\");\n      return TPM_FAIL;\n    }\n    if (tpm_compute_pubkey_digest(&pubKey, &blobDigest) != 0) {\n      debug(\"tpm_compute_pubkey_digest() failed.\");\n      free_TPM_PUBKEY(pubKey);\n      return TPM_FAIL;\n    }\n    free_TPM_PUBKEY(pubKey);\n    if (memcmp(&blob.pubKeyDigest, &blobDigest, sizeof(TPM_DIGEST)) != 0)\n      return TPM_KEYNOTFOUND;\n    /* get family table row */\n    debug(\"family id = %d\", blob.pub.familyID);\n    fr = tpm_get_family_row(blob.pub.familyID);\n    if (fr == NULL) return TPM_BADINDEX;\n    if (!(fr->flags & TPM_FAMFLAG_ENABLED)) return TPM_DISABLED_CMD;\n    if (fr->verificationCount != blob.pub.verificationCount) return TPM_FAIL;\n    /* decrypt sensitive data */\n    if (tpm_decrypt_sensitive(blob.additionalArea, blob.additionalSize,\n          blob.sensitiveArea, blob.sensitiveSize, &sens, &sens_buf)) {\n      debug(\"tpm_decrypt_sensitive() failed\");\n      return TPM_DECRYPT_ERROR;\n   }\n   if (sens.tag != TPM_TAG_DELEGATE_SENSITIVE) {\n     tpm_free(sens_buf);\n     return TPM_BAD_DELEGATE;\n   }\n   memcpy(&secret, &sens.authValue, sizeof(TPM_SECRET));\n   memcpy(&session->permissions, &blob.pub.permissions, sizeof(TPM_DELEGATIONS));\n   session->handle = keyHandle;\n   session->familyID = blob.pub.familyID;\n   tpm_free(sens_buf);\n  } else {\n    return TPM_BAD_PARAMETER;\n  }\n  /* save entity type */\n  session->entityType = entityType;\n  /* generate nonces */\n  tpm_get_random_bytes(nonceEven->nonce, sizeof(nonceEven->nonce));\n  memcpy(&session->nonceEven, nonceEven, sizeof(TPM_NONCE));\n  tpm_get_random_bytes(nonceEvenDSAP->nonce, sizeof(nonceEvenDSAP->nonce));\n  /* compute shared secret */\n  tpm_hmac_init(&ctx, secret, sizeof(secret));\n  tpm_hmac_update(&ctx, nonceEvenDSAP->nonce, sizeof(nonceEvenDSAP->nonce));\n  tpm_hmac_update(&ctx, nonceOddDSAP->nonce, sizeof(nonceOddDSAP->nonce));\n  tpm_hmac_final(&ctx, session->sharedSecret);\n  debug(\"handle = %08x\", *authHandle);\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_SetOwnerPointer(TPM_ENTITY_TYPE entityType, UINT32 entityValue)\n{\n  info(\"TPM_SetOwnerPointer() is not supported\");\n  return TPM_DISABLED_CMD;\n}\n\n#define IS_SET(val, mask) (((val) & (mask)) == (mask))\n\nstatic BOOL is_owner_delegation_permitted(TPM_COMMAND_CODE ordinal,\n                                          UINT32 per1, UINT32 per2)\n{\n  switch (ordinal) {\n    case TPM_ORD_SetOrdinalAuditStatus:\n      return IS_SET(per1, TPM_DELEGATE_SetOrdinalAuditStatus);\n    case TPM_ORD_DirWriteAuth:\n      return IS_SET(per1, TPM_DELEGATE_DirWriteAuth);\n    case TPM_ORD_CMK_ApproveMA:\n      return IS_SET(per1, TPM_DELEGATE_CMK_ApproveMA);\n    case TPM_ORD_NV_WriteValue:\n      return IS_SET(per1, TPM_DELEGATE_NV_WriteValue);\n    case TPM_ORD_CMK_CreateTicket:\n      return IS_SET(per1, TPM_DELEGATE_CMK_CreateTicket);\n    case TPM_ORD_NV_ReadValue:\n      return IS_SET(per1, TPM_DELEGATE_NV_ReadValue);\n    case TPM_ORD_Delegate_LoadOwnerDelegation:\n      return IS_SET(per1, TPM_DELEGATE_Delegate_LoadOwnerDelegation);\n    case TPM_ORD_DAA_Join:\n      return IS_SET(per1, TPM_DELEGATE_DAA_Join);\n    case TPM_ORD_AuthorizeMigrationKey:\n      return IS_SET(per1, TPM_DELEGATE_AuthorizeMigrationKey);\n    case TPM_ORD_CreateMaintenanceArchive:\n      return IS_SET(per1, TPM_DELEGATE_CreateMaintenanceArchive);\n    case TPM_ORD_LoadMaintenanceArchive:\n      return IS_SET(per1, TPM_DELEGATE_LoadMaintenanceArchive);\n    case TPM_ORD_KillMaintenanceFeature:\n      return IS_SET(per1, TPM_DELEGATE_KillMaintenanceFeature);\n    case TPM_ORD_OwnerReadInternalPub:\n      return IS_SET(per1, TPM_DELEGATE_OwnerReadInternalPub);\n    case TPM_ORD_ResetLockValue:\n      return IS_SET(per1, TPM_DELEGATE_ResetLockValue);\n    case TPM_ORD_OwnerClear:\n      return IS_SET(per1, TPM_DELEGATE_OwnerClear);\n    case TPM_ORD_DisableOwnerClear:\n      return IS_SET(per1, TPM_DELEGATE_DisableOwnerClear);\n    case TPM_ORD_NV_DefineSpace:\n      return IS_SET(per1, TPM_DELEGATE_NV_DefineSpace);\n    case TPM_ORD_OwnerSetDisable:\n      return IS_SET(per1, TPM_DELEGATE_OwnerSetDisable);\n    case TPM_ORD_SetCapability:\n      return IS_SET(per1, TPM_DELEGATE_SetCapability);\n    case TPM_ORD_MakeIdentity:\n      return IS_SET(per1, TPM_DELEGATE_MakeIdentity);\n    case TPM_ORD_ActivateIdentity:\n      return IS_SET(per1, TPM_DELEGATE_ActivateIdentity);\n    case TPM_ORD_OwnerReadPubek:\n      return IS_SET(per1, TPM_DELEGATE_OwnerReadPubek);\n    case TPM_ORD_DisablePubekRead:\n      return IS_SET(per1, TPM_DELEGATE_DisablePubekRead);\n    case TPM_ORD_SetRedirection:\n      return IS_SET(per1, TPM_DELEGATE_SetRedirection);\n    case TPM_ORD_FieldUpgrade:\n      return IS_SET(per1, TPM_DELEGATE_FieldUpgrade);\n    case TPM_ORD_Delegate_UpdateVerification:\n      return IS_SET(per1, TPM_DELEGATE_Delegate_UpdateVerification);\n    case TPM_ORD_CreateCounter:\n      return IS_SET(per1, TPM_DELEGATE_CreateCounter);\n    case TPM_ORD_ReleaseCounterOwner:\n      return IS_SET(per1, TPM_DELEGATE_ReleaseCounterOwner);\n    case TPM_ORD_Delegate_Manage:\n      return IS_SET(per1, TPM_DELEGATE_Delegate_Manage);\n    case TPM_ORD_Delegate_CreateOwnerDelegation:\n      return IS_SET(per1, TPM_DELEGATE_Delegate_CreateOwnerDelegation);\n    case TPM_ORD_DAA_Sign:\n      return IS_SET(per1, TPM_DELEGATE_DAA_Sign);\n  }\n  return FALSE;\n}\n\nstatic BOOL is_key_delegation_permitted(TPM_COMMAND_CODE ordinal,\n                                        UINT32 per1, UINT32 per2)\n{\n  switch (ordinal) {\n    case TPM_ORD_CMK_ConvertMigration:\n      return IS_SET(per1, TPM_KEY_DELEGATE_CMK_ConvertMigration);\n    case TPM_ORD_TickStampBlob:\n      return IS_SET(per1, TPM_KEY_DELEGATE_TickStampBlob);\n    case TPM_ORD_ChangeAuthAsymStart:\n      return IS_SET(per1, TPM_KEY_DELEGATE_ChangeAuthAsymStart);\n    case TPM_ORD_ChangeAuthAsymFinish:\n      return IS_SET(per1, TPM_KEY_DELEGATE_ChangeAuthAsymFinish);\n    case TPM_ORD_CMK_CreateKey:\n      return IS_SET(per1, TPM_KEY_DELEGATE_CMK_CreateKey);\n    case TPM_ORD_MigrateKey:\n      return IS_SET(per1, TPM_KEY_DELEGATE_MigrateKey);\n    case TPM_ORD_LoadKey2:\n      return IS_SET(per1, TPM_KEY_DELEGATE_LoadKey2);\n    case TPM_ORD_EstablishTransport:\n      return IS_SET(per1, TPM_KEY_DELEGATE_EstablishTransport);\n    case TPM_ORD_ReleaseTransportSigned:\n      return IS_SET(per1, TPM_KEY_DELEGATE_ReleaseTransportSigned);\n    case TPM_ORD_Quote2:\n      return IS_SET(per1, TPM_KEY_DELEGATE_Quote2);\n    case TPM_ORD_Sealx:\n      return IS_SET(per1, TPM_KEY_DELEGATE_Sealx);\n    case TPM_ORD_MakeIdentity:\n      return IS_SET(per1, TPM_KEY_DELEGATE_MakeIdentity);\n    case TPM_ORD_ActivateIdentity:\n      return IS_SET(per1, TPM_KEY_DELEGATE_ActivateIdentity);\n    case TPM_ORD_GetAuditDigestSigned:\n      return IS_SET(per1, TPM_KEY_DELEGATE_GetAuditDigestSigned);\n    case TPM_ORD_Sign:\n      return IS_SET(per1, TPM_KEY_DELEGATE_Sign);\n    case TPM_ORD_CertifyKey2:\n      return IS_SET(per1, TPM_KEY_DELEGATE_CertifyKey2);\n    case TPM_ORD_CertifyKey:\n      return IS_SET(per1, TPM_KEY_DELEGATE_CertifyKey);\n    case TPM_ORD_CreateWrapKey:\n      return IS_SET(per1, TPM_KEY_DELEGATE_CreateWrapKey);\n    case TPM_ORD_CMK_CreateBlob:\n      return IS_SET(per1, TPM_KEY_DELEGATE_CMK_CreateBlob);\n    case TPM_ORD_CreateMigrationBlob:\n      return IS_SET(per1, TPM_KEY_DELEGATE_CreateMigrationBlob);\n    case TPM_ORD_ConvertMigrationBlob:\n      return IS_SET(per1, TPM_KEY_DELEGATE_ConvertMigrationBlob);\n    case TPM_ORD_Delegate_CreateKeyDelegation:\n      return IS_SET(per1, TPM_KEY_DELEGATE_Delegate_CreateKeyDelegation);\n    case TPM_ORD_ChangeAuth:\n      return IS_SET(per1, TPM_KEY_DELEGATE_ChangeAuth);\n    case TPM_ORD_GetPubKey:\n      return IS_SET(per1, TPM_KEY_DELEGATE_GetPubKey);\n    case TPM_ORD_Quote:\n      return IS_SET(per1, TPM_KEY_DELEGATE_Quote);\n    case TPM_ORD_Unseal:\n      return IS_SET(per1, TPM_KEY_DELEGATE_Unseal);\n    case TPM_ORD_Seal:\n      return IS_SET(per1, TPM_KEY_DELEGATE_Seal);\n    case TPM_ORD_LoadKey:\n      return IS_SET(per1, TPM_KEY_DELEGATE_LoadKey);\n  }\n  return FALSE;\n}\n\nTPM_RESULT tpm_verify_auth(TPM_AUTH *auth, TPM_SECRET secret,\n                           TPM_HANDLE handle)\n{\n  tpm_hmac_ctx_t ctx;\n  TPM_SESSION_DATA *session;\n  BYTE digest[SHA1_DIGEST_LENGTH];\n\n  info(\"tpm_verify_auth()\");\n  debug(\"handle = %08x\", auth->authHandle);\n  /* get dedicated authorization or transport session */\n  session = tpm_get_auth(auth->authHandle);\n  if (session == NULL) session = tpm_get_transport(auth->authHandle);\n  if (session == NULL) return TPM_INVALID_AUTHHANDLE;\n  /* setup authorization */\n  if (session->type == TPM_ST_OIAP) {\n    debug(\"[TPM_ST_OIAP]\");\n    /* We copy the secret because it might be deleted or invalidated\n       afterwards, but we need it again for authorizing the response. */\n    memcpy(session->sharedSecret, secret, sizeof(TPM_SECRET));\n  } else if (session->type == TPM_ST_OSAP) {\n    debug(\"[TPM_ST_OSAP]\");\n    if (session->handle != handle) return TPM_AUTHFAIL;\n  } else if (session->type == TPM_ST_DSAP) {\n    debug(\"[TPM_ST_DSAP]\");\n    if (session->handle != handle) return TPM_AUTHFAIL;\n    /* check permissions */\n    debug(\"delegation type = %d\", session->permissions.delegateType);\n    if (session->permissions.delegateType == TPM_DEL_OWNER_BITS) {\n      if (!is_owner_delegation_permitted(auth->ordinal,\n             session->permissions.per1, session->permissions.per2))\n        return TPM_DISABLED_CMD;\n    } else if (session->permissions.delegateType == TPM_DEL_KEY_BITS) {\n      if (!is_key_delegation_permitted(auth->ordinal,\n             session->permissions.per1, session->permissions.per2))\n        return TPM_DISABLED_CMD;\n    } else {\n      return TPM_AUTHFAIL;\n    }\n  } else if (session->type == TPM_ST_TRANSPORT) {\n    debug(\"[TPM_ST_TRANSPORT]\");\n    memcpy(session->sharedSecret, session->transInternal.authData,\n           sizeof(TPM_SECRET));\n  } else {\n    return TPM_INVALID_AUTHHANDLE;\n  }\n  memcpy(auth->secret, session->sharedSecret, sizeof(TPM_SECRET));\n  /* verify authorization */\n  tpm_hmac_init(&ctx, auth->secret, sizeof(auth->secret));\n  tpm_hmac_update(&ctx, auth->digest, sizeof(auth->digest));\n  tpm_hmac_update(&ctx, session->nonceEven.nonce, sizeof(session->nonceEven.nonce));\n  tpm_hmac_update(&ctx, auth->nonceOdd.nonce, sizeof(auth->nonceOdd.nonce));\n  tpm_hmac_update(&ctx, &auth->continueAuthSession, 1);\n  tpm_hmac_final(&ctx, digest);\n  if (memcmp(digest, auth->auth, sizeof(auth->auth))) return TPM_AUTHFAIL;\n  /* generate new nonceEven */\n  memcpy(&session->lastNonceEven, &session->nonceEven, sizeof(TPM_NONCE));\n  tpm_get_random_bytes(auth->nonceEven.nonce, sizeof(auth->nonceEven.nonce));\n  memcpy(&session->nonceEven, &auth->nonceEven, sizeof(TPM_NONCE));\n  return TPM_SUCCESS;\n}\n\nvoid tpm_decrypt_auth_secret(TPM_ENCAUTH encAuth, TPM_SECRET secret,\n                             TPM_NONCE *nonce, TPM_SECRET plainAuth)\n{\n  unsigned int i;\n  tpm_sha1_ctx_t ctx;\n  tpm_sha1_init(&ctx);\n  tpm_sha1_update(&ctx, secret, sizeof(TPM_SECRET));\n  tpm_sha1_update(&ctx, nonce->nonce, sizeof(nonce->nonce));\n  tpm_sha1_final(&ctx, plainAuth);\n  for (i = 0; i < sizeof(TPM_SECRET); i++)\n    plainAuth[i] ^= encAuth[i];\n}\n"
  },
  {
    "path": "tpm/tpm_capability.c",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *               2005-2008 Heiko Stamer <stamer@gaos.org>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: tpm_capability.c 446 2010-06-12 10:44:08Z mast $\n */\n\n#include \"tpm_emulator.h\"\n#include \"tpm_commands.h\"\n#include \"tpm_marshalling.h\"\n#include \"tpm_data.h\"\n#include \"tpm_handles.h\"\n\n/*\n * The GetCapability Commands ([TPM_Part3], Section 7)\n * The GetCapability command allows the TPM to report back to the requester \n * what type of TPM it is dealing with. The request for information requires \n * the requester to specify which piece of information that is required. \n */\n\nstatic inline TPM_RESULT return_UINT32(UINT32 *respSize, BYTE **resp, UINT32 value)\n{\n  UINT32 len = *respSize = 4;\n  BYTE *ptr = *resp = tpm_malloc(*respSize);\n  if (ptr == NULL || tpm_marshal_UINT32(&ptr, &len, value)) {\n    tpm_free(*resp);\n    return TPM_FAIL;\n  }\n  return TPM_SUCCESS;\n}\n\nstatic inline TPM_RESULT return_UINT32_array(UINT32 *respSize, BYTE **resp, \n\t\t                             UINT32 *array, UINT32 array_len)\n{\n  UINT32 len = *respSize = 4 * array_len;\n  BYTE *ptr = *resp = tpm_malloc(*respSize);\n  if (ptr == NULL || tpm_marshal_UINT32_ARRAY(&ptr, &len, array, array_len)) {\n    tpm_free(*resp);\t \n    return TPM_FAIL;\n  }\n  return TPM_SUCCESS;\n}\n\nstatic inline TPM_RESULT return_BOOL(UINT32 *respSize, BYTE **resp, BOOL value)\n{\n  UINT32 len = *respSize = 1;\n  BYTE *ptr = *resp = tpm_malloc(*respSize);\n  if (ptr == NULL || tpm_marshal_BOOL(&ptr, &len, value)) {\n    tpm_free(*resp);\n    return TPM_FAIL;\n  }\n  return TPM_SUCCESS;\n}\n\nstatic TPM_RESULT cap_property(UINT32 subCapSize, BYTE *subCap, \n                               UINT32 *respSize, BYTE **resp)\n{\n  UINT32 i, j, property;\n\n  if (tpm_unmarshal_UINT32(&subCap, &subCapSize, &property))\n    return TPM_BAD_MODE;\n  switch (property) {\n    case TPM_CAP_PROP_PCR:\n      debug(\"[TPM_CAP_PROP_PCR]\");\n      return return_UINT32(respSize, resp, TPM_NUM_PCR);\n\n    case TPM_CAP_PROP_DIR:\n      debug(\"[TPM_CAP_PROP_DIR]\");\n      return return_UINT32(respSize, resp, 1);\n\n    case TPM_CAP_PROP_MANUFACTURER:\n      debug(\"[TPM_CAP_PROP_MANUFACTURER]\");\n      return return_UINT32(respSize, resp, TPM_MANUFACTURER);\n\n    case TPM_CAP_PROP_KEYS:\n      debug(\"[TPM_CAP_PROP_KEYS]\");\n      for (i = 0, j = TPM_MAX_KEYS; i < TPM_MAX_KEYS; i++)\n        if (tpmData.permanent.data.keys[i].payload) j--;\n      return return_UINT32(respSize, resp, j); \n\n    case TPM_CAP_PROP_MIN_COUNTER:\n      debug(\"[TPM_CAP_PROP_MIN_COUNTER]\");\n      return return_UINT32(respSize, resp, 1);\n\n    case TPM_CAP_PROP_AUTHSESS:\n      debug(\"[TPM_CAP_PROP_AUTHSESS]\");\n      for (i = 0, j = TPM_MAX_SESSIONS; i < TPM_MAX_SESSIONS; i++)\n        if (tpmData.stany.data.sessions[i].type != TPM_ST_INVALID) j--;\n      return return_UINT32(respSize, resp, j);\n\n    case TPM_CAP_PROP_TRANSESS:\n      debug(\"[TPM_CAP_PROP_TRANSESS]\");\n      for (i = 0, j = TPM_MAX_SESSIONS; i < TPM_MAX_SESSIONS; i++)\n        if (tpmData.stany.data.sessions[i].type != TPM_ST_INVALID) j--;\n      return return_UINT32(respSize, resp, j);\n\n    case TPM_CAP_PROP_COUNTERS:\n      debug(\"[TPM_CAP_PROP_COUNTERS]\");\n      for (i = 0, j = TPM_MAX_COUNTERS; i < TPM_MAX_COUNTERS; i++)\n        if (tpmData.permanent.data.counters[i].valid) j--;\n      return return_UINT32(respSize, resp, j);\n\n    case TPM_CAP_PROP_MAX_AUTHSESS:\n      debug(\"[TPM_CAP_PROP_MAX_AUTHSESS]\");\n      return return_UINT32(respSize, resp, TPM_MAX_SESSIONS);\n\n    case TPM_CAP_PROP_MAX_TRANSESS:\n      debug(\"[TPM_CAP_PROP_MAX_TRANSESS]\");\n      return return_UINT32(respSize, resp, TPM_MAX_SESSIONS);\n\n    case TPM_CAP_PROP_MAX_COUNTERS:\n      debug(\"[TPM_CAP_PROP_MAX_COUNTERS]\");\n      return return_UINT32(respSize, resp, TPM_MAX_COUNTERS);\n\n    case TPM_CAP_PROP_MAX_KEYS:\n      debug(\"[TPM_CAP_PROP_MAX_KEYS]\");\n      return return_UINT32(respSize, resp, TPM_MAX_KEYS);\n\n    case TPM_CAP_PROP_OWNER:\n      debug(\"[TPM_CAP_PROP_OWNER]\");\n      return return_BOOL(respSize, resp, tpmData.permanent.flags.owned);\n\n    case TPM_CAP_PROP_CONTEXT:\n      debug(\"[TPM_CAP_PROP_CONTEXT]\");\n      for (i = 0, j = 0; i < TPM_MAX_SESSION_LIST; i++)\n        if (tpmData.stany.data.contextList[i] == 0) j++;\n      return return_UINT32(respSize, resp, j);\n\n    case TPM_CAP_PROP_MAX_CONTEXT:\n      debug(\"[TPM_CAP_PROP_MAX_CONTEXT]\");\n      return return_UINT32(respSize, resp, TPM_MAX_SESSION_LIST);\n\n    case TPM_CAP_PROP_FAMILYROWS:\n      debug(\"[TPM_CAP_PROP_FAMILYROWS]\");\n      return return_UINT32(respSize, resp, TPM_NUM_FAMILY_TABLE_ENTRY);\n\n    case TPM_CAP_PROP_TIS_TIMEOUT:\n      debug(\"[TPM_CAP_PROP_TIS_TIMEOUT]\");\n      return return_UINT32_array(respSize, resp,\n        tpmData.permanent.data.tis_timeouts, TPM_NUM_TIS_TIMEOUTS);\n\n    case TPM_CAP_PROP_STARTUP_EFFECT:\n      debug(\"[TPM_CAP_PROP_STARTUP_EFFECT]\");\n      return return_UINT32(respSize, resp, 0x4f);\n\n    case TPM_CAP_PROP_DELEGATE_ROW:\n      debug(\"[TPM_CAP_PROP_DELEGATE_ROW]\");\n      return return_UINT32(respSize, resp, TPM_NUM_DELEGATE_TABLE_ENTRY);\n\n    case TPM_CAP_PROP_MAX_DAASESS:\n      debug(\"[TPM_CAP_PROP_MAX_DAASESS]\");\n      return return_UINT32(respSize, resp, TPM_MAX_SESSIONS_DAA);\n\n    case TPM_CAP_PROP_DAASESS:\n      debug(\"[TPM_CAP_PROP_DAASESS]\");\n      for (i = 0, j = TPM_MAX_SESSIONS_DAA; i < TPM_MAX_SESSIONS_DAA; i++)\n        if (tpmData.stany.data.sessionsDAA[i].type != TPM_ST_INVALID) j--;\n      return return_UINT32(respSize, resp, j);\n\n    case TPM_CAP_PROP_CONTEXT_DIST:\n      debug(\"[TPM_CAP_PROP_CONTEXT_DIST]\");\n      return return_UINT32(respSize, resp, 0xfffffffe);\n\n    case TPM_CAP_PROP_DAA_INTERRUPT:\n      debug(\"[TPM_CAP_PROP_DAA_INTERRUPT]\");\n      /* A value of TRUE indicates that the TPM will accept ANY command \n       * while executing a DAA Join or Sign. A value of FALSE indicates \n       * that the TPM will invalidate the DAA Join or Sign upon the \n       * receipt of any command other than the next join/sign in the \n       * session or a TPM_SaveContext. */\n      return return_BOOL(respSize, resp, TRUE);\n\n    case TPM_CAP_PROP_SESSIONS:\n      debug(\"[TPM_CAP_PROP_SESSIONS]\");\n      for (i = 0, j = TPM_MAX_SESSIONS; i < TPM_MAX_SESSIONS; i++)\n        if (tpmData.stany.data.sessions[i].type != TPM_ST_INVALID) j--;\n      return return_UINT32(respSize, resp, j);\n\n    case TPM_CAP_PROP_MAX_SESSIONS:\n      debug(\"[TPM_CAP_PROP_MAX_SESSIONS]\");\n      return return_UINT32(respSize, resp, TPM_MAX_SESSIONS);\n\n    case TPM_CAP_PROP_CMK_RESTRICTION:\n      debug(\"[TPM_CAP_PROP_CMK_RESTRICTION]\");\n      return return_UINT32(respSize, resp,\n                           tpmData.permanent.data.restrictDelegate);\n\n    case TPM_CAP_PROP_DURATION:\n      debug(\"[TPM_CAP_PROP_DURATION]\");\n      return return_UINT32_array(respSize, resp,\n              tpmData.permanent.data.cmd_durations, TPM_NUM_CMD_DURATIONS);\n\n    case TPM_CAP_PROP_ACTIVE_COUNTER:\n      debug(\"[TPM_CAP_PROP_ACTIVE_COUNTER]\");\n      return return_UINT32(respSize, resp, tpmData.stclear.data.countID);\n\n    case TPM_CAP_PROP_MAX_NV_AVAILABLE:\n      debug(\"[TPM_CAP_PROP_MAX_NV_AVAILABLE]\");\n      return return_UINT32(respSize, resp, TPM_MAX_NV_SIZE\n                           - tpmData.permanent.data.nvDataSize);\n\n    case TPM_CAP_PROP_INPUT_BUFFER:\n      debug(\"[TPM_CAP_PROP_INPUT_BUFFER]\");\n      return return_UINT32(respSize, resp, TPM_CMD_BUF_SIZE);\n\n    default:\n      return TPM_BAD_MODE;\n  }\n}\n\n/* changed since v1.2 rev 94: returned version MUST BE 1.1.0.0 */\nstatic TPM_RESULT cap_version(UINT32 *respSize, BYTE **resp)\n{\n  UINT32 len = *respSize = 4;\n  BYTE *ptr = *resp = tpm_malloc(*respSize);\n  TPM_STRUCT_VER version;\n  version.major = version.minor = 1;\n  version.revMajor = version.revMinor = 0;\n  if (ptr == NULL || tpm_marshal_TPM_STRUCT_VER(&ptr, &len, &version)) {\n    tpm_free(*resp);\n    return TPM_FAIL;\n  }\n  return TPM_SUCCESS;\n}\n\n/* manufacturer specific */\nstatic TPM_RESULT cap_mfr(UINT32 subCapSize, BYTE *subCap,\n                          UINT32 *respSize, BYTE **resp)\n{\n  UINT32 len, type;\n  BYTE *ptr;\n  \n  if (tpm_unmarshal_UINT32(&subCap, &subCapSize, &type))\n    return TPM_BAD_MODE;\n  \n  switch (type) {\n    default:\n      *respSize = 4;\n      ptr = *resp = tpm_malloc(*respSize);\n      if (ptr == NULL || tpm_marshal_TPM_VERSION(&ptr, &len, \n                           &tpmData.permanent.data.version)) {\n          tpm_free(*resp);\n          return TPM_FAIL;\n      }\n      return TPM_SUCCESS;\n  }\n}\n\nstatic TPM_RESULT cap_nv_list(UINT32 *respSize, BYTE **resp)\n{\n  UINT32 i, len;\n  BYTE *ptr = *resp = tpm_malloc(TPM_MAX_NVS * sizeof(TPM_NV_INDEX));\n  \n  if (ptr == NULL) return TPM_FAIL;\n  *respSize = 0;\n  for (i = 0; i < TPM_MAX_NVS; i++) {\n    if (tpmData.permanent.data.nvStorage[i].valid) {\n      len = sizeof(TPM_NV_INDEX);\n      ptr = (*resp) + *respSize;\n      *respSize += len;\n      if (tpm_marshal_UINT32(&ptr, &len, \n          tpmData.permanent.data.nvStorage[i].pubInfo.nvIndex)) {\n        tpm_free(*resp);\n        return TPM_FAIL;\n      }\n    }\n  }\n  return TPM_SUCCESS;\n}\n\nstatic TPM_RESULT cap_nv_index(UINT32 subCapSize, BYTE *subCap,\n                               UINT32 *respSize, BYTE **resp)\n{\n  TPM_NV_INDEX nvIndex;\n  TPM_NV_DATA_SENSITIVE *nv;\n  UINT32 len;\n  BYTE *ptr;\n\n  if (tpm_unmarshal_TPM_NV_INDEX(&subCap, &subCapSize, &nvIndex))\n    return TPM_BAD_MODE;\n  nv = tpm_get_nvs(nvIndex);\n  if (nv == NULL) return TPM_BADINDEX;\n  len = *respSize = sizeof_TPM_NV_DATA_PUBLIC(nv->pubInfo);\n  ptr = *resp = tpm_malloc(len);\n  if (ptr == NULL \n      || tpm_marshal_TPM_NV_DATA_PUBLIC(&ptr, &len, &nv->pubInfo)) {\n    tpm_free(*resp);\n    return TPM_FAIL;\n  }\n  *respSize -= len;\n  return TPM_SUCCESS;\n}\n\nstatic TPM_RESULT cap_handle(UINT32 subCapSize, BYTE *subCap,\n                             UINT32 *respSize, BYTE **resp)\n{\n  UINT32 i, len, type;\n  BYTE *ptr; \n  /* maximum of { TPM_MAX_KEYS, TPM_MAX_SESSIONS } */\n  UINT32 list_size =\n    (TPM_MAX_KEYS > TPM_MAX_SESSIONS) ? TPM_MAX_KEYS : TPM_MAX_SESSIONS;\n  UINT32 handles[list_size];\n  TPM_KEY_HANDLE_LIST list = { 0, handles };\n\n  if (tpm_unmarshal_UINT32(&subCap, &subCapSize, &type))\n    return TPM_BAD_MODE;\n  switch (type) {\n    case TPM_RT_KEY:\n      debug(\"[TPM_RT_KEY]\");\n      for (i = 0; i < TPM_MAX_KEYS; i++)\n        if (tpmData.permanent.data.keys[i].payload) {\n          list.loaded++;\n          list.handle[i] = INDEX_TO_KEY_HANDLE(i);\n        }\n      break;\n    case TPM_RT_AUTH:\n      debug(\"[TPM_RT_AUTH]\");\n      for (i = 0; i < TPM_MAX_SESSIONS; i++)\n        if (tpmData.stany.data.sessions[i].type == TPM_ST_OIAP\n            || tpmData.stany.data.sessions[i].type == TPM_ST_OSAP) {\n          list.loaded++;\n          list.handle[i] = INDEX_TO_AUTH_HANDLE(i);\n        }\n      break;\n    case TPM_RT_TRANS:\n      debug(\"[TPM_RT_TRANS]\");\n      for (i = 0; i < TPM_MAX_SESSIONS; i++)\n        if (tpmData.stany.data.sessions[i].type == TPM_ST_TRANSPORT) {\n          list.loaded++;\n          list.handle[i] = INDEX_TO_TRANS_HANDLE(i);\n        }\n      break;\n    case TPM_RT_COUNTER:\n      debug(\"[TPM_RT_COUNTER]\");\n      for (i = 0; i < TPM_MAX_COUNTERS; i++)\n        if (tpmData.permanent.data.counters[i].valid) {\n          list.loaded++;\n          list.handle[i] = INDEX_TO_COUNTER_HANDLE(i);\n        }\n      break;\n    case TPM_RT_CONTEXT:\n      debug(\"[TPM_RT_CONTEXT]\");\n      for (i = 0; i < TPM_MAX_SESSION_LIST; i++)\n        if (tpmData.stany.data.contextList[i] != 0) {\n          list.loaded++;\n          list.handle[i] = tpmData.stany.data.contextList[i];\n        }\n      break;\n    default:\n      return TPM_BAD_MODE;\n  }\n  /* marshal handle list */\n  len = *respSize = 2 + list.loaded * 4;\n  ptr = *resp = tpm_malloc(len);\n  if (ptr == NULL || tpm_marshal_TPM_KEY_HANDLE_LIST(&ptr, &len, &list)) {\n    tpm_free(*resp);\n    return TPM_FAIL;\n  }\n  return TPM_SUCCESS;\n}\n\nstatic TPM_RESULT cap_ord(UINT32 subCapSize, BYTE *subCap,\n                          UINT32 *respSize, BYTE **resp)\n{\n  TPM_COMMAND_CODE ord;\n  if (tpm_unmarshal_TPM_COMMAND_CODE(&subCap, &subCapSize, &ord))\n    return TPM_BAD_MODE;\n  switch (ord) {\n    case TPM_ORD_Init:\n    case TPM_ORD_Startup:\n    case TPM_ORD_SaveState:\n    case TPM_ORD_SelfTestFull:\n    case TPM_ORD_ContinueSelfTest:\n    case TPM_ORD_GetTestResult:\n    case TPM_ORD_SetOwnerInstall:\n    case TPM_ORD_OwnerSetDisable:\n    case TPM_ORD_PhysicalEnable:\n    case TPM_ORD_PhysicalDisable:\n    case TPM_ORD_PhysicalSetDeactivated:\n    case TPM_ORD_SetTempDeactivated:\n    case TPM_ORD_SetOperatorAuth:\n    case TPM_ORD_TakeOwnership:\n    case TPM_ORD_OwnerClear:\n    case TPM_ORD_ForceClear:\n    case TPM_ORD_DisableOwnerClear:\n    case TPM_ORD_DisableForceClear:\n    case TSC_ORD_PhysicalPresence:\n    case TSC_ORD_ResetEstablishmentBit:\n    case TPM_ORD_GetCapability:\n    case TPM_ORD_SetCapability:\n    case TPM_ORD_GetCapabilityOwner:\n    case TPM_ORD_GetAuditDigest:\n    case TPM_ORD_GetAuditDigestSigned:\n    case TPM_ORD_SetOrdinalAuditStatus:\n    case TPM_ORD_FieldUpgrade:\n    case TPM_ORD_SetRedirection:\n    case TPM_ORD_ResetLockValue:\n    case TPM_ORD_Seal:\n    case TPM_ORD_Unseal:\n    case TPM_ORD_UnBind:\n    case TPM_ORD_CreateWrapKey:\n    case TPM_ORD_LoadKey2:\n    case TPM_ORD_GetPubKey:\n    case TPM_ORD_Sealx:\n    case TPM_ORD_CreateMigrationBlob:\n    case TPM_ORD_ConvertMigrationBlob:\n    case TPM_ORD_AuthorizeMigrationKey:\n    case TPM_ORD_MigrateKey:\n    case TPM_ORD_CMK_SetRestrictions:\n    case TPM_ORD_CMK_ApproveMA:\n    case TPM_ORD_CMK_CreateKey:\n    case TPM_ORD_CMK_CreateTicket:\n    case TPM_ORD_CMK_CreateBlob:\n    case TPM_ORD_CMK_ConvertMigration:\n    case TPM_ORD_CreateMaintenanceArchive:\n    case TPM_ORD_LoadMaintenanceArchive:\n    case TPM_ORD_KillMaintenanceFeature:\n    case TPM_ORD_LoadManuMaintPub:\n    case TPM_ORD_ReadManuMaintPub:\n    case TPM_ORD_SHA1Start:\n    case TPM_ORD_SHA1Update:\n    case TPM_ORD_SHA1Complete:\n    case TPM_ORD_SHA1CompleteExtend:\n    case TPM_ORD_Sign:\n    case TPM_ORD_GetRandom:\n    case TPM_ORD_StirRandom:\n    case TPM_ORD_CertifyKey:\n    case TPM_ORD_CertifyKey2:\n    case TPM_ORD_CreateEndorsementKeyPair:\n    case TPM_ORD_CreateRevocableEK:\n    case TPM_ORD_RevokeTrust:\n    case TPM_ORD_ReadPubek:\n    case TPM_ORD_OwnerReadInternalPub:\n    case TPM_ORD_MakeIdentity:\n    case TPM_ORD_ActivateIdentity:\n    case TPM_ORD_Extend:\n    case TPM_ORD_PCRRead:\n    case TPM_ORD_Quote:\n    case TPM_ORD_PCR_Reset:\n    case TPM_ORD_Quote2:\n    case TPM_ORD_ChangeAuth:\n    case TPM_ORD_ChangeAuthOwner:\n    case TPM_ORD_OIAP:\n    case TPM_ORD_OSAP:\n    case TPM_ORD_DSAP:\n    case TPM_ORD_SetOwnerPointer:\n    case TPM_ORD_Delegate_Manage:\n    case TPM_ORD_Delegate_CreateKeyDelegation:\n    case TPM_ORD_Delegate_CreateOwnerDelegation:\n    case TPM_ORD_Delegate_LoadOwnerDelegation:\n    case TPM_ORD_Delegate_ReadTable:\n    case TPM_ORD_Delegate_UpdateVerification:\n    case TPM_ORD_Delegate_VerifyDelegation:\n    case TPM_ORD_NV_DefineSpace:\n    case TPM_ORD_NV_WriteValue:\n    case TPM_ORD_NV_WriteValueAuth:\n    case TPM_ORD_NV_ReadValue:\n    case TPM_ORD_NV_ReadValueAuth:\n    case TPM_ORD_KeyControlOwner:\n    case TPM_ORD_SaveContext:\n    case TPM_ORD_LoadContext:\n    case TPM_ORD_FlushSpecific:\n    case TPM_ORD_GetTicks:\n    case TPM_ORD_TickStampBlob:\n    case TPM_ORD_EstablishTransport:\n    case TPM_ORD_ExecuteTransport:\n    case TPM_ORD_ReleaseTransportSigned:\n    case TPM_ORD_CreateCounter:\n    case TPM_ORD_IncrementCounter:\n    case TPM_ORD_ReadCounter:\n    case TPM_ORD_ReleaseCounter:\n    case TPM_ORD_ReleaseCounterOwner:\n    case TPM_ORD_DAA_Join:\n    case TPM_ORD_DAA_Sign:\n    /* Deprecated but supported are the following commands */\n    case TPM_ORD_EvictKey:\n    case TPM_ORD_Terminate_Handle:\n    case TPM_ORD_SaveKeyContext:\n    case TPM_ORD_LoadKeyContext:\n    case TPM_ORD_SaveAuthContext:\n    case TPM_ORD_LoadAuthContext:\n    case TPM_ORD_DirWriteAuth:\n    case TPM_ORD_DirRead:\n    case TPM_ORD_ChangeAuthAsymStart:\n    case TPM_ORD_ChangeAuthAsymFinish:\n    case TPM_ORD_Reset:\n    case TPM_ORD_OwnerReadPubek:\n    case TPM_ORD_DisablePubekRead:\n    case TPM_ORD_LoadKey:\n      return return_BOOL(respSize, resp, TRUE);\n    default:\n      return return_BOOL(respSize, resp, FALSE);\n  }\n}\n\nstatic TPM_RESULT cap_alg(UINT32 subCapSize, BYTE *subCap,\n                          UINT32 *respSize, BYTE **resp)\n{\n  TPM_ALGORITHM_ID id;\n  if (tpm_unmarshal_TPM_ALGORITHM_ID(&subCap, &subCapSize, &id))\n    return TPM_BAD_MODE;\n  switch (id) {\n    case TPM_ALG_RSA:\n      return return_BOOL(respSize, resp, TRUE);\n    default:\n      return return_BOOL(respSize, resp, FALSE);\n  }\n}\n\nstatic TPM_RESULT cap_pid(UINT32 subCapSize, BYTE *subCap,\n                          UINT32 *respSize, BYTE **resp)\n{\n  TPM_PROTOCOL_ID id;\n  if (tpm_unmarshal_TPM_PROTOCOL_ID(&subCap, &subCapSize, &id))\n    return TPM_BAD_MODE;\n  switch (id) {\n    case TPM_PID_OIAP:\n    case TPM_PID_OSAP:\n    case TPM_PID_ADIP:\n    case TPM_PID_ADCP:\n    case TPM_PID_OWNER:\n    case TPM_PID_DSAP:\n    case TPM_PID_TRANSPORT:\n      return return_BOOL(respSize, resp, TRUE);\n    default:\n      return return_BOOL(respSize, resp, FALSE);\n  }\n}\n\nstatic TPM_RESULT cap_flag(UINT32 subCapSize, BYTE *subCap,\n                           UINT32 *respSize, BYTE **resp)\n{\n  UINT32 type, len;\n  BYTE *ptr;\n  if (tpm_unmarshal_UINT32(&subCap, &subCapSize, &type)) return TPM_BAD_MODE;\n  switch (type) {\n    case TPM_CAP_FLAG_PERMANENT:\n      debug(\"[TPM_CAP_FLAG_PERMANENT\");\n      *respSize = len = sizeof_TPM_PERMANENT_FLAGS(tpmData.permanent.flags);\n      *resp = ptr = tpm_malloc(len);\n      if (ptr == NULL \n          || tpm_marshal_TPM_PERMANENT_FLAGS(&ptr, &len, &tpmData.permanent.flags)) {\n        tpm_free(*resp);\n        return TPM_FAIL;\n      }\n      return TPM_SUCCESS;\n    case TPM_CAP_FLAG_VOLATILE:\n      debug(\"[TPM_CAP_FLAG_VOLATILE]\");\n      *respSize = len = sizeof_TPM_STCLEAR_FLAGS(tpmData.stclear.flags);\n      *resp = ptr = tpm_malloc(len);\n      if (ptr == NULL\n          || tpm_marshal_TPM_STCLEAR_FLAGS(&ptr, &len, &tpmData.stclear.flags)) {\n        tpm_free(*resp);\n        return TPM_FAIL;\n      }\n      return TPM_SUCCESS;\n    default:\n      return TPM_BAD_MODE;\n  }\n}\n\nstatic TPM_RESULT cap_loaded(UINT32 subCapSize, BYTE *subCap,\n                             UINT32 *respSize, BYTE **resp)\n{\n  int i;\n  BOOL free_space = FALSE;\n  TPM_KEY_PARMS parms;\n  if (tpm_unmarshal_TPM_KEY_PARMS(&subCap, &subCapSize, &parms))\n    return TPM_BAD_MODE;\n  for (i = 0; i < TPM_MAX_KEYS; i++) \n    if (!tpmData.permanent.data.keys[i].payload) free_space = TRUE;\n  if (free_space\n      && parms.algorithmID == TPM_ALG_RSA\n      && parms.parms.rsa.keyLength <= 2048\n      && parms.parms.rsa.numPrimes == 2) \n    return return_BOOL(respSize, resp, TRUE);\n  return return_BOOL(respSize, resp, FALSE);\n}\n\nstatic TPM_RESULT cap_auth_encrypt(UINT32 subCapSize, BYTE *subCap,\n                                   UINT32 *respSize, BYTE **resp)\n{\n  TPM_ALGORITHM_ID id;\n  if (tpm_unmarshal_TPM_ALGORITHM_ID(&subCap, &subCapSize, &id))\n    return TPM_BAD_MODE;\n  switch (id) {\n    case TPM_ALG_XOR:\n      return return_BOOL(respSize, resp, TRUE);\n    default:\n      return return_BOOL(respSize, resp, FALSE);\n  }\n}\n\nstatic TPM_RESULT cap_sym_mode(UINT32 subCapSize, BYTE *subCap,\n                               UINT32 *respSize, BYTE **resp)\n{\n  TPM_SYM_MODE mode;\n  if (tpm_unmarshal_TPM_SYM_MODE(&subCap, &subCapSize, &mode))\n    return TPM_BAD_MODE;\n  switch (mode) {\n    case TPM_ES_SYM_CTR:\n    case TPM_ES_SYM_OFB:\n    default:\n      return return_BOOL(respSize, resp, FALSE);\n  }\n}\n\nstatic TPM_RESULT cap_key_status(UINT32 subCapSize, BYTE *subCap,\n                                 UINT32 *respSize, BYTE **resp)\n{\n  TPM_KEY_HANDLE handle;\n  TPM_KEY_DATA *key;\n  if (tpm_unmarshal_TPM_KEY_HANDLE(&subCap, &subCapSize, &handle))\n    return TPM_BAD_MODE;\n  key = tpm_get_key(handle);\n  if (key == NULL) return TPM_INVALID_KEYHANDLE;\n  return return_BOOL(respSize, resp,\n                     key->keyControl & TPM_KEY_CONTROL_OWNER_EVICT);\n}\n\nstatic TPM_RESULT cap_trans_alg(UINT32 subCapSize, BYTE *subCap,\n                                UINT32 *respSize, BYTE **resp)\n{\n  TPM_ALGORITHM_ID id;\n  if (tpm_unmarshal_TPM_ALGORITHM_ID(&subCap, &subCapSize, &id))\n    return TPM_BAD_MODE;\n  switch (id) {\n    case TPM_ALG_RSA:\n      return return_BOOL(respSize, resp, TRUE);\n    default:\n      return return_BOOL(respSize, resp, FALSE);\n  }\n}\n\nstatic TPM_RESULT cap_trans_es(UINT32 subCapSize, BYTE *subCap,\n                               UINT32 *respSize, BYTE **resp)\n{\n  TPM_ENC_SCHEME es;\n  if (tpm_unmarshal_TPM_ENC_SCHEME(&subCap, &subCapSize, &es))\n    return TPM_BAD_MODE;\n  switch (es) {\n    case TPM_ES_RSAESOAEP_SHA1_MGF1:\n    case TPM_ES_RSAESPKCSv15:\n      return return_BOOL(respSize, resp, TRUE);\n    default:\n      return return_BOOL(respSize, resp, FALSE);\n  }\n}\n\nstatic TPM_RESULT cap_select_size(UINT32 subCapSize, BYTE *subCap,\n                                  UINT32 *respSize, BYTE **resp)\n{\n  TPM_SELECT_SIZE size;\n  if (tpm_unmarshal_TPM_SELECT_SIZE(&subCap, &subCapSize, &size))\n    return TPM_BAD_MODE;\n  return return_BOOL(respSize, resp, (size.reqSize <= TPM_NUM_PCR/8));\n}\n\nstatic TPM_RESULT cap_version_val(UINT32 *respSize, BYTE **resp)\n{\n  UINT32 len;\n  BYTE *ptr;\n  TPM_CAP_VERSION_INFO version;\n  \n  version.tag = TPM_TAG_CAP_VERSION_INFO;\n  version.version = tpmData.permanent.data.version;\n  version.specLevel = 0x0002; /* see [TPM_Part2], Section 21.6 */\n  version.errataRev = 0x01;   /* 0x01 = rev 94, 0x02 = rev 103 */\n  len = 4, ptr = version.tpmVendorID;\n  if (tpm_marshal_UINT32(&ptr, &len, TPM_MANUFACTURER))\n    return TPM_FAIL;\n  version.vendorSpecificSize = 0;\n  version.vendorSpecific = NULL;\n  \n  len = *respSize = sizeof_TPM_CAP_VERSION_INFO(version);\n  ptr = *resp = tpm_malloc(*respSize);\n  if (ptr == NULL || tpm_marshal_TPM_CAP_VERSION_INFO(&ptr, &len, &version)) {\n    tpm_free(*resp);\n    return TPM_FAIL;\n  }\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_GetCapability(TPM_CAPABILITY_AREA capArea, UINT32 subCapSize, \n                             BYTE *subCap, UINT32 *respSize, BYTE **resp)\n{\n  info(\"TPM_GetCapability()\");\n  switch (capArea) {\n\n    case TPM_CAP_ORD:\n      debug(\"[TPM_CAP_ORD]\");\n      return cap_ord(subCapSize, subCap, respSize, resp);\n\n    case TPM_CAP_ALG:\n      debug(\"[TPM_CAP_ALG]\");\n      return cap_alg(subCapSize, subCap, respSize, resp);\n\n    case TPM_CAP_PID:\n      debug(\"[TPM_CAP_PID]\");\n      return cap_pid(subCapSize, subCap, respSize, resp);\n\n    case TPM_CAP_FLAG:\n      debug(\"[TPM_CAP_FLAG]\");\n      return cap_flag(subCapSize, subCap, respSize, resp);\n\n    case TPM_CAP_PROPERTY:\n      debug(\"[TPM_CAP_PROPERTY]\");\n      return cap_property(subCapSize, subCap, respSize, resp);\n\n    case TPM_CAP_VERSION:\n      debug(\"[TPM_CAP_VERSION]\");\n      return cap_version(respSize, resp);\n\n    case TPM_CAP_KEY_HANDLE:\n      debug(\"[TPM_CAP_KEY_HANDLE]\");\n      BYTE buf[4];\n      buf[0] = (TPM_RT_KEY >> 24) & 0xff;\n      buf[1] = (TPM_RT_KEY >> 16) & 0xff;\n      buf[2] = (TPM_RT_KEY >>  8) & 0xff;\n      buf[3] = TPM_RT_KEY & 0xff;\n      return cap_handle(4, buf, respSize, resp);\n\n    case TPM_CAP_CHECK_LOADED:\n      debug(\"[TPM_CAP_CHECK_LOADED]\");\n      return cap_loaded(subCapSize, subCap, respSize, resp);\n\n    case TPM_CAP_SYM_MODE:\n      debug(\"[TPM_CAP_SYM_MODE]\");\n      return cap_sym_mode(subCapSize, subCap, respSize, resp);\n\n    case TPM_CAP_KEY_STATUS:\n      debug(\"[TPM_CAP_KEY_STATUS]\");\n      return cap_key_status(subCapSize, subCap, respSize, resp);\n\n    case TPM_CAP_NV_LIST:\n      debug(\"[TPM_CAP_NV_LIST]\");\n      return cap_nv_list(respSize, resp);\n\n    case TPM_CAP_MFR:\n      debug(\"[TPM_CAP_MFR]\");\n      return cap_mfr(subCapSize, subCap, respSize, resp);\n\n    case TPM_CAP_NV_INDEX:\n      debug(\"[TPM_CAP_NV_INDEX]\");\n      return cap_nv_index(subCapSize, subCap, respSize, resp);\n\n    case TPM_CAP_TRANS_ALG:\n      debug(\"[TPM_CAP_TRANS_ALG]\");\n      return cap_trans_alg(subCapSize, subCap, respSize, resp);\n\n    case TPM_CAP_HANDLE:\n      debug(\"[TPM_CAP_HANDLE]\");\n      return cap_handle(subCapSize, subCap, respSize, resp);\n\n    case TPM_CAP_TRANS_ES:\n      debug(\"[TPM_CAP_TRANS_ES]\");\n      return cap_trans_es(subCapSize, subCap, respSize, resp);\n\n    case TPM_CAP_AUTH_ENCRYPT:\n      debug(\"[TPM_CAP_AUTH_ENCRYPT]\");\n      return cap_auth_encrypt(subCapSize, subCap, respSize, resp);\n\n    case TPM_CAP_SELECT_SIZE:\n      debug(\"[TPM_CAP_SELECT_SIZE]\");\n      return cap_select_size(subCapSize, subCap, respSize, resp);\n\n    case TPM_CAP_VERSION_VAL:\n      debug(\"[TPM_CAP_VERSION_VAL]\");\n      return cap_version_val(respSize, resp);\n\n    default:\n      return TPM_BAD_MODE;\n  }\n}\n\nstatic TPM_RESULT set_perm_flags(UINT32 subCap, BOOL flag, BOOL ownerAuth,\n                                 BOOL  deactivated, BOOL disabled)\n{\n  switch (subCap) {\n    case 1:\n      if (!ownerAuth && !tpm_get_physical_presence()) return TPM_AUTHFAIL;\n      tpmData.permanent.flags.disable = flag;\n      return TPM_SUCCESS;\n\n    case 2:\n      if (!tpm_get_physical_presence()) return TPM_AUTHFAIL;\n      if (tpmData.permanent.flags.owned) return TPM_OWNER_SET;\n      if (deactivated) return TPM_DEACTIVATED;\n      if (disabled) return TPM_DISABLED;\n      tpmData.permanent.flags.ownership = flag;\n      return TPM_SUCCESS;\n\n    case 3:\n      if (!tpm_get_physical_presence()) return TPM_AUTHFAIL;\n      if (disabled) return TPM_DISABLED;\n      tpmData.permanent.flags.deactivated = flag;\n      return TPM_SUCCESS;\n\n    case 4:\n      if (!ownerAuth) return TPM_AUTHFAIL;\n      if (deactivated) return TPM_DEACTIVATED;\n      if (disabled) return TPM_DISABLED;\n      tpmData.permanent.flags.readPubek = flag;\n      return TPM_SUCCESS;\n\n    case 5:\n      if (!ownerAuth) return TPM_AUTHFAIL;\n      if (deactivated) return TPM_DEACTIVATED;\n      if (disabled) return TPM_DISABLED;\n      if (flag == FALSE) return TPM_BAD_PARAMETER;\n      tpmData.permanent.flags.disableOwnerClear = TRUE;\n      return TPM_SUCCESS;\n\n    case 6:\n      if (!ownerAuth) return TPM_AUTHFAIL;\n      if (deactivated) return TPM_DEACTIVATED;\n      if (disabled) return TPM_DISABLED;\n      if (flag == TRUE) return TPM_BAD_PARAMETER;\n      tpmData.permanent.flags.allowMaintenance = FALSE;\n      return TPM_SUCCESS;\n\n    case 17:\n      if (!ownerAuth) return TPM_AUTHFAIL;\n      if (deactivated) return TPM_DEACTIVATED;\n      if (disabled) return TPM_DISABLED;\n      tpmData.permanent.flags.readSRKPub = flag;\n      return TPM_SUCCESS;\n\n    case 18:\n      if (tpmData.stany.flags.localityModifier\n          & (TPM_LOC_THREE | TPM_LOC_FOUR)) return TPM_BAD_LOCALITY;\n      if (flag == TRUE)  return TPM_BAD_PARAMETER;\n      tpmData.permanent.flags.tpmEstablished = FALSE;\n      return TPM_SUCCESS;\n\n    case 20:\n      if (!ownerAuth) return TPM_AUTHFAIL;\n      tpmData.permanent.flags.disableFullDALogicInfo = flag;\n      return TPM_SUCCESS;\n  }\n  return TPM_BAD_PARAMETER;\n}\n\nstatic TPM_RESULT set_stclear_flags(UINT32 subCap, BOOL flag, BOOL ownerAuth,\n                                    BOOL  deactivated, BOOL disabled)\n{\n  switch (subCap) {\n    case 2:\n      if (deactivated) return TPM_DEACTIVATED;\n      if (disabled) return TPM_DISABLED;\n      if (flag == FALSE)  return TPM_BAD_PARAMETER;\n      tpmData.stclear.flags.disableForceClear = TRUE;\n      return TPM_SUCCESS;\n  }\n  return TPM_BAD_PARAMETER;\n}\n\nstatic TPM_RESULT set_stany_flags(UINT32 subCap, BOOL flag, BOOL ownerAuth,\n                                  BOOL deactivated, BOOL disabled)\n{\n    switch (subCap) {\n      case 2:\n        if (tpmData.stany.flags.localityModifier\n            & (TPM_LOC_THREE | TPM_LOC_FOUR)) return TPM_BAD_LOCALITY;\n        if (deactivated) return TPM_DEACTIVATED;\n        if (disabled) return TPM_DISABLED;\n        if (flag == TRUE)  return TPM_BAD_PARAMETER;\n        tpmData.stany.flags.TOSPresent = FALSE;\n        return TPM_SUCCESS;\n    }\n    return TPM_BAD_PARAMETER;\n}\n\nstatic TPM_RESULT set_perm_data(UINT32 subCap, BYTE *setValue,\n                                UINT32 setValueSize, BOOL ownerAuth,\n                                BOOL deactivated, BOOL disabled)\n{\n  TPM_CMK_DELEGATE del;\n  TPM_NONCE nonce;\n  switch (subCap) {\n\n    case 16:\n      if (tpmConf & TPM_CONF_ALLOW_PRNG_STATE_SETTING) {\n        if (setValueSize != sizeof(tpmData.permanent.data.rngState))\n          return TPM_BAD_PARAMETER;\n        memcpy(&tpmData.permanent.data.rngState, setValue, setValueSize);\n        return TPM_SUCCESS;\n      } else {\n        return TPM_BAD_PARAMETER;\n      }\n\n    case 23:\n      if (!ownerAuth) return TPM_AUTHFAIL;\n      if (deactivated) return TPM_DEACTIVATED;\n      if (disabled) return TPM_DISABLED;\n      if  (tpm_unmarshal_TPM_CMK_DELEGATE(&setValue, &setValueSize, &del) != 0)\n        return TPM_BAD_PARAMETER;\n      tpmData.permanent.data.restrictDelegate = del;\n      return TPM_SUCCESS;\n\n    case 25:\n      if (!ownerAuth) return TPM_AUTHFAIL;\n      if  (tpm_unmarshal_TPM_NONCE(&setValue, &setValueSize, &nonce) != 0)\n        return TPM_BAD_PARAMETER;\n      memcpy(&tpmData.permanent.data.daaProof, &nonce, sizeof(TPM_NONCE));\n      return TPM_SUCCESS;\n\n  }\n  return TPM_BAD_PARAMETER;\n}\n\nstatic TPM_RESULT set_stclear_data(UINT32 subCap, BYTE *setValue,\n                                   UINT32 setValueSize, BOOL ownerAuth,\n                                   BOOL deactivated, BOOL disabled)\n{\n  UINT32 presence;\n  switch (subCap) {\n    case 23:\n      if  (tpm_unmarshal_UINT32(&setValue, &setValueSize, &presence) != 0)\n        return TPM_BAD_PARAMETER;\n      /* without physical presence we are only allowed to disable bits */\n      if (((tpmData.stclear.data.deferredPhysicalPresence | presence)\n           != tpmData.stclear.data.deferredPhysicalPresence)\n          && !tpm_get_physical_presence()) return TPM_BAD_PARAMETER;\n      tpmData.stclear.data.deferredPhysicalPresence = presence;\n      return TPM_SUCCESS;\n  }\n  return TPM_BAD_PARAMETER;\n}\n\nstatic TPM_RESULT set_stany_data(UINT32 subCap, BYTE *setValue,\n                                 UINT32 setValueSize, BOOL ownerAuth,\n                                 BOOL deactivated, BOOL disabled)\n{\n  return TPM_BAD_PARAMETER;\n}\n\nstatic TPM_RESULT set_vendor(UINT32 subCap, BYTE *setValue,\n                             UINT32 setValueSize, BOOL ownerAuth,\n                             BOOL deactivated, BOOL disabled)\n{\n  /* set the capability area with the specified data, on failure\n     deactivate the TPM */\n  switch (subCap) {\n    case TPM_SET_PERM_FLAGS:\n      debug(\"[TPM_SET_PERM_FLAGS]\");\n      if (tpm_unmarshal_TPM_PERMANENT_FLAGS(&setValue, &setValueSize,\n          &tpmData.permanent.flags) != 0) {\n        tpmData.stclear.flags.deactivated = TRUE;\n        return TPM_BAD_PARAMETER;\n      }\n      return TPM_SUCCESS;\n\n    case TPM_SET_STCLEAR_FLAGS:\n      debug(\"[TPM_SET_STCLEAR_FLAGS]\");\n      if (tpm_unmarshal_TPM_STCLEAR_FLAGS(&setValue, &setValueSize,\n          &tpmData.stclear.flags) != 0) {\n        tpmData.stclear.flags.deactivated = TRUE;\n        return TPM_BAD_PARAMETER;\n      }\n      return TPM_SUCCESS;\n\n    case TPM_SET_STANY_FLAGS:\n      debug(\"[TPM_SET_STANY_FLAGS]\");\n      if (tpm_unmarshal_TPM_STANY_FLAGS(&setValue, &setValueSize,\n          &tpmData.stany.flags) != 0) {\n        tpmData.stclear.flags.deactivated = TRUE;\n        return TPM_BAD_PARAMETER;\n      }\n      return TPM_SUCCESS;\n\n    case TPM_SET_PERM_DATA:\n      debug(\"[TPM_SET_PERM_DATA]\");\n      if (tpm_unmarshal_TPM_PERMANENT_DATA(&setValue, &setValueSize,\n          &tpmData.permanent.data) != 0) {\n        tpmData.stclear.flags.deactivated = TRUE;\n        return TPM_BAD_PARAMETER;\n      }\n      return TPM_SUCCESS;\n\n    case TPM_SET_STCLEAR_DATA:\n      debug(\"[TPM_SET_STCLEAR_DATA]\");\n      if (tpm_unmarshal_TPM_STCLEAR_DATA(&setValue, &setValueSize,\n          &tpmData.stclear.data) != 0) {\n        tpmData.stclear.flags.deactivated = TRUE;\n        return TPM_BAD_PARAMETER;\n      }\n      return TPM_SUCCESS;\n\n    case TPM_SET_STANY_DATA:\n      debug(\"[TPM_SET_STANY_DATA]\");\n      if (tpm_unmarshal_TPM_STANY_DATA(&setValue, &setValueSize,\n          &tpmData.stany.data) != 0) {\n        tpmData.stclear.flags.deactivated = TRUE;\n        return TPM_BAD_PARAMETER;\n      }\n      return TPM_SUCCESS;\n  }\n  return TPM_BAD_PARAMETER;\n}\n\nTPM_RESULT TPM_SetCapability(TPM_CAPABILITY_AREA capArea, UINT32 subCapSize, \n                             BYTE *subCap, UINT32 setValueSize, BYTE *setValue,\n                             TPM_AUTH *auth1)\n{\n  TPM_RESULT res;\n  BOOL ownerAuth = FALSE;\n  UINT32 subCapVal;\n  BOOL deactivated = tpmData.permanent.flags.deactivated\n                     || tpmData.stclear.flags.deactivated;\n  BOOL disabled = tpmData.permanent.flags.disable;\n\n  info(\"TPM_SetCapability()\");\n  /* verify owner authorization if TPM_TAG_RQU_AUTH1_COMMAND */\n  if (auth1->authHandle != TPM_INVALID_HANDLE) {\n    res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);\n    if (res != TPM_SUCCESS) return res;\n    ownerAuth = TRUE;\n  }\n  /* unmarshal subCap */\n  if (tpm_unmarshal_UINT32(&subCap, &subCapSize, &subCapVal) != 0)\n    return TPM_BAD_PARAMETER;\n  /* set capability area */\n  switch (capArea) {\n    case TPM_SET_PERM_FLAGS:\n      debug(\"[TPM_SET_PERM_FLAGS]:%d\", subCapVal);\n      if (setValueSize != 1 || setValue[0] & 0xfe) return TPM_BAD_PARAMETER;\n      return set_perm_flags(subCapVal, setValue[0], ownerAuth,\n                            deactivated, disabled);\n    case TPM_SET_STCLEAR_FLAGS:\n      debug(\"[TPM_SET_STCLEAR_FLAGS]:%d\", subCapVal);\n      if (setValueSize != 1 || setValue[0] & 0xfe) return TPM_BAD_PARAMETER;\n      return set_stclear_flags(subCapVal, setValue[0], ownerAuth,\n                               deactivated, disabled);\n    case TPM_SET_STANY_FLAGS:\n      debug(\"[TPM_SET_STANY_FLAGS]:%d\", subCapVal);\n      if (setValueSize != 1 || setValue[0] & 0xfe) return TPM_BAD_PARAMETER;\n      return set_stany_flags(subCapVal, setValue[0], ownerAuth,\n                             deactivated, disabled);\n    case TPM_SET_PERM_DATA:\n      debug(\"[TPM_SET_PERM_DATA]:%d\", subCapVal);\n      return set_perm_data(subCapVal, setValue, setValueSize, ownerAuth,\n                           deactivated, disabled);\n    case TPM_SET_STCLEAR_DATA:\n      debug(\"[TPM_SET_STCLEAR_DATA]:%d\", subCapVal);\n      return set_stclear_data(subCapVal, setValue, setValueSize, ownerAuth,\n                              deactivated, disabled);\n    case TPM_SET_STANY_DATA:\n      debug(\"[TPM_SET_STANY_DATA]:%d\", subCapVal);\n      return set_stany_data(subCapVal, setValue, setValueSize, ownerAuth,\n                            deactivated, disabled);\n    case TPM_SET_VENDOR:\n      debug(\"[TPM_SET_VENDOR]:%d\", subCapVal);\n      return set_vendor(subCapVal, setValue, setValueSize, ownerAuth,\n                        deactivated, disabled);\n  }\n  return TPM_BAD_PARAMETER;\n}\n\nTPM_RESULT TPM_GetCapabilityOwner(TPM_AUTH *auth1, TPM_VERSION *version,\n                                  UINT32 *non_volatile_flags, \n                                  UINT32 *volatile_flags)\n{\n  TPM_RESULT res;\n  \n  info(\"TPM_GetCapabilityOwner()\");\n  /* verify owner authorization */\n  res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);\n  if (res != TPM_SUCCESS) return res;\n  /* initialize */\n  *version = tpmData.permanent.data.version;\n  *non_volatile_flags = *volatile_flags = 0;\n  \n  /* set non-volatile flags */\n  if (tpmData.permanent.flags.disable)\n    *non_volatile_flags |= (1 <<  0);\n  if (tpmData.permanent.flags.ownership)\n    *non_volatile_flags |= (1 <<  1);\n  if (tpmData.permanent.flags.deactivated)\n    *non_volatile_flags |= (1 <<  2);\n  if (tpmData.permanent.flags.readPubek)\n    *non_volatile_flags |= (1 <<  3);\n  if (tpmData.permanent.flags.disableOwnerClear)\n    *non_volatile_flags |= (1 <<  4);\n  if (tpmData.permanent.flags.allowMaintenance)\n    *non_volatile_flags |= (1 <<  5);\n  if (tpmData.permanent.flags.physicalPresenceLifetimeLock)\n    *non_volatile_flags |= (1 <<  6);\n  if (tpmData.permanent.flags.physicalPresenceHWEnable)\n    *non_volatile_flags |= (1 <<  7);\n  if (tpmData.permanent.flags.physicalPresenceCMDEnable)\n    *non_volatile_flags |= (1 <<  8);\n  if (tpmData.permanent.flags.CEKPUsed)\n    *non_volatile_flags |= (1 <<  9);\n  if (tpmData.permanent.flags.TPMpost)\n    *non_volatile_flags |= (1 << 10);\n  if (tpmData.permanent.flags.TPMpostLock)\n    *non_volatile_flags |= (1 << 11);\n  if (tpmData.permanent.flags.FIPS)\n    *non_volatile_flags |= (1 << 12);\n  if (tpmData.permanent.flags.operator)\n    *non_volatile_flags |= (1 << 13);\n  if (tpmData.permanent.flags.enableRevokeEK)\n    *non_volatile_flags |= (1 << 14);\n  if (tpmData.permanent.flags.nvLocked)\n    *non_volatile_flags |= (1 << 15);\n  if (tpmData.permanent.flags.readSRKPub)\n    *non_volatile_flags |= (1 << 16);\n  if (tpmData.permanent.flags.tpmEstablished)\n    *non_volatile_flags |= (1 << 17);\n  if (tpmData.permanent.flags.maintenanceDone)\n    *non_volatile_flags |= (1 << 18);\n  if (tpmData.permanent.flags.disableFullDALogicInfo)\n    *non_volatile_flags |= (1 << 19);\n  \n  /* set volatile flags */\n  if (tpmData.stclear.flags.deactivated)\n    *volatile_flags |= (1 <<  0);\n  if (tpmData.stclear.flags.disableForceClear)\n    *volatile_flags |= (1 <<  1);\n  if (tpmData.stclear.flags.physicalPresence)\n    *volatile_flags |= (1 <<  2);\n  if (tpmData.stclear.flags.physicalPresenceLock)\n    *volatile_flags |= (1 <<  3);\n  if (tpmData.stclear.flags.bGlobalLock)\n    *volatile_flags |= (1 <<  4);\n  \n  return TPM_SUCCESS;\n}\n"
  },
  {
    "path": "tpm/tpm_cmd_handler.c",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: tpm_cmd_handler.c 467 2011-07-19 17:36:12Z mast $\n */\n\n#include \"tpm_marshalling.h\"\n#include \"tpm_commands.h\"\n#include \"crypto/sha1.h\"\n#include \"crypto/hmac.h\"\n#include \"tpm_data.h\"\n#include \"tpm_handles.h\"\n\n#ifdef MTM_EMULATOR\n#include \"mtm/mtm_commands.h\"\n#endif\n\nUINT32 tpm_get_in_param_offset(TPM_COMMAND_CODE ordinal)\n{\n  switch (ordinal) {\n    case TPM_ORD_ActivateIdentity:\n    case TPM_ORD_ChangeAuth:\n    case TPM_ORD_ChangeAuthAsymStart:\n    case TPM_ORD_CMK_ConvertMigration:\n    case TPM_ORD_CMK_CreateBlob:\n    case TPM_ORD_CMK_CreateKey:\n    case TPM_ORD_ConvertMigrationBlob:\n    case TPM_ORD_CreateMigrationBlob:\n    case TPM_ORD_CreateWrapKey:\n    case TPM_ORD_Delegate_CreateKeyDelegation:\n    case TPM_ORD_DSAP:\n    case TPM_ORD_EstablishTransport:\n    case TPM_ORD_EvictKey:\n    case TPM_ORD_FlushSpecific:\n    case TPM_ORD_GetAuditDigestSigned:\n    case TPM_ORD_GetPubKey:\n    case TPM_ORD_KeyControlOwner:\n    case TPM_ORD_LoadKey:\n    case TPM_ORD_LoadKey2:\n    case TPM_ORD_MigrateKey:\n    case TPM_ORD_Quote:\n    case TPM_ORD_Quote2:\n    case TPM_ORD_ReleaseTransportSigned:\n    case TPM_ORD_SaveKeyContext:\n    case TPM_ORD_Seal:\n    case TPM_ORD_Sealx:\n    case TPM_ORD_SetRedirection:\n    case TPM_ORD_Sign:\n    case TPM_ORD_TickStampBlob:\n    case TPM_ORD_UnBind:\n    case TPM_ORD_Unseal:\n    case TPM_ORD_DAA_Join:\n    case TPM_ORD_DAA_Sign:\n      return 4;\n\n    case TPM_ORD_CertifyKey:\n    case TPM_ORD_CertifyKey2:\n    case TPM_ORD_ChangeAuthAsymFinish:\n      return 8;\n\n    case TPM_ORD_OSAP:\n      return 26;\n\n    default:\n      return 0;\n  }\n}\n\nUINT32 tpm_get_out_param_offset(TPM_COMMAND_CODE ordinal)\n{\n  switch (ordinal) {\n\n    case TPM_ORD_EstablishTransport:\n    case TPM_ORD_LoadKey2:\n      return 4;\n\n    case TPM_ORD_OIAP:\n      return 24;\n\n    case TPM_ORD_OSAP:\n      return 44;\n\n    default:\n      return 0;\n  }\n}\n  \nvoid tpm_compute_in_param_digest(TPM_REQUEST *req)\n{\n  tpm_sha1_ctx_t sha1;\n  UINT32 offset = tpm_get_in_param_offset(req->ordinal);\n\n  /* compute SHA1 hash */\n  if (offset <= req->paramSize) {\n    tpm_sha1_init(&sha1);\n    tpm_sha1_update_be32(&sha1, req->ordinal);\n    /* skip all handles at the beginning */\n    tpm_sha1_update(&sha1, req->param + offset, req->paramSize - offset);\n    tpm_sha1_final(&sha1, req->auth1.digest);\n    memcpy(req->auth2.digest, req->auth1.digest, sizeof(req->auth1.digest));\n  }\n}\n\nvoid tpm_compute_out_param_digest(TPM_COMMAND_CODE ordinal, TPM_RESPONSE *rsp)\n{\n  tpm_sha1_ctx_t sha1;\n  UINT32 offset = tpm_get_out_param_offset(ordinal);\n\n  /* compute SHA1 hash */\n  tpm_sha1_init(&sha1);\n  tpm_sha1_update_be32(&sha1, rsp->result);\n  tpm_sha1_update_be32(&sha1, ordinal);\n  tpm_sha1_update(&sha1, rsp->param + offset, rsp->paramSize - offset);\n  tpm_sha1_final(&sha1, rsp->auth1->digest);\n  if (rsp->auth2 != NULL) memcpy(rsp->auth2->digest, \n    rsp->auth1->digest, sizeof(rsp->auth1->digest));\n}\n\nstatic TPM_RESULT execute_TPM_Startup(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_STARTUP_TYPE startupType;\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_STARTUP_TYPE(&ptr, &len, &startupType)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  return TPM_Startup(startupType);\n}\n\nstatic TPM_RESULT execute_TPM_SaveState(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  /* execute command */\n  return TPM_SaveState();\n}\n\nstatic TPM_RESULT execute_TPM_SelfTestFull(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  /* execute command */\n  return TPM_SelfTestFull();\n}\n\nstatic TPM_RESULT execute_TPM_ContinueSelfTest(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  /* execute command */\n  return TPM_ContinueSelfTest();\n}\n\nstatic TPM_RESULT execute_TPM_GetTestResult(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  UINT32 outDataSize;\n  BYTE *outData = NULL;\n  TPM_RESULT res;\n  /* execute command */\n  res = TPM_GetTestResult(&outDataSize, &outData);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 4 + outDataSize;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_UINT32(&ptr, &len, outDataSize)\n      || tpm_marshal_BLOB(&ptr, &len, outData, outDataSize)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  tpm_free(outData);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_SetOwnerInstall(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  BOOL state;\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_BOOL(&ptr, &len, &state)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  return TPM_SetOwnerInstall(state);\n}\n\nstatic TPM_RESULT execute_TPM_OwnerSetDisable(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  BOOL disableState;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_BOOL(&ptr, &len, &disableState)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  return TPM_OwnerSetDisable(disableState, &req->auth1);\n}\n\nstatic TPM_RESULT execute_TPM_PhysicalEnable(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  /* execute command */\n  return TPM_PhysicalEnable();\n}\n\nstatic TPM_RESULT execute_TPM_PhysicalDisable(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  /* execute command */\n  return TPM_PhysicalDisable();\n}\n\nstatic TPM_RESULT execute_TPM_PhysicalSetDeactivated(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  BOOL state;\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_BOOL(&ptr, &len, &state)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  return TPM_PhysicalSetDeactivated(state);\n}\n\nstatic TPM_RESULT execute_TPM_SetTempDeactivated(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* execute command */\n  return TPM_SetTempDeactivated(&req->auth1);\n}\n\nstatic TPM_RESULT execute_TPM_SetOperatorAuth(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_SECRET operatorAuth;\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_SECRET(&ptr, &len, &operatorAuth)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  return TPM_SetOperatorAuth(&operatorAuth);\n}\n\nstatic TPM_RESULT execute_TPM_TakeOwnership(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_PROTOCOL_ID protocolID;\n  UINT32 encOwnerAuthSize;\n  BYTE *encOwnerAuth;\n  UINT32 encSrkAuthSize;\n  BYTE *encSrkAuth;\n  TPM_KEY srkParams;\n  TPM_KEY srkPub;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_PROTOCOL_ID(&ptr, &len, &protocolID)\n      || tpm_unmarshal_UINT32(&ptr, &len, &encOwnerAuthSize)\n      || tpm_unmarshal_BLOB(&ptr, &len, &encOwnerAuth, encOwnerAuthSize)\n      || tpm_unmarshal_UINT32(&ptr, &len, &encSrkAuthSize)\n      || tpm_unmarshal_BLOB(&ptr, &len, &encSrkAuth, encSrkAuthSize)\n      || tpm_unmarshal_TPM_KEY(&ptr, &len, &srkParams)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_TakeOwnership(protocolID, encOwnerAuthSize, encOwnerAuth, \n    encSrkAuthSize, encSrkAuth, &srkParams, &req->auth1, &srkPub);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = sizeof_TPM_KEY(srkPub);\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_KEY(&ptr, &len, &srkPub)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  free_TPM_KEY(srkPub);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_OwnerClear(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* execute command */\n  return TPM_OwnerClear(&req->auth1);\n}\n\nstatic TPM_RESULT execute_TPM_ForceClear(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  /* execute command */\n  return TPM_ForceClear();\n}\n\nstatic TPM_RESULT execute_TPM_DisableOwnerClear(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* execute command */\n  return TPM_DisableOwnerClear(&req->auth1);\n}\n\nstatic TPM_RESULT execute_TPM_DisableForceClear(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  /* execute command */\n  return TPM_DisableForceClear();\n}\n\nstatic TPM_RESULT execute_TSC_PhysicalPresence(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_PHYSICAL_PRESENCE physicalPresence;\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_PHYSICAL_PRESENCE(&ptr, &len, &physicalPresence)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  return TSC_PhysicalPresence(physicalPresence);\n}\n\nstatic TPM_RESULT execute_TSC_ResetEstablishmentBit(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  /* execute command */\n  return TSC_ResetEstablishmentBit();\n}\n\nstatic TPM_RESULT execute_TPM_GetCapability(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_CAPABILITY_AREA capArea;\n  UINT32 subCapSize;\n  BYTE *subCap;\n  UINT32 respSize;\n  BYTE *resp = NULL;\n  TPM_RESULT res;\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_CAPABILITY_AREA(&ptr, &len, &capArea)\n      || tpm_unmarshal_UINT32(&ptr, &len, &subCapSize)\n      || tpm_unmarshal_BLOB(&ptr, &len, &subCap, subCapSize)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n#ifdef MTM_EMULATOR\n  res = MTM_GetCapability(capArea, subCapSize, subCap, &respSize, &resp);\n#else\n  res = TPM_GetCapability(capArea, subCapSize, subCap, &respSize, &resp);\n#endif\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 4 + respSize;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_UINT32(&ptr, &len, respSize)\n      || tpm_marshal_BLOB(&ptr, &len, resp, respSize)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  tpm_free(resp);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_SetCapability(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_CAPABILITY_AREA capArea;\n  UINT32 subCapSize, setValueSize;\n  BYTE *subCap, *setValue;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_CAPABILITY_AREA(&ptr, &len, &capArea)\n      || tpm_unmarshal_UINT32(&ptr, &len, &subCapSize)\n      || tpm_unmarshal_BLOB(&ptr, &len, &subCap, subCapSize)\n      || tpm_unmarshal_UINT32(&ptr, &len, &setValueSize)\n      || tpm_unmarshal_BLOB(&ptr, &len, &setValue, setValueSize)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  return TPM_SetCapability(capArea, subCapSize, subCap, setValueSize, setValue, &req->auth1);\n}\n\nstatic TPM_RESULT execute_TPM_GetCapabilityOwner(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  UINT32 non_volatile_flags, volatile_flags;\n  TPM_VERSION version;\n  BYTE *resp = NULL;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* execute command */\n  res = TPM_GetCapabilityOwner(&req->auth1, &version, &non_volatile_flags, &volatile_flags);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 12;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_VERSION(&ptr, &len, &version)\n      || tpm_marshal_UINT32(&ptr, &len, non_volatile_flags)\n      || tpm_marshal_UINT32(&ptr, &len, volatile_flags)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  tpm_free(resp);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_GetAuditDigest(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  UINT32 startOrdinal;\n  TPM_COUNTER_VALUE counterValue;\n  TPM_DIGEST auditDigest;\n  BOOL more;\n  UINT32 ordSize;\n  UINT32 *ordList = NULL;\n  TPM_RESULT res;\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_UINT32(&ptr, &len, &startOrdinal)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_GetAuditDigest(startOrdinal, &counterValue, &auditDigest, &more, &ordSize, &ordList);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 10 + 20 + 1 + 4 + ordSize;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_COUNTER_VALUE(&ptr, &len, &counterValue)\n      || tpm_marshal_TPM_DIGEST(&ptr, &len, &auditDigest)\n      || tpm_marshal_BOOL(&ptr, &len, more)\n      || tpm_marshal_UINT32(&ptr, &len, ordSize)\n      || tpm_marshal_UINT32_ARRAY(&ptr, &len, ordList, ordSize/4)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  tpm_free(ordList);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_GetAuditDigestSigned(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_KEY_HANDLE keyHandle;\n  BOOL closeAudit;\n  TPM_NONCE antiReplay;\n  TPM_COUNTER_VALUE counterValue;\n  TPM_DIGEST auditDigest;\n  TPM_DIGEST ordinalDigest;\n  UINT32 sigSize;\n  BYTE *sig = NULL;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_KEY_HANDLE(&ptr, &len, &keyHandle)\n      || tpm_unmarshal_BOOL(&ptr, &len, &closeAudit)\n      || tpm_unmarshal_TPM_NONCE(&ptr, &len, &antiReplay)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_GetAuditDigestSigned(keyHandle, closeAudit, &antiReplay, &req->auth1,\n    &counterValue, &auditDigest, &ordinalDigest, &sigSize, &sig);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 10 + 20 + 20 + 4 + sigSize;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_COUNTER_VALUE(&ptr, &len, &counterValue)\n      || tpm_marshal_TPM_DIGEST(&ptr, &len, &auditDigest)\n      || tpm_marshal_TPM_DIGEST(&ptr, &len, &ordinalDigest)\n      || tpm_marshal_UINT32(&ptr, &len, sigSize)\n      || tpm_marshal_BLOB(&ptr, &len, sig, sigSize)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  tpm_free(sig);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_SetOrdinalAuditStatus(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_COMMAND_CODE ordinalToAudit;\n  BOOL auditState;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_COMMAND_CODE(&ptr, &len, &ordinalToAudit)\n      || tpm_unmarshal_BOOL(&ptr, &len, &auditState)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  return TPM_SetOrdinalAuditStatus(ordinalToAudit, auditState, &req->auth1);\n}\n\nstatic TPM_RESULT execute_TPM_FieldUpgrade(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  /* execute command */\n  return TPM_FieldUpgrade();\n}\n\nstatic TPM_RESULT execute_TPM_SetRedirection(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_KEY_HANDLE keyHandle;\n  TPM_REDIR_COMMAND redirCmd;\n  UINT32 inputDataSize;\n  BYTE *inputData;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_KEY_HANDLE(&ptr, &len, &keyHandle)\n      || tpm_unmarshal_TPM_REDIR_COMMAND(&ptr, &len, &redirCmd)\n      || tpm_unmarshal_UINT32(&ptr, &len, &inputDataSize)\n      || tpm_unmarshal_BLOB(&ptr, &len, &inputData, inputDataSize)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  return TPM_SetRedirection(keyHandle, redirCmd, inputDataSize, inputData, &req->auth1);\n}\n\nstatic TPM_RESULT execute_TPM_ResetLockValue(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* execute command */\n  return TPM_ResetLockValue(&req->auth1);\n}\n\nstatic TPM_RESULT execute_TPM_Seal(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_KEY_HANDLE keyHandle;\n  TPM_ENCAUTH encAuth;\n  UINT32 pcrInfoSize;\n  TPM_PCR_INFO pcrInfo;\n  UINT32 inDataSize;\n  BYTE *inData;\n  TPM_STORED_DATA sealedData;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_KEY_HANDLE(&ptr, &len, &keyHandle)\n      || tpm_unmarshal_TPM_ENCAUTH(&ptr, &len, &encAuth)\n      || tpm_unmarshal_UINT32(&ptr, &len, &pcrInfoSize)\n      || (pcrInfoSize > 0\n          && tpm_unmarshal_TPM_PCR_INFO(&ptr, &len, &pcrInfo))\n      || tpm_unmarshal_UINT32(&ptr, &len, &inDataSize)\n      || tpm_unmarshal_BLOB(&ptr, &len, &inData, inDataSize)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_Seal(keyHandle, &encAuth, pcrInfoSize, &pcrInfo, inDataSize, inData, \n    &req->auth1, &sealedData);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = sizeof_TPM_STORED_DATA(sealedData);\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_STORED_DATA(&ptr, &len, &sealedData)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  free_TPM_STORED_DATA(sealedData);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_Unseal(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_KEY_HANDLE parentHandle;\n  TPM_STORED_DATA inData;\n  UINT32 sealedDataSize;\n  BYTE *secret = NULL;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_KEY_HANDLE(&ptr, &len, &parentHandle)\n      || tpm_unmarshal_TPM_STORED_DATA(&ptr, &len, &inData)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_Unseal(parentHandle, &inData, &req->auth1, &req->auth2, &sealedDataSize, &secret);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 4 + sealedDataSize;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_UINT32(&ptr, &len, sealedDataSize)\n      || tpm_marshal_BLOB(&ptr, &len, secret, sealedDataSize)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  tpm_free(secret);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_UnBind(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_KEY_HANDLE keyHandle;\n  UINT32 inDataSize;\n  BYTE *inData;\n  UINT32 outDataSize;\n  BYTE *outData = NULL;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_KEY_HANDLE(&ptr, &len, &keyHandle)\n      || tpm_unmarshal_UINT32(&ptr, &len, &inDataSize)\n      || tpm_unmarshal_BLOB(&ptr, &len, &inData, inDataSize)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_UnBind(keyHandle, inDataSize, inData, &req->auth1, &outDataSize, &outData);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 4 + outDataSize;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_UINT32(&ptr, &len, outDataSize)\n      || tpm_marshal_BLOB(&ptr, &len, outData, outDataSize)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  tpm_free(outData);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_CreateWrapKey(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_KEY_HANDLE parentHandle;\n  TPM_ENCAUTH dataUsageAuth;\n  TPM_ENCAUTH dataMigrationAuth;\n  TPM_KEY keyInfo;\n  TPM_KEY wrappedKey;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_KEY_HANDLE(&ptr, &len, &parentHandle)\n      || tpm_unmarshal_TPM_ENCAUTH(&ptr, &len, &dataUsageAuth)\n      || tpm_unmarshal_TPM_ENCAUTH(&ptr, &len, &dataMigrationAuth)\n      || tpm_unmarshal_TPM_KEY(&ptr, &len, &keyInfo)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_CreateWrapKey(parentHandle, &dataUsageAuth, &dataMigrationAuth, \n    &keyInfo, &req->auth1, &wrappedKey);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = sizeof_TPM_KEY(wrappedKey);\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_KEY(&ptr, &len, &wrappedKey)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  free_TPM_KEY(wrappedKey);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_LoadKey(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_KEY_HANDLE parentHandle;\n  TPM_KEY inKey;\n  TPM_KEY_HANDLE inkeyHandle;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_KEY_HANDLE(&ptr, &len, &parentHandle)\n      || tpm_unmarshal_TPM_KEY(&ptr, &len, &inKey)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_LoadKey(parentHandle, &inKey, &req->auth1, &inkeyHandle);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 4;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_KEY_HANDLE(&ptr, &len, inkeyHandle)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_LoadKey2(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_KEY_HANDLE parentHandle;\n  TPM_KEY inKey;\n  TPM_KEY_HANDLE inkeyHandle;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_KEY_HANDLE(&ptr, &len, &parentHandle)\n      || tpm_unmarshal_TPM_KEY(&ptr, &len, &inKey)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_LoadKey2(parentHandle, &inKey, &req->auth1, &inkeyHandle);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 4;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_KEY_HANDLE(&ptr, &len, inkeyHandle)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_GetPubKey(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_KEY_HANDLE keyHandle;\n  TPM_PUBKEY pubKey;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_KEY_HANDLE(&ptr, &len, &keyHandle)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_GetPubKey(keyHandle, &req->auth1, &pubKey);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = sizeof_TPM_PUBKEY(pubKey);\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_PUBKEY(&ptr, &len, &pubKey)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  free_TPM_PUBKEY(pubKey);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_Sealx(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_KEY_HANDLE keyHandle;\n  TPM_ENCAUTH encAuth;\n  UINT32 pcrInfoSize;\n  TPM_PCR_INFO pcrInfo;\n  UINT32 inDataSize;\n  BYTE *inData;\n  TPM_STORED_DATA sealedData;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_KEY_HANDLE(&ptr, &len, &keyHandle)\n      || tpm_unmarshal_TPM_ENCAUTH(&ptr, &len, &encAuth)\n      || tpm_unmarshal_UINT32(&ptr, &len, &pcrInfoSize)\n      || (pcrInfoSize > 0\n          && tpm_unmarshal_TPM_PCR_INFO(&ptr, &len, &pcrInfo))\n      || tpm_unmarshal_UINT32(&ptr, &len, &inDataSize)\n      || tpm_unmarshal_BLOB(&ptr, &len, &inData, inDataSize)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_Sealx(keyHandle, &encAuth, pcrInfoSize, &pcrInfo, inDataSize, inData, \n    &req->auth1, &sealedData);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = sizeof_TPM_STORED_DATA(sealedData);\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_STORED_DATA(&ptr, &len, &sealedData)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  free_TPM_STORED_DATA(sealedData);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_CreateMigrationBlob(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_KEY_HANDLE parentHandle;\n  TPM_MIGRATE_SCHEME migrationType;\n  TPM_MIGRATIONKEYAUTH migrationKeyAuth;\n  UINT32 encDataSize;\n  BYTE *encData;\n  UINT32 randomSize;\n  BYTE *random = NULL;\n  UINT32 outDataSize;\n  BYTE *outData = NULL;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_KEY_HANDLE(&ptr, &len, &parentHandle)\n      || tpm_unmarshal_TPM_MIGRATE_SCHEME(&ptr, &len, &migrationType)\n      || tpm_unmarshal_TPM_MIGRATIONKEYAUTH(&ptr, &len, &migrationKeyAuth)\n      || tpm_unmarshal_UINT32(&ptr, &len, &encDataSize)\n      || tpm_unmarshal_BLOB(&ptr, &len, &encData, encDataSize)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_CreateMigrationBlob(parentHandle, migrationType, &migrationKeyAuth, encDataSize, \n    encData, &req->auth1, &req->auth2, &randomSize, &random, &outDataSize, &outData);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 4 + randomSize + 4 + outDataSize;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_UINT32(&ptr, &len, randomSize)\n      || tpm_marshal_BLOB(&ptr, &len, random, randomSize)\n      || tpm_marshal_UINT32(&ptr, &len, outDataSize)\n      || tpm_marshal_BLOB(&ptr, &len, outData, outDataSize)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  tpm_free(random);\n  tpm_free(outData);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_ConvertMigrationBlob(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_KEY_HANDLE parentHandle;\n  UINT32 inDataSize;\n  BYTE *inData;\n  UINT32 randomSize;\n  BYTE *random;\n  UINT32 outDataSize;\n  BYTE *outData = NULL;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_KEY_HANDLE(&ptr, &len, &parentHandle)\n      || tpm_unmarshal_UINT32(&ptr, &len, &inDataSize)\n      || tpm_unmarshal_BLOB(&ptr, &len, &inData, inDataSize)\n      || tpm_unmarshal_UINT32(&ptr, &len, &randomSize)\n      || tpm_unmarshal_BLOB(&ptr, &len, &random, randomSize)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_ConvertMigrationBlob(parentHandle, inDataSize, inData, randomSize, \n    random, &req->auth1, &outDataSize, &outData);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 4 + outDataSize;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_UINT32(&ptr, &len, outDataSize)\n      || tpm_marshal_BLOB(&ptr, &len, outData, outDataSize)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  tpm_free(outData);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_AuthorizeMigrationKey(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_MIGRATE_SCHEME migrateScheme;\n  TPM_PUBKEY migrationKey;\n  TPM_MIGRATIONKEYAUTH outData;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_MIGRATE_SCHEME(&ptr, &len, &migrateScheme)\n      || tpm_unmarshal_TPM_PUBKEY(&ptr, &len, &migrationKey)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_AuthorizeMigrationKey(migrateScheme, &migrationKey, &req->auth1, &outData);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = sizeof_TPM_MIGRATIONKEYAUTH(outData);\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_MIGRATIONKEYAUTH(&ptr, &len, &outData)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  free_TPM_MIGRATIONKEYAUTH(outData);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_MigrateKey(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_KEY_HANDLE maKeyHandle;\n  TPM_PUBKEY pubKey;\n  UINT32 inDataSize;\n  BYTE *inData;\n  UINT32 outDataSize;\n  BYTE *outData = NULL;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_KEY_HANDLE(&ptr, &len, &maKeyHandle)\n      || tpm_unmarshal_TPM_PUBKEY(&ptr, &len, &pubKey)\n      || tpm_unmarshal_UINT32(&ptr, &len, &inDataSize)\n      || tpm_unmarshal_BLOB(&ptr, &len, &inData, inDataSize)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_MigrateKey(maKeyHandle, &pubKey, inDataSize, inData, \n    &req->auth1, &outDataSize, &outData);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 4 + outDataSize;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_UINT32(&ptr, &len, outDataSize)\n      || tpm_marshal_BLOB(&ptr, &len, outData, outDataSize)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  tpm_free(outData);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_CMK_SetRestrictions(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_CMK_DELEGATE restriction;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_CMK_DELEGATE(&ptr, &len, &restriction)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  return TPM_CMK_SetRestrictions(restriction, &req->auth1);\n}\n\nstatic TPM_RESULT execute_TPM_CMK_ApproveMA(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_DIGEST migrationAuthorityDigest;\n  TPM_HMAC outData;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_DIGEST(&ptr, &len, &migrationAuthorityDigest)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_CMK_ApproveMA(&migrationAuthorityDigest, &req->auth1, &outData);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 20;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_HMAC(&ptr, &len, &outData)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_CMK_CreateKey(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_KEY_HANDLE parentHandle;\n  TPM_ENCAUTH dataUsageAuth;\n  TPM_KEY keyInfo;\n  TPM_HMAC migrationAuthorityApproval;\n  TPM_DIGEST migrationAuthorityDigest;\n  TPM_KEY wrappedKey;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_KEY_HANDLE(&ptr, &len, &parentHandle)\n      || tpm_unmarshal_TPM_ENCAUTH(&ptr, &len, &dataUsageAuth)\n      || tpm_unmarshal_TPM_KEY(&ptr, &len, &keyInfo)\n      || tpm_unmarshal_TPM_HMAC(&ptr, &len, &migrationAuthorityApproval)\n      || tpm_unmarshal_TPM_DIGEST(&ptr, &len, &migrationAuthorityDigest)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_CMK_CreateKey(parentHandle, &dataUsageAuth, &keyInfo, &migrationAuthorityApproval,\n    &migrationAuthorityDigest, &req->auth1, &req->auth2, &wrappedKey);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = sizeof_TPM_KEY(wrappedKey);\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_KEY(&ptr, &len, &wrappedKey)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  free_TPM_KEY(wrappedKey);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_CMK_CreateTicket(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_PUBKEY verificationKey;\n  TPM_DIGEST signedData;\n  UINT32 signatureValueSize;\n  BYTE *signatureValue;\n  TPM_DIGEST sigTicket;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_PUBKEY(&ptr, &len, &verificationKey)\n      || tpm_unmarshal_TPM_DIGEST(&ptr, &len, &signedData)\n      || tpm_unmarshal_UINT32(&ptr, &len, &signatureValueSize)\n      || tpm_unmarshal_BLOB(&ptr, &len, &signatureValue, signatureValueSize)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_CMK_CreateTicket(&verificationKey, &signedData, signatureValueSize, \n    signatureValue, &req->auth1, &sigTicket);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 20;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_DIGEST(&ptr, &len, &sigTicket)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_CMK_CreateBlob(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_KEY_HANDLE parentHandle;\n  TPM_MIGRATE_SCHEME migrationType;\n  TPM_MIGRATIONKEYAUTH migrationKeyAuth;\n  TPM_DIGEST pubSourceKeyDigest;\n  UINT32 msaListSize;\n  TPM_MSA_COMPOSITE msaList;\n  UINT32 restrictTicketSize;\n  TPM_CMK_AUTH restrictTicket;\n  UINT32 sigTicketSize;\n  TPM_HMAC sigTicket;\n  UINT32 encDataSize;\n  BYTE *encData;\n  UINT32 randomSize;\n  BYTE *random = NULL;\n  UINT32 outDataSize;\n  BYTE *outData = NULL;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_KEY_HANDLE(&ptr, &len, &parentHandle)\n      || tpm_unmarshal_TPM_MIGRATE_SCHEME(&ptr, &len, &migrationType)\n      || tpm_unmarshal_TPM_MIGRATIONKEYAUTH(&ptr, &len, &migrationKeyAuth)\n      || tpm_unmarshal_TPM_DIGEST(&ptr, &len, &pubSourceKeyDigest)\n      || tpm_unmarshal_UINT32(&ptr, &len, &msaListSize)\n      || tpm_unmarshal_TPM_MSA_COMPOSITE(&ptr, &len, &msaList)\n      || tpm_unmarshal_UINT32(&ptr, &len, &restrictTicketSize)\n      || (restrictTicketSize > 0\n          && tpm_unmarshal_TPM_CMK_AUTH(&ptr, &len, &restrictTicket))\n      || tpm_unmarshal_UINT32(&ptr, &len, &sigTicketSize)\n      || (sigTicketSize > 0\n          && tpm_unmarshal_TPM_HMAC(&ptr, &len, &sigTicket))\n      || tpm_unmarshal_UINT32(&ptr, &len, &encDataSize)\n      || tpm_unmarshal_BLOB(&ptr, &len, &encData, encDataSize)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_CMK_CreateBlob(parentHandle, migrationType, &migrationKeyAuth,\n    &pubSourceKeyDigest, &msaList,\n    restrictTicketSize > 0 ? &restrictTicket : NULL,\n    sigTicketSize > 0 ? &sigTicket : NULL,\n    encDataSize, encData, &req->auth1, &randomSize, &random, &outDataSize, &outData);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 4 + randomSize + 4 + outDataSize;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_UINT32(&ptr, &len, randomSize)\n      || tpm_marshal_BLOB(&ptr, &len, random, randomSize)\n      || tpm_marshal_UINT32(&ptr, &len, outDataSize)\n      || tpm_marshal_BLOB(&ptr, &len, outData, outDataSize)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  tpm_free(random);\n  tpm_free(outData);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_CMK_ConvertMigration(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_KEY_HANDLE parentHandle;\n  TPM_CMK_AUTH restrictTicket;\n  TPM_HMAC sigTicket;\n  TPM_KEY migratedKey;\n  UINT32 msaListSize;\n  TPM_MSA_COMPOSITE msaList;\n  UINT32 randomSize;\n  BYTE *random;\n  UINT32 outDataSize;\n  BYTE *outData = NULL;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_KEY_HANDLE(&ptr, &len, &parentHandle)\n      || tpm_unmarshal_TPM_CMK_AUTH(&ptr, &len, &restrictTicket)\n      || tpm_unmarshal_TPM_HMAC(&ptr, &len, &sigTicket)\n      || tpm_unmarshal_TPM_KEY(&ptr, &len, &migratedKey)\n      || tpm_unmarshal_UINT32(&ptr, &len, &msaListSize)\n      || tpm_unmarshal_TPM_MSA_COMPOSITE(&ptr, &len, &msaList)\n      || tpm_unmarshal_UINT32(&ptr, &len, &randomSize)\n      || tpm_unmarshal_BLOB(&ptr, &len, &random, randomSize)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_CMK_ConvertMigration(parentHandle, &restrictTicket, &sigTicket, \n    &migratedKey, &msaList, randomSize, random, &req->auth1, &outDataSize,\n    &outData);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 4 + outDataSize;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_UINT32(&ptr, &len, outDataSize)\n      || tpm_marshal_BLOB(&ptr, &len, outData, outDataSize)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  tpm_free(outData);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_CreateMaintenanceArchive(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  BOOL generateRandom;\n  UINT32 randomSize;\n  BYTE *random = NULL;\n  UINT32 archiveSize;\n  BYTE *archive = NULL;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_BOOL(&ptr, &len, &generateRandom)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_CreateMaintenanceArchive(generateRandom, &req->auth1, &randomSize, \n    &random, &archiveSize, &archive);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 4 + randomSize + 4 + archiveSize;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_UINT32(&ptr, &len, randomSize)\n      || tpm_marshal_BLOB(&ptr, &len, random, randomSize)\n      || tpm_marshal_UINT32(&ptr, &len, archiveSize)\n      || tpm_marshal_BLOB(&ptr, &len, archive, archiveSize)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  tpm_free(random);\n  tpm_free(archive);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_LoadMaintenanceArchive(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  UINT32 archiveSize;\n  BYTE *archive;\n  UINT32 sigSize;\n  BYTE *sig;\n  UINT32 randomSize;\n  BYTE *random;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_UINT32(&ptr, &len, &archiveSize)\n      || tpm_unmarshal_BLOB(&ptr, &len, &archive, archiveSize)\n      || tpm_unmarshal_UINT32(&ptr, &len, &sigSize)\n      || tpm_unmarshal_BLOB(&ptr, &len, &sig, sigSize)\n      || tpm_unmarshal_UINT32(&ptr, &len, &randomSize)\n      || tpm_unmarshal_BLOB(&ptr, &len, &random, randomSize)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  return TPM_LoadMaintenanceArchive(archiveSize, archive, sigSize, sig,\n   randomSize, random, &req->auth1);\n}\n\nstatic TPM_RESULT execute_TPM_KillMaintenanceFeature(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* execute command */\n  return TPM_KillMaintenanceFeature(&req->auth1);\n}\n\nstatic TPM_RESULT execute_TPM_LoadManuMaintPub(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_NONCE antiReplay;\n  TPM_PUBKEY pubKey;\n  TPM_DIGEST checksum;\n  TPM_RESULT res;\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_NONCE(&ptr, &len, &antiReplay)\n      || tpm_unmarshal_TPM_PUBKEY(&ptr, &len, &pubKey)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_LoadManuMaintPub(&antiReplay, &pubKey, &checksum);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 20;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_DIGEST(&ptr, &len, &checksum)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_ReadManuMaintPub(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_NONCE antiReplay;\n  TPM_DIGEST checksum;\n  TPM_RESULT res;\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_NONCE(&ptr, &len, &antiReplay)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_ReadManuMaintPub(&antiReplay, &checksum);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 20;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_DIGEST(&ptr, &len, &checksum)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_SHA1Start(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  UINT32 maxNumBytes;\n  TPM_RESULT res;\n  /* execute command */\n  res = TPM_SHA1Start(&maxNumBytes);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 4;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_UINT32(&ptr, &len, maxNumBytes)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_SHA1Update(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  UINT32 numBytes;\n  BYTE *hashData;\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_UINT32(&ptr, &len, &numBytes)\n      || tpm_unmarshal_BLOB(&ptr, &len, &hashData, numBytes)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  return TPM_SHA1Update(numBytes, hashData);\n}\n\nstatic TPM_RESULT execute_TPM_SHA1Complete(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  UINT32 hashDataSize;\n  BYTE *hashData;\n  TPM_DIGEST hashValue;\n  TPM_RESULT res;\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_UINT32(&ptr, &len, &hashDataSize)\n      || tpm_unmarshal_BLOB(&ptr, &len, &hashData, hashDataSize)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_SHA1Complete(hashDataSize, hashData, &hashValue);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 20;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_DIGEST(&ptr, &len, &hashValue)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_SHA1CompleteExtend(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_PCRINDEX pcrNum;\n  UINT32 hashDataSize;\n  BYTE *hashData;\n  TPM_DIGEST hashValue;\n  TPM_PCRVALUE outDigest;\n  TPM_RESULT res;\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_PCRINDEX(&ptr, &len, &pcrNum)\n      || tpm_unmarshal_UINT32(&ptr, &len, &hashDataSize)\n      || tpm_unmarshal_BLOB(&ptr, &len, &hashData, hashDataSize)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_SHA1CompleteExtend(pcrNum, hashDataSize, hashData, &hashValue, &outDigest);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 20 + 20;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_DIGEST(&ptr, &len, &hashValue)\n      || tpm_marshal_TPM_PCRVALUE(&ptr, &len, &outDigest)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_Sign(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_KEY_HANDLE keyHandle;\n  UINT32 areaToSignSize;\n  BYTE *areaToSign;\n  UINT32 sigSize;\n  BYTE *sig = NULL;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_KEY_HANDLE(&ptr, &len, &keyHandle)\n      || tpm_unmarshal_UINT32(&ptr, &len, &areaToSignSize)\n      || tpm_unmarshal_BLOB(&ptr, &len, &areaToSign, areaToSignSize)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_Sign(keyHandle, areaToSignSize, areaToSign, &req->auth1, &sigSize, &sig);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 4 + sigSize;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_UINT32(&ptr, &len, sigSize)\n      || tpm_marshal_BLOB(&ptr, &len, sig, sigSize)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  tpm_free(sig);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_GetRandom(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  UINT32 bytesRequested;\n  UINT32 randomBytesSize;\n  BYTE *randomBytes = NULL;\n  TPM_RESULT res;\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_UINT32(&ptr, &len, &bytesRequested)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_GetRandom(bytesRequested, &randomBytesSize, &randomBytes);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 4 + randomBytesSize;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_UINT32(&ptr, &len, randomBytesSize)\n      || tpm_marshal_BLOB(&ptr, &len, randomBytes, randomBytesSize)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  tpm_free(randomBytes);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_StirRandom(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  UINT32 dataSize;\n  BYTE *inData;\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_UINT32(&ptr, &len, &dataSize)\n      || tpm_unmarshal_BLOB(&ptr, &len, &inData, dataSize)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  return TPM_StirRandom(dataSize, inData);\n}\n\nstatic TPM_RESULT execute_TPM_CertifyKey(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_KEY_HANDLE certHandle;\n  TPM_KEY_HANDLE keyHandle;\n  TPM_NONCE antiReplay;\n  TPM_CERTIFY_INFO certifyInfo;\n  UINT32 outDataSize;\n  BYTE *outData = NULL;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_KEY_HANDLE(&ptr, &len, &certHandle)\n      || tpm_unmarshal_TPM_KEY_HANDLE(&ptr, &len, &keyHandle)\n      || tpm_unmarshal_TPM_NONCE(&ptr, &len, &antiReplay)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_CertifyKey(certHandle, keyHandle, &antiReplay, &req->auth1, \n    &req->auth2, &certifyInfo, &outDataSize, &outData);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = sizeof_TPM_CERTIFY_INFO(certifyInfo) + 4 + outDataSize;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_CERTIFY_INFO(&ptr, &len, &certifyInfo)\n      || tpm_marshal_UINT32(&ptr, &len, outDataSize)\n      || tpm_marshal_BLOB(&ptr, &len, outData, outDataSize)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  free_TPM_CERTIFY_INFO(certifyInfo);\n  tpm_free(outData);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_CertifyKey2(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_KEY_HANDLE keyHandle;\n  TPM_KEY_HANDLE certHandle;\n  TPM_DIGEST migrationPubDigest;\n  TPM_NONCE antiReplay;\n  TPM_CERTIFY_INFO certifyInfo;\n  UINT32 outDataSize;\n  BYTE *outData = NULL;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_KEY_HANDLE(&ptr, &len, &keyHandle)\n      || tpm_unmarshal_TPM_KEY_HANDLE(&ptr, &len, &certHandle)\n      || tpm_unmarshal_TPM_DIGEST(&ptr, &len, &migrationPubDigest)\n      || tpm_unmarshal_TPM_NONCE(&ptr, &len, &antiReplay)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_CertifyKey2(keyHandle, certHandle, &migrationPubDigest, &antiReplay, \n    &req->auth1, &req->auth2, &certifyInfo, &outDataSize, &outData);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = sizeof_TPM_CERTIFY_INFO(certifyInfo) + 4 + outDataSize;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_CERTIFY_INFO(&ptr, &len, &certifyInfo)\n      || tpm_marshal_UINT32(&ptr, &len, outDataSize)\n      || tpm_marshal_BLOB(&ptr, &len, outData, outDataSize)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  free_TPM_CERTIFY_INFO(certifyInfo);\n  tpm_free(outData);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_CreateEndorsementKeyPair(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_NONCE antiReplay;\n  TPM_KEY_PARMS keyInfo;\n  TPM_PUBKEY pubEndorsementKey;\n  TPM_DIGEST Checksum;\n  TPM_RESULT res;\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_NONCE(&ptr, &len, &antiReplay)\n      || tpm_unmarshal_TPM_KEY_PARMS(&ptr, &len, &keyInfo)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_CreateEndorsementKeyPair(&antiReplay, &keyInfo, &pubEndorsementKey, &Checksum);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = sizeof_TPM_PUBKEY(pubEndorsementKey) + 20;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_PUBKEY(&ptr, &len, &pubEndorsementKey)\n      || tpm_marshal_TPM_DIGEST(&ptr, &len, &Checksum)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  free_TPM_PUBKEY(pubEndorsementKey);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_CreateRevocableEK(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_NONCE antiReplay;\n  TPM_KEY_PARMS keyInfo;\n  BOOL generateReset;\n  TPM_NONCE inputEKreset;\n  TPM_PUBKEY pubEndorsementKey;\n  TPM_DIGEST Checksum;\n  TPM_NONCE outputEKreset;\n  TPM_RESULT res;\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_NONCE(&ptr, &len, &antiReplay)\n      || tpm_unmarshal_TPM_KEY_PARMS(&ptr, &len, &keyInfo)\n      || tpm_unmarshal_BOOL(&ptr, &len, &generateReset)\n      || tpm_unmarshal_TPM_NONCE(&ptr, &len, &inputEKreset)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_CreateRevocableEK(&antiReplay, &keyInfo, generateReset, \n    &inputEKreset, &pubEndorsementKey, &Checksum, &outputEKreset);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = sizeof_TPM_PUBKEY(pubEndorsementKey) + 20 + 20;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_PUBKEY(&ptr, &len, &pubEndorsementKey)\n      || tpm_marshal_TPM_DIGEST(&ptr, &len, &Checksum)\n      || tpm_marshal_TPM_NONCE(&ptr, &len, &outputEKreset)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  free_TPM_PUBKEY(pubEndorsementKey);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_RevokeTrust(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_NONCE EKReset;\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_NONCE(&ptr, &len, &EKReset)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  return TPM_RevokeTrust(&EKReset);\n}\n\nstatic TPM_RESULT execute_TPM_ReadPubek(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_NONCE antiReplay;\n  TPM_PUBKEY pubEndorsementKey;\n  TPM_DIGEST checksum;\n  TPM_RESULT res;\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_NONCE(&ptr, &len, &antiReplay)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_ReadPubek(&antiReplay, &pubEndorsementKey, &checksum);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = sizeof_TPM_PUBKEY(pubEndorsementKey) + 20;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_PUBKEY(&ptr, &len, &pubEndorsementKey)\n      || tpm_marshal_TPM_DIGEST(&ptr, &len, &checksum)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  free_TPM_PUBKEY(pubEndorsementKey);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_DisablePubekRead(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* execute command */\n  return TPM_DisablePubekRead(&req->auth1);\n}\n\nstatic TPM_RESULT execute_TPM_OwnerReadInternalPub(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_KEY_HANDLE keyHandle;\n  TPM_PUBKEY publicPortion;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_KEY_HANDLE(&ptr, &len, &keyHandle)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_OwnerReadInternalPub(keyHandle, &req->auth1, &publicPortion);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = sizeof_TPM_PUBKEY(publicPortion);\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_PUBKEY(&ptr, &len, &publicPortion)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  free_TPM_PUBKEY(publicPortion);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_MakeIdentity(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_ENCAUTH identityAuth;\n  TPM_CHOSENID_HASH labelPrivCADigest;\n  TPM_KEY idKeyParams;\n  TPM_KEY idKey;\n  UINT32 identityBindingSize;\n  BYTE *identityBinding = NULL;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_ENCAUTH(&ptr, &len, &identityAuth)\n      || tpm_unmarshal_TPM_CHOSENID_HASH(&ptr, &len, &labelPrivCADigest)\n      || tpm_unmarshal_TPM_KEY(&ptr, &len, &idKeyParams)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_MakeIdentity(&identityAuth, &labelPrivCADigest, &idKeyParams, \n    &req->auth1, &req->auth2, &idKey, &identityBindingSize, &identityBinding);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = sizeof_TPM_KEY(idKey) + 4 + identityBindingSize;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_KEY(&ptr, &len, &idKey)\n      || tpm_marshal_UINT32(&ptr, &len, identityBindingSize)\n      || tpm_marshal_BLOB(&ptr, &len, identityBinding, identityBindingSize)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  free_TPM_KEY(idKey);\n  tpm_free(identityBinding);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_ActivateIdentity(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_KEY_HANDLE idKeyHandle;\n  UINT32 blobSize;\n  BYTE *blob;\n  TPM_SYMMETRIC_KEY symmetricKey;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_KEY_HANDLE(&ptr, &len, &idKeyHandle)\n      || tpm_unmarshal_UINT32(&ptr, &len, &blobSize)\n      || tpm_unmarshal_BLOB(&ptr, &len, &blob, blobSize)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* allocate memory for the symmetricKey data */\n  symmetricKey.size = blobSize;\n  symmetricKey.data = tpm_malloc(blobSize);\n  if (symmetricKey.data == NULL)\n    return TPM_NOSPACE;\n  /* execute command */\n  res = TPM_ActivateIdentity(idKeyHandle, blobSize, blob, &req->auth1, \n    &req->auth2, &symmetricKey);\n  if (res != TPM_SUCCESS) {\n    free_TPM_SYMMETRIC_KEY(symmetricKey);\n    return res;\n  }\n  /* marshal output */\n  rsp->paramSize = len = sizeof_TPM_SYMMETRIC_KEY(symmetricKey);\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL)\n    res = TPM_NOSPACE;\n  else if (tpm_marshal_TPM_SYMMETRIC_KEY(&ptr, &len, &symmetricKey)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  free_TPM_SYMMETRIC_KEY(symmetricKey);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_Extend(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_PCRINDEX pcrNum;\n  TPM_DIGEST inDigest;\n  TPM_PCRVALUE outDigest;\n  TPM_RESULT res;\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_PCRINDEX(&ptr, &len, &pcrNum)\n      || tpm_unmarshal_TPM_DIGEST(&ptr, &len, &inDigest)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n#ifdef MTM_EMULATOR\n  res = MTM_Extend(pcrNum, &inDigest, &outDigest);\n#else\n  res = TPM_Extend(pcrNum, &inDigest, &outDigest);\n#endif\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 20;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_PCRVALUE(&ptr, &len, &outDigest)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_PCRRead(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_PCRINDEX pcrIndex;\n  TPM_PCRVALUE outDigest;\n  TPM_RESULT res;\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_PCRINDEX(&ptr, &len, &pcrIndex)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_PCRRead(pcrIndex, &outDigest);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 20;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_PCRVALUE(&ptr, &len, &outDigest)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_Quote(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_KEY_HANDLE keyHandle;\n  TPM_NONCE extrnalData;\n  TPM_PCR_SELECTION targetPCR;\n  TPM_PCR_COMPOSITE pcrData;\n  UINT32 sigSize;\n  BYTE *sig = NULL;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_KEY_HANDLE(&ptr, &len, &keyHandle)\n      || tpm_unmarshal_TPM_NONCE(&ptr, &len, &extrnalData)\n      || tpm_unmarshal_TPM_PCR_SELECTION(&ptr, &len, &targetPCR)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_Quote(keyHandle, &extrnalData, &targetPCR, &req->auth1, &pcrData, &sigSize, &sig);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = sizeof_TPM_PCR_COMPOSITE(pcrData) + 4 + sigSize;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_PCR_COMPOSITE(&ptr, &len, &pcrData)\n      || tpm_marshal_UINT32(&ptr, &len, sigSize)\n      || tpm_marshal_BLOB(&ptr, &len, sig, sigSize)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  tpm_free(sig);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_PCR_Reset(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_PCR_SELECTION pcrSelection;\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_PCR_SELECTION(&ptr, &len, &pcrSelection)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n#ifdef MTM_EMULATOR\n  return MTM_PCR_Reset(&pcrSelection);\n#else\n  return TPM_PCR_Reset(&pcrSelection);\n#endif\n}\n\nstatic TPM_RESULT execute_TPM_Quote2(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_KEY_HANDLE keyHandle;\n  TPM_NONCE externalData;\n  TPM_PCR_SELECTION targetPCR;\n  BOOL addVersion;\n  TPM_PCR_INFO_SHORT pcrData;\n  UINT32 versionInfoSize;\n  TPM_CAP_VERSION_INFO versionInfo;\n  UINT32 sigSize;\n  BYTE *sig = NULL;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_KEY_HANDLE(&ptr, &len, &keyHandle)\n      || tpm_unmarshal_TPM_NONCE(&ptr, &len, &externalData)\n      || tpm_unmarshal_TPM_PCR_SELECTION(&ptr, &len, &targetPCR)\n      || tpm_unmarshal_BOOL(&ptr, &len, &addVersion)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_Quote2(keyHandle, &externalData, &targetPCR, addVersion, \n    &req->auth1, &pcrData, &versionInfoSize, &versionInfo, &sigSize, &sig);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = sizeof_TPM_PCR_INFO_SHORT(pcrData) + 4 \n    + versionInfoSize + 4 + sigSize;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_PCR_INFO_SHORT(&ptr, &len, &pcrData)\n      || tpm_marshal_UINT32(&ptr, &len, versionInfoSize)\n      || ((addVersion == TRUE)\n          && tpm_marshal_TPM_CAP_VERSION_INFO(&ptr, &len, &versionInfo))\n      || tpm_marshal_UINT32(&ptr, &len, sigSize)\n      || tpm_marshal_BLOB(&ptr, &len, sig, sigSize)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  tpm_free(sig);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_ChangeAuth(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_KEY_HANDLE parentHandle;\n  TPM_PROTOCOL_ID protocolID;\n  TPM_ENCAUTH newAuth;\n  TPM_ENTITY_TYPE entityType;\n  UINT32 encDataSize;\n  BYTE *encData;\n  UINT32 outDataSize;\n  BYTE *outData = NULL;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_KEY_HANDLE(&ptr, &len, &parentHandle)\n      || tpm_unmarshal_TPM_PROTOCOL_ID(&ptr, &len, &protocolID)\n      || tpm_unmarshal_TPM_ENCAUTH(&ptr, &len, &newAuth)\n      || tpm_unmarshal_TPM_ENTITY_TYPE(&ptr, &len, &entityType)\n      || tpm_unmarshal_UINT32(&ptr, &len, &encDataSize)\n      || tpm_unmarshal_BLOB(&ptr, &len, &encData, encDataSize)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_ChangeAuth(parentHandle, protocolID, &newAuth, entityType, encDataSize, \n    encData, &req->auth1, &req->auth2, &outDataSize, &outData);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 4 + outDataSize;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_UINT32(&ptr, &len, outDataSize)\n      || tpm_marshal_BLOB(&ptr, &len, outData, outDataSize)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  tpm_free(outData);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_ChangeAuthOwner(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_PROTOCOL_ID protocolID;\n  TPM_ENCAUTH newAuth;\n  TPM_ENTITY_TYPE entityType;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_PROTOCOL_ID(&ptr, &len, &protocolID)\n      || tpm_unmarshal_TPM_ENCAUTH(&ptr, &len, &newAuth)\n      || tpm_unmarshal_TPM_ENTITY_TYPE(&ptr, &len, &entityType)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  return TPM_ChangeAuthOwner(protocolID, &newAuth, entityType, &req->auth1);\n}\n\nstatic TPM_RESULT execute_TPM_OIAP(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_AUTHHANDLE authHandle;\n  TPM_NONCE nonceEven;\n  TPM_RESULT res;\n  /* execute command */\n  res = TPM_OIAP(&authHandle, &nonceEven);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 4 + 20;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_AUTHHANDLE(&ptr, &len, authHandle)\n      || tpm_marshal_TPM_NONCE(&ptr, &len, &nonceEven)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_OSAP(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_ENTITY_TYPE entityType;\n  UINT32 entityValue;\n  TPM_NONCE nonceOddOSAP;\n  TPM_AUTHHANDLE authHandle;\n  TPM_NONCE nonceEven;\n  TPM_NONCE nonceEvenOSAP;\n  TPM_RESULT res;\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_ENTITY_TYPE(&ptr, &len, &entityType)\n      || tpm_unmarshal_UINT32(&ptr, &len, &entityValue)\n      || tpm_unmarshal_TPM_NONCE(&ptr, &len, &nonceOddOSAP)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_OSAP(entityType, entityValue, &nonceOddOSAP, &authHandle, \n    &nonceEven, &nonceEvenOSAP);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 4 + 20 + 20;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_AUTHHANDLE(&ptr, &len, authHandle)\n      || tpm_marshal_TPM_NONCE(&ptr, &len, &nonceEven)\n      || tpm_marshal_TPM_NONCE(&ptr, &len, &nonceEvenOSAP)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_DSAP(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_ENTITY_TYPE entityType;\n  TPM_KEY_HANDLE keyHandle;\n  UINT32 entityValueSize;\n  BYTE *entityValue;\n  TPM_NONCE nonceOddDSAP;\n  TPM_AUTHHANDLE authHandle;\n  TPM_NONCE nonceEven;\n  TPM_NONCE nonceEvenDSAP;\n  TPM_RESULT res;\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_ENTITY_TYPE(&ptr, &len, &entityType)\n      || tpm_unmarshal_TPM_KEY_HANDLE(&ptr, &len, &keyHandle)\n      || tpm_unmarshal_TPM_NONCE(&ptr, &len, &nonceOddDSAP)\n      || tpm_unmarshal_UINT32(&ptr, &len, &entityValueSize)\n      || tpm_unmarshal_BLOB(&ptr, &len, &entityValue, entityValueSize)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_DSAP(entityType, keyHandle, &nonceOddDSAP, entityValueSize,\n    entityValue, &authHandle, &nonceEven, &nonceEvenDSAP);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 4 + 20 + 20;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_AUTHHANDLE(&ptr, &len, authHandle)\n      || tpm_marshal_TPM_NONCE(&ptr, &len, &nonceEven)\n      || tpm_marshal_TPM_NONCE(&ptr, &len, &nonceEvenDSAP)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_SetOwnerPointer(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_ENTITY_TYPE entityType;\n  UINT32 entityValue;\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_ENTITY_TYPE(&ptr, &len, &entityType)\n      || tpm_unmarshal_UINT32(&ptr, &len, &entityValue)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  return TPM_SetOwnerPointer(entityType, entityValue);\n}\n\nstatic TPM_RESULT execute_TPM_Delegate_Manage(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_FAMILY_ID familyID;\n  TPM_FAMILY_OPERATION opFlag;\n  UINT32 opDataSize;\n  BYTE *opData;\n  UINT32 retDataSize;\n  BYTE *retData = NULL;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_FAMILY_ID(&ptr, &len, &familyID)\n      || tpm_unmarshal_TPM_FAMILY_OPERATION(&ptr, &len, &opFlag)\n      || tpm_unmarshal_UINT32(&ptr, &len, &opDataSize)\n      || tpm_unmarshal_BLOB(&ptr, &len, &opData, opDataSize)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_Delegate_Manage(familyID, opFlag, opDataSize, opData, \n    &req->auth1, &retDataSize, &retData);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 4 + retDataSize;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_UINT32(&ptr, &len, retDataSize)\n      || tpm_marshal_BLOB(&ptr, &len, retData, retDataSize)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  tpm_free(retData);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_Delegate_CreateKeyDelegation(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_KEY_HANDLE keyHandle;\n  TPM_DELEGATE_PUBLIC publicInfo;\n  TPM_ENCAUTH delAuth;\n  UINT32 blobSize;\n  TPM_DELEGATE_KEY_BLOB blob;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_KEY_HANDLE(&ptr, &len, &keyHandle)\n      || tpm_unmarshal_TPM_DELEGATE_PUBLIC(&ptr, &len, &publicInfo)\n      || tpm_unmarshal_TPM_ENCAUTH(&ptr, &len, &delAuth)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_Delegate_CreateKeyDelegation(keyHandle, &publicInfo, &delAuth, \n    &req->auth1, &blob);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  blobSize = sizeof_TPM_DELEGATE_KEY_BLOB(blob);\n  rsp->paramSize = len = 4 + blobSize;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_UINT32(&ptr, &len, blobSize)\n      || tpm_marshal_TPM_DELEGATE_KEY_BLOB(&ptr, &len, &blob)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  free_TPM_DELEGATE_KEY_BLOB(blob);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_Delegate_CreateOwnerDelegation(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  BOOL increment;\n  TPM_DELEGATE_PUBLIC publicInfo;\n  TPM_ENCAUTH delAuth;\n  UINT32 blobSize;\n  TPM_DELEGATE_OWNER_BLOB blob;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_BOOL(&ptr, &len, &increment)\n      || tpm_unmarshal_TPM_DELEGATE_PUBLIC(&ptr, &len, &publicInfo)\n      || tpm_unmarshal_TPM_ENCAUTH(&ptr, &len, &delAuth)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_Delegate_CreateOwnerDelegation(increment, &publicInfo, &delAuth, \n    &req->auth1, &blob);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  blobSize = sizeof_TPM_DELEGATE_OWNER_BLOB(blob);\n  rsp->paramSize = len = 4 + blobSize;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_UINT32(&ptr, &len, blobSize)\n      || tpm_marshal_TPM_DELEGATE_OWNER_BLOB(&ptr, &len, &blob)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  free_TPM_DELEGATE_OWNER_BLOB(blob);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_Delegate_LoadOwnerDelegation(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_DELEGATE_INDEX index;\n  UINT32 blobSize;\n  TPM_DELEGATE_OWNER_BLOB blob;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_DELEGATE_INDEX(&ptr, &len, &index)\n      || tpm_unmarshal_UINT32(&ptr, &len, &blobSize)\n      || tpm_unmarshal_TPM_DELEGATE_OWNER_BLOB(&ptr, &len, &blob)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  return TPM_Delegate_LoadOwnerDelegation(index, &blob, &req->auth1);\n}\n\nstatic TPM_RESULT execute_TPM_Delegate_ReadTable(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  UINT32 familyTableSize;\n  BYTE *familyTable = NULL;\n  UINT32 delegateTableSize;\n  BYTE *delegateTable = NULL;\n  TPM_RESULT res;\n  /* execute command */\n  res = TPM_Delegate_ReadTable(&familyTableSize, &familyTable, &delegateTableSize, &delegateTable);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 4 + familyTableSize + 4 + delegateTableSize;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_UINT32(&ptr, &len, familyTableSize)\n      || tpm_marshal_BLOB(&ptr, &len, familyTable, familyTableSize)\n      || tpm_marshal_UINT32(&ptr, &len, delegateTableSize)\n      || tpm_marshal_BLOB(&ptr, &len, delegateTable, delegateTableSize)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  tpm_free(familyTable);\n  tpm_free(delegateTable);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_Delegate_UpdateVerification(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  UINT32 inputSize;\n  BYTE *inputData;\n  UINT32 outputSize;\n  BYTE *outputData = NULL;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_UINT32(&ptr, &len, &inputSize)\n      || tpm_unmarshal_BLOB(&ptr, &len, &inputData, inputSize)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_Delegate_UpdateVerification(inputSize, inputData, \n    &req->auth1, &outputSize, &outputData);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 4 + outputSize;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_UINT32(&ptr, &len, outputSize)\n      || tpm_marshal_BLOB(&ptr, &len, outputData, outputSize)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  tpm_free(outputData);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_Delegate_VerifyDelegation(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  UINT32 delegateSize;\n  BYTE *delegation;\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_UINT32(&ptr, &len, &delegateSize)\n      || tpm_unmarshal_BLOB(&ptr, &len, &delegation, delegateSize)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  return TPM_Delegate_VerifyDelegation(delegateSize, delegation);\n}\n\nstatic TPM_RESULT execute_TPM_NV_DefineSpace(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_NV_DATA_PUBLIC pubInfo;\n  TPM_ENCAUTH encAuth;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_NV_DATA_PUBLIC(&ptr, &len, &pubInfo)\n      || tpm_unmarshal_TPM_ENCAUTH(&ptr, &len, &encAuth)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  return TPM_NV_DefineSpace(&pubInfo, &encAuth, &req->auth1);\n}\n\nstatic TPM_RESULT execute_TPM_NV_WriteValue(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_NV_INDEX nvIndex;\n  UINT32 offset;\n  UINT32 dataSize;\n  BYTE *data;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_NV_INDEX(&ptr, &len, &nvIndex)\n      || tpm_unmarshal_UINT32(&ptr, &len, &offset)\n      || tpm_unmarshal_UINT32(&ptr, &len, &dataSize)\n      || tpm_unmarshal_BLOB(&ptr, &len, &data, dataSize)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  return TPM_NV_WriteValue(nvIndex, offset, dataSize, data, &req->auth1);\n}\n\nstatic TPM_RESULT execute_TPM_NV_WriteValueAuth(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_NV_INDEX nvIndex;\n  UINT32 offset;\n  UINT32 dataSize;\n  BYTE *data;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_NV_INDEX(&ptr, &len, &nvIndex)\n      || tpm_unmarshal_UINT32(&ptr, &len, &offset)\n      || tpm_unmarshal_UINT32(&ptr, &len, &dataSize)\n      || tpm_unmarshal_BLOB(&ptr, &len, &data, dataSize)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  return TPM_NV_WriteValueAuth(nvIndex, offset, dataSize, data, &req->auth1);\n}\n\nstatic TPM_RESULT execute_TPM_NV_ReadValue(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_NV_INDEX nvIndex;\n  UINT32 offset;\n  UINT32 inDataSize;\n  UINT32 outDataSize;\n  BYTE *data = NULL;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_NV_INDEX(&ptr, &len, &nvIndex)\n      || tpm_unmarshal_UINT32(&ptr, &len, &offset)\n      || tpm_unmarshal_UINT32(&ptr, &len, &inDataSize)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_NV_ReadValue(nvIndex, offset, inDataSize, &req->auth1, &outDataSize, &data);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 4 + outDataSize;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_UINT32(&ptr, &len, outDataSize)\n      || tpm_marshal_BLOB(&ptr, &len, data, outDataSize)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  tpm_free(data);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_NV_ReadValueAuth(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_NV_INDEX nvIndex;\n  UINT32 offset;\n  UINT32 inDataSize;\n  UINT32 outDataSize;\n  BYTE *data = NULL;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_NV_INDEX(&ptr, &len, &nvIndex)\n      || tpm_unmarshal_UINT32(&ptr, &len, &offset)\n      || tpm_unmarshal_UINT32(&ptr, &len, &inDataSize)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_NV_ReadValueAuth(nvIndex, offset, inDataSize, &req->auth1, &outDataSize, &data);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 4 + outDataSize;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_UINT32(&ptr, &len, outDataSize)\n      || tpm_marshal_BLOB(&ptr, &len, data, outDataSize)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  tpm_free(data);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_KeyControlOwner(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_KEY_HANDLE keyHandle;\n  TPM_PUBKEY pubKey;\n  UINT32 bitName;\n  BOOL bitValue;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_KEY_HANDLE(&ptr, &len, &keyHandle)\n      || tpm_unmarshal_TPM_PUBKEY(&ptr, &len, &pubKey)\n      || tpm_unmarshal_UINT32(&ptr, &len, &bitName)\n      || tpm_unmarshal_BOOL(&ptr, &len, &bitValue)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  return TPM_KeyControlOwner(keyHandle, pubKey, bitName, bitValue, &req->auth1);\n}\n\nstatic TPM_RESULT execute_TPM_SaveContext(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_HANDLE handle;\n  TPM_RESOURCE_TYPE resourceType;\n  BYTE label[16];\n  UINT32 contextSize;\n  TPM_CONTEXT_BLOB contextBlob;\n  TPM_RESULT res;\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_HANDLE(&ptr, &len, &handle)\n      || tpm_unmarshal_TPM_RESOURCE_TYPE(&ptr, &len, &resourceType)\n      || tpm_unmarshal_BYTE_ARRAY(&ptr, &len, label, 16)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_SaveContext(handle, resourceType, label, &contextSize, &contextBlob);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 4 + contextSize;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_UINT32(&ptr, &len, contextSize)\n      || tpm_marshal_TPM_CONTEXT_BLOB(&ptr, &len, &contextBlob)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  free_TPM_CONTEXT_BLOB(contextBlob);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_LoadContext(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_HANDLE entityHandle;\n  BOOL keepHandle;\n  UINT32 contextSize;\n  TPM_CONTEXT_BLOB contextBlob;\n  TPM_HANDLE handle;\n  TPM_RESULT res;\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_HANDLE(&ptr, &len, &entityHandle)\n      || tpm_unmarshal_BOOL(&ptr, &len, &keepHandle)\n      || tpm_unmarshal_UINT32(&ptr, &len, &contextSize)\n      || tpm_unmarshal_TPM_CONTEXT_BLOB(&ptr, &len, &contextBlob)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_LoadContext(entityHandle, keepHandle, contextSize, &contextBlob, &handle);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 4;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_HANDLE(&ptr, &len, handle)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_FlushSpecific(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_HANDLE handle;\n  TPM_RESOURCE_TYPE resourceType;\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_HANDLE(&ptr, &len, &handle)\n      || tpm_unmarshal_TPM_RESOURCE_TYPE(&ptr, &len, &resourceType)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n#ifdef MTM_EMULATOR\n  return MTM_FlushSpecific(handle, resourceType);\n#else\n  return TPM_FlushSpecific(handle, resourceType);\n#endif\n}\n\nstatic TPM_RESULT execute_TPM_GetTicks(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_CURRENT_TICKS currentTime;\n  TPM_RESULT res;\n  /* execute command */\n  res = TPM_GetTicks(&currentTime);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 32;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_CURRENT_TICKS(&ptr, &len, &currentTime)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_TickStampBlob(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_KEY_HANDLE keyHandle;\n  TPM_NONCE antiReplay;\n  TPM_DIGEST digestToStamp;\n  TPM_CURRENT_TICKS currentTicks;\n  UINT32 sigSize;\n  BYTE *sig = NULL;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_KEY_HANDLE(&ptr, &len, &keyHandle)\n      || tpm_unmarshal_TPM_NONCE(&ptr, &len, &antiReplay)\n      || tpm_unmarshal_TPM_DIGEST(&ptr, &len, &digestToStamp)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_TickStampBlob(keyHandle, &antiReplay, &digestToStamp, &req->auth1, \n    &currentTicks, &sigSize, &sig);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 32 + 4 + sigSize;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_CURRENT_TICKS(&ptr, &len, &currentTicks)\n      || tpm_marshal_UINT32(&ptr, &len, sigSize)\n      || tpm_marshal_BLOB(&ptr, &len, sig, sigSize)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  tpm_free(sig);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_EstablishTransport(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_KEY_HANDLE encHandle;\n  TPM_TRANSPORT_PUBLIC transPublic;\n  UINT32 secretSize;\n  BYTE *secret;\n  TPM_TRANSHANDLE transHandle;\n  TPM_MODIFIER_INDICATOR locality;\n  TPM_CURRENT_TICKS currentTicks;\n  TPM_NONCE transNonce;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_KEY_HANDLE(&ptr, &len, &encHandle)\n      || tpm_unmarshal_TPM_TRANSPORT_PUBLIC(&ptr, &len, &transPublic)\n      || tpm_unmarshal_UINT32(&ptr, &len, &secretSize)\n      || tpm_unmarshal_BLOB(&ptr, &len, &secret, secretSize)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_EstablishTransport(encHandle, &transPublic, secretSize, secret, \n    &req->auth1, &transHandle, &locality, &currentTicks, &transNonce);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 4 + 4 + 32 + 20;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_TRANSHANDLE(&ptr, &len, transHandle)\n      || tpm_marshal_TPM_MODIFIER_INDICATOR(&ptr, &len,  locality)\n      || tpm_marshal_TPM_CURRENT_TICKS(&ptr, &len, &currentTicks)\n      || tpm_marshal_TPM_NONCE(&ptr, &len, &transNonce)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_ExecuteTransport(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  UINT32 inWrappedCmdSize;\n  BYTE *inWrappedCmd;\n  UINT64 currentTicks;\n  TPM_MODIFIER_INDICATOR locality;\n  UINT32 outWrappedCmdSize;\n  BYTE *outWrappedCmd = NULL;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_UINT32(&ptr, &len, &inWrappedCmdSize)\n      || tpm_unmarshal_BLOB(&ptr, &len, &inWrappedCmd, inWrappedCmdSize)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_ExecuteTransport(inWrappedCmdSize, inWrappedCmd, &req->auth1, \n    &currentTicks, &locality, &outWrappedCmdSize, &outWrappedCmd);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 8 + 4 + 4 + outWrappedCmdSize;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_UINT64(&ptr, &len, currentTicks)\n      || tpm_marshal_TPM_MODIFIER_INDICATOR(&ptr, &len, locality)\n      || tpm_marshal_UINT32(&ptr, &len, outWrappedCmdSize)\n      || tpm_marshal_BLOB(&ptr, &len, outWrappedCmd, outWrappedCmdSize)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  tpm_free(outWrappedCmd);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_ReleaseTransportSigned(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_KEY_HANDLE key;\n  TPM_NONCE antiReplay;\n  TPM_MODIFIER_INDICATOR locality;\n  TPM_CURRENT_TICKS currentTicks;\n  UINT32 signSize;\n  BYTE *signature = NULL;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_KEY_HANDLE(&ptr, &len, &key)\n      || tpm_unmarshal_TPM_NONCE(&ptr, &len, &antiReplay)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_ReleaseTransportSigned(key, &antiReplay, &req->auth1, &req->auth2, \n    &locality, &currentTicks, &signSize, &signature);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 4 + 32 + 4 + signSize;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_MODIFIER_INDICATOR(&ptr, &len, locality)\n      || tpm_marshal_TPM_CURRENT_TICKS(&ptr, &len, &currentTicks)\n      || tpm_marshal_UINT32(&ptr, &len, signSize)\n      || tpm_marshal_BLOB(&ptr, &len, signature, signSize)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  tpm_free(signature);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_CreateCounter(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_ENCAUTH authData;\n  BYTE label[4];\n  TPM_COUNT_ID countID;\n  TPM_COUNTER_VALUE counterValue;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_ENCAUTH(&ptr, &len, &authData)\n      || tpm_unmarshal_BYTE_ARRAY(&ptr, &len, label, 4)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_CreateCounter(&authData, label, &req->auth1, &countID, &counterValue);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 4 + sizeof_TPM_COUNTER_VALUE(counterValue);\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_COUNT_ID(&ptr, &len, countID)\n      || tpm_marshal_TPM_COUNTER_VALUE(&ptr, &len, &counterValue)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_IncrementCounter(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_COUNT_ID countID;\n  TPM_COUNTER_VALUE count;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_COUNT_ID(&ptr, &len, &countID)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_IncrementCounter(countID, &req->auth1, &count);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 10;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_COUNTER_VALUE(&ptr, &len, &count)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_ReadCounter(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_COUNT_ID countID;\n  TPM_COUNTER_VALUE count;\n  TPM_RESULT res;\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_COUNT_ID(&ptr, &len, &countID)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_ReadCounter(countID, &count);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 10;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_COUNTER_VALUE(&ptr, &len, &count)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_ReleaseCounter(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_COUNT_ID countID;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_COUNT_ID(&ptr, &len, &countID)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n#ifdef MTM_EMULATOR\n  return MTM_ReleaseCounter(countID, &req->auth1);\n#else\n  return TPM_ReleaseCounter(countID, &req->auth1);\n#endif\n}\n\nstatic TPM_RESULT execute_TPM_ReleaseCounterOwner(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_COUNT_ID countID;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_COUNT_ID(&ptr, &len, &countID)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n#ifdef MTM_EMULATOR\n  return MTM_ReleaseCounterOwner(countID, &req->auth1);\n#else\n  return TPM_ReleaseCounterOwner(countID, &req->auth1);\n#endif\n}\n\nstatic TPM_RESULT execute_TPM_DAA_Join(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_HANDLE handle;\n  BYTE stage;\n  UINT32 inputSize0;\n  BYTE *inputData0;\n  UINT32 inputSize1;\n  BYTE *inputData1;\n  TPM_COMMAND_CODE ordinal;\n  UINT32 outputSize;\n  BYTE *outputData = NULL;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_HANDLE(&ptr, &len, &handle)\n      || tpm_unmarshal_BYTE(&ptr, &len, &stage)\n      || tpm_unmarshal_UINT32(&ptr, &len, &inputSize0)\n      || tpm_unmarshal_BLOB(&ptr, &len, &inputData0, inputSize0)\n      || tpm_unmarshal_UINT32(&ptr, &len, &inputSize1)\n      || tpm_unmarshal_BLOB(&ptr, &len, &inputData1, inputSize1)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_DAA_Join(handle, stage, inputSize0, inputData0, inputSize1, \n    inputData1, &req->auth1, &ordinal, &outputSize, &outputData);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 4 + outputSize;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_UINT32(&ptr, &len, outputSize)\n      || tpm_marshal_BLOB(&ptr, &len, outputData, outputSize)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  tpm_free(outputData);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_DAA_Sign(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_HANDLE handle;\n  BYTE stage;\n  UINT32 inputSize0;\n  BYTE *inputData0;\n  UINT32 inputSize1;\n  BYTE *inputData1;\n  TPM_COMMAND_CODE ordinal;\n  UINT32 outputSize;\n  BYTE *outputData = NULL;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_HANDLE(&ptr, &len, &handle)\n      || tpm_unmarshal_BYTE(&ptr, &len, &stage)\n      || tpm_unmarshal_UINT32(&ptr, &len, &inputSize0)\n      || tpm_unmarshal_BLOB(&ptr, &len, &inputData0, inputSize0)\n      || tpm_unmarshal_UINT32(&ptr, &len, &inputSize1)\n      || tpm_unmarshal_BLOB(&ptr, &len, &inputData1, inputSize1)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_DAA_Sign(handle, stage, inputSize0, inputData0, inputSize1, \n    inputData1, &req->auth1, &ordinal, &outputSize, &outputData);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 4 + outputSize;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_UINT32(&ptr, &len, outputSize)\n      || tpm_marshal_BLOB(&ptr, &len, outputData, outputSize)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  tpm_free(outputData);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_EvictKey(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_KEY_HANDLE evictHandle;\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_KEY_HANDLE(&ptr, &len, &evictHandle)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  return TPM_EvictKey(evictHandle);\n}\n\nstatic TPM_RESULT execute_TPM_Terminate_Handle(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_AUTHHANDLE handle;\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_AUTHHANDLE(&ptr, &len, &handle)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  return TPM_Terminate_Handle(handle);\n}\n\nstatic TPM_RESULT execute_TPM_SaveKeyContext(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_KEY_HANDLE keyHandle;\n  UINT32 keyContextSize;\n  BYTE *keyContextBlob = NULL;\n  TPM_RESULT res;\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_KEY_HANDLE(&ptr, &len, &keyHandle)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_SaveKeyContext(keyHandle, &keyContextSize, &keyContextBlob);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 4 + keyContextSize;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_UINT32(&ptr, &len, keyContextSize)\n      || tpm_marshal_BLOB(&ptr, &len, keyContextBlob, keyContextSize)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  tpm_free(keyContextBlob);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_LoadKeyContext(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  UINT32 keyContextSize;\n  BYTE *keyContextBlob;\n  TPM_KEY_HANDLE keyHandle;\n  TPM_RESULT res;\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_UINT32(&ptr, &len, &keyContextSize)\n      || tpm_unmarshal_BLOB(&ptr, &len, &keyContextBlob, keyContextSize)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_LoadKeyContext(keyContextSize, keyContextBlob, &keyHandle);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 4;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_KEY_HANDLE(&ptr, &len, keyHandle)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_SaveAuthContext(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_AUTHHANDLE authandle;\n  UINT32 authContextSize;\n  BYTE *authContextBlob = NULL;\n  TPM_RESULT res;\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_AUTHHANDLE(&ptr, &len, &authandle)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_SaveAuthContext(authandle, &authContextSize, &authContextBlob);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 4 + authContextSize;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_UINT32(&ptr, &len, authContextSize)\n      || tpm_marshal_BLOB(&ptr, &len, authContextBlob, authContextSize)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  tpm_free(authContextBlob);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_LoadAuthContext(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  UINT32 authContextSize;\n  BYTE *authContextBlob;\n  TPM_KEY_HANDLE authHandle;\n  TPM_RESULT res;\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_UINT32(&ptr, &len, &authContextSize)\n      || tpm_unmarshal_BLOB(&ptr, &len, &authContextBlob, authContextSize)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_LoadAuthContext(authContextSize, authContextBlob, &authHandle);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 4;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_KEY_HANDLE(&ptr, &len, authHandle)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_DirWriteAuth(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_DIRINDEX dirIndex;\n  TPM_DIRVALUE newContents;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_DIRINDEX(&ptr, &len, &dirIndex)\n      || tpm_unmarshal_TPM_DIRVALUE(&ptr, &len, &newContents)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  return TPM_DirWriteAuth(dirIndex, &newContents, &req->auth1);\n}\n\nstatic TPM_RESULT execute_TPM_DirRead(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_DIRINDEX dirIndex;\n  TPM_DIRVALUE dirContents;\n  TPM_RESULT res;\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_DIRINDEX(&ptr, &len, &dirIndex)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_DirRead(dirIndex, &dirContents);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 20;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_DIRVALUE(&ptr, &len, &dirContents)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_ChangeAuthAsymStart(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_KEY_HANDLE idHandle;\n  TPM_NONCE antiReplay;\n  TPM_KEY_PARMS inTempKey;\n  TPM_CERTIFY_INFO certifyInfo;\n  UINT32 sigSize;\n  BYTE *sig = NULL;\n  TPM_KEY_HANDLE ephHandle;\n  TPM_KEY outTempKey;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_KEY_HANDLE(&ptr, &len, &idHandle)\n      || tpm_unmarshal_TPM_NONCE(&ptr, &len, &antiReplay)\n      || tpm_unmarshal_TPM_KEY_PARMS(&ptr, &len, &inTempKey)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_ChangeAuthAsymStart(idHandle, &antiReplay, &inTempKey, &req->auth1, \n    &certifyInfo, &sigSize, &sig, &ephHandle, &outTempKey);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 95 + 4 + sigSize + 4 + sizeof_TPM_KEY(outTempKey);\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_CERTIFY_INFO(&ptr, &len, &certifyInfo)\n      || tpm_marshal_UINT32(&ptr, &len, sigSize)\n      || tpm_marshal_BLOB(&ptr, &len, sig, sigSize)\n      || tpm_marshal_TPM_KEY_HANDLE(&ptr, &len, ephHandle)\n      || tpm_marshal_TPM_KEY(&ptr, &len, &outTempKey)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  tpm_free(sig);\n  free_TPM_KEY(outTempKey);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_ChangeAuthAsymFinish(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_KEY_HANDLE parentHandle;\n  TPM_KEY_HANDLE ephHandle;\n  TPM_ENTITY_TYPE entityType;\n  TPM_HMAC newAuthLink;\n  UINT32 newAuthSize;\n  BYTE *encNewAuth;\n  UINT32 encDataSize;\n  BYTE *encData;\n  UINT32 outDataSize;\n  BYTE *outData = NULL;\n  TPM_NONCE saltNonce;\n  TPM_DIGEST changeProof;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* unmarshal input */\n  ptr = req->param;\n  len = req->paramSize;\n  if (tpm_unmarshal_TPM_KEY_HANDLE(&ptr, &len, &parentHandle)\n      || tpm_unmarshal_TPM_KEY_HANDLE(&ptr, &len, &ephHandle)\n      || tpm_unmarshal_TPM_ENTITY_TYPE(&ptr, &len, &entityType)\n      || tpm_unmarshal_TPM_HMAC(&ptr, &len, &newAuthLink)\n      || tpm_unmarshal_UINT32(&ptr, &len, &newAuthSize)\n      || tpm_unmarshal_BLOB(&ptr, &len, &encNewAuth, newAuthSize)\n      || tpm_unmarshal_UINT32(&ptr, &len, &encDataSize)\n      || tpm_unmarshal_BLOB(&ptr, &len, &encData, encDataSize)\n      || len != 0) return TPM_BAD_PARAMETER;\n  /* execute command */\n  res = TPM_ChangeAuthAsymFinish(parentHandle, ephHandle, entityType, \n    &newAuthLink, newAuthSize, encNewAuth, encDataSize, encData, &req->auth1, \n    &outDataSize, &outData, &saltNonce, &changeProof);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = 4 + outDataSize + 20 + 20;\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_UINT32(&ptr, &len, outDataSize)\n      || tpm_marshal_BLOB(&ptr, &len, outData, outDataSize)\n      || tpm_marshal_TPM_NONCE(&ptr, &len, &saltNonce)\n      || tpm_marshal_TPM_DIGEST(&ptr, &len, &changeProof)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  tpm_free(outData);\n  return res;\n}\n\nstatic TPM_RESULT execute_TPM_Reset(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  /* execute command */\n  return TPM_Reset();\n}\n\nstatic TPM_RESULT execute_TPM_OwnerReadPubek(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  BYTE *ptr;\n  UINT32 len;\n  TPM_PUBKEY pubEndorsementKey;\n  TPM_RESULT res;\n  /* compute parameter digest */\n  tpm_compute_in_param_digest(req);\n  /* execute command */\n  res = TPM_OwnerReadPubek(&req->auth1, &pubEndorsementKey);\n  if (res != TPM_SUCCESS) return res;\n  /* marshal output */\n  rsp->paramSize = len = sizeof_TPM_PUBKEY(pubEndorsementKey);\n  rsp->param = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_PUBKEY(&ptr, &len, &pubEndorsementKey)) {\n    tpm_free(rsp->param);\n    res = TPM_FAIL;\n  }\n  free_TPM_PUBKEY(pubEndorsementKey);\n  return res;\n}\n\nstatic void tpm_setup_rsp_auth(TPM_COMMAND_CODE ordinal, TPM_RESPONSE *rsp) \n{\n  tpm_hmac_ctx_t hmac;\n\n  /* compute parameter digest */\n  if (ordinal != TPM_ORD_ExecuteTransport)\n    tpm_compute_out_param_digest(ordinal, rsp);\n  /* compute authorization values */\n  switch (rsp->tag) {\n    case TPM_TAG_RSP_AUTH2_COMMAND:\n      tpm_hmac_init(&hmac, rsp->auth2->secret, sizeof(rsp->auth2->secret));\n      tpm_hmac_update(&hmac, rsp->auth2->digest, sizeof(rsp->auth2->digest));\n      tpm_hmac_update(&hmac, rsp->auth2->nonceEven.nonce, \n                  sizeof(rsp->auth2->nonceEven.nonce));\n      tpm_hmac_update(&hmac, rsp->auth2->nonceOdd.nonce, \n                  sizeof(rsp->auth2->nonceOdd.nonce));\n      tpm_hmac_update(&hmac, (BYTE*)&rsp->auth2->continueAuthSession, 1);\n      tpm_hmac_final(&hmac, rsp->auth2->auth);\n      break;\n    case TPM_TAG_RSP_AUTH1_COMMAND:\n      tpm_hmac_init(&hmac, rsp->auth1->secret, sizeof(rsp->auth1->secret));\n      tpm_hmac_update(&hmac, rsp->auth1->digest, sizeof(rsp->auth1->digest));\n      tpm_hmac_update(&hmac, rsp->auth1->nonceEven.nonce, \n        sizeof(rsp->auth1->nonceEven.nonce));\n      tpm_hmac_update(&hmac, rsp->auth1->nonceOdd.nonce, \n        sizeof(rsp->auth1->nonceOdd.nonce));\n      tpm_hmac_update(&hmac, (BYTE*)&rsp->auth1->continueAuthSession, 1);\n      tpm_hmac_final(&hmac, rsp->auth1->auth);\n      break;\n  }\n}\n\nstatic void tpm_setup_error_response(TPM_RESULT res, TPM_RESPONSE *rsp)\n{\n  rsp->tag = TPM_TAG_RSP_COMMAND;\n  rsp->size = 10;\n  rsp->result = res;\n  rsp->param = NULL;\n  rsp->paramSize = 0;\n}\n\nstatic TPM_RESULT tpm_check_status_and_mode(TPM_REQUEST *req)\n{\n  /* verify that self-test succeeded */\n  if (!tpmData.permanent.flags.selfTestSucceeded) return TPM_FAILEDSELFTEST;\n  /* initialisation must be finished before we execute any command */\n  if (tpmData.stany.flags.postInitialise) return TPM_INVALID_POSTINIT;\n  /* if the TPM is deactivated only a subset of all commands can be performed */\n  if ((tpmData.permanent.flags.deactivated || tpmData.stclear.flags.deactivated)\n      && req->ordinal != TPM_ORD_Reset\n      && req->ordinal != TPM_ORD_Init\n      && req->ordinal != TPM_ORD_Startup\n      && req->ordinal != TPM_ORD_SaveState\n      && req->ordinal != TPM_ORD_SHA1Start\n      && req->ordinal != TPM_ORD_SHA1Update\n      && req->ordinal != TPM_ORD_SHA1Complete\n      && req->ordinal != TPM_ORD_SHA1CompleteExtend\n      && req->ordinal != TPM_ORD_OIAP\n      && req->ordinal != TPM_ORD_OSAP\n      && req->ordinal != TPM_ORD_DSAP\n      && req->ordinal != TPM_ORD_GetCapability\n      && req->ordinal != TPM_ORD_SetCapability\n      && req->ordinal != TPM_ORD_TakeOwnership\n      && req->ordinal != TPM_ORD_OwnerSetDisable\n      && req->ordinal != TPM_ORD_PhysicalDisable\n      && req->ordinal != TPM_ORD_PhysicalEnable\n      && req->ordinal != TPM_ORD_PhysicalSetDeactivated\n      && req->ordinal != TPM_ORD_ContinueSelfTest\n      && req->ordinal != TPM_ORD_SelfTestFull\n      && req->ordinal != TPM_ORD_GetTestResult\n      && req->ordinal != TPM_ORD_FlushSpecific\n      && req->ordinal != TPM_ORD_Terminate_Handle\n      && req->ordinal != TPM_ORD_Extend\n      && req->ordinal != TPM_ORD_PCR_Reset\n      && req->ordinal != TPM_ORD_NV_DefineSpace\n      && req->ordinal != TPM_ORD_NV_ReadValue\n      && req->ordinal != TPM_ORD_NV_WriteValue\n      && req->ordinal != TSC_ORD_PhysicalPresence\n      && req->ordinal != TSC_ORD_ResetEstablishmentBit\n      ) return TPM_DEACTIVATED;\n  /* if the TPM is disabled only a subset of all commands can be performed */\n  if (tpmData.permanent.flags.disable\n      && req->ordinal != TPM_ORD_Reset\n      && req->ordinal != TPM_ORD_Init\n      && req->ordinal != TPM_ORD_Startup\n      && req->ordinal != TPM_ORD_SaveState\n      && req->ordinal != TPM_ORD_SHA1Start\n      && req->ordinal != TPM_ORD_SHA1Update\n      && req->ordinal != TPM_ORD_SHA1Complete\n      && req->ordinal != TPM_ORD_SHA1CompleteExtend\n      && req->ordinal != TPM_ORD_OIAP\n      && req->ordinal != TPM_ORD_OSAP\n      && req->ordinal != TPM_ORD_DSAP\n      && req->ordinal != TPM_ORD_GetCapability\n      && req->ordinal != TPM_ORD_SetCapability\n      && req->ordinal != TPM_ORD_OwnerSetDisable\n      && req->ordinal != TPM_ORD_PhysicalEnable\n      && req->ordinal != TPM_ORD_ContinueSelfTest\n      && req->ordinal != TPM_ORD_SelfTestFull\n      && req->ordinal != TPM_ORD_GetTestResult\n      && req->ordinal != TPM_ORD_FlushSpecific\n      && req->ordinal != TPM_ORD_Terminate_Handle\n      && req->ordinal != TPM_ORD_Extend\n      && req->ordinal != TPM_ORD_PCR_Reset\n      && req->ordinal != TPM_ORD_NV_DefineSpace\n      && req->ordinal != TPM_ORD_NV_ReadValue\n      && req->ordinal != TPM_ORD_NV_WriteValue\n      && req->ordinal != TSC_ORD_PhysicalPresence\n      && req->ordinal != TSC_ORD_ResetEstablishmentBit\n      ) return TPM_DISABLED;\n  return TPM_SUCCESS; \n}\n\nvoid tpm_execute_command(TPM_REQUEST *req, TPM_RESPONSE *rsp)\n{\n  TPM_RESULT res;\n  \n  /* setup authorisation as well as response tag and size */\n  memset(rsp, 0, sizeof(*rsp));\n  switch (req->tag) {\n    case TPM_TAG_RQU_AUTH2_COMMAND:\n      debug(\"[TPM_TAG_RQU_AUTH2_COMMAND]\");\n      rsp->tag = TPM_TAG_RSP_AUTH2_COMMAND;\n      rsp->size = 10 + 2 * 41;\n      rsp->auth1 = &req->auth1;\n      rsp->auth2 = &req->auth2;\n      break;\n\n    case TPM_TAG_RQU_AUTH1_COMMAND:\n      debug(\"[TPM_TAG_RQU_AUTH1_COMMAND]\");\n      rsp->tag = TPM_TAG_RSP_AUTH1_COMMAND;\n      rsp->size = 10 + 41;\n      rsp->auth1 = &req->auth1;\n      break;\n\n    case TPM_TAG_RQU_COMMAND:\n      debug(\"[TPM_TAG_RQU_COMMAND]\");\n      rsp->tag = TPM_TAG_RSP_COMMAND;\n      rsp->size = 10;\n      break;\n\n    default:\n      info(\"The tag value sent to for a command (0x%02x) is invalid\", req->tag);\n      tpm_setup_error_response(TPM_BADTAG, rsp);\n      return;\n  }\n\n  /* check whether the command is allowed in the current mode of the TPM */\n  res = tpm_check_status_and_mode(req);\n  if (res != TPM_SUCCESS) {\n    info(\"tpm_check_status_and_mode(0x%02x) failed: (0x%02x) %s\", \n         req->ordinal, res, tpm_error_to_string(res));\n    tpm_setup_error_response(res, rsp);\n    return;\n  }\n\n  /* handle command ordinal */\n  switch (req->ordinal) {\n    case TPM_ORD_Startup:\n      debug(\"[TPM_ORD_Startup]\");\n      res = execute_TPM_Startup(req, rsp);\n    break;\n\n    case TPM_ORD_SaveState:\n      debug(\"[TPM_ORD_SaveState]\");\n      res = execute_TPM_SaveState(req, rsp);\n    break;\n\n    case TPM_ORD_SelfTestFull:\n      debug(\"[TPM_ORD_SelfTestFull]\");\n      res = execute_TPM_SelfTestFull(req, rsp);\n    break;\n\n    case TPM_ORD_ContinueSelfTest:\n      debug(\"[TPM_ORD_ContinueSelfTest]\");\n      res = execute_TPM_ContinueSelfTest(req, rsp);\n    break;\n\n    case TPM_ORD_GetTestResult:\n      debug(\"[TPM_ORD_GetTestResult]\");\n      res = execute_TPM_GetTestResult(req, rsp);\n    break;\n\n    case TPM_ORD_SetOwnerInstall:\n      debug(\"[TPM_ORD_SetOwnerInstall]\");\n      res = execute_TPM_SetOwnerInstall(req, rsp);\n    break;\n\n    case TPM_ORD_OwnerSetDisable:\n      debug(\"[TPM_ORD_OwnerSetDisable]\");\n      res = execute_TPM_OwnerSetDisable(req, rsp);\n    break;\n\n    case TPM_ORD_PhysicalEnable:\n      debug(\"[TPM_ORD_PhysicalEnable]\");\n      res = execute_TPM_PhysicalEnable(req, rsp);\n    break;\n\n    case TPM_ORD_PhysicalDisable:\n      debug(\"[TPM_ORD_PhysicalDisable]\");\n      res = execute_TPM_PhysicalDisable(req, rsp);\n    break;\n\n    case TPM_ORD_PhysicalSetDeactivated:\n      debug(\"[TPM_ORD_PhysicalSetDeactivated]\");\n      res = execute_TPM_PhysicalSetDeactivated(req, rsp);\n    break;\n\n    case TPM_ORD_SetTempDeactivated:\n      debug(\"[TPM_ORD_SetTempDeactivated]\");\n      res = execute_TPM_SetTempDeactivated(req, rsp);\n    break;\n\n    case TPM_ORD_SetOperatorAuth:\n      debug(\"[TPM_ORD_SetOperatorAuth]\");\n      res = execute_TPM_SetOperatorAuth(req, rsp);\n    break;\n\n    case TPM_ORD_TakeOwnership:\n      debug(\"[TPM_ORD_TakeOwnership]\");\n      res = execute_TPM_TakeOwnership(req, rsp);\n    break;\n\n    case TPM_ORD_OwnerClear:\n      debug(\"[TPM_ORD_OwnerClear]\");\n      res = execute_TPM_OwnerClear(req, rsp);\n    break;\n\n    case TPM_ORD_ForceClear:\n      debug(\"[TPM_ORD_ForceClear]\");\n      res = execute_TPM_ForceClear(req, rsp);\n    break;\n\n    case TPM_ORD_DisableOwnerClear:\n      debug(\"[TPM_ORD_DisableOwnerClear]\");\n      res = execute_TPM_DisableOwnerClear(req, rsp);\n    break;\n\n    case TPM_ORD_DisableForceClear:\n      debug(\"[TPM_ORD_DisableForceClear]\");\n      res = execute_TPM_DisableForceClear(req, rsp);\n    break;\n\n    case TSC_ORD_PhysicalPresence:\n      res = execute_TSC_PhysicalPresence(req, rsp);\n    break;\n\n    case TSC_ORD_ResetEstablishmentBit:\n      res = execute_TSC_ResetEstablishmentBit(req, rsp);\n    break;\n\n    case TPM_ORD_GetCapability:\n      debug(\"[TPM_ORD_GetCapability]\");\n      res = execute_TPM_GetCapability(req, rsp);\n    break;\n\n    case TPM_ORD_SetCapability:\n      debug(\"[TPM_ORD_SetCapability]\");\n      res = execute_TPM_SetCapability(req, rsp);\n    break;\n\n    case TPM_ORD_GetCapabilityOwner:\n      debug(\"[TPM_ORD_GetCapabilityOwner]\");\n      res = execute_TPM_GetCapabilityOwner(req, rsp);\n    break;\n\n    case TPM_ORD_GetAuditDigest:\n      debug(\"[TPM_ORD_GetAuditDigest]\");\n      res = execute_TPM_GetAuditDigest(req, rsp);\n    break;\n\n    case TPM_ORD_GetAuditDigestSigned:\n      debug(\"[TPM_ORD_GetAuditDigestSigned]\");\n      res = execute_TPM_GetAuditDigestSigned(req, rsp);\n    break;\n\n    case TPM_ORD_SetOrdinalAuditStatus:\n      debug(\"[TPM_ORD_SetOrdinalAuditStatus]\");\n      res = execute_TPM_SetOrdinalAuditStatus(req, rsp);\n    break;\n\n    case TPM_ORD_FieldUpgrade:\n      debug(\"[TPM_ORD_FieldUpgrade]\");\n      res = execute_TPM_FieldUpgrade(req, rsp);\n    break;\n\n    case TPM_ORD_SetRedirection:\n      debug(\"[TPM_ORD_SetRedirection]\");\n      res = execute_TPM_SetRedirection(req, rsp);\n    break;\n\n    case TPM_ORD_ResetLockValue:\n      debug(\"[TPM_ORD_ResetLockValue]\");\n      res = execute_TPM_ResetLockValue(req, rsp);\n    break;\n\n    case TPM_ORD_Seal:\n      debug(\"[TPM_ORD_Seal]\");\n      res = execute_TPM_Seal(req, rsp);\n    break;\n\n    case TPM_ORD_Unseal:\n      debug(\"[TPM_ORD_Unseal]\");\n      res = execute_TPM_Unseal(req, rsp);\n    break;\n\n    case TPM_ORD_UnBind:\n      debug(\"[TPM_ORD_UnBind]\");\n      res = execute_TPM_UnBind(req, rsp);\n    break;\n\n    case TPM_ORD_CreateWrapKey:\n      debug(\"[TPM_ORD_CreateWrapKey]\");\n      res = execute_TPM_CreateWrapKey(req, rsp);\n    break;\n\n    case TPM_ORD_LoadKey:\n      debug(\"[TPM_ORD_LoadKey]\");\n      res = execute_TPM_LoadKey(req, rsp);\n    break;\n\n    case TPM_ORD_LoadKey2:\n      debug(\"[TPM_ORD_LoadKey2]\");\n      res = execute_TPM_LoadKey2(req, rsp);\n    break;\n\n    case TPM_ORD_GetPubKey:\n      debug(\"[TPM_ORD_GetPubKey]\");\n      res = execute_TPM_GetPubKey(req, rsp);\n    break;\n\n    case TPM_ORD_Sealx:\n      debug(\"[TPM_ORD_Sealx]\");\n      res = execute_TPM_Sealx(req, rsp);\n    break;\n\n    case TPM_ORD_CreateMigrationBlob:\n      debug(\"[TPM_ORD_CreateMigrationBlob]\");\n      res = execute_TPM_CreateMigrationBlob(req, rsp);\n    break;\n\n    case TPM_ORD_ConvertMigrationBlob:\n      debug(\"[TPM_ORD_ConvertMigrationBlob]\");\n      res = execute_TPM_ConvertMigrationBlob(req, rsp);\n    break;\n\n    case TPM_ORD_AuthorizeMigrationKey:\n      debug(\"[TPM_ORD_AuthorizeMigrationKey]\");\n      res = execute_TPM_AuthorizeMigrationKey(req, rsp);\n    break;\n\n    case TPM_ORD_MigrateKey:\n      debug(\"[TPM_ORD_MigrateKey]\");\n      res = execute_TPM_MigrateKey(req, rsp);\n    break;\n\n    case TPM_ORD_CMK_SetRestrictions:\n      debug(\"[TPM_ORD_CMK_SetRestrictions]\");\n      res = execute_TPM_CMK_SetRestrictions(req, rsp);\n    break;\n\n    case TPM_ORD_CMK_ApproveMA:\n      debug(\"[TPM_ORD_CMK_ApproveMA]\");\n      res = execute_TPM_CMK_ApproveMA(req, rsp);\n    break;\n\n    case TPM_ORD_CMK_CreateKey:\n      debug(\"[TPM_ORD_CMK_CreateKey]\");\n      res = execute_TPM_CMK_CreateKey(req, rsp);\n    break;\n\n    case TPM_ORD_CMK_CreateTicket:\n      debug(\"[TPM_ORD_CMK_CreateTicket]\");\n      res = execute_TPM_CMK_CreateTicket(req, rsp);\n    break;\n\n    case TPM_ORD_CMK_CreateBlob:\n      debug(\"[TPM_ORD_CMK_CreateBlob]\");\n      res = execute_TPM_CMK_CreateBlob(req, rsp);\n    break;\n\n    case TPM_ORD_CMK_ConvertMigration:\n      debug(\"[TPM_ORD_CMK_ConvertMigration]\");\n      res = execute_TPM_CMK_ConvertMigration(req, rsp);\n    break;\n\n    case TPM_ORD_CreateMaintenanceArchive:\n      debug(\"[TPM_ORD_CreateMaintenanceArchive]\");\n      res = execute_TPM_CreateMaintenanceArchive(req, rsp);\n    break;\n\n    case TPM_ORD_LoadMaintenanceArchive:\n      debug(\"[TPM_ORD_LoadMaintenanceArchive]\");\n      res = execute_TPM_LoadMaintenanceArchive(req, rsp);\n    break;\n\n    case TPM_ORD_KillMaintenanceFeature:\n      debug(\"[TPM_ORD_KillMaintenanceFeature]\");\n      res = execute_TPM_KillMaintenanceFeature(req, rsp);\n    break;\n\n    case TPM_ORD_LoadManuMaintPub:\n      debug(\"[TPM_ORD_LoadManuMaintPub]\");\n      res = execute_TPM_LoadManuMaintPub(req, rsp);\n    break;\n\n    case TPM_ORD_ReadManuMaintPub:\n      debug(\"[TPM_ORD_ReadManuMaintPub]\");\n      res = execute_TPM_ReadManuMaintPub(req, rsp);\n    break;\n\n    case TPM_ORD_SHA1Start:\n      debug(\"[TPM_ORD_SHA1Start]\");\n      res = execute_TPM_SHA1Start(req, rsp);\n    break;\n\n    case TPM_ORD_SHA1Update:\n      debug(\"[TPM_ORD_SHA1Update]\");\n      res = execute_TPM_SHA1Update(req, rsp);\n    break;\n\n    case TPM_ORD_SHA1Complete:\n      debug(\"[TPM_ORD_SHA1Complete]\");\n      res = execute_TPM_SHA1Complete(req, rsp);\n    break;\n\n    case TPM_ORD_SHA1CompleteExtend:\n      debug(\"[TPM_ORD_SHA1CompleteExtend]\");\n      res = execute_TPM_SHA1CompleteExtend(req, rsp);\n    break;\n\n    case TPM_ORD_Sign:\n      debug(\"[TPM_ORD_Sign]\");\n      res = execute_TPM_Sign(req, rsp);\n    break;\n\n    case TPM_ORD_GetRandom:\n      debug(\"[TPM_ORD_GetRandom]\");\n      res = execute_TPM_GetRandom(req, rsp);\n    break;\n\n    case TPM_ORD_StirRandom:\n      debug(\"[TPM_ORD_StirRandom]\");\n      res = execute_TPM_StirRandom(req, rsp);\n    break;\n\n    case TPM_ORD_CertifyKey:\n      debug(\"[TPM_ORD_CertifyKey]\");\n      res = execute_TPM_CertifyKey(req, rsp);\n    break;\n\n    case TPM_ORD_CertifyKey2:\n      debug(\"[TPM_ORD_CertifyKey2]\");\n      res = execute_TPM_CertifyKey2(req, rsp);\n    break;\n\n    case TPM_ORD_CreateEndorsementKeyPair:\n      debug(\"[TPM_ORD_CreateEndorsementKeyPair]\");\n      res = execute_TPM_CreateEndorsementKeyPair(req, rsp);\n    break;\n\n    case TPM_ORD_CreateRevocableEK:\n      debug(\"[TPM_ORD_CreateRevocableEK]\");\n      res = execute_TPM_CreateRevocableEK(req, rsp);\n    break;\n\n    case TPM_ORD_RevokeTrust:\n      debug(\"[TPM_ORD_RevokeTrust]\");\n      res = execute_TPM_RevokeTrust(req, rsp);\n    break;\n\n    case TPM_ORD_ReadPubek:\n      debug(\"[TPM_ORD_ReadPubek]\");\n      res = execute_TPM_ReadPubek(req, rsp);\n    break;\n\n    case TPM_ORD_DisablePubekRead:\n      debug(\"[TPM_ORD_DisablePubekRead]\");\n      res = execute_TPM_DisablePubekRead(req, rsp);\n    break;\n\n    case TPM_ORD_OwnerReadInternalPub:\n      debug(\"[TPM_ORD_OwnerReadInternalPub]\");\n      res = execute_TPM_OwnerReadInternalPub(req, rsp);\n    break;\n\n    case TPM_ORD_MakeIdentity:\n      debug(\"[TPM_ORD_MakeIdentity]\");\n      res = execute_TPM_MakeIdentity(req, rsp);\n    break;\n\n    case TPM_ORD_ActivateIdentity:\n      debug(\"[TPM_ORD_ActivateIdentity]\");\n      res = execute_TPM_ActivateIdentity(req, rsp);\n    break;\n\n    case TPM_ORD_Extend:\n      debug(\"[TPM_ORD_Extend]\");\n      res = execute_TPM_Extend(req, rsp);\n    break;\n\n    case TPM_ORD_PCRRead:\n      debug(\"[TPM_ORD_PCRRead]\");\n      res = execute_TPM_PCRRead(req, rsp);\n    break;\n\n    case TPM_ORD_Quote:\n      debug(\"[TPM_ORD_Quote]\");\n      res = execute_TPM_Quote(req, rsp);\n    break;\n\n    case TPM_ORD_PCR_Reset:\n      debug(\"[TPM_ORD_PCR_Reset]\");\n      res = execute_TPM_PCR_Reset(req, rsp);\n    break;\n\n    case TPM_ORD_Quote2:\n      debug(\"[TPM_ORD_Quote2]\");\n      res = execute_TPM_Quote2(req, rsp);\n    break;\n\n    case TPM_ORD_ChangeAuth:\n      debug(\"[TPM_ORD_ChangeAuth]\");\n      res = execute_TPM_ChangeAuth(req, rsp);\n    break;\n\n    case TPM_ORD_ChangeAuthOwner:\n      debug(\"[TPM_ORD_ChangeAuthOwner]\");\n      res = execute_TPM_ChangeAuthOwner(req, rsp);\n    break;\n\n    case TPM_ORD_OIAP:\n      debug(\"[TPM_ORD_OIAP]\");\n      res = execute_TPM_OIAP(req, rsp);\n    break;\n\n    case TPM_ORD_OSAP:\n      debug(\"[TPM_ORD_OSAP]\");\n      res = execute_TPM_OSAP(req, rsp);\n    break;\n\n    case TPM_ORD_DSAP:\n      debug(\"[TPM_ORD_DSAP]\");\n      res = execute_TPM_DSAP(req, rsp);\n    break;\n\n    case TPM_ORD_SetOwnerPointer:\n      debug(\"[TPM_ORD_SetOwnerPointer]\");\n      res = execute_TPM_SetOwnerPointer(req, rsp);\n    break;\n\n    case TPM_ORD_Delegate_Manage:\n      debug(\"[TPM_ORD_Delegate_Manage]\");\n      res = execute_TPM_Delegate_Manage(req, rsp);\n    break;\n\n    case TPM_ORD_Delegate_CreateKeyDelegation:\n      debug(\"[TPM_ORD_Delegate_CreateKeyDelegation]\");\n      res = execute_TPM_Delegate_CreateKeyDelegation(req, rsp);\n    break;\n\n    case TPM_ORD_Delegate_CreateOwnerDelegation:\n      debug(\"[TPM_ORD_Delegate_CreateOwnerDelegation]\");\n      res = execute_TPM_Delegate_CreateOwnerDelegation(req, rsp);\n    break;\n\n    case TPM_ORD_Delegate_LoadOwnerDelegation:\n      debug(\"[TPM_ORD_Delegate_LoadOwnerDelegation]\");\n      res = execute_TPM_Delegate_LoadOwnerDelegation(req, rsp);\n    break;\n\n    case TPM_ORD_Delegate_ReadTable:\n      debug(\"[TPM_ORD_Delegate_ReadTable]\");\n      res = execute_TPM_Delegate_ReadTable(req, rsp);\n    break;\n\n    case TPM_ORD_Delegate_UpdateVerification:\n      debug(\"[TPM_ORD_Delegate_UpdateVerification]\");\n      res = execute_TPM_Delegate_UpdateVerification(req, rsp);\n    break;\n\n    case TPM_ORD_Delegate_VerifyDelegation:\n      debug(\"[TPM_ORD_Delegate_VerifyDelegation]\");\n      res = execute_TPM_Delegate_VerifyDelegation(req, rsp);\n    break;\n\n    case TPM_ORD_NV_DefineSpace:\n      debug(\"[TPM_ORD_NV_DefineSpace]\");\n      res = execute_TPM_NV_DefineSpace(req, rsp);\n    break;\n\n    case TPM_ORD_NV_WriteValue:\n      debug(\"[TPM_ORD_NV_WriteValue]\");\n      res = execute_TPM_NV_WriteValue(req, rsp);\n    break;\n\n    case TPM_ORD_NV_WriteValueAuth:\n      debug(\"[TPM_ORD_NV_WriteValueAuth]\");\n      res = execute_TPM_NV_WriteValueAuth(req, rsp);\n    break;\n\n    case TPM_ORD_NV_ReadValue:\n      debug(\"[TPM_ORD_NV_ReadValue]\");\n      res = execute_TPM_NV_ReadValue(req, rsp);\n    break;\n\n    case TPM_ORD_NV_ReadValueAuth:\n      debug(\"[TPM_ORD_NV_ReadValueAuth]\");\n      res = execute_TPM_NV_ReadValueAuth(req, rsp);\n    break;\n\n    case TPM_ORD_KeyControlOwner:\n      debug(\"[TPM_ORD_KeyControlOwner]\");\n      res = execute_TPM_KeyControlOwner(req, rsp);\n    break;\n\n    case TPM_ORD_SaveContext:\n      debug(\"[TPM_ORD_SaveContext]\");\n      res = execute_TPM_SaveContext(req, rsp);\n    break;\n\n    case TPM_ORD_LoadContext:\n      debug(\"[TPM_ORD_LoadContext]\");\n      res = execute_TPM_LoadContext(req, rsp);\n    break;\n\n    case TPM_ORD_FlushSpecific:\n      debug(\"[TPM_ORD_FlushSpecific]\");\n      res = execute_TPM_FlushSpecific(req, rsp);\n    break;\n\n    case TPM_ORD_GetTicks:\n      debug(\"[TPM_ORD_GetTicks]\");\n      res = execute_TPM_GetTicks(req, rsp);\n    break;\n\n    case TPM_ORD_TickStampBlob:\n      debug(\"[TPM_ORD_TickStampBlob]\");\n      res = execute_TPM_TickStampBlob(req, rsp);\n    break;\n\n    case TPM_ORD_EstablishTransport:\n      debug(\"[TPM_ORD_EstablishTransport]\");\n      res = execute_TPM_EstablishTransport(req, rsp);\n    break;\n\n    case TPM_ORD_ExecuteTransport:\n      debug(\"[TPM_ORD_ExecuteTransport]\");\n      res = execute_TPM_ExecuteTransport(req, rsp);\n    break;\n\n    case TPM_ORD_ReleaseTransportSigned:\n      debug(\"[TPM_ORD_ReleaseTransportSigned]\");\n      res = execute_TPM_ReleaseTransportSigned(req, rsp);\n    break;\n\n    case TPM_ORD_CreateCounter:\n      debug(\"[TPM_ORD_CreateCounter]\");\n      res = execute_TPM_CreateCounter(req, rsp);\n    break;\n\n    case TPM_ORD_IncrementCounter:\n      debug(\"[TPM_ORD_IncrementCounter]\");\n      res = execute_TPM_IncrementCounter(req, rsp);\n    break;\n\n    case TPM_ORD_ReadCounter:\n      debug(\"[TPM_ORD_ReadCounter]\");\n      res = execute_TPM_ReadCounter(req, rsp);\n    break;\n\n    case TPM_ORD_ReleaseCounter:\n      debug(\"[TPM_ORD_ReleaseCounter]\");\n      res = execute_TPM_ReleaseCounter(req, rsp);\n    break;\n\n    case TPM_ORD_ReleaseCounterOwner:\n      debug(\"[TPM_ORD_ReleaseCounterOwner]\");\n      res = execute_TPM_ReleaseCounterOwner(req, rsp);\n    break;\n\n    case TPM_ORD_DAA_Join:\n      debug(\"[TPM_ORD_DAA_Join]\");\n      res = execute_TPM_DAA_Join(req, rsp);\n    break;\n\n    case TPM_ORD_DAA_Sign:\n      debug(\"[TPM_ORD_DAA_Sign]\");\n      res = execute_TPM_DAA_Sign(req, rsp);\n    break;\n\n    case TPM_ORD_EvictKey:\n      debug(\"[TPM_ORD_EvictKey]\");\n      res = execute_TPM_EvictKey(req, rsp);\n    break;\n\n    case TPM_ORD_Terminate_Handle:\n      debug(\"[TPM_ORD_Terminate_Handle]\");\n      res = execute_TPM_Terminate_Handle(req, rsp);\n    break;\n\n    case TPM_ORD_SaveKeyContext:\n      debug(\"[TPM_ORD_SaveKeyContext]\");\n      res = execute_TPM_SaveKeyContext(req, rsp);\n    break;\n\n    case TPM_ORD_LoadKeyContext:\n      debug(\"[TPM_ORD_LoadKeyContext]\");\n      res = execute_TPM_LoadKeyContext(req, rsp);\n    break;\n\n    case TPM_ORD_SaveAuthContext:\n      debug(\"[TPM_ORD_SaveAuthContext]\");\n      res = execute_TPM_SaveAuthContext(req, rsp);\n    break;\n\n    case TPM_ORD_LoadAuthContext:\n      debug(\"[TPM_ORD_LoadAuthContext]\");\n      res = execute_TPM_LoadAuthContext(req, rsp);\n    break;\n\n    case TPM_ORD_DirWriteAuth:\n      debug(\"[TPM_ORD_DirWriteAuth]\");\n      res = execute_TPM_DirWriteAuth(req, rsp);\n    break;\n\n    case TPM_ORD_DirRead:\n      debug(\"[TPM_ORD_DirRead]\");\n      res = execute_TPM_DirRead(req, rsp);\n    break;\n\n    case TPM_ORD_ChangeAuthAsymStart:\n      debug(\"[TPM_ORD_ChangeAuthAsymStart]\");\n      res = execute_TPM_ChangeAuthAsymStart(req, rsp);\n    break;\n\n    case TPM_ORD_ChangeAuthAsymFinish:\n      debug(\"[TPM_ORD_ChangeAuthAsymFinish]\");\n      res = execute_TPM_ChangeAuthAsymFinish(req, rsp);\n    break;\n\n    case TPM_ORD_Reset:\n      debug(\"[TPM_ORD_Reset]\");\n      res = execute_TPM_Reset(req, rsp);\n    break;\n\n    case TPM_ORD_OwnerReadPubek:\n      debug(\"[TPM_ORD_OwnerReadPubek]\");\n      res = execute_TPM_OwnerReadPubek(req, rsp);\n    break;\n\n    default:\n#ifdef MTM_EMULATOR\n      res = mtm_execute_command(req, rsp);\n      if (res != TPM_BAD_ORDINAL) break;\n#endif\n      info(\"The ordinal (0x%02x) was unknown or inconsistent\", req->ordinal);\n      tpm_setup_error_response(TPM_BAD_ORDINAL, rsp);\n      return;\n  }\n\n  /* setup response */\n  if (res != TPM_SUCCESS) {\n    info(\"TPM command failed: (0x%02x) %s\", res, tpm_error_to_string(res));\n    tpm_setup_error_response(res, rsp);\n    if (!(res & TPM_NON_FATAL)) {\n      if (rsp->auth1 != NULL) rsp->auth1->continueAuthSession = FALSE;\n      if (rsp->auth2 != NULL) rsp->auth2->continueAuthSession = FALSE;\n    }\n  } else {\n    info(\"TPM command succeeded\");\n    rsp->size += rsp->paramSize;\n    if (rsp->tag != TPM_TAG_RSP_COMMAND) tpm_setup_rsp_auth(req->ordinal, rsp);\n    if (tpmConf & TPM_CONF_STRONG_PERSISTENCE) {\n      if (tpm_store_permanent_data() != 0) {\n        error(\"tpm_store_permanent_data() failed\");\n      }\n    }\n  }\n  /* terminate authorization sessions if necessary */\n  if (rsp->auth1 != NULL && !rsp->auth1->continueAuthSession) \n    TPM_FlushSpecific(rsp->auth1->authHandle, HANDLE_TO_RT(rsp->auth1->authHandle));\n  if (rsp->auth2 != NULL && !rsp->auth2->continueAuthSession) \n    TPM_FlushSpecific(rsp->auth2->authHandle, TPM_RT_AUTH);\n  /* if transportExclusive is set, only the execution of TPM_ExecuteTransport\n     and TPM_ReleaseTransportSigned is allowed */\n  if (tpmData.stany.flags.transportExclusive\n      && req->ordinal != TPM_ORD_ExecuteTransport\n      && req->ordinal != TPM_ORD_ReleaseTransportSigned) {\n    TPM_FlushSpecific(tpmData.stany.data.transExclusive, TPM_RT_TRANS);\n    tpmData.stany.flags.transportExclusive = FALSE;\n  }\n}\n\nint tpm_emulator_init(uint32_t startup, uint32_t conf)\n{\n  /* initialize external functions and data */\n  if (tpm_extern_init() != 0) return -1;\n  /* initialize the emulator */\n  debug(\"tpm_emulator_init(%d, 0x%08x)\", startup, conf);\n  tpmConf = conf;\n#ifdef MTM_EMULATOR\n  info(\"MTM support enabled\");\n#endif\n  /* try to restore data, if it fails use default values */\n  if (tpm_restore_permanent_data() != 0) tpm_init_data();\n  TPM_Init(startup);\n  return 0;\n}\n\nvoid tpm_emulator_shutdown()\n{\n  debug(\"tpm_emulator_shutdown()\");\n  if (TPM_SaveState() != TPM_SUCCESS) {\n    error(\"TPM_SaveState() failed\");\n  }\n  tpm_release_data();\n  /* release external functions and data */\n  tpm_extern_release();\n}\n\nint tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size)\n{\n  TPM_REQUEST req;\n  TPM_RESPONSE rsp;\n  BYTE *ptr;\n  UINT32 len;\n  BOOL free_out;\n\n  debug(\"tpm_handle_command()\");\n\n  /* we need the whole packet at once, otherwise unmarshalling will fail */\n  if (tpm_unmarshal_TPM_REQUEST((uint8_t**)&in, &in_size, &req) != 0) {\n    error(\"tpm_unmarshal_TPM_REQUEST() failed\");\n    return -1;\n  }\n  \n  /* update timing ticks */\n  tpm_update_ticks();\n  \n  /* audit request */\n  tpm_audit_request(req.ordinal, &req);\n\n  /* execute command */\n  tpm_execute_command(&req, &rsp);\n\n  /* audit response */\n  tpm_audit_response(req.ordinal, &rsp);\n\n  /* init output and marshal response */\n  if (*out != NULL) {\n    if (*out_size < rsp.size) {\n      error(\"output buffer to small (%d/%d)\", *out_size, rsp.size);\n      tpm_free(rsp.param);\n      return -1;\n    }\n    *out_size = len = rsp.size;\n    ptr = *out;\n    free_out = FALSE;\n  } else {\n    *out_size = len = rsp.size;\n    *out = ptr = tpm_malloc(len);\n    if (ptr == NULL) {\n      error(\"tpm_malloc() failed\");\n      tpm_free(rsp.param);\n      return -1;\n    }\n    free_out = TRUE;\n  }\n  if (tpm_marshal_TPM_RESPONSE(&ptr, &len, &rsp) != 0) {\n    error(\"tpm_marshal_TPM_RESPONSE() failed\");\n    if (free_out) tpm_free(*out);\n    tpm_free(rsp.param);\n    return -1;\n  }\n  tpm_free(rsp.param);\n  return 0;\n}\n\n"
  },
  {
    "path": "tpm/tpm_commands.h",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: tpm_commands.h 452 2010-07-19 19:05:05Z mast $\n */\n\n#ifndef _TPM_COMMANDS_H_\n#define _TPM_COMMANDS_H_\n\n#include \"tpm_structures.h\"\n\n/*\n * The following commands are specified in\n * TPM Main Part 3 Commands [TPM_Part3].\n */\n\n/*\n * Admin Startup and State ([TPM_Part3], Section 3)\n * [tpm_startup.c]\n * This section describes the commands that start a TPM.\n */\n\n/**\n * TPM_Init - initializes the TPM\n * @startupType: [in] Type of startup that is occurring\n * \n * Description: ([TPM_Part3], Section 3.1)\n * TPM_Init is a \"physical\" method of initializing a TPM,  \n * there is no TPM_Init ordinal. \n */\nvoid TPM_Init(\n  TPM_STARTUP_TYPE startupType\n);\n\n/**\n * TPM_Startup - starts the TPM\n * @startupType: [in] Type of startup that is occurring\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 3.2)\n * The TPM can startup in three different modes. (1) \"clear\" start where all \n * variables go back to their default or non-volatile set state. (2) \"save\" \n * start where the TPM recovers appropriate information and restores various \n * values based on a prior TPM_SaveState. (3) \"deactivated\" start where the \n * TPM turns itself off and requires another TPM_Init before the TPM will \n * execute in a fully operational state.\n */\nTPM_RESULT TPM_Startup(  \n  TPM_STARTUP_TYPE startupType\n);\n\n/**\n * TPM_SaveState - saves the current state of the TPM \n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 3.3)\n * This warns a TPM to save some state information. If the relevant shielded \n * storage is non-volatile, this command need have no effect. If the relevant \n * shielded storage is volatile and the TPM alone is unable to detect the loss \n * of external power in time to move data to non-volatile memory, this command \n * should be presented before the systems enters a low or no power state.\n */\nTPM_RESULT TPM_SaveState(void);\n\n/*\n * Admin Testing ([TPM_Part3], Section 4)\n * [tpm_testing.c]\n */\n\n/**\n * TPM_SelfTestFull - tests all of the TPM capabilities\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 4.1)\n * Tests all of the TPM capabilities.\n */\nTPM_RESULT TPM_SelfTestFull(void);\n\n/**\n * TPM_ContinueSelfTest - continues a started self test\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 4.2)\n * Informs the TPM that it may complete the self test of all TPM functions.\n */\nTPM_RESULT TPM_ContinueSelfTest(void);\n\n/**\n * TPM_GetTestResult - provides the results of the self test\n * @outDataSize: [out] The size of the outData area \n * @outData: [out] The outData this is manufacturer specific\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 4.3)\n * TPM_GetTestResult provides manufacturer specific information regarding the \n * results of the self test. This command will also work when the TPM is in \n * self test failure mode. \n */\nTPM_RESULT TPM_GetTestResult(  \n  UINT32 *outDataSize,\n  BYTE **outData  \n);\n\n/*\n * Admin Opt-in ([TPM_Part3], Section 5)\n * [tpm_owner.c]\n */\n\n/**\n * TPM_SetOwnerInstall - sets the persistent owner-install flag\n * @state: [in] State to which ownership flag is to be set\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 5.1)\n * When enabled but without an owner this command sets the persistent flag \n * that allows or disallows the ability to insert an owner.\n */\nTPM_RESULT TPM_SetOwnerInstall(  \n  BOOL state\n);\n\n/**\n * TPM_OwnerSetDisable - sets the persistent disable flag\n * @disableState: [in] Value for disable state, enable if TRUE\n * @auth1: [in, out] Authorization protocol parameters\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 5.2)\n * The TPM owner sets the persistent disable flag.\n */\nTPM_RESULT TPM_OwnerSetDisable(  \n  BOOL disableState,\n  TPM_AUTH *auth1\n);\n\n/**\n * TPM_PhysicalEnable - sets the persistent disable flag to FALSE\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 5.3)\n * Sets the persistent disable flag to FALSE using physical presence as \n * authorization.\n */\nTPM_RESULT TPM_PhysicalEnable(void);\n\n/**\n * TPM_PhysicalDisable - sets the persistent disable flag to TRUE\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 5.4)\n * Sets the persistent disable flag to TRUE using physical presence as \n * authorization.\n */\nTPM_RESULT TPM_PhysicalDisable(void);\n\n/**\n * TPM_PhysicalSetDeactivated - sets the deactivated flag\n * @state: [in] State to which deactivated flag is to be set\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 5.5)\n * Sets the deactivated flag using physical presence as authorization.\n */\nTPM_RESULT TPM_PhysicalSetDeactivated(  \n  BOOL state\n);\n\n/**\n * TPM_SetTempDeactivated - deactivates the TPM until the next boot\n * @auth1: [in, out] Authorization protocol parameters\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 5.6)\n * This command allows the operator of the platform to deactivate the TPM until \n * the next boot of the platform. The operator can provide the authorization by \n * either the assertion of physical presence or presenting the operation \n * authorization value.\n */\nTPM_RESULT TPM_SetTempDeactivated(  \n  TPM_AUTH *auth1\n);\n\n/**\n * TPM_SetOperatorAuth - sets the operator authorization value\n * @operatorAuth: [in] The operator authorization\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 5.7)\n * This command allows the setting of the operator authorization value. There \n * is no confidentiality applied to the operator authorization as the value is \n * sent under the assumption of being local to the platform. \n */\nTPM_RESULT TPM_SetOperatorAuth(  \n  TPM_SECRET *operatorAuth\n);\n\n/*\n * Admin Ownership ([TPM_Part3], Section 6)\n * [tpm_owner.c]\n */\n\n/**\n * TPM_TakeOwnership - inserts the TPM Ownership value into the TPM\n * @protocolID: [in] The ownership protocol in use\n * @encOwnerAuthSize: [in] The size of the encOwnerAuth field\n * @encOwnerAuth: [in] The owner authorization data encrypted with PUBEK\n * @encSrkAuthSize: [in] The size of the encSrkAuth field\n * @encSrkAuth: [in] The SRK authorization data encrypted with PUBEK\n * @srkParams: [in] All parameters of the new SRK\n * @auth1: [in, out] Authorization protocol parameters\n * @srkPub: [out] All parameters of the new SRK\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 6.1)\n * This command inserts the TPM Ownership value into the TPM.\n */\nTPM_RESULT TPM_TakeOwnership(  \n  TPM_PROTOCOL_ID protocolID,\n  UINT32 encOwnerAuthSize,\n  BYTE *encOwnerAuth,\n  UINT32 encSrkAuthSize,\n  BYTE *encSrkAuth,\n  TPM_KEY *srkParams,\n  TPM_AUTH *auth1,\n  TPM_KEY *srkPub\n);\n\n/**\n * tpm_owner_clear - owner clear operation\n */\nvoid tpm_owner_clear(void);\n\n/**\n * TPM_OwnerClear - performs the clear operation\n * @auth1: [in, out] Authorization protocol parameters\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 6.2)\n * This command performs the clear operation under Owner authorization. It \n * is available until the Owner executes the DisableOwnerClear, at which \n * time any further invocation of this command returns TPM_CLEAR_DISABLED.\n */\nTPM_RESULT TPM_OwnerClear(  \n  TPM_AUTH *auth1\n);\n\n/**\n * TPM_ForceClear - forces the clear operation\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 6.3)\n * This command performs the clear operation under physical access. It is\n * available until the execution of DisableForceClear, at which time any \n * further invocation of this command returns TPM_CLEAR_DISABLED.\n */\nTPM_RESULT TPM_ForceClear(void);\n\n/**\n * TPM_DisableOwnerClear - disables the ability to execute TPM_OwnerClear\n * @auth1: [in, out] Authorization protocol parameters\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 6.4)\n * This command disables the ability to execute the TPM_OwnerClear command \n * permanently. Once invoked the only method of clearing the TPM will require \n * physical access to the TPM. \n */\nTPM_RESULT TPM_DisableOwnerClear(  \n  TPM_AUTH *auth1\n);\n\n/**\n * TPM_DisableForceClear - disables the ability to execute TPM_ForceClear\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 6.5)\n * The DisableForceClear command disables the execution of the ForceClear \n * command until the next startup cycle. Once this command is executed, \n * the TPM_ForceClear is disabled until another startup cycle is run.\n */\nTPM_RESULT TPM_DisableForceClear(void);\n\n/**\n * TSC_PhysicalPresence - sets the physical presence flag\n * @physicalPresence: [in] The state to set the TPM's Physical Presence flags\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 6.6)\n * This command allows a process on the platform to indicate the assertion \n * of physical presence. \n */\nTPM_RESULT TSC_PhysicalPresence(  \n  TPM_PHYSICAL_PRESENCE physicalPresence\n);\n\n/**\n * TSC_ResetEstablishmentBit - resets the establishment bit\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 6.7)\n * The PC TPM Interface Specification (TIS) specifies a bit that is set upon \n * execution of the HASH_START sequence. This command allows for the resetting \n * of the bit under controlled circumstances.\n */\nTPM_RESULT TSC_ResetEstablishmentBit(void);\n\n/*\n * The GetCapability Commands ([TPM_Part3], Section 7)\n * [tpm_capability.c]\n * The GetCapability command allows the TPM to report back to the requester \n * what type of TPM it is dealing with. The request for information requires \n * the requester to specify which piece of information that is required. \n */\n\n/**\n * TPM_GetCapability - provides current information regarding the TPM\n * @capArea: [in] Partition of capabilities to be interrogated\n * @subCapSize: [in] Size of subCap parameter \n * @subCap: [in] Further definition of information\n * @respSize: [out] The length of the returned capability response \n * @resp: [out] The capability response\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 7.1)\n * This command provides current information regarding the TPM.\n */\nTPM_RESULT TPM_GetCapability(\n  TPM_CAPABILITY_AREA capArea,\n  UINT32 subCapSize,\n  BYTE *subCap,\n  UINT32 *respSize,\n  BYTE **resp\n);\n\n/**\n * TPM_SetCapability - sets values in the TPM\n * @capArea: [in] Partition of capabilities to be set\n * @subCapSize: [in] Size of subCap parameter\n * @subCap: [in] Further definition of information\n * @setValueSize: [in] Size of the value to set\n * @setValue: [in] Value to set\n * @auth1: [in, out] Authorization protocol parameters\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 7.2)\n * This command sets values in the TPM.\n */\nTPM_RESULT TPM_SetCapability(\n  TPM_CAPABILITY_AREA capArea,\n  UINT32 subCapSize,\n  BYTE *subCap,\n  UINT32 setValueSize,\n  BYTE *setValue,\n  TPM_AUTH *auth1\n);\n\n/**\n * TPM_GetCapabilityOwner (deprecated)\n * @auth1: [in, out] Authorization protocol parameters\n * @version: [out] Properly filled out version structure\n * @non_volatile_flags: [out] Current state of the non-volatile flags\n * @volatile_flags: [out] Current state of the volatile flags\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 7.3)\n * This command is deprecated.\n */\nTPM_RESULT TPM_GetCapabilityOwner(\n  TPM_AUTH *auth1,\n  TPM_VERSION *version,\n  UINT32 *non_volatile_flags,\n  UINT32 *volatile_flags\n);\n\n/*\n * Auditing ([TPM_Part3], Section 8)\n * [tpm_audit.c]\n * The TPM generates an audit event in response to the TPM executing a \n * function that has the audit flag set to TRUE for that function. The \n * TPM maintains an extended value for all audited operations. \n */\n\n/**\n * tpm_audit_request - audits a TPM request\n * @ordinal: [in] The ordinal of the request\n * @req: [in] The request to audit\n */\nvoid tpm_audit_request(\n  TPM_COMMAND_CODE ordinal, \n  TPM_REQUEST *req\n);\n\n/**\n * tpm_audit_response - audits a TPM response\n * @ordinal: [in] The ordinal of the response\n * @rsp: [in] The response to audit\n */\nvoid tpm_audit_response(\n  TPM_COMMAND_CODE ordinal, \n  TPM_RESPONSE *rsp\n);\n\n/**\n * TPM_GetAuditDigest - provides the current audit digest\n * @startOrdinal: [in] The starting ordinal for the list of audited ordinals\n * @counterValue: [out] The current value of the audit monotonic counter\n * @auditDigest: [out] Log of all audited events\n * @more: [out] TRUE if the output does not contain all audited ordinals\n * @ordSize: [out] Size of the ordinal list in bytes\n * @ordList: [out] List of ordinals that are audited\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 8.3)\n * This provides the current audit digest. The external audit log has the \n * responsibility to track the parameters that constitute the audit digest. \n */\nTPM_RESULT TPM_GetAuditDigest(  \n  UINT32 startOrdinal,  \n  TPM_COUNTER_VALUE *counterValue,\n  TPM_DIGEST *auditDigest,\n  BOOL *more,\n  UINT32 *ordSize,\n  UINT32 **ordList  \n);\n\n/**\n * TPM_GetAuditDigestSigned - provides the current (signed) audit digest\n * @keyHandle: [in] Handle of a loaded key that can perform digital signatures\n * @closeAudit: [in] Indication if audit session should be closed\n * @antiReplay: [in] A nonce to prevent replay attacks\n * @auth1: [in, out] Authorization protocol parameters\n * @counterValue: [out] The value of the audit monotonic counter\n * @auditDigest: [out] Log of all audited events\n * @ordinalDigest: [out] Digest of all audited ordinals\n * @sigSize: [out] The size of the sig parameter\n * @sig: [out] The signature of the area\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 8.4)\n * The signing of the audit log provides the entire digest value and the list \n * of currently audited commands. The inclusion of the list of audited commands \n * as an atomic operation is to tie the current digest value with the list of \n * commands that are being audited. \n */\nTPM_RESULT TPM_GetAuditDigestSigned(  \n  TPM_KEY_HANDLE keyHandle,\n  BOOL closeAudit,\n  TPM_NONCE *antiReplay,\n  TPM_AUTH *auth1,  \n  TPM_COUNTER_VALUE *counterValue,\n  TPM_DIGEST *auditDigest,\n  TPM_DIGEST *ordinalDigest,\n  UINT32 *sigSize,\n  BYTE **sig  \n);\n\n/**\n * TPM_SetOrdinalAuditStatus - set the audit flag for a given ordinal\n * @ordinalToAudit: [in] The ordinal whose audit flag is to be set\n * @auditState: [in] Value for audit flag\n * @auth1: [in, out] Authorization protocol parameters\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 8.5)\n * Set the audit flag for a given ordinal. This command requires the \n * authorization of the TPM Owner.\n */\nTPM_RESULT TPM_SetOrdinalAuditStatus(  \n  TPM_COMMAND_CODE ordinalToAudit,\n  BOOL auditState,\n  TPM_AUTH *auth1\n);\n\n/*\n * Administrative Functions ([TPM_Part3], Section 9)\n * [tpm_management.c]\n */\n\n/**\n * TPM_FieldUpgrade - updates the protected capabilities\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 9.1)\n * This command provides a manufacturer specific method of updating\n * the protected capabilities\n */\nTPM_RESULT TPM_FieldUpgrade(void);\n\n/**\n * TPM_SetRedirection - attaches a key to a redirection receiver\n * @keyHandle: [in] Handle of a loaded key that can implement redirection\n * @redirCmd: [in] The command to execute\n * @inputDataSize: [in] The size of the input data\n * @inputData: [in] Manufacturer parameter\n * @auth1: [in, out] Authorization protocol parameters\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 9.2)\n */\nTPM_RESULT TPM_SetRedirection(\n  TPM_KEY_HANDLE keyHandle,\n  TPM_REDIR_COMMAND redirCmd,\n  UINT32 inputDataSize,\n  BYTE *inputData,\n  TPM_AUTH *auth1\n);\n\n/**\n * TPM_ResetLockValue - resets the TPM dictionary attack mitigation values\n * @auth1: [in, out] Authorization protocol parameters\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 9.3)\n */\nTPM_RESULT TPM_ResetLockValue(\n  TPM_AUTH *auth1\n);\n\n/*\n * Storage functions ([TPM_Part3], Section 10)\n * [tpm_storage.c]\n */\n\n/**\n * TPM_Seal - seals the TPM configuration\n * @keyHandle: [in] Handle of a loaded key that can perform seal operations\n * @encAuth: [in] The encrypted authorization data for the sealed data\n * @pcrInfoSize: [in] The size of the pcrInfo parameter\n * @pcrInfo: [in] The PCR selection information\n * @inDataSize: [in] The size of the inData parameter\n * @inData: [in] The data to be sealed to the platform and any specified PCRs\n * @auth1: [in, out] Authorization protocol parameters\n * @sealedData: [out] Encrypted, integrity-protected data object\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 10.1)\n * The Seal operation allows software to explicitly state the future trusted\n * configuration that the platform must be in for the secret to be revealed.\n */\nTPM_RESULT TPM_Seal(\n  TPM_KEY_HANDLE keyHandle,\n  TPM_ENCAUTH *encAuth,\n  UINT32 pcrInfoSize,\n  TPM_PCR_INFO *pcrInfo,\n  UINT32 inDataSize,\n  BYTE *inData,\n  TPM_AUTH *auth1,\n  TPM_STORED_DATA *sealedData\n);\n\n/**\n * TPM_Unseal - unseals the TPM configuration\n * @parentHandle: [in] Handle of a loaded key that can unseal the data\n * @inData: [in] The encrypted data generated by TPM_Seal\n * @auth1: [in, out] Authorization protocol parameters\n * @auth2: [in, out] Authorization protocol parameters\n * @sealedDataSize: [out] The used size of the output area for secret\n * @secret: [out] Decrypted data that had been sealed\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 10.2)\n * The Unseal operation will reveal TPM_Sealed data only if it was encrypted \n * on this platform and the current configuration (as defined by the named PCR \n * contents) is the one named as qualified to decrypt it.\n */\nTPM_RESULT TPM_Unseal(\n  TPM_KEY_HANDLE parentHandle,\n  TPM_STORED_DATA *inData,\n  TPM_AUTH *auth1,\n  TPM_AUTH *auth2,\n  UINT32 *sealedDataSize,\n  BYTE **secret\n);\n\n/**\n * TPM_UnBind - decrypts the result of a TSS_Bind command\n * @keyHandle: [in] Handle of a loaded key that can perform UnBind operations\n * @inDataSize: [in] The size of the input blob\n * @inData: [in] Encrypted blob to be decrypted\n * @auth1: [in, out] Authorization protocol parameters\n * @outDataSize: [out] The length of the returned decrypted data\n * @outData: [out] The resulting decrypted data\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 10.3)\n * TPM_UnBind takes the data blob that is the result of a TSS_Bind command and\n * decrypts it for export to the User. The caller must authorize the use of the\n * key that will decrypt the incoming blob. UnBInd operates on a block-by-block\n * basis, and has no notion of any relation between one block and another.\n */\nTPM_RESULT TPM_UnBind(\n  TPM_KEY_HANDLE keyHandle,\n  UINT32 inDataSize,\n  BYTE *inData,\n  TPM_AUTH *auth1,\n  UINT32 *outDataSize,\n  BYTE **outData\n);\n\n/**\n * TPM_CreateWrapKey - generates and creates a wrapped asymmetric key\n * @parentHandle: [in] Handle of a loaded key that can perform key wrapping\n * @dataUsageAuth: [in] Encrypted usage authorization data\n * @dataMigrationAuth: [in] Encrypted migration authorization data\n * @keyInfo: [in] Information about key to be created\n * @auth1: [in, out] Authorization protocol parameters\n * @wrappedKey: [out] The public and encrypted private key\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 10.4)\n * The TPM_CreateWrapKey command both generates and creates a secure storage\n * bundle for asymmetric keys. The newly created key can be locked to a\n * specific PCR value by specifying a set of PCR registers.\n */\nTPM_RESULT TPM_CreateWrapKey(\n  TPM_KEY_HANDLE parentHandle,\n  TPM_ENCAUTH *dataUsageAuth,\n  TPM_ENCAUTH *dataMigrationAuth,\n  TPM_KEY *keyInfo,\n  TPM_AUTH *auth1,\n  TPM_KEY *wrappedKey\n);\n\n/**\n * TPM_LoadKey - loads a key into the TPM for further use\n * @parentHandle: [in] TPM handle of parent key\n * @inKey: [in] Incoming key structure, both private and public portions\n * @auth1: [in, out] Authorization protocol parameters\n * @inkeyHandle: [out] Internal TPM handle where decrypted key was loaded\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 10.5)\n * Before the TPM can use a key to either wrap, unwrap, bind, unbind, seal,\n * unseal, sign or perform any other action, it needs to be present in the\n * TPM. The TPM_LoadKey function loads the key into the TPM for further use.\n */\nTPM_RESULT TPM_LoadKey(\n  TPM_KEY_HANDLE parentHandle,\n  TPM_KEY *inKey,\n  TPM_AUTH *auth1,\n  TPM_KEY_HANDLE *inkeyHandle\n);\n\n/**\n * TPM_LoadKey2 - loads a key into the TPM for further use\n * @parentHandle: [in] TPM handle of parent key\n * @inKey: [in] Incoming key structure, both private and public portions\n * @auth1: [in, out] Authorization protocol parameters\n * @inkeyHandle: [out] Internal TPM handle where decrypted key was loaded\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 10.5)\n * Before the TPM can use a key to either wrap, unwrap, bind, unbind, seal,\n * unseal, sign or perform any other action, it needs to be present in the\n * TPM. The TPM_LoadKey function loads the key into the TPM for further use.\n */\nTPM_RESULT TPM_LoadKey2(\n  TPM_KEY_HANDLE parentHandle,\n  TPM_KEY *inKey,\n  TPM_AUTH *auth1,\n  TPM_KEY_HANDLE *inkeyHandle\n);\n\n/**\n * TPM_GetPubKey - provides the public key value from a loaded key\n * @keyHandle: [in] TPM handle of key\n * @auth1: [in, out] Authorization protocol parameters\n * @pubKey: [out] Public portion of key in keyHandle\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 10.6)\n * The owner of a key may wish to obtain the public key value from a loaded\n * key. This information may have privacy concerns so the command must have\n * authorization from the key owner.\n */\nTPM_RESULT TPM_GetPubKey(\n  TPM_KEY_HANDLE keyHandle,\n  TPM_AUTH *auth1,\n  TPM_PUBKEY *pubKey\n);\n\n/**\n * TPM_Sealx - seals encrypted data to a TPM configuration\n * @keyHandle: [in] Handle of a loaded key that can perform seal operations\n * @encAuth: [in] The encrypted authorization data for the sealed data\n * @pcrInfoSize: [in] The size of the pcrInfo parameter\n * @pcrInfo: [in] The PCR selection information (MUST be TPM_PCR_INFO_LONG)\n * @inDataSize: [in] The size of the inData parameter\n * @inData: [in] The data to be sealed to the platform and any specified PCRs\n * @auth1: [in, out] Authorization protocol parameters\n * @sealedData: [out] Encrypted, integrity-protected data object\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 10.7)\n * The SEALX command works exactly like the SEAL command with the additional\n * requirement of encryption for the inData parameter. This command also\n * places in the sealed blob the information that the unseal also requires\n * encryption.\n */\nTPM_RESULT TPM_Sealx(\n  TPM_KEY_HANDLE keyHandle,\n  TPM_ENCAUTH *encAuth,\n  UINT32 pcrInfoSize,\n  TPM_PCR_INFO *pcrInfo,\n  UINT32 inDataSize,\n  BYTE *inData,\n  TPM_AUTH *auth1,\n  TPM_STORED_DATA *sealedData\n);\n\n/**\n * tpm_get_free_key - allocates a new key slot\n * Returns: the key handle on success, TPM_INVALID_HANDLE otherwise.\n\n */\nTPM_KEY_HANDLE tpm_get_free_key(void);\n\n/**\n * tpm_encrypt_public - encrypts the input data with the specified public key\n * @key: [in], Public key\n * @in: [in] Input data to encrypt\n * @in_size: [in] Size of the input data\n * @enc: [out] Encrypted data\n * @enc_size: [out] Size of the encrypted data\n * Returns: 0 on success, -1 otherwise.\n */\nint tpm_encrypt_public(\n  TPM_PUBKEY_DATA *key,\n  BYTE *in,\n  UINT32 in_size,\n  BYTE *enc,\n  UINT32 *enc_size\n);\n\n/**\n * tpm_encrypt_private - encrypts the input data with the specified private key\n * @key: [in], Private key\n * @in: [in] Input data to encrypt\n * @in_size: [in] Size of the input data\n * @enc: [out] Encrypted data\n * @enc_size: [out] Size of the encrypted data\n * Returns: 0 on success, -1 otherwise.\n */\nint tpm_encrypt_private(\n  TPM_KEY_DATA *key,\n  BYTE *in,\n  UINT32 in_size,\n  BYTE *enc,\n  UINT32 *enc_size\n);\n\n/**\n * tpm_decrypt - decrypts the input data with the specified private key\n * @key: [in], Private key\n * @enc: [in] Encrypted data\n * @enc_size: [in] Size of the encrypted data\n * @out: [out] Decrypted data\n * @out_size: [out] Size of the decrypted data\n * Returns: 0 on success, -1 otherwise.\n */\nint tpm_decrypt(\n  TPM_KEY_DATA *key,\n  BYTE *enc,\n  UINT32 enc_size,\n  BYTE *out,\n  UINT32 *out_size\n);\n\n/**\n * tpm_encrypt_sealed_data - encrypts a TPM_SEALED_DATA structure\n * @key: [in], Private key\n * @seal: [in] Structure to encrypt\n * @enc: [out] Encrypted structure\n * @enc_size: [out] Size of the encrypted structure\n * Returns: 0 on success, -1 otherwise.\n */\nint tpm_encrypt_sealed_data(\n  TPM_KEY_DATA *key,\n  TPM_SEALED_DATA *seal,\n  BYTE *enc,\n  UINT32 *enc_size\n);\n\n/**\n * tpm_decrypt_sealed_data - decrypts a TPM_SEALED_DATA structure\n * @key: [in], Private key\n * @enc: [in] Encrypted structure\n * @enc_size: [in] Size of the encrypted structure\n * @seal: [out] Decrypted structure\n * @buf: [out] Buffer for the decrypted structure (to be freed by the caller)\n * Returns: 0 on success, -1 otherwise.\n */\nint tpm_decrypt_sealed_data(\n  TPM_KEY_DATA *key,\n  BYTE *enc,\n  UINT32 enc_size,\n  TPM_SEALED_DATA *seal,\n  BYTE **buf\n);\n\n/**\n * tpm_encrypt_sealed_data - encrypts a TPM_STORE_ASYMKEY structure\n * @key: [in], Private key\n * @store: [in] Structure to encrypt\n * @enc: [out] Encrypted structure\n * @enc_size: [out] Size of the encrypted structure\n * Returns: 0 on success, -1 otherwise.\n */\nint tpm_encrypt_private_key(\n  TPM_KEY_DATA *key,\n  TPM_STORE_ASYMKEY *store,\n  BYTE *enc,\n  UINT32 *enc_size\n);\n\n/**\n * tpm_decrypt_sealed_data - decrypts a TPM_STORE_ASYMKEY structure\n * @key: [in], Private key\n * @enc: [in] Encrypted structure\n * @enc_size: [in] Size of the encrypted structure\n * @store: [out] Decrypted structure\n * @buf: [out] Buffer for the decrypted structure (to be freed by the caller)\n * @buf_size: [out] Size of the buffer\n * Returns: 0 on success, -1 otherwise.\n */\nint tpm_decrypt_private_key(\n  TPM_KEY_DATA *key,\n  BYTE *enc,\n  UINT32 enc_size,\n  TPM_STORE_ASYMKEY *store,\n  BYTE **buf,\n  UINT32 *buf_size\n);\n\n/**\n * tpm_compute_key_digest - computes the digest of a key\n * @key: [in] Key\n * @digest: [out] Digest of the key\n * @Returns: 0 on success, -1 otherwise.\n */\nint tpm_compute_key_digest(\n  TPM_KEY *key,\n  TPM_DIGEST *digest\n);\n\n/**\n * tpm_compute_key_data_digest - computes the digest of the public part of a key\n * @key: [in] Key\n * @digest: [out] Digest of the key\n * @Returns: 0 on success, -1 otherwise.\n */\nint tpm_compute_key_data_digest(\n  TPM_KEY_DATA *key,\n  TPM_DIGEST *digest\n);\n\n/**\n * tpm_compute_pubkey_checksum - computes the checksum of a public key\n * @antiReplay: [in] Nonce to prevent replay of messages\n * @pubKey: [in] Public key\n * @checksum: [out] Checksum of the public key and the nonce\n * @Returns: 0 on success, -1 otherwise.\n */\nint tpm_compute_pubkey_checksum(\n  TPM_NONCE *antiReplay,\n  TPM_PUBKEY *pubKey,\n  TPM_DIGEST *checksum\n);\n\n/**\n * tpm_compute_pubkey_digest - computes the digest of a public key\n * @key: [in] Public key\n * @digest: [out] Digest of the key\n * @Returns: 0 on success, -1 otherwise.\n */\nint tpm_compute_pubkey_digest(\n  TPM_PUBKEY *key,\n  TPM_DIGEST *digest\n);\n\n/**\n * tpm_setup_key_parms - sets the key parameters according to the given key\n * @key: [in] Key\n * @params: [out] Key parameters to set\n * @Returns: 0 on success, -1 otherwise.\n */\nint tpm_setup_key_parms(\n  TPM_KEY_DATA *key,\n  TPM_KEY_PARMS *parms\n);\n\n/**\n * tpm_setup_pubkey_data - creates an internal public key based on the given key\n * @in: [in] Public Key of type TPM_PUBKEY\n * @out: [out] Internal public key of type TPM_PUBKEY_DATA\n * @Returns: 0 on success, -1 otherwise.\n */\nint tpm_setup_pubkey_data(\n  TPM_PUBKEY *in,\n  TPM_PUBKEY_DATA *out\n);\n\n/**\n * tpm_extract_pubkey - extracts the public part of the specified key\n * @in: [in] Key\n * @out: [out] Public key\n * @Returns: 0 on success, -1 otherwise.\n */\nint tpm_extract_pubkey(\n  TPM_KEY_DATA *key,\n  TPM_PUBKEY *pubKey\n);\n\n/**\n * tpm_extract_store_pubkey - extracts the public part of the specified key\n * @in: [in] Key\n * @out: [out] Public key\n * @Returns: 0 on success, -1 otherwise.\n */\nint tpm_extract_store_pubkey(\n  TPM_KEY_DATA *key,\n  TPM_STORE_PUBKEY *pubKey\n);\n\n/**\n * internal_TPM_LoadKey - loads the specified key into the TPM\n * @inKey: [in] Incoming key structure, both private and public portions\n * @inkeyHandle: [out] Internal TPM handle where decrypted key was loaded\n */\nTPM_RESULT internal_TPM_LoadKey(\n  TPM_KEY *inKey,\n  TPM_KEY_HANDLE *inkeyHandle\n);\n\n/*\n * Migration ([TPM_Part3], Section 11)\n * [tpm_migration.c]\n */\n\n/**\n * TPM_CreateMigrationBlob - creates a migration blob\n * @parentHandle: [in] Handle of the parent key that can decrypt encData\n * @migrationType: [in] The migration type, either MIGRATE or REWRAP\n * @migrationKeyAuth: [in] Migration public key and its authorization digest\n * @encDataSize: [in] The size of the encData parameter\n * @encData: [in] The encrypted entity that is to be modified\n * @auth1: [in, out] Authorization protocol parameters\n * @auth2: [in, out] Authorization protocol parameters\n * @randomSize: [out] The used size of the output area for random\n * @random: [out] String used for xor encryption \n * @outDataSize: [out] The used size of the output area for outData\n * @outData: [out] The modified, encrypted entity\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 11.1)\n * The TPM_CreateMigrationBlob command implements the first step in the\n * process of moving a migratable key to a new parent or platform.\n */\nTPM_RESULT TPM_CreateMigrationBlob(\n  TPM_KEY_HANDLE parentHandle,\n  TPM_MIGRATE_SCHEME migrationType,\n  TPM_MIGRATIONKEYAUTH *migrationKeyAuth,\n  UINT32 encDataSize,\n  BYTE *encData,\n  TPM_AUTH *auth1,\n  TPM_AUTH *auth2,\n  UINT32 *randomSize,\n  BYTE **random,\n  UINT32 *outDataSize,\n  BYTE **outData\n);\n\n/**\n * TPM_ConvertMigrationBlob - converts a migration into a wrapped blob\n * @parentHandle: [in] Handle of a loaded key that can decrypt keys\n * @inDataSize: [in] Size of inData\n * @inData: [in] The XOR d and encrypted key\n * @randomSize: [in] Size of random\n * @random: [in] Random value used to hide key data\n * @auth1: [in, out] Authorization protocol parameters\n * @outDataSize: [out] The used size of the output area for outData\n * @outData: [out] The encrypted private key that can be loaded with LoadKey\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 11.2)\n * This command takes a migration blob and creates a normal wrapped blob.\n * The migrated blob must be loaded into the TPM using the normal TPM_LoadKey\n * function. Note that the command migrates private keys, only.\n */\nTPM_RESULT TPM_ConvertMigrationBlob(\n  TPM_KEY_HANDLE parentHandle,\n  UINT32 inDataSize,\n  BYTE *inData,\n  UINT32 randomSize,\n  BYTE *random,\n  TPM_AUTH *auth1,\n  UINT32 *outDataSize,\n  BYTE **outData\n);\n\n/**\n * TPM_AuthorizeMigrationKey - creates an authorization blob\n * @migrateScheme: [in] Migration operation that is to be permitted for this key\n * @migrationKey: [in] The public key to be authorized\n * @auth1: [in, out] Authorization protocol parameters\n * @outData: [out] Returned public key and authorization digest\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 11.3)\n * This command creates an authorization blob, to allow the TPM owner to\n * specify which migration facility they will use and allow users to migrate\n * information without further involvement with the TPM owner.\n */\nTPM_RESULT TPM_AuthorizeMigrationKey(\n  TPM_MIGRATE_SCHEME migrateScheme,\n  TPM_PUBKEY *migrationKey,\n  TPM_AUTH *auth1,\n  TPM_MIGRATIONKEYAUTH *outData\n);\n\n/**\n * TPM_MigrateKey - performs the function of a migration authority\n * @maKeyHandle: [in] Handle of the key to be used to migrate the key\n * @pubKey: [in] Public key to which the blob is to be migrated\n * @inDataSize: [in] The size of inData\n * @inData: [in] The input blob\n * @auth1: [in, out] Authorization protocol parameters\n * @outDataSize: [out] The used size of the output area for outData\n * @outData: [out] The re-encrypted blob\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 11.4)\n */\nTPM_RESULT TPM_MigrateKey(\n  TPM_KEY_HANDLE maKeyHandle,\n  TPM_PUBKEY *pubKey,\n  UINT32 inDataSize,\n  BYTE *inData,\n  TPM_AUTH *auth1,\n  UINT32 *outDataSize,\n  BYTE **outData\n);\n\n/**\n * TPM_CMK_SetRestrictions - dictates the usage of a restricted migration key\n * @restriction: [in] The bit mask of how to set the restrictions on CMK keys\n * @auth1: [in, out] Authorization protocol parameters\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 11.5)\n * This command is used by the Owner to dictate the usage of a restricted-\n * migration key with delegated authorisation (authorisation other than actual\n * Owner authorisation).\n */\nTPM_RESULT TPM_CMK_SetRestrictions(\n  TPM_CMK_DELEGATE restriction,\n  TPM_AUTH *auth1\n);\n\n/**\n * TPM_CMK_ApproveMA - creates an authorization ticket\n * @migrationAuthorityDigest: [in] A digest of a TPM_MSA_COMPOSITE structure\n * @auth1: [in, out] Authorization protocol parameters\n * @outData: [out] HMAC of the migrationAuthorityDigest\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 11.6)\n */\nTPM_RESULT TPM_CMK_ApproveMA(\n  TPM_DIGEST *migrationAuthorityDigest,\n  TPM_AUTH *auth1,\n  TPM_HMAC *outData\n);\n\n/**\n * TPM_CMK_CreateKey - generates and creates a wrapped CMK\n * @parentHandle: [in] Handle of a loaded key that can perform key wrapping\n * @dataUsageAuth: [in] Encrypted usage authorization data for the sealed data\n * @keyInfo: [in] Information about key to be created\n * @migrationAuthorityApproval: [in] A ticket created by the TPM owner\n * @migrationAuthorityDigest: [in] The digest of the public key of the MSA or MA\n * @auth1: [in, out] Authorization protocol parameters\n * @auth2: [in, out] Authorization protocol parameters\n * @wrappedKey: [out] The public and encrypted private key\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 11.7)\n * The TPM_CreateWrapRestrictedKey command both generates and creates a\n * secure storage bundle for asymmetric keys whose migration is controlled\n * by a migration authority.\n */\nTPM_RESULT TPM_CMK_CreateKey(\n  TPM_KEY_HANDLE parentHandle,\n  TPM_ENCAUTH *dataUsageAuth,\n  TPM_KEY *keyInfo,\n  TPM_HMAC *migrationAuthorityApproval,\n  TPM_DIGEST *migrationAuthorityDigest,\n  TPM_AUTH *auth1,\n  TPM_AUTH *auth2,\n  TPM_KEY *wrappedKey\n);\n\n/**\n * TPM_CMK_CreateTicket - creates a ticket for proving a signature verification\n * @verificationKey: [in] The public key to be used to check signatureValue\n * @signedData: [in] The data proported to be signed\n * @signatureValueSize: [in] The size of the signatureValue\n * @signatureValue: [in] The signatureValue to be verified\n * @auth1: [in, out] Authorization protocol parameters\n * @sigTicket: [out] Ticket that proves digest created on this TPM\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 11.8)\n * The TPM_verifySignature command uses a public key to verify the signature\n * over a digest. TPM_verifySignature provides a ticket that can be used to\n * prove to the same TPM that signature verification with a particular public\n * key was successful.\n */\nTPM_RESULT TPM_CMK_CreateTicket(\n  TPM_PUBKEY *verificationKey,\n  TPM_DIGEST *signedData,\n  UINT32 signatureValueSize,\n  BYTE *signatureValue,\n  TPM_AUTH *auth1,\n  TPM_DIGEST *sigTicket\n);\n\n/**\n * TPM_CMK_CreateBlob - creates a migration blob\n * @parentHandle: [in] Handle of the parent key that can decrypt encData\n * @migrationType: [in] The migration type\n * @migrationKeyAuth: [in] Migration public key and its authorization digest\n * @pubSourceKeyDigest: [in] Digest of the entity's public key to be migrated\n * @msaList: [in] Digests of public keys belonging to MAs\n * @restrictTicket: [in] The digests of the public keys\n * @sigTicket: [in] A signature ticket, generate by the TPM\n * @encDataSize: [in] The size of the encData parameter\n * @encData: [in] The encrypted entity that is to be modified\n * @auth1: [in, out] Authorization protocol parameters\n * @randomSize: [out] The used size of the output area for random\n * @random: [out] String used for xor encryption\n * @outDataSize: [out] The used size of the output area for outData\n * @outData: [out] The modified, encrypted entity\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 11.9)\n * TPM_CMK_CreateBlob command is very similar to TPM_CreateMigrationBlob,\n * except that it (1) uses an extra ticket (restrictedKeyAuth) instead\n * of a migrationAuth authorization session; (2) uses the migration options\n * TPM_MS_RESTRICT_MIGRATE or TPM_MS_RESTRICT_APPROVE.\n */\nTPM_RESULT TPM_CMK_CreateBlob(\n  TPM_KEY_HANDLE parentHandle,\n  TPM_MIGRATE_SCHEME migrationType,\n  TPM_MIGRATIONKEYAUTH *migrationKeyAuth,\n  TPM_DIGEST *pubSourceKeyDigest,\n  TPM_MSA_COMPOSITE *msaList,\n  TPM_CMK_AUTH *restrictTicket,\n  TPM_HMAC *sigTicket,\n  UINT32 encDataSize,\n  BYTE *encData,\n  TPM_AUTH *auth1,\n  UINT32 *randomSize,\n  BYTE **random,\n  UINT32 *outDataSize,\n  BYTE **outData\n);\n\n/**\n * TPM_CMK_ConvertMigration - completes the migration of certified blobs\n * @parentHandle: [in] Handle of a loaded key that can decrypt keys\n * @restrictTicket: [in] The digests of the public keys\n * @sigTicket: [in] A signature ticket, generated by the TPM\n * @migratedKey: [in] The public key of the key to be migrated\n * @msaList: [in] One or more digests of public keys belonging to MAs\n * @randomSize: [in] Size of random\n * @random: [in] Random value used to hide key data\n * @auth1: [in, out] Authorization protocol parameters\n * @outDataSize: [out] The used size of the output area for outData\n * @outData: [out] The encrypted private key that can be loaded\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 11.10)\n */\nTPM_RESULT TPM_CMK_ConvertMigration(\n  TPM_KEY_HANDLE parentHandle,\n  TPM_CMK_AUTH *restrictTicket,\n  TPM_HMAC *sigTicket,\n  TPM_KEY *migratedKey,\n  TPM_MSA_COMPOSITE *msaList,\n  UINT32 randomSize,\n  BYTE *random,\n  TPM_AUTH *auth1,\n  UINT32 *outDataSize,\n  BYTE **outData\n);\n\n/*\n * Maintenance Functions ([TPM_Part3], Section 12)\n * [tpm_maintenance.c]\n */\n\n/**\n * TPM_CreateMaintenanceArchive - creates the maintenance archive\n * @generateRandom: [in] Use RNG or Owner auth to generate random\n * @auth1: [in, out] Authorization protocol parameters\n * @randomSize: [out] Size of the returned random data\n * @random: [out] Random data to XOR with result\n * @archiveSize: [out] Size of the encrypted archive \n * @archive: [out] Encrypted key archive\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 12.1)\n * This command creates the maintenance archive. It can only be executed by \n * the owner, and may be shut off with the KillMaintenanceFeature command.\n */\nTPM_RESULT TPM_CreateMaintenanceArchive(  \n  BOOL generateRandom,\n  TPM_AUTH *auth1,  \n  UINT32 *randomSize,\n  BYTE **random ,\n  UINT32 *archiveSize,\n  BYTE **archive  \n);\n\n/**\n * TPM_LoadMaintenanceArchive - loads in a maintenance archive\n * @archiveSize: [in] Size of encrypted key archive\n * @archive: [in] Encrypted key archive\n * @sigSize: [in] Size of archive signature\n * @sig: [in] archive signature\n * @randomSize: [in] Size of the random data\n * @random: [in] Random data to XOR with encrypted archive\n * @auth1: [in, out] Authorization protocol parameters\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 12.2)\n * This command loads in a maintenance archive that has been massaged \n * by the manufacturer to load into another TPM.\n */\nTPM_RESULT TPM_LoadMaintenanceArchive(\n  UINT32 archiveSize,\n  BYTE *archive,\n  UINT32 sigSize,\n  BYTE *sig,\n  UINT32 randomSize,\n  BYTE *random,\n  TPM_AUTH *auth1\n);\n\n/**\n * TPM_KillMaintenanceFeature - prevents the creation of a maintenance archive\n * @auth1: [in, out] Authorization protocol parameters\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 12.3)\n * The KillMaintencanceFeature is a permanent action that prevents ANYONE from \n * creating a maintenance archive. This action, once taken, is permanent until \n * a new TPM Owner is set. This action is to allow those customers who do not \n * want the maintenance feature to prohibit it. \n */\nTPM_RESULT TPM_KillMaintenanceFeature(  \n  TPM_AUTH *auth1\n);\n\n/**\n * TPM_LoadManuMaintPub - loads the manufacturer's public key\n * @antiReplay: [in] AntiReplay and validation nonce \n * @pubKey: [in] The public key of the manufacturer to be in use for maintenance\n * @checksum: [out] Digest of pubKey and antiReplay\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 12.4)\n * The LoadManuMaintPub command loads the manufacturer's public key for use in\n * the maintenance process. The command installs ManuMaintPub in persistent \n * data storage inside a TPM. \n */\nTPM_RESULT TPM_LoadManuMaintPub(  \n  TPM_NONCE *antiReplay,\n  TPM_PUBKEY *pubKey,  \n  TPM_DIGEST *checksum \n);\n\n/**\n * TPM_ReadManuMaintPub - provides a digest of the manufacturer's public key\n * @antiReplay: [in] AntiReplay and validation nonce\n * @checksum: [out] Digest of pubKey and antiReplay\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 12.5)\n * The ReadManuMaintPub command is used to check whether the manufacturer's \n * public maintenance key in a TPM has the expected value. The command \n * provides a digest of the installed key, rather than the key itself. \n */\nTPM_RESULT TPM_ReadManuMaintPub(  \n  TPM_NONCE *antiReplay,  \n  TPM_DIGEST *checksum \n);\n\n/*\n * Cryptographic Functions ([TPM_Part3], Section 13)\n * [tpm_crypto.c]\n */\n\n/**\n * TPM_SHA1Start - starts the process of calculating a SHA-1 digest\n * @maxNumBytes: [out] Maximum number of bytes that can be sent to SHA1Update\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 13.1)\n * This capability starts the process of calculating a SHA-1 digest.\n */\nTPM_RESULT TPM_SHA1Start(  \n  UINT32 *maxNumBytes \n);\n\n/**\n * TPM_SHA1Update - inputs blocks of data into a pending SHA-1 digest\n * @numBytes: [in] The number of bytes in hashData\n * @hashData: [in] Bytes to be hashed\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 13.2)\n * This capability inputs complete blocks of data into a pending SHA-1 digest. \n * At the end of the process, the digest remains pending.\n */\nTPM_RESULT TPM_SHA1Update(  \n  UINT32 numBytes,\n  BYTE *hashData\n);\n\n/**\n * TPM_SHA1Complete - terminates a pending SHA-1 calculation\n * @hashDataSize: [in] Number of bytes in hashData, MUST be 64 or less \n * @hashData: [in] Final bytes to be hashed\n * @hashValue: [out] The output of the SHA-1 hash\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 13.3)\n * This capability terminates a pending SHA-1 calculation.\n */\nTPM_RESULT TPM_SHA1Complete(  \n  UINT32 hashDataSize,\n  BYTE *hashData,  \n  TPM_DIGEST *hashValue \n);\n\n/**\n * TPM_SHA1CompleteExtend - terminates and extends a pending SHA-1 calculation\n * @pcrNum: [in] Index of the PCR to be modified\n * @hashDataSize: [in] Number of bytes in hashData, MUST be 64 or less \n * @hashData: [in] Final bytes to be hashed\n * @hashValue: [out] The output of the SHA-1 hash\n * @outDigest: [out] The PCR value after execution of the command\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 13.4)\n * This capability terminates a pending SHA-1 calculation and EXTENDS the \n * result into a Platform Configuration Register using a SHA-1 hash process. \n */\nTPM_RESULT TPM_SHA1CompleteExtend(  \n  TPM_PCRINDEX pcrNum,\n  UINT32 hashDataSize,\n  BYTE *hashData,  \n  TPM_DIGEST *hashValue,\n  TPM_PCRVALUE *outDigest \n);\n\n/**\n * tpm_verify - verifies the signature with the specified key\n * @key: [in] key to verify the signature\n * @auth: [in, out] Authorization protocol parameters\n * @isInfo: [in] True if the input data is of type TPM_SIGN_INFO\n * @data: [in] The input data\n * @dataSize: [in] The size of the input data\n * @sig: [in] The digital signature\n * @sigSize: [in] The size of the digital signature\n * Returns: TPM_SUCCESS if the signature is valid, a TPM error code otherwise.\n */\nTPM_RESULT tpm_verify(\n  TPM_PUBKEY_DATA *key,\n  TPM_AUTH *auth,\n  BOOL isInfo,\n  BYTE *data,\n  UINT32 dataSize,\n  BYTE *sig,\n  UINT32 sigSize\n);\n\n/**\n * tpm_sign - signs data with the specified key\n * @key: [in] key to compute the signature\n * @auth: [in, out] Authorization protocol parameters\n * @isInfo: [in] True if the input data is of type TPM_SIGN_INFO\n * @areaToSign: [in] The value to sign\n * @areaToSignSize: [in] The size of the areaToSign parameter\n * @sig: [out] The digital signature\n * @sigSize: [out] The size of the digital signature\n * Returns: TPM_SUCCESS if the signature is valid, a TPM error code otherwise.\n */\nTPM_RESULT tpm_sign(\n  TPM_KEY_DATA *key,\n  TPM_AUTH *auth,\n  BOOL isInfo,\n  BYTE *areaToSign,\n  UINT32 areaToSignSize,\n  BYTE **sig,\n  UINT32 *sigSize\n);\n\n/**\n * TPM_Sign - signs data and provides the resulting digital signature\n * @keyHandle: [in] Handle of a loaded key that can perform digital signatures\n * @areaToSignSize: [in] The size of the areaToSign parameter \n * @areaToSign: [in] The value to sign\n * @auth1: [in, out] Authorization protocol parameters\n * @sigSize: [out] The length of the returned digital signature \n * @sig: [out] The resulting digital signature\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 13.5)\n * The Sign command signs data and provides the resulting digital signature.\n */\nTPM_RESULT TPM_Sign(  \n  TPM_KEY_HANDLE keyHandle,\n  UINT32 areaToSignSize,\n  BYTE *areaToSign,\n  TPM_AUTH *auth1,  \n  UINT32 *sigSize,\n  BYTE **sig  \n);\n\n/**\n * tpm_get_random_bytes - provides the requested amount of random bytes\n * @buf: [out] buffer to fill with random data\n * @nbytes: [in] requested number of random bytes\n */\nvoid tpm_get_random_bytes(\n  void *buf,\n  size_t nbytes\n);\n\n/**\n * TPM_GetRandom - provides the next bytes from the RNG\n * @bytesRequested: [in] Number of bytes to return\n * @randomBytesSize: [out] The number of bytes returned \n * @randomBytes: [out] The returned bytes\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 13.6)\n * GetRandom provides the next bytesRequested bytes from the random number \n * generator to the caller. \n */\nTPM_RESULT TPM_GetRandom(  \n  UINT32 bytesRequested,  \n  UINT32 *randomBytesSize,\n  BYTE **randomBytes  \n);\n\n/**\n * TPM_StirRandom - adds entropy to the RNG state\n * @dataSize: [in] Number of bytes of input (256) \n * @inData: [in] Data to add entropy to RNG state\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 13.7)\n * StirRandom adds entropy to the RNG state.\n */\nTPM_RESULT TPM_StirRandom(  \n  UINT32 dataSize,\n  BYTE *inData\n);\n\n/**\n * TPM_CertifyKey - certifies the public portion of a non-migratable key\n * @certHandle: [in] Handle of the key to be used to certify the key\n * @keyHandle: [in] Handle of the key to be certified\n * @antiReplay: [in] 160 bits of externally supplied data (typically a nonce)\n * @auth1: [in, out] Authorization protocol parameters\n * @auth2: [in, out] Authorization protocol parameters\n * @certifyInfo: [out] Certify information relative to keyhandle \n * @outDataSize: [out] The used size of the output area for outData \n * @outData: [out] The signed public key\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 13.8)\n * The TPM_CERTIFYKEY operation allows a key to certify the public portion of \n * certain storage and signing keys. A TPM identity key may be used to certify \n * non-migratable keys but is not permitted to certify migratory keys. \n */\nTPM_RESULT TPM_CertifyKey(  \n  TPM_KEY_HANDLE certHandle,\n  TPM_KEY_HANDLE keyHandle,\n  TPM_NONCE *antiReplay,\n  TPM_AUTH *auth1,\n  TPM_AUTH *auth2,  \n  TPM_CERTIFY_INFO *certifyInfo,\n  UINT32 *outDataSize,\n  BYTE **outData  \n);\n\n/**\n * TPM_CertifyKey2 - certifies a CMK\n * @certHandle: [in] Handle of the key to be used to certify the key\n * @keyHandle: [in] Handle of the key to be certified\n * @migrationPubDigest: [in] Digest of the public key of a Migration Authority \n * @antiReplay: [in] 160 bits of externally supplied data (typically a nonce)\n * @auth1: [in, out] Authorization protocol parameters\n * @auth2: [in, out] Authorization protocol parameters\n * @certifyInfo: [out] TPM_CERTIFY_INFO2 relative to keyHandle \n * @outDataSize: [out] The used size of the output area for outData \n * @outData: [out] The signed public key\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 13.9)\n * This command provides the ability to certify a Certifiable Migration Key \n * (CMK). This certification requires additional parameters and output then \n * the TPM_CertifyKey. This command always uses the TPM_SIGN_INFO2 structure. \n * All other aspects of the command are the same as TPM_CertifyKey. \n */\nTPM_RESULT TPM_CertifyKey2(  \n  TPM_KEY_HANDLE certHandle,\n  TPM_KEY_HANDLE keyHandle,\n  TPM_DIGEST *migrationPubDigest,\n  TPM_NONCE *antiReplay,\n  TPM_AUTH *auth1,\n  TPM_AUTH *auth2,  \n  TPM_CERTIFY_INFO *certifyInfo,\n  UINT32 *outDataSize,\n  BYTE **outData  \n);\n\n/*\n * Credential Handling ([TPM_Part3], Section 14)\n * [tpm_credentials.c]\n * There are two create EK commands. The first matches the 1.1 functionality. \n * The second provides the mechanism to enable revokeEK and provides \n * FIPS 140-2 compatibility. \n */\n\n/**\n * TPM_CreateEndorsementKeyPair - creates the TPM endorsement key\n * @antiReplay: [in] Arbitrary data \n * @keyInfo: [in] Information about key to be created\n * @pubEndorsementKey: [out] The public endorsement key\n * @Checksum: [out] Hash of pubEndorsementKey and antiReplay\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 14.1)\n * This command creates the TPM endorsement key. It returns a failure code if \n * an endorsement key already exists.\n */\nTPM_RESULT TPM_CreateEndorsementKeyPair(  \n  TPM_NONCE *antiReplay,\n  TPM_KEY_PARMS *keyInfo,  \n  TPM_PUBKEY *pubEndorsementKey,\n  TPM_DIGEST *Checksum \n);\n\n/**\n * TPM_CreateRevocableEK - creates the TPM endorsement key\n * @antiReplay: [in] Arbitrary data \n * @keyInfo: [in] Information about key to be created\n * @generateReset: [in] If TRUE generate EKreset otherwise use the passed value\n * @inputEKreset: [in] Authorization value to be used if generateReset is FALSE\n * @pubEndorsementKey: [out] The public endorsement key\n * @Checksum: [out] Hash of pubEndorsementKey and antiReplay\n * @outputEKreset: [out] The authorization value to use TPM_RevokeTrust\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 14.2)\n * This command creates the TPM endorsement key. It returns a failure code if \n * an endorsement key already exists. \n */\nTPM_RESULT TPM_CreateRevocableEK(  \n  TPM_NONCE *antiReplay,\n  TPM_KEY_PARMS *keyInfo,\n  BOOL generateReset,\n  TPM_NONCE *inputEKreset,  \n  TPM_PUBKEY *pubEndorsementKey,\n  TPM_DIGEST *Checksum,\n  TPM_NONCE *outputEKreset \n);\n\n/**\n * TPM_RevokeTrust - clears the EK and sets the TPM to a pure default state\n * @EKReset: [in] The value that will be matched to EK Reset\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 14.3)\n * This command clears the EK and sets the TPM back to a pure default state. \n * The generation of the authorization value occurs during the generation of \n * the EK. It is the responsibility of the EK generator to properly protect \n * and disseminate the RevokeTrust authorization. \n */\nTPM_RESULT TPM_RevokeTrust(  \n  TPM_NONCE *EKReset\n);\n\n/**\n * tpm_get_pubek - extracts the public portion of the EK\n * @pubEndorsementKey: [out] The public endorsement key\n */\nTPM_RESULT tpm_get_pubek(\n  TPM_PUBKEY *pubEndorsementKey\n);\n\n/**\n * TPM_ReadPubek - provides the public portion of the EK\n * @antiReplay: [in] Arbitrary data\n * @pubEndorsementKey: [out] The public endorsement key\n * @checksum: [out] Hash of pubEndorsementKey and antiReplay\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 14.4)\n * Provides the endorsement key public portion. This value should have \n * controls placed upon access as it is a privacy sensitive value.\n */\nTPM_RESULT TPM_ReadPubek(  \n  TPM_NONCE *antiReplay,  \n  TPM_PUBKEY *pubEndorsementKey,\n  TPM_DIGEST *checksum \n);\n\n/**\n * TPM_DisablePubekRead - disables the TPM_ReadPubk command\n * @auth1: [in, out] Authorization protocol parameters\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 14.5)\n * The TPM Owner may wish to prevent any entity from reading the PUBEK. \n * This command sets the non-volatile flag so that the TPM_ReadPubek \n * command always returns TPM_DISABLED_CMD.\n */\nTPM_RESULT TPM_DisablePubekRead(  \n  TPM_AUTH *auth1\n);\n\n/**\n * TPM_OwnerReadInternalPub - provides the public portion of the EK or SRK\n * @keyHandle: [in] Handle for either PUBEK or SRK\n * @auth1: [in, out] Authorization protocol parameters\n * @publicPortion: [out] The public portion of the requested key \n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 14.6)\n * A TPM Owner authorized command that provides the public portion of \n * the EK or SRK.\n */\nTPM_RESULT TPM_OwnerReadInternalPub(  \n  TPM_KEY_HANDLE keyHandle,\n  TPM_AUTH *auth1,  \n  TPM_PUBKEY *publicPortion \n);\n\n/*\n * Identity Creation and Activation ([TPM_Part3], Section 15)\n * [tpm_identity.c]\n */\n\n/**\n * TPM_MakeIdentity - generates a new AIK\n * @identityAuth: [in] Encrypted usage authorization data for the new identity \n * @labelPrivCADigest: [in] Digest of the identity label and the new privacy CA\n * @idKeyParams: [in] All parameters of the new identity key\n * @auth1: [in, out] Authorization protocol parameters\n * @auth2: [in, out] Authorization protocol parameters\n * @idKey: [out] The newly created identity key\n * @identityBindingSize: [out] The size of the output area for identityBinding \n * @identityBinding: [out] Signature of TPM_IDENTITY_CONTENTS using idKey\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 15.1)\n * Generate a new Attestation Identity Key (AIK).\n */\nTPM_RESULT TPM_MakeIdentity(  \n  TPM_ENCAUTH *identityAuth,\n  TPM_CHOSENID_HASH *labelPrivCADigest,\n  TPM_KEY *idKeyParams,\n  TPM_AUTH *auth1,\n  TPM_AUTH *auth2,  \n  TPM_KEY *idKey,\n  UINT32 *identityBindingSize,\n  BYTE **identityBinding  \n);\n\n/**\n * TPM_ActivateIdentity - activates a TPM identity\n * @idKeyHandle: [in] Identity key to be activated \n * @blobSize: [in] Size of encrypted blob from CA \n * @blob: [in] The encrypted ASYM_CA_CONTENTS or TPM_EK_BLOB\n * @auth1: [in, out] Authorization protocol parameters (usageAuth)\n * @auth2: [in, out] Authorization protocol parameters (ownerAuth)\n * @symmetricKey: [out] The decrypted symmetric key\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 15.2)\n * The purpose of TPM_ActivateIdentity is to twofold. The first purpose is to \n * obtain assurance that the credential in the TPM_SYM_CA_ATTESTATION is for \n * this TPM. The second purpose is to obtain the session key used to encrypt \n * the TPM_IDENTITY_CREDENTIAL. \n */\nTPM_RESULT TPM_ActivateIdentity(  \n  TPM_KEY_HANDLE idKeyHandle,\n  UINT32 blobSize,\n  BYTE *blob,\n  TPM_AUTH *auth1,\n  TPM_AUTH *auth2,  \n  TPM_SYMMETRIC_KEY *symmetricKey \n);\n\n/*\n * Integrity Collection and Reporting ([TPM_Part3], Section 16)\n * [tpm_integrity.c]\n * This section deals with what commands have direct access to the PCR.\n */\n\n/**\n * TPM_Extend - adds a new measurement to a PCR\n * @pcrNum: [in] The PCR to be updated\n * @inDigest: [in] The 160 bit value representing the event to be recorded\n * @outDigest: [out] The PCR value after execution of the command\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 16.1)\n * This adds a new measurement to a Platform Configuration Register (PCR).\n */\nTPM_RESULT TPM_Extend(\n  TPM_PCRINDEX pcrNum,\n  TPM_DIGEST *inDigest,\n  TPM_PCRVALUE *outDigest\n);\n\n/**\n * TPM_PCRRead - provides the contents of a named PCR\n * @pcrIndex: [in] Index of the PCR to be read\n * @outDigest: [out] The current contents of the named PCR\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 16.2)\n * The TPM_PCRRead operation provides non-cryptographic reporting of the\n * contents of a named PCR.\n */\nTPM_RESULT TPM_PCRRead(\n  TPM_PCRINDEX pcrIndex,\n  TPM_PCRVALUE *outDigest\n);\n\n/**\n * TPM_Quote - provides cryptographic reporting of PCR values\n * @keyHandle: [in] Handle of a loaded key that can sign the PCR values\n * @extrnalData: [in] 160 bits of externally supplied data (typically a nonce)\n * @targetPCR: [in] The indices of the PCRs that are to be reported\n * @auth1: [in, out] Authorization protocol parameters\n * @pcrData: [out] The indices and values of the PCRs listed in targetPCR\n * @sigSize: [out] The used size of the output area for the signature\n * @sig: [out] The signed data blob\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 16.3)\n * The TPM_Quote operation provides cryptographic reporting of PCR values.\n * A loaded key is required for operation TPM_Quote uses a key to sign a\n * statement that names the current value of a chosen PCR and externally\n * supplied data (which may be a nonce supplied by a Challenger).\n */\nTPM_RESULT TPM_Quote(\n  TPM_KEY_HANDLE keyHandle,\n  TPM_NONCE *extrnalData,\n  TPM_PCR_SELECTION *targetPCR,\n  TPM_AUTH *auth1,\n  TPM_PCR_COMPOSITE *pcrData,\n  UINT32 *sigSize,\n  BYTE **sig\n);\n\n/**\n * TPM_PCR_Reset - resets the indicated PCRs\n * @pcrSelection: [in] The PCRs to reset\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 16.4)\n * Resets the indicated PCRs. This command uses the locality modifier.\n * The modifier for a command to indicate locality is a platform specific\n * issue.\n */\nTPM_RESULT TPM_PCR_Reset(\n  TPM_PCR_SELECTION *pcrSelection\n);\n\n/**\n * TPM_Quote2 - provides cryptographic reporting of PCR values\n * @keyHandle: [in] Handle of a loaded key that can sign the PCR values\n * @extrnalData: [in] 160 bits of externally supplied data (typically a nonce)\n * @targetPCR: [in] The indices of the PCRs that are to be reported\n * @addVersion: [in] When TRUE add TPM_CAP_VERSION_INFO to the output\n * @auth1: [in, out] Authorization protocol parameters\n * @pcrData: [out] The value created and signed for the quote\n * @versionInfoSize: [out] Size of the version info\n * @versionInfo: [out] The version info\n * @sigSize: [out] The used size of the output area for the signature\n * @sig: [out] The signed data blob\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 16.5)\n */\nTPM_RESULT TPM_Quote2(\n  TPM_KEY_HANDLE keyHandle,\n  TPM_NONCE *externalData,\n  TPM_PCR_SELECTION *targetPCR,\n  BOOL addVersion,\n  TPM_AUTH *auth1,\n  TPM_PCR_INFO_SHORT *pcrData,\n  UINT32 *versionInfoSize,\n  TPM_CAP_VERSION_INFO *versionInfo,\n  UINT32 *sigSize,\n  BYTE **sig\n);\n\n/**\n * tpm_compute_pcr_digest - computes a PCR composite hash\n * @pcrSelection: [in] The PCRs to include\n * @digest: [out] The computed composite hash\n * @composite: [out] If not NULL the used composite is stored into it\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n *\n * Description: ([TPM_Part3], Section 5.3.1)\n * Computes the PCR composite hash over a given set of PCRs.\n */\nTPM_RESULT tpm_compute_pcr_digest(\n  TPM_PCR_SELECTION *pcrSelection,\n  TPM_COMPOSITE_HASH *digest,\n  TPM_PCR_COMPOSITE *composite\n);\n\n/**\n * tpm_verify_pcr - verifies the PCR composite hash of the specified key\n * @key: [in] The key whose PCR composite hash should be verified\n * @atrelease: [in] If TRUE the AtRelease composite hash is verified\n * @atcreation: [in] If TRUE the AtCreation composite hash is verified\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n *\n * Description: ([TPM_Part3], Section 5.3.1)\n * Computes the PCR composite hash over a given set of PCRs.\n */\nTPM_RESULT tpm_verify_pcr(\n  TPM_KEY_DATA *key, \n  BOOL atrelease, \n  BOOL atcreation\n);\n\n/*\n * Authorization Changing ([TPM_Part3], Section 17)\n * [tpm_authorization.c]\n */\n\n/**\n * TPM_ChangeAuth - changes the authorization data for the entity\n * @parentHandle: [in] Handle of the parent key to the entity\n * @protocolID: [in] The protocol in use\n * @newAuth: [in] The encrypted new authorization data for the entity\n * @entityType: [in] The type of entity to be modified \n * @encDataSize: [in] The size of the encData parameter \n * @encData: [in] The encrypted entity that is to be modified\n * @auth1: [in, out] Authorization protocol parameters\n * @auth2: [in, out] Authorization protocol parameters\n * @outDataSize: [out] The used size of the output area for outData \n * @outData: [out] The modified, encrypted entity\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 17.1)\n * The TPM_ChangeAuth command allows the owner of an entity to change the \n * authorization data for the entity. TPM_ChangeAuth requires the encryption \n * of one parameter (NewAuth). \n */\nTPM_RESULT TPM_ChangeAuth(  \n  TPM_KEY_HANDLE parentHandle,\n  TPM_PROTOCOL_ID protocolID,\n  TPM_ENCAUTH *newAuth,\n  TPM_ENTITY_TYPE entityType,\n  UINT32 encDataSize,\n  BYTE *encData,\n  TPM_AUTH *auth1,\n  TPM_AUTH *auth2,  \n  UINT32 *outDataSize,\n  BYTE **outData  \n);\n\n/**\n * TPM_ChangeAuthOwner - changes the authorization data for the TPM Owner\n * @protocolID: [in] The protocol in use\n * @newAuth: [in] The encrypted new authorization data for the entity\n * @entityType: [in] The type of entity to be modified\n * @auth1: [in, out] Authorization protocol parameters\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 17.2)\n * The TPM_ChangeAuthOwner command allows the owner of an entity to change \n * the authorization data for the TPM Owner or the SRK. This command requires \n * authorization from the current TPM Owner to execute.\n */\nTPM_RESULT TPM_ChangeAuthOwner(  \n  TPM_PROTOCOL_ID protocolID,\n  TPM_ENCAUTH *newAuth,\n  TPM_ENTITY_TYPE entityType,\n  TPM_AUTH *auth1\n);\n\n/*\n * Authorization Sessions ([TPM_Part3], Section 18)\n * [tpm_authorization.c]\n */\n\n/**\n * TPM_OIAP - creates an authorization handle for the OIAP\n * @authHandle: [out] Handle that points to the authorization state\n * @nonceEven: [out] Nonce associated with session\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 18.1)\n * The TPM_OIAP command creates an authorization handle and generates \n * nonceEven for the Object-Independent Authorization Protocol (OIAP).\n */\nTPM_RESULT TPM_OIAP(  \n  TPM_AUTHHANDLE *authHandle,\n  TPM_NONCE *nonceEven \n);\n\n/**\n * TPM_OSAP - creates an authorization handle for the OSAP\n * @entityType: [in] The type of entity in use\n * @entityValue: [in] The selection value based on entityType\n * @nonceOddOSAP: [in] The nonce generated by the caller\n * @authHandle: [out] Handle that points to the authorization state\n * @nonceEven: [out] Nonce associated with session\n * @nonceEvenOSAP: [out] Nonce associated with shared secret\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 18.2)\n * The TPM_OSAP command creates an authorization handle, the shared secret \n * and generates nonceEven and nonceEvenOSAP for the Object-Specific \n * Authorization Protocol (OSAP).\n */\nTPM_RESULT TPM_OSAP(  \n  TPM_ENTITY_TYPE entityType,\n  UINT32 entityValue,\n  TPM_NONCE *nonceOddOSAP,  \n  TPM_AUTHHANDLE *authHandle,\n  TPM_NONCE *nonceEven,\n  TPM_NONCE *nonceEvenOSAP \n);\n\n/**\n * TPM_DSAP - creates an authorization handle for the DSAP\n * @entityType [in] The type of delegation information to use\n * @keyHandle: [in] Key for which delegated authority corresponds\n * @nonceOddDSAP: [in] The nonce generated by the caller\n * @entityValueSize: [in] The size of entityValue \n * @entityValue: [in] The entity value based on entityType\n * @authHandle: [out] Handle that points to the authorization state\n * @nonceEven: [out] Nonce associated with session\n * @nonceEvenDSAP: [out] Nonce associated with shared secret\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 18.3)\n * The TPM_DSAP command creates the authorization handle using a delegated \n * authorization value passed into the command as an encrypted blob or from \n * the internal delegation table for the Delegate-Specific Authorization \n * Protocol (DSAP). \n */\nTPM_RESULT TPM_DSAP(\n  TPM_ENTITY_TYPE entityType,\n  TPM_KEY_HANDLE keyHandle,\n  TPM_NONCE *nonceOddDSAP,\n  UINT32 entityValueSize,\n  BYTE *entityValue,\n  TPM_AUTHHANDLE *authHandle,\n  TPM_NONCE *nonceEven,\n  TPM_NONCE *nonceEvenDSAP \n);\n\n/**\n * TPM_SetOwnerPointer - sets an owner secret for OIAP or OSAP \n * @entityType: [in] The type of entity in use\n * @entityValue: [in] The selection value based on entityType,\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 18.4)\n * This command will set a reference to which secret the TPM will use when \n * executing an owner secret related OIAP or OSAP session. This command \n * should only be used if legacy code must be enabled for delegation to work.\n */\nTPM_RESULT TPM_SetOwnerPointer(  \n  TPM_ENTITY_TYPE entityType,\n  UINT32 entityValue\n);\n\n/**\n * tpm_verify_auth - verifies an authorization session\n * @auth: [in] The handle to the authorization session\n * @secret: [in] The secret associated with the resource\n * @handle: [in] The handle used to access the resource\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n *\n * Description: ([TPM_Part3], Section 18.1.1 and 18.2.1)\n * Verifies a OIAP and OSAP session. In addition to the protocol \n * parameters auth->digest is supposed to contain the the SHA-1 digest \n * of the input parameters.\n */\nTPM_RESULT tpm_verify_auth(\n  TPM_AUTH *auth,\n  TPM_SECRET secret,\n  TPM_HANDLE handle\n);\n\n/**\n * tpm_decrypt_auth_secret - decrypts an authorization secret\n * @encAuth: [in] The encrypted authorization secret\n * @secret: [in] The shared secret of the OSAP session \n * @nonce: [in] The nonce for decryption\n * @plainAuth: [out]: The decrypted authorization secret\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n *\n * Description:\n * Decrypts an encrypted authorization secret by xoring it with\n * the key SHA-1(secret||nonce).\n */\nvoid tpm_decrypt_auth_secret(\n  TPM_ENCAUTH encAuth, \n  TPM_SECRET secret,\n  TPM_NONCE *nonce, \n  TPM_SECRET plainAuth\n);\n\n/*\n * Delegation Commands ([TPM_Part3], Section 19)\n * [tpm_delegation.c]\n */\n\n/**\n * TPM_Delegate_Manage - manages the Family tables\n * @familyID: [in] The familyID that is to be managed \n * @opFlag: [in] Operation to be performed by this command\n * @opDataSize: [in] Size in bytes of opData \n * @opData: [in] Data necessary to implement opFlag\n * @auth1: [in, out] Authorization protocol parameters\n * @retDataSize: [out] Size in bytes of retData \n * @retData: [out] Returned data \n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 19.1)\n * TPM_Delegate_Manage is the fundamental process for managing the Family \n * tables, including enabling/disabling Delegation for a selected Family. \n */\nTPM_RESULT TPM_Delegate_Manage(  \n  TPM_FAMILY_ID familyID,\n  TPM_FAMILY_OPERATION opFlag,\n  UINT32 opDataSize,\n  BYTE *opData,\n  TPM_AUTH *auth1,  \n  UINT32 *retDataSize,\n  BYTE **retData  \n);\n\n/**\n * TPM_Delegate_CreateKeyDelegation - delegates privilege to use a key\n * @keyHandle: [in] Handle of a loaded key\n * @publicInfo: [in] The public information necessary to fill in the blob \n * @delAuth: [in] The encrypted new authorization data for the blob\n * @auth1: [in, out] Authorization protocol parameters\n * @blob: [out] The partially encrypted delegation information\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 19.2)\n * This command delegates privilege to use a key by creating a blob that can \n * be used by TPM_DSAP. \n */\nTPM_RESULT TPM_Delegate_CreateKeyDelegation(  \n  TPM_KEY_HANDLE keyHandle,\n  TPM_DELEGATE_PUBLIC *publicInfo,\n  TPM_ENCAUTH *delAuth,\n  TPM_AUTH *auth1,  \n  TPM_DELEGATE_KEY_BLOB *blob \n);\n\n/**\n * TPM_Delegate_CreateOwnerDelegation - delegates the Owner's privilege\n * @increment: [in] Flag dictates whether verificationCount will be incremented\n * @publicInfo: [in] The public parameters for the blob \n * @delAuth: [in] The encrypted new authorization data for the blob\n * @auth1: [in, out] Authorization protocol parameters\n * @blob: [out] The partially encrypted delegation information\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 19.3)\n * TPM_Delegate_CreateOwnerDelegation delegates the Owner's privilege to use \n * a set of command ordinals, by creating a blob. Such blobs can be used as \n * input data for TPM_DSAP or TPM_Delegate_LoadOwnerDelegation. \n */\nTPM_RESULT TPM_Delegate_CreateOwnerDelegation(  \n  BOOL increment,\n  TPM_DELEGATE_PUBLIC *publicInfo,\n  TPM_ENCAUTH *delAuth,\n  TPM_AUTH *auth1,  \n  TPM_DELEGATE_OWNER_BLOB *blob \n);\n\n/**\n * TPM_Delegate_LoadOwnerDelegation - loads a delegate table row blob\n * @index: [in] The index of the delegate row to be written\n * @blob: [in] the delegation information\n * @auth1: [in, out] Authorization protocol parameters\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 19.4)\n * This command loads a delegate table row blob into a non-volatile delegate \n * table row. Delegate_LoadOwnerDelegation can be used during manufacturing or \n * on first boot (when no Owner is installed), or after an Owner is installed. \n */\nTPM_RESULT TPM_Delegate_LoadOwnerDelegation(  \n  TPM_DELEGATE_INDEX index,\n  TPM_DELEGATE_OWNER_BLOB *blob,\n  TPM_AUTH *auth1\n);\n\n/**\n * TPM_Delegate_ReadTable - reads from the family and delegate tables\n * @familyTableSize: [out] Size in bytes of familyTable \n * @familyTable: [out] Array of TPM_FAMILY_TABLE_ENTRY elements\n * @delegateTableSize: [out] Size in bytes of delegateTable \n * @delegateTable: [out] Array of TPM_DELEGATE_TABLE_PUBLIC elements\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 19.5)\n * This command is used to read from the TPM the public contents of the \n * family and delegate tables that are stored on the TPM. \n */\nTPM_RESULT TPM_Delegate_ReadTable(  \n  UINT32 *familyTableSize,\n  BYTE **familyTable ,\n  UINT32 *delegateTableSize,\n  BYTE **delegateTable\n);\n\n/**\n * TPM_Delegate_UpdateVerification - updates the verificationCount \n * @inputSize: [in] The size of inputData\n * @inputData: [in] TPM_DELEGATE_KEY_BLOB, -OWNER_BLOB or table index\n * @auth1: [in, out] Authorization protocol parameters\n * @outputSize: [out] The size of the output \n * @outputData: [out] TPM_DELEGATE_KEY_BLOB or TPM_DELEGATE_OWNER_BLOB\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 19.6)\n * UpdateVerification sets the verificationCount in an entity (a blob or a \n * delegation row) to the current family value, in order that the delegations \n * represented by that entity will continue to be accepted by the TPM.\n */\nTPM_RESULT TPM_Delegate_UpdateVerification(  \n  UINT32 inputSize,\n  BYTE *inputData,\n  TPM_AUTH *auth1,  \n  UINT32 *outputSize,\n  BYTE **outputData  \n);\n\n/**\n * TPM_Delegate_VerifyDelegation - verifies a delegate blob\n * @delegateSize: [in] The length of the delegated information blob \n * @delegation: [in] TPM_DELEGATE_KEY_BLOB or TPM_DELEGATE_OWNER_BLOB\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 19.7)\n * VerifyDelegation loads a delegate blob and returns success or failure, \n * depending on whether the blob is currently valid.\n */\nTPM_RESULT TPM_Delegate_VerifyDelegation(  \n  UINT32 delegateSize,\n  BYTE *delegation\n);\n\n/**\n * tpm_get_family_row - returns the family row for the specified id\n * @id: [in] family id\n * Returns: The matching family row on success, NULL otherwise.\n */\nTPM_FAMILY_TABLE_ENTRY *tpm_get_family_row(\n  TPM_FAMILY_ID id\n);\n\n/**\n * tpm_get_delegate_row - returns the delegate row for the specified index\n * @row: [in] row index\n * Returns: The matching delegate row on success, NULL otherwise.\n */\nTPM_DELEGATE_TABLE_ROW *tpm_get_delegate_row(\n  UINT32 row\n);\n\n/**\n * tpm_compute_owner_blob_digest - computes the digest of an owner blob\n * @blob: [in] Owner blob\n * @digest: [out] Digest of the specified owner blob\n */\nvoid tpm_compute_owner_blob_digest(\n  TPM_DELEGATE_OWNER_BLOB *blob,\n  TPM_DIGEST *digest\n);\n\n/**\n * tpm_compute_key_blob_digest - computes the digest of a key blob\n * @blob: [in] Key blob\n * @digest: [out] Digest of the specified key blob\n */\nvoid tpm_compute_key_blob_digest(\n  TPM_DELEGATE_KEY_BLOB *blob,\n  TPM_DIGEST *digest\n);\n\n/**\n * tpm_encrypt_sensitive - encrypts a TPM_DELEGATE_SENSITIVE structure\n * @iv: [in] IV value\n * @iv_size: [in] Size of the IV value\n * @sensitive: [in] structure to encrypt\n * @enc: [out] Encrypted structure\n * @enc_size: [out] Size of the encrypted structure\n * Returns 0 on success, -1 otherwise.\n */\nint tpm_encrypt_sensitive(\n  BYTE *iv,\n  UINT32 iv_size,\n  TPM_DELEGATE_SENSITIVE *sensitive,\n  BYTE **enc,\n  UINT32 *enc_size\n);\n\n/**\n * tpm_decrypt_sensitive - decrypts a TPM_DELEGATE_SENSITIVE structure\n * @iv: [in] IV value\n * @iv_size: [in] Size of the IV value\n * @enc: [in] Encrypted structure\n * @enc_size: [in] Size of the encrypted structure\n * @sensitive: [out] decrypted structure\n * Returns 0 on success, -1 otherwise.\n */\nint tpm_decrypt_sensitive(\n  BYTE *iv,\n  UINT32 iv_size,\n  BYTE *enc,\n  UINT32 enc_size,\n  TPM_DELEGATE_SENSITIVE *sensitive,\n  BYTE **buf\n);\n\n/*\n * Non-volatile Storage ([TPM_Part3], Section 20)\n * [tpm_nv_storage.c]\n * This section handles the allocation and use of the TPM non-volatile storage.\n */\n\n/**\n * TPM_NV_DefineSpace - establishes the necessary space\n * @pubInfo: [in] The public parameters of the NV area\n * @encAuth: [in] The encrypted authorization (if reqired)\n * @auth1: [in, out] Authorization protocol parameters\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 20.1)\n * This establishes the space necessary for the indicated index. The definition \n * will include the access requirements for writing and reading the area. The \n * space definition size does not include the area needed to manage the space.\n */\nTPM_RESULT TPM_NV_DefineSpace(  \n  TPM_NV_DATA_PUBLIC *pubInfo,\n  TPM_ENCAUTH *encAuth,\n  TPM_AUTH *auth1\n);\n\n/**\n * TPM_NV_WriteValue - writes a value to a defined NV area\n * @nvIndex: [in] The index of the area to set\n * @offset: [in] The offset into the NV Area\n * @dataSize: [in] The size of the data area\n * @data: [in] The data to set the area to\n * @auth1: [in, out] Authorization protocol parameters\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 20.2)\n * This command writes a value to a defined area. The write can be TPM Owner \n * authorized or unauthorized and protected by other attributes and will work \n * when no TPM Owner is present.\n */\nTPM_RESULT TPM_NV_WriteValue(  \n  TPM_NV_INDEX nvIndex,\n  UINT32 offset,\n  UINT32 dataSize,\n  BYTE *data,\n  TPM_AUTH *auth1\n);\n\n/**\n * TPM_NV_WriteValueAuth - writes a value to a protected NV area\n * @nvIndex: [in] The index of the area to set\n * @offset: [in] The offset into the chunk \n * @dataSize: [in] The size of the data area \n * @data: [in] The data to set the area to\n * @auth1: [in, out] Authorization protocol parameters\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 20.3)\n * This command writes to a previously defined area. The area must require \n * authorization to write. This command is for using when authorization other \n * than the owner authorization is to be used. \n */\nTPM_RESULT TPM_NV_WriteValueAuth(  \n  TPM_NV_INDEX nvIndex,\n  UINT32 offset,\n  UINT32 dataSize,\n  BYTE *data,\n  TPM_AUTH *auth1\n);\n\n/**\n * TPM_NV_ReadValue - reads a value from a defined NV area\n * @nvIndex: [in] The index of the area to set\n * @offset: [in] The offset into the area \n * @inDataSize: [in] The size of the data area\n * @auth1: [in, out] Authorization protocol parameters\n * @outDataSize: [out] The size of the data area \n * @data: [out] The data to set the area to\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 20.4)\n * Read a value from the NV store. This command uses optional owner \n * authorization.\n */\nTPM_RESULT TPM_NV_ReadValue(  \n  TPM_NV_INDEX nvIndex,\n  UINT32 offset,\n  UINT32 inDataSize,\n  TPM_AUTH *auth1,  \n  UINT32 *outDataSize,\n  BYTE **data  \n);\n\n/**\n * TPM_NV_ReadValueAuth - reads a value from a protected NV area\n * @nvIndex: [in] The index of the area to set\n * @offset: [in] The offset from the data area \n * @inDataSize: [in] The size of the data area\n * @auth1: [in, out] Authorization protocol parameters\n * @outDataSize: [out] The size of the data area \n * @data: [out] The data\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 20.5)\n * This command requires that the read be authorized by a value set \n * with the blob.\n */\nTPM_RESULT TPM_NV_ReadValueAuth(  \n  TPM_NV_INDEX nvIndex,\n  UINT32 offset,\n  UINT32 inDataSize,\n  TPM_AUTH *auth1,  \n  UINT32 *outDataSize,\n  BYTE **data  \n);\n\n/**\n * tpm_nv_remove_data - removes the specified data from the NV area\n * @nv: [in] Data area to be removed\n */\nvoid tpm_nv_remove_data(\n  TPM_NV_DATA_SENSITIVE *nv\n);\n\n/*\n * Session Management ([TPM_Part3], Section 21)\n * [tpm_context.c]\n */\n\n/**\n * TPM_KeyControlOwner - controls attributes of keys within the key cache\n * @keyHandle: [in] Handle of a loaded key\n * @pubKey: [in] The public key associated with the loaded key\n * @bitName: [in] The name of the bit to be modified\n * @bitValue: [in] The value to set the bit to\n * @auth1: [in, out] Authorization protocol parameters\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 21.1)\n * This command controls some attributes of keys that are stored within \n * the TPM key cache. \n */\nTPM_RESULT TPM_KeyControlOwner(  \n  TPM_KEY_HANDLE keyHandle,\n  TPM_PUBKEY pubKey,\n  UINT32 bitName,\n  BOOL bitValue,\n  TPM_AUTH *auth1\n);\n\n/**\n * TPM_SaveContext - saves a loaded resource outside the TPM\n * @handle: [in] Handle of the resource being saved\n * @resourceType: [in] The type of resource that is being saved\n * @label[16]: [in] Label for identification purposes\n * @contextSize: [out] The actual size of the outgoing context blob \n * @contextBlob: [out] The context blob\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 21.2)\n * SaveContext saves a loaded resource outside the TPM. After successful \n * execution of the command the TPM automatically releases the internal \n * memory for sessions but leaves keys in place.\n */\nTPM_RESULT TPM_SaveContext(  \n  TPM_HANDLE handle,\n  TPM_RESOURCE_TYPE resourceType,\n  const BYTE label[16],  \n  UINT32 *contextSize,\n  TPM_CONTEXT_BLOB *contextBlob \n);\n\n/**\n * TPM_LoadContext - loads a previously saved context into the TPM\n * @entityHandle: [in] The hint handle the TPM MAY use to locate a OSAP session\n * @keepHandle: [in] Indication if the handle MUST be preserved\n * @contextSize: [in] The size of the following context blob\n * @contextBlob: [in] The context blob\n * @handle: [out] Handle assigned to the resource\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 21.3)\n * LoadContext loads into the TPM a previously saved context. The command \n * returns the type of blob and a handle.\n */\nTPM_RESULT TPM_LoadContext(\n  TPM_HANDLE entityHandle,\n  BOOL keepHandle,\n  UINT32 contextSize,\n  TPM_CONTEXT_BLOB *contextBlob,  \n  TPM_HANDLE *handle \n);\n\n/**\n * tpm_get_free_session - allocates a new session\n * @type: [in] The session type\n * Returns: the session handle on success, TPM_INVALID_HANDLE otherwise.\n */\nUINT32 tpm_get_free_session(\n  BYTE type\n);\n\n/**\n * tpm_invalidate_sessions - invalidates all sessions associated with the handle\n * @handle: [in] Session handle\n */\nvoid tpm_invalidate_sessions(\n  TPM_HANDLE handle\n);\n\n/*\n * Eviction ([TPM_Part3], Section 22)\n * [tpm_eviction.c]\n * The TPM has numerous resources held inside of the TPM that may need \n * eviction. The need for eviction occurs when the number or resources \n * in use by the TPM exceed the available space. In version 1.1 there were \n * separate commands to evict separate resource types. This new command \n * set uses the resource types defined for context saving and creates a \n * generic command that will evict all resource types.\n */\n\n/**\n * TPM_FlushSpecific - flushes a specific handle\n * @handle: [in] Handle of the item to flush\n * @resourceType: [in] The type of resource that is being flushed\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 22.1)\n * TPM_FlushSpecific flushes from the TPM a specific handle.\n */\nTPM_RESULT TPM_FlushSpecific(  \n  TPM_HANDLE handle,\n  TPM_RESOURCE_TYPE resourceType\n);\n\n/*\n * Timing Ticks ([TPM_Part3], Section 23)\n * [tpm_ticks.c]\n * The TPM timing ticks are always available for use. The association of \n * timing ticks to actual time is a protocol that occurs outside of the TPM. \n * See the design document for details. \n */\n\n/**\n * TPM_GetTicks - provides the current tick count\n * @currentTime: [out] The current time held in the TPM descriptions \n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 23.2)\n * This command provides the current tick count of the TPM.\n */\nTPM_RESULT TPM_GetTicks(  \n  TPM_CURRENT_TICKS *currentTime \n);\n\n/**\n * TPM_TickStampBlob - applies a time stamp to the passed blob\n * @keyHandle: [in] Handle of a loaded key that can perform digital signatures\n * @antiReplay: [in] Anti replay value to added to signature\n * @digestToStamp: [in] The digest to perform the tick stamp on  \n * @auth1: [in, out] Authorization protocol parameters\n * @currentTicks: [out] The current time according to the TPM\n * @sigSize: [out] The length of the returned digital signature \n * @sig: [out] The resulting digital signature\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 23.3)\n * This command applies a time stamp to the passed blob. The TPM makes no \n * representation regarding the blob merely that the blob was present at \n * the TPM at the time indicated.\n */\nTPM_RESULT TPM_TickStampBlob(  \n  TPM_KEY_HANDLE keyHandle,\n  TPM_NONCE *antiReplay,\n  TPM_DIGEST *digestToStamp,\n  TPM_AUTH *auth1,  \n  TPM_CURRENT_TICKS *currentTicks,\n  UINT32 *sigSize,\n  BYTE **sig  \n);\n\n/**\n * tpm_update_ticks - updates the current tick session\n */\nvoid tpm_update_ticks(void);\n\n/*\n * Transport Sessions ([TPM_Part3], Section 24)\n * [tpm_transport.c]\n */\n\n/**\n * TPM_EstablishTransport - establishes a transport session\n * @encHandle: [in] Handle to the key that encrypted the blob \n * @transPublic: [in] The public information describing the transport session\n * @secretSize: [in] The size of the secret Area \n * @secret: [in] The encrypted secret area\n * @auth1: [in, out] Authorization protocol parameters\n * @transHandle: [out] Handle for the transport session\n * @locality [out] The locality that called this command\n * @currentTicks: [out] The current tick count \n * @transNonce: [out] The even nonce in use for subsequent execute transport \n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 24.1)\n * This establishes a transport session. Depending on the attributes \n * specified for the session this may establish shared secrets, encryption \n * keys and session logs. The session will be in use for by the \n * TPM_ExecuteTransport command.\n */\nTPM_RESULT TPM_EstablishTransport(  \n  TPM_KEY_HANDLE encHandle,\n  TPM_TRANSPORT_PUBLIC *transPublic,\n  UINT32 secretSize,\n  BYTE *secret,\n  TPM_AUTH *auth1,  \n  TPM_TRANSHANDLE *transHandle,\n  TPM_MODIFIER_INDICATOR *locality,\n  TPM_CURRENT_TICKS *currentTicks,\n  TPM_NONCE *transNonce \n);\n\n/**\n * TPM_ExecuteTransport - executes a wrapped TPM command\n * @inWrappedCmdSize: [in] Size of the wrapped command \n * @inWrappedCmd: [in] The wrapped command\n * @auth1: [in, out] Authorization protocol parameters\n * @currentTicks: [out] The current ticks when the command was executed\n * @locality [out] The locality that called this command\n * @outWrappedCmdSize: [out] Size of the wrapped command \n * @outWrappedCmd: [out] The wrapped command\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 24.2)\n * Delivers a wrapped TPM command to the TPM where the TPM unwraps the \n * command and then executes the command. \n */\nTPM_RESULT TPM_ExecuteTransport(  \n  UINT32 inWrappedCmdSize,\n  BYTE *inWrappedCmd,\n  TPM_AUTH *auth1,  \n  UINT64 *currentTicks,\n  TPM_MODIFIER_INDICATOR *locality,\n  UINT32 *outWrappedCmdSize,\n  BYTE **outWrappedCmd  \n);\n\n/**\n * TPM_ReleaseTransportSigned - completes a transport session\n * @Key: [in] The key that will perform the signing \n * @antiReplay: [in] Value provided by caller for anti-replay protection\n * @auth1: [in, out] Authorization protocol parameters\n * @auth2: [in, out] Authorization protocol parameters\n * @locality [out] The locality that called this command\n * @currentTicks: [out] The current ticks when the command was executed\n * @signSize: [out] The size of the signature area \n * @signature: [out] The signature of the digest \n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 24.3)\n * This command completes a transport session. If logging for this session \n * is turned on, then this command returns a signed hash of all operations \n * performed during the session. This command serves no purpose if logging \n * is turned off and results in an error if attempted. \n */\nTPM_RESULT TPM_ReleaseTransportSigned(  \n  TPM_KEY_HANDLE Key,\n  TPM_NONCE *antiReplay,\n  TPM_AUTH *auth1,\n  TPM_AUTH *auth2,\n  TPM_MODIFIER_INDICATOR *locality,\n  TPM_CURRENT_TICKS *currentTicks,\n  UINT32 *signSize,\n  BYTE **signature  \n);\n\n/*\n * Monotonic Counter ([TPM_Part3], Section 25)\n * [tpm_counter.c]\n */\n\n/**\n * TPM_CreateCounter - creates a counter but does not select it\n * @authData: [in] The encrypted auth data for the new counter \n * @label[4]: [in] Label to associate with counter\n * @auth1: [in, out] Authorization protocol parameters\n * @countID: [out] Handle for the counter\n * @counterValue: [out] The starting counter value\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 25.1)\n * This command creates a counter but does not select it. Counter creation \n * assigns an authorization value to the counter and sets the counters \n * original start value to the current internal base value plus one. \n */\nTPM_RESULT TPM_CreateCounter(  \n  TPM_ENCAUTH *authData,\n  BYTE label[4],\n  TPM_AUTH *auth1,  \n  TPM_COUNT_ID *countID,\n  TPM_COUNTER_VALUE *counterValue \n);\n\n/**\n * TPM_IncrementCounter - increments the indicated counter by one\n * @countID: [in] Handle of a valid counter\n * @auth1: [in, out] Authorization protocol parameters\n * @count: [out] The counter value\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 25.2)\n * This authorized command increments the indicated counter by one. Once a \n * counter has been incremented then all subsequent increments must be for \n * the same handle until a successful TPM_Startup(ST_CLEAR) is executed.\n */\nTPM_RESULT TPM_IncrementCounter(  \n  TPM_COUNT_ID countID,\n  TPM_AUTH *auth1,  \n  TPM_COUNTER_VALUE *count \n);\n\n/**\n * TPM_ReadCounter - provides the current counter number\n * @countID: [in] ID value of the counter\n * @count: [out] The counter value\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 25.3)\n * Reading the counter provides the caller with the current number \n * in the sequence.\n */\nTPM_RESULT TPM_ReadCounter(  \n  TPM_COUNT_ID countID,  \n  TPM_COUNTER_VALUE *count \n);\n\n/**\n * TPM_ReleaseCounter - releases a counter\n * @countID: [in] ID value of the counter\n * @auth1: [in, out] Authorization protocol parameters\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 25.4)\n * This command releases a counter such that no reads or increments \n * of the indicated counter will succeed.\n */\nTPM_RESULT TPM_ReleaseCounter(  \n  TPM_COUNT_ID countID,\n  TPM_AUTH *auth1\n);\n\n/**\n * TPM_ReleaseCounterOwner - releases a counter\n * @countID: [in] ID value of the counter\n * @auth1: [in, out] Authorization protocol parameters\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 25.5)\n * This command releases a counter such that no reads or increments \n * of the indicated counter will succeed.\n */\nTPM_RESULT TPM_ReleaseCounterOwner(  \n  TPM_COUNT_ID countID,\n  TPM_AUTH *auth1\n);\n\n/*\n * DAA commands ([TPM_Part3], Section 26)\n * [tpm_daa.c]\n * Operations that are necessary to setup a TPM for DAA, execute the \n * JOIN process, and execute the SIGN process.\n */\n\n/**\n * TPM_DAA_Join - establishes the DAA parameters\n * @handle: [in] Session handle\n * @stage: [in] Processing stage of join\n * @inputSize0: [in] Size of inputData0 for this stage of JOIN \n * @inputData0: [in] Data to be used by this capability\n * @inputSize1: [in] Size of inputData1 for this stage of JOIN \n * @inputData1: [in] Data to be used by this capability\n * @auth1: [in, out] Authorization protocol parameters\n * @ordinal: [out] Command ordinal: TPM_ORD_DAA_Join\n * @outputSize: [out] Size of outputData \n * @outputData: [out] Data produced by this capability\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 26.1)\n * TPM_DAA_Join is the process that establishes the DAA parameters in \n * the TPM for a specific DAA issuing authority.\n */\nTPM_RESULT TPM_DAA_Join(  \n  TPM_HANDLE handle,\n  BYTE stage,\n  UINT32 inputSize0,\n  BYTE *inputData0,\n  UINT32 inputSize1,\n  BYTE *inputData1,\n  TPM_AUTH *auth1,  \n  TPM_COMMAND_CODE *ordinal,\n  UINT32 *outputSize,\n  BYTE **outputData  \n);\n\n/**\n * TPM_DAA_Sign - proves the attestation held by a TPM\n * @handle: [in] Handle to the sign session\n * @stage: [in] Stage of the sign process\n * @inputSize0: [in] Size of inputData0 for this stage of DAA_Sign \n * @inputData0: [in] Data to be used by this capability\n * @inputSize1: [in] Size of inputData1 for this stage of DAA_Sign \n * @inputData1: [in] Data to be used by this capability\n * @auth1: [in, out] Authorization protocol parameters\n * @ordinal: [out] Command ordinal:TPM_ORD_DAA_SIGN\n * @outputSize: [out] Size of outputData \n * @outputData: [out] Data produced by this capability\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 26.2)\n * TPM_DAA_Sign responds to a challenge and proves the attestation \n * held by a TPM without revealing the attestation held by that TPM.\n */\nTPM_RESULT TPM_DAA_Sign(  \n  TPM_HANDLE handle,\n  BYTE stage,\n  UINT32 inputSize0,\n  BYTE *inputData0,\n  UINT32 inputSize1,\n  BYTE *inputData1,\n  TPM_AUTH *auth1,  \n  TPM_COMMAND_CODE *ordinal,\n  UINT32 *outputSize,\n  BYTE **outputData  \n);\n\n/**\n * tpm_get_free_daa_session - allocates a new DAA session\n * Returns: the session handle on success, TPM_INVALID_HANDLE otherwise.\n */\nUINT32 tpm_get_free_daa_session(void);\n\n/*\n * Deprecated commands ([TPM_Part3], Section 28)\n * [tpm_deprecated.c]\n * This section covers the commands that were in version 1.1 but now have \n * new functionality in other functions. The deprecated commands are still \n * available in 1.2 but all new software should use the new functionality. \n * There is no requirement that the deprecated commands work with new \n * structures.\n */\n\n/**\n * TPM_EvictKey - evicts a key\n * @evictHandle: [in] Handle of the key to be evicted\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 28.1.1)\n * The key commands are deprecated as the new way to handle keys is to use\n * the standard context commands. So TPM_EvictKey is now handled by\n * TPM_FlushSpecific, TPM_TerminateHandle by TPM_FlushSpecific.\n */\nTPM_RESULT TPM_EvictKey(  \n  TPM_KEY_HANDLE evictHandle\n);\n\n/**\n * TPM_Terminate_Handle - clears out information in a session handle\n * @handle: [in] Handle to terminate\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 28.1.2)\n * This allows the TPM manager to clear out information in a session handle. \n */\nTPM_RESULT TPM_Terminate_Handle(  \n  TPM_AUTHHANDLE handle\n);\n\n/**\n * TPM_SaveKeyContext - saves a loaded key outside the TPM\n * @keyHandle: [in] The key which will be kept outside the TPM\n * @keyContextSize: [out] The actual size of the outgoing key context blob\n * @keyContextBlob: [out] The key context blob\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 28.2.1)\n * SaveKeyContext saves a loaded key outside the TPM. After creation of the \n * key context blob the TPM automatically releases the internal memory used \n * by that key. The format of the key context blob is specific to a TPM.\n */\nTPM_RESULT TPM_SaveKeyContext(  \n  TPM_KEY_HANDLE keyHandle,  \n  UINT32 *keyContextSize,\n  BYTE **keyContextBlob  \n);\n\n/**\n * TPM_LoadKeyContext - loads a key context blob into the TPM\n * @keyContextSize: [in] The size of the following key context blob\n * @keyContextBlob: [in] The key context blob\n * @keyHandle: [out] Handle assigned to the key\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 28.2.2)\n * LoadKeyContext loads a key context blob into the TPM previously retrieved \n * by a SaveKeyContext call. After successful completion the handle returned \n * by this command can be used to access the key.\n */\nTPM_RESULT TPM_LoadKeyContext(  \n  UINT32 keyContextSize,\n  BYTE *keyContextBlob,  \n  TPM_KEY_HANDLE *keyHandle \n);\n\n/**\n * TPM_SaveAuthContext - saves an authorization session outside the TPM\n * @authHandle: [in] Authorization session which will be kept outside the TPM\n * @authContextSize: [out] The size of the outgoing authorization context blob\n * @authContextBlob: [out] The authorization context blob\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 28.2.3)\n * SaveAuthContext saves a loaded authorization session outside the TPM. \n * The format of the authorization context blob is specific to a TPM.\n */\nTPM_RESULT TPM_SaveAuthContext(  \n  TPM_AUTHHANDLE authHandle,  \n  UINT32 *authContextSize,\n  BYTE **authContextBlob  \n);\n\n/**\n * TPM_LoadAuthContext - loads an authorization context blob into the TPM\n * @authContextSize: [in] The size of the following authorization context blob\n * @authContextBlob: [in] The authorization context blob\n * @authHandle: [out] Handle assigned to the authorization session\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 28.2.4)\n * LoadAuthContext loads an authorization context blob into the TPM previously \n * retrieved by a SaveAuthContext call. After successful completion the handle \n * returned by this command can be used to access the authorization session.\n */\nTPM_RESULT TPM_LoadAuthContext(  \n  UINT32 authContextSize,\n  BYTE *authContextBlob,  \n  TPM_KEY_HANDLE *authHandle \n);\n\n/**\n * TPM_DirWriteAuth - provides write access to the DIRs\n * @dirIndex: [in] Index of the DIR\n * @newContents: [in] New value to be stored in named DIR\n * @auth1: [in, out] Authorization protocol parameters\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 28.3.1)\n * The TPM_DirWriteAuth operation provides write access to the Data Integrity \n * Registers. DIRs are non-volatile memory registers held in a TPM-shielded \n * location. \n */\nTPM_RESULT TPM_DirWriteAuth(  \n  TPM_DIRINDEX dirIndex,\n  TPM_DIRVALUE *newContents,\n  TPM_AUTH *auth1\n);\n\n/**\n * TPM_DirRead - provides read access to the DIRs\n * @dirIndex: [in] Index of the DIR to be read\n * @dirContents: [out] The current contents of the named DIR\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 28.3.2)\n * The TPM_DirRead operation provides read access to the DIRs. No \n * authentication is required to perform this action. \n */\nTPM_RESULT TPM_DirRead(  \n  TPM_DIRINDEX dirIndex,  \n  TPM_DIRVALUE *dirContents \n);\n\n/**\n * TPM_ChangeAuthAsymStart - starts the ChangeAuth process\n * @idHandle: [in] Handle of a loaded identity ID key \n * @antiReplay: [in] The nonce to be inserted into the certifyInfo structure \n * @inTempKey: [in] Structure containing all parameters of the ephemeral key\n * @auth1: [in, out] Authorization protocol parameters\n * @certifyInfo: [out] The certifyInfo structure that is to be signed\n * @sigSize: [out] The used size of the output area for the signature \n * @sig: [out] The signature of the certifyInfo parameter\n * @ephHandle: [out] Handle to be used by ChangeAuthAsymFinish for ephemeral key\n * @outTempKey: [out] Structure containing all parameters and public part of ephemeral key\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 28.4.1)\n * The TPM_ChangeAuthAsymStart starts the process of changing authorization \n * for an entity. It sets up an OIAP session that must be retained for use by \n * its twin TPM_ChangeAuthAsymFinish command. \n */\nTPM_RESULT TPM_ChangeAuthAsymStart(  \n  TPM_KEY_HANDLE idHandle,\n  TPM_NONCE *antiReplay,\n  TPM_KEY_PARMS *inTempKey,\n  TPM_AUTH *auth1,  \n  TPM_CERTIFY_INFO *certifyInfo,\n  UINT32 *sigSize,\n  BYTE **sig ,\n  TPM_KEY_HANDLE *ephHandle,\n  TPM_KEY *outTempKey \n);\n\n/**\n * TPM_ChangeAuthAsymFinish - terminates the ChangeAuth process\n * @parentHandle: [in] Handle of the parent key for the input data\n * @ephHandle: [in] Handle for the ephemeral key\n * @entityType: [in] The type of entity to be modified \n * @newAuthLink: [in] HMAC over the old and new authorization values\n * @newAuthSize: [in] Size of encNewAuth \n * @encNewAuth: [in] New authorization data encrypted with ephemeral key\n * @encDataSize: [in] The size of the inData parameter \n * @encData: [in] The encrypted entity that is to be modified\n * @auth1: [in, out] Authorization protocol parameters\n * @outDataSize: [out] The used size of the output area for outData \n * @outData: [out] The modified, encrypted entity\n * @saltNonce: [out] A nonce value to add entropy to the changeProof value \n * @changeProof: [out] Proof that authorization data has changed\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 28.4.2)\n * The TPM_ChangeAuth command allows the owner of an entity to change the \n * authorization data for the entity. The command requires knowledge of \n * the existing authorization information.\n */\nTPM_RESULT TPM_ChangeAuthAsymFinish(  \n  TPM_KEY_HANDLE parentHandle,\n  TPM_KEY_HANDLE ephHandle,\n  TPM_ENTITY_TYPE entityType,\n  TPM_HMAC *newAuthLink,\n  UINT32 newAuthSize,\n  BYTE *encNewAuth,\n  UINT32 encDataSize,\n  BYTE *encData,\n  TPM_AUTH *auth1,  \n  UINT32 *outDataSize,\n  BYTE **outData ,\n  TPM_NONCE *saltNonce,\n  TPM_DIGEST *changeProof \n);\n\n/**\n * TPM_Reset - releases all resources \n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 28.5)\n * TPM_Reset releases all resources associated with existing authorization \n * sessions. This is useful if a TSS driver has lost track of the state in \n * the TPM.\n */\nTPM_RESULT TPM_Reset(void);\n\n/**\n * TPM_CertifySelfTest - performs a full self-test and signs the result\n * @keyHandle: [in] Handle of a loaded key that can perform digital signatures\n * @antiReplay: [in] AnitReplay nonce to prevent replay of messages\n * @auth1: [in, out] Authorization protocol parameters\n * @sigSize: [out] The length of the returned digital signature \n * @sig: [out] The resulting digital signature\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 28.6)\n * CertifySelfTest causes the TPM to perform a full self-test and return \n * an authenticated value if the test passes. \n */\nTPM_RESULT TPM_CertifySelfTest(  \n  TPM_KEY_HANDLE keyHandle,\n  TPM_NONCE *antiReplay,\n  TPM_AUTH *auth1,  \n  UINT32 *sigSize,\n  BYTE **sig  \n);\n\n/**\n * TPM_OwnerReadPubek - provides the endorsement key public portion\n * @auth1: [in, out] Authorization protocol parameters\n * @pubEndorsementKey: [out] The public endorsement key\n * Returns: TPM_SUCCESS on success, a TPM error code otherwise.\n * \n * Description: ([TPM_Part3], Section 28.7)\n * Provides the endorsement key public portion. \n */\nTPM_RESULT TPM_OwnerReadPubek(  \n  TPM_AUTH *auth1,  \n  TPM_PUBKEY *pubEndorsementKey \n);\n\n/*\n * Error handling\n * [tpm_error.c]\n */\n\n/**\n * tpm_error_to_string - converts the specified error code into a string message\n * @res: [in] Error code\n * Returns: Human-readable description of the error code.\n */\nconst char *tpm_error_to_string(\n  TPM_RESULT res\n);\n\n#endif /* _TPM_COMMANDS_H_ */\n"
  },
  {
    "path": "tpm/tpm_context.c",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: tpm_context.c 452 2010-07-19 19:05:05Z mast $\n */\n\n#include \"tpm_emulator.h\"\n#include \"tpm_commands.h\"\n#include \"tpm_data.h\"\n#include \"tpm_handles.h\"\n#include \"tpm_marshalling.h\"\n#include <crypto/rc4.h>\n#include <crypto/hmac.h>\n\n/*\n * Session Management ([TPM_Part3], Section 21)\n */\n\nUINT32 tpm_get_free_session(BYTE type)\n{\n  UINT32 i;\n  for (i = 0; i < TPM_MAX_SESSIONS; i++) {\n    if (tpmData.stany.data.sessions[i].type == TPM_ST_INVALID) {\n      tpmData.stany.data.sessions[i].type = type;\n      if (type == TPM_ST_TRANSPORT) return INDEX_TO_TRANS_HANDLE(i);\n      else return INDEX_TO_AUTH_HANDLE(i);\n    }\n  }\n  return TPM_INVALID_HANDLE;\n}\n\nvoid tpm_invalidate_sessions(TPM_HANDLE handle)\n{\n  TPM_SESSION_DATA *session;\n  int i;\n\n  for (i = 0; i < TPM_MAX_SESSIONS; i++) {\n    session = &tpmData.stany.data.sessions[i];\n    if ((session->type == TPM_ST_OSAP && session->handle == handle)\n        || (session->type == TPM_ST_DSAP && session->handle == handle)\n        || (session->type == TPM_ST_TRANSPORT && session->handle == handle))\n      memset(session, 0, sizeof(*session));\n  }\n}\n\nTPM_RESULT TPM_KeyControlOwner(TPM_KEY_HANDLE keyHandle, TPM_PUBKEY pubKey,\n                               UINT32 bitName, BOOL bitValue, TPM_AUTH *auth1)\n{\n  TPM_RESULT res;\n  TPM_KEY_DATA *key;\n  TPM_PUBKEY pubKey2;\n  TPM_DIGEST keyDigest, keyDigest2;\n  info(\"TPM_KeyControlOwner()\");\n  /* get key */\n  key = tpm_get_key(keyHandle);\n  if (key == NULL) return TPM_INVALID_KEYHANDLE;\n  /* verify authorization */\n  res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);\n  if (res != TPM_SUCCESS) return res;\n  /* verify public key */\n  if (tpm_compute_pubkey_digest(&pubKey, &keyDigest)) {\n    debug(\"tpm_compute_pubkey_digest() failed\");\n    return TPM_FAIL;\n  }\n  if (tpm_extract_pubkey(key, &pubKey2)) {\n    debug(\"tpm_extraxt_pubkey() failed.\");\n    return TPM_FAIL;\n  }\n  if (tpm_compute_pubkey_digest(&pubKey2, &keyDigest2)) {\n    debug(\"tpm_compute_pubkey_digest() failed\");\n    free_TPM_PUBKEY(pubKey2);\n    return TPM_FAIL;\n  }\n  free_TPM_PUBKEY(pubKey2);\n  if (memcmp(&keyDigest, &keyDigest2, sizeof(TPM_DIGEST)) != 0)\n    return TPM_BAD_PARAMETER;\n  /* get bit name */\n  debug(\"bitName = %d\", bitName);\n  if (bitName & TPM_KEY_CONTROL_OWNER_EVICT) {\n    if (bitValue) {\n      int i, num = 0;\n      for (i = 0; i < TPM_MAX_KEYS; i++) {\n        if (!tpmData.permanent.data.keys[i].payload ||\n            !(tpmData.permanent.data.keys[i].keyControl\n              & TPM_KEY_CONTROL_OWNER_EVICT)) num++;\n      }\n      if (num < 2) return TPM_NOSPACE;\n      if (key->parentPCRStatus || (key->keyFlags & TPM_KEY_FLAG_VOLATILE))\n        return TPM_BAD_PARAMETER;\n      key->keyControl |= TPM_KEY_CONTROL_OWNER_EVICT;\n    } else {\n      key->keyControl &= ~TPM_KEY_CONTROL_OWNER_EVICT;\n    }\n  } else {\n    return TPM_BAD_MODE;\n  }\n  return TPM_SUCCESS;\n}\n\nstatic int encrypt_context(BYTE *iv, UINT32 iv_size, TPM_CONTEXT_SENSITIVE *context, \n                           BYTE **enc, UINT32 *enc_size)\n{\n  UINT32 len;\n  BYTE *ptr;\n  tpm_rc4_ctx_t rc4_ctx;\n  BYTE key[TPM_SYM_KEY_SIZE + iv_size];\n  /* marshal context */\n  *enc_size = len = sizeof_TPM_CONTEXT_SENSITIVE((*context));\n  *enc = ptr = tpm_malloc(len);\n  if (*enc == NULL) return -1;\n  if (tpm_marshal_TPM_CONTEXT_SENSITIVE(&ptr, &len, context)) {\n    tpm_free(*enc);\n    return -1;\n  }\n  /* encrypt context */\n  memcpy(key, tpmData.permanent.data.contextKey, TPM_SYM_KEY_SIZE);\n  memcpy(&key[TPM_SYM_KEY_SIZE], iv, iv_size);\n  tpm_rc4_init(&rc4_ctx, key, sizeof(key));\n  tpm_rc4_crypt(&rc4_ctx, *enc, *enc, *enc_size);\n  return 0;\n}\n\nstatic int decrypt_context(BYTE *iv, UINT32 iv_size, BYTE *enc, UINT32 enc_size, \n                           TPM_CONTEXT_SENSITIVE *context, BYTE **buf) \n{\n  UINT32 len;\n  BYTE *ptr;\n  tpm_rc4_ctx_t rc4_ctx;\n  BYTE key[TPM_SYM_KEY_SIZE + iv_size];\n  len = enc_size;\n  *buf = ptr = tpm_malloc(len);\n  if (*buf == NULL) return -1;\n  /* decrypt context */\n  memcpy(key, tpmData.permanent.data.contextKey, TPM_SYM_KEY_SIZE);\n  memcpy(&key[TPM_SYM_KEY_SIZE], iv, iv_size);\n  tpm_rc4_init(&rc4_ctx, key, sizeof(key));  \n  tpm_rc4_crypt(&rc4_ctx, enc, *buf, enc_size);\n  /* unmarshal context */\n  if (tpm_unmarshal_TPM_CONTEXT_SENSITIVE(&ptr, &len, context)) {\n    tpm_free(*buf);\n    return -1;\n  }\n  return 0;\n}\n\nstatic int compute_context_digest(TPM_CONTEXT_BLOB *contextBlob, TPM_DIGEST *digest)\n{\n  BYTE *buf, *ptr;\n  UINT32 len;\n  tpm_hmac_ctx_t hmac_ctx;\n  len = sizeof_TPM_CONTEXT_BLOB((*contextBlob));\n  buf = ptr = tpm_malloc(len);\n  if (buf == NULL) return -1;\n  if (tpm_marshal_TPM_CONTEXT_BLOB(&ptr, &len, contextBlob)) {\n    tpm_free(buf);\n    return -1;\n  }\n  memset(&buf[30], 0, 20);\n  tpm_hmac_init(&hmac_ctx, tpmData.permanent.data.tpmProof.nonce, \n    sizeof(tpmData.permanent.data.tpmProof.nonce));\n  tpm_hmac_update(&hmac_ctx, buf, sizeof_TPM_CONTEXT_BLOB((*contextBlob)));\n  tpm_hmac_final(&hmac_ctx, digest->digest);\n  tpm_free(buf);\n  return 0;\n}\n\nTPM_RESULT TPM_SaveContext(TPM_HANDLE handle, TPM_RESOURCE_TYPE resourceType,\n                           const BYTE label[16], UINT32 *contextSize,\n                           TPM_CONTEXT_BLOB *contextBlob)\n{\n  TPM_CONTEXT_SENSITIVE context;\n  TPM_SESSION_DATA *session = NULL;\n  TPM_DAA_SESSION_DATA *sessionDAA = NULL;\n  TPM_KEY_DATA *key = NULL;\n  int i = 0;\n  info(\"TPM_SaveContext() resourceType = %08x\", resourceType);\n  /* setup context data */\n  context.tag = TPM_TAG_CONTEXT_SENSITIVE;\n  context.resourceType = resourceType;\n  if (resourceType == TPM_RT_AUTH || resourceType == TPM_RT_TRANS) {\n    session = (resourceType == TPM_RT_AUTH) ? tpm_get_auth(handle) : \n               tpm_get_transport(handle);\n    if (session == NULL) return TPM_INVALID_RESOURCE;\n    /* store session data */\n    memcpy(&context.internalData.session, session, sizeof(TPM_SESSION_DATA));\n    context.internalSize = sizeof_TPM_SESSION_DATA((*session));\n    /* set context nonce */\n    memcpy(&context.contextNonce, &tpmData.stany.data.contextNonceSession, \n           sizeof(TPM_NONCE));\n  } else if (resourceType == TPM_RT_KEY) {\n    key = tpm_get_key(handle);\n    debug(\"resourceType = TPM_RT_KEY, handle = %08x, key = %p\", handle, key);\n    if (key == NULL) return TPM_INVALID_RESOURCE;\n    if (key->keyControl & TPM_KEY_CONTROL_OWNER_EVICT) return TPM_OWNER_CONTROL;\n    /* store key data (shallow copy is ok) */\n    memcpy(&context.internalData.key, key, sizeof(TPM_KEY_DATA));\n    context.internalSize = sizeof_TPM_KEY_DATA((*key));\n    /* set context nonce */\n    memcpy(&context.contextNonce, &tpmData.stclear.data.contextNonceKey, \n           sizeof(TPM_NONCE));\n  } else if (resourceType == TPM_RT_DAA_TPM) {\n    sessionDAA = tpm_get_daa(handle);\n    if (sessionDAA == NULL) return TPM_INVALID_RESOURCE;\n    /* store sessionDAA data */\n    memcpy(&context.internalData.sessionDAA, sessionDAA,\n           sizeof(TPM_DAA_SESSION_DATA));\n    context.internalSize = sizeof(TPM_DAA_SESSION_DATA);\n    /* set context nonce */\n    memcpy(&context.contextNonce, &tpmData.stany.data.contextNonceSession, \n           sizeof(TPM_NONCE));\n  } else {\n    return TPM_INVALID_RESOURCE;\n  }\n  /* setup context blob */\n  contextBlob->tag = TPM_TAG_CONTEXTBLOB;\n  contextBlob->resourceType = resourceType;\n  contextBlob->handle = handle;\n  memset(&contextBlob->integrityDigest, 0, sizeof(TPM_DIGEST));\n  memcpy(contextBlob->label, label, sizeof(contextBlob->label));\n  contextBlob->additionalSize = TPM_SYM_KEY_SIZE;\n  contextBlob->additionalData = tpm_malloc(contextBlob->additionalSize);\n  if (contextBlob->additionalData == NULL) return TPM_FAIL;\n  tpm_get_random_bytes(contextBlob->additionalData, \n                       contextBlob->additionalSize);\n  /* increment context counter */\n  if (resourceType == TPM_RT_KEY) {\n    contextBlob->contextCount = 0;\n  } else {\n    if (tpmData.stany.data.contextCount >= 0xfffffffc) {\n      tpm_free(contextBlob->additionalData);\n      return TPM_TOOMANYCONTEXTS;\n    }\n    contextBlob->contextCount = ++tpmData.stany.data.contextCount;\n    for (i = 0; i < TPM_MAX_SESSION_LIST; i++) {\n      if (tpmData.stany.data.contextList[i] == 0) break;\n    }\n    if (i >= TPM_MAX_SESSION_LIST) {\n      tpm_free(contextBlob->additionalData);\n      return TPM_NOCONTEXTSPACE;\n    }\n    tpmData.stany.data.contextCount++;\n    tpmData.stany.data.contextList[i] = tpmData.stany.data.contextCount;\n    contextBlob->contextCount = tpmData.stany.data.contextCount;\n  }\n  debug(\"context counter = %d\", tpmData.stany.data.contextCount);\n  /* encrypt sensitive data */\n  if (encrypt_context(contextBlob->additionalData, contextBlob->additionalSize,\n      &context, &contextBlob->sensitiveData, &contextBlob->sensitiveSize)) {\n        tpm_free(contextBlob->additionalData);\n        return TPM_ENCRYPT_ERROR;\n  }\n  /* compute context digest */\n  if (compute_context_digest(contextBlob, &contextBlob->integrityDigest)) {\n    tpm_free(contextBlob->additionalData);\n    return TPM_FAIL;\n  }\n  *contextSize = sizeof_TPM_CONTEXT_BLOB((*contextBlob));\n  if (resourceType != TPM_RT_KEY) {\n    /* The TPM MUST invalidate all information regarding the resource \n     * except for information needed for reloading. */\n    if (resourceType != TPM_RT_DAA_TPM)\n      session->type = TPM_ST_INVALID;\n    else {\n      memset(sessionDAA, 0, sizeof(TPM_DAA_SESSION_DATA));\n      sessionDAA->type = TPM_ST_INVALID;\n      tpmData.stany.data.currentDAA = 0;\n    }\n  }\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_LoadContext(TPM_HANDLE entityHandle, BOOL keepHandle,\n                           UINT32 contextSize, TPM_CONTEXT_BLOB *contextBlob,\n                           TPM_HANDLE *handle)\n{\n  TPM_CONTEXT_SENSITIVE context;\n  BYTE *context_buf;\n  TPM_SESSION_DATA *session;\n  TPM_DAA_SESSION_DATA *sessionDAA;\n  TPM_KEY_DATA *key;\n  TPM_DIGEST digest;\n  int i = 0;\n  info(\"TPM_LoadContext()\");\n  if (decrypt_context(contextBlob->additionalData, contextBlob->additionalSize,\n      contextBlob->sensitiveData, contextBlob->sensitiveSize, \n      &context, &context_buf)) return TPM_DECRYPT_ERROR;\n  /* validate structure */\n  if (compute_context_digest(contextBlob, &digest)\n      || memcmp(&digest, &contextBlob->integrityDigest, sizeof(TPM_DIGEST))) {\n    tpm_free(context_buf);\n    return TPM_BADCONTEXT;\n  }\n  if (contextBlob->resourceType == TPM_RT_KEY) {\n   /* check contextNonce */\n    if (context.internalData.key.parentPCRStatus \n        || (context.internalData.key.keyFlags & TPM_KEY_FLAG_VOLATILE)) {\n      if (memcmp(&context.contextNonce, &tpmData.stclear.data.contextNonceKey,\n          sizeof(TPM_NONCE)) != 0) {\n        tpm_free(context_buf);\n        return TPM_BADCONTEXT;\n      }\n    }\n    /* check handle */\n    key = tpm_get_key_slot(entityHandle);\n    if (key == NULL || !key->payload) {\n      if (keepHandle) {\n        tpm_free(context_buf);\n        return TPM_BAD_HANDLE;\n      }    \n      *handle = tpm_get_free_key();\n      if (*handle == TPM_INVALID_HANDLE) {\n        tpm_free(context_buf);\n        return TPM_RESOURCES;\n      }\n      key = &tpmData.permanent.data.keys[HANDLE_TO_INDEX(*handle)];\n    } else {\n      *handle = entityHandle;\n    }\n    /* reload resource */\n    memcpy(key, &context.internalData.key, sizeof(TPM_KEY_DATA));\n    tpm_rsa_copy_key(&key->key, &context.internalData.key.key);\n  } else if (contextBlob->resourceType == TPM_RT_DAA_TPM) {\n    /* check contextNonce */\n    if (memcmp(&context.contextNonce, &tpmData.stany.data.contextNonceSession, \n        sizeof(TPM_NONCE)) != 0) {\n      tpm_free(context_buf);\n      return TPM_BADCONTEXT;\n    }\n    /* check context list */\n    for (i = 0; i < TPM_MAX_SESSION_LIST; i++)\n      if (tpmData.stany.data.contextList[i] == contextBlob->contextCount) break;\n    if (i >= TPM_MAX_SESSION_LIST) {\n      tpm_free(context_buf);\n      return TPM_BADCONTEXT;\n    }\n    tpmData.stany.data.contextList[i] = 0;\n    /* check handle */\n    info(\"entityHandle = %08x, keepHandle = %d\", entityHandle, keepHandle);\n    sessionDAA = tpm_get_daa_slot(entityHandle);\n    if (sessionDAA == NULL) {\n      if (keepHandle) {\n        tpm_free(context_buf);\n        return TPM_BAD_HANDLE;\n      }\n      *handle = tpm_get_free_daa_session();\n      if (*handle == TPM_INVALID_HANDLE) {\n        tpm_free(context_buf);\n        return TPM_RESOURCES;\n      }\n      sessionDAA = &tpmData.stany.data.sessionsDAA[HANDLE_TO_INDEX(*handle)];\n    } else if (sessionDAA->type != TPM_ST_INVALID) {\n      if (keepHandle) {\n        tpm_free(context_buf);\n        return TPM_BAD_HANDLE;\n      }\n      *handle = tpm_get_free_daa_session();\n      if (*handle == TPM_INVALID_HANDLE) {\n        tpm_free(context_buf);\n        return TPM_RESOURCES;\n      }\n      sessionDAA = &tpmData.stany.data.sessionsDAA[HANDLE_TO_INDEX(*handle)];\n    } else {\n      if (HANDLE_TO_RT(entityHandle) != TPM_RT_DAA_TPM) {\n        if (keepHandle) {\n          tpm_free(context_buf);\n          return TPM_BAD_HANDLE;\n        }\n        *handle = tpm_get_free_daa_session();\n        if (*handle == TPM_INVALID_HANDLE) {\n          tpm_free(context_buf);\n          return TPM_RESOURCES;\n        }\n        sessionDAA = &tpmData.stany.data.sessionsDAA[HANDLE_TO_INDEX(*handle)];\n      } else\n        *handle = entityHandle;\n    }\n    /* reload resource */\n    tpmData.stany.data.currentDAA = *handle;\n    info(\"stany.data.currentDAA := %.8x\", *handle);\n    memset(sessionDAA, 0, sizeof(TPM_DAA_SESSION_DATA));\n    memcpy(sessionDAA, &context.internalData.sessionDAA, context.internalSize);\n  } else {\n    /* check contextNonce */\n    if (memcmp(&context.contextNonce, &tpmData.stany.data.contextNonceSession, \n        sizeof(TPM_NONCE)) != 0) {\n      tpm_free(context_buf);\n      return TPM_BADCONTEXT;\n    }\n    if (context.internalData.session.type == TPM_ST_OSAP\n        && tpm_get_key(context.internalData.session.handle) == NULL) {\n      tpm_free(context_buf);\n      return TPM_RESOURCEMISSING;\n    }\n    /* check context list */\n    for (i = 0; i < TPM_MAX_SESSION_LIST; i++)\n      if (tpmData.stany.data.contextList[i] == contextBlob->contextCount) break;\n    if (i >= TPM_MAX_SESSION_LIST) {\n      tpm_free(context_buf);\n      return TPM_BADCONTEXT;\n    }\n    tpmData.stany.data.contextList[i] = 0;\n    /* check handle */\n    session = tpm_get_session_slot(entityHandle);\n    if (session == NULL || session->type != TPM_ST_INVALID) {\n      if (keepHandle) {\n        tpm_free(context_buf);\n        return TPM_BAD_HANDLE;\n      }\n      *handle = tpm_get_free_session(context.internalData.session.type);\n      if (*handle == TPM_INVALID_HANDLE) {\n        tpm_free(context_buf);\n        return TPM_RESOURCES;\n      }\n      session = &tpmData.stany.data.sessions[HANDLE_TO_INDEX(*handle)];\n    } else {\n      *handle = entityHandle;\n    }\n    /* reload resource */\n    memcpy(session, &context.internalData.session, sizeof(TPM_SESSION_DATA));\n  }\n  tpm_free(context_buf);\n  return TPM_SUCCESS;\n}\n"
  },
  {
    "path": "tpm/tpm_counter.c",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: tpm_counter.c 472 2011-11-12 09:00:22Z mast $\n */\n\n#include \"tpm_emulator.h\"\n#include \"tpm_commands.h\"\n#include \"tpm_handles.h\"\n#include \"tpm_data.h\"\n\n/*\n * Monotonic Counter ([TPM_Part3], Section 25)\n */\n\nstatic TPM_ACTUAL_COUNT get_max_counter_value(void)\n{\n  UINT32 i;\n  TPM_ACTUAL_COUNT max = 0;\n  for (i = 0; i < TPM_MAX_COUNTERS; i++) {\n    if (tpmData.permanent.data.counters[i].valid\n        && tpmData.permanent.data.counters[i].counter > max)\n      max = tpmData.permanent.data.counters[i].counter;\n  }\n  return max;\n}\n\nstatic TPM_COUNT_ID get_free_counter(void)\n{\n  UINT32 i;\n  for (i = 0; i < TPM_MAX_COUNTERS; i++) {\n    if (!tpmData.permanent.data.counters[i].valid) {\n      tpmData.permanent.data.counters[i].valid = TRUE;\n      return INDEX_TO_COUNTER_HANDLE(i);\n    }\n  }\n  return TPM_INVALID_HANDLE;\n}\n\nTPM_RESULT TPM_CreateCounter(TPM_ENCAUTH *authData, BYTE label[4],\n                             TPM_AUTH *auth1, TPM_COUNT_ID *countID, \n                             TPM_COUNTER_VALUE *counterValue)\n{\n  TPM_RESULT res;\n  TPM_COUNTER_VALUE *counter;\n  TPM_SESSION_DATA *session;\n  info(\"TPM_CreateCounter()\");\n  /* get a free counter if any is left */\n  *countID = get_free_counter();\n  counter = tpm_get_counter(*countID);\n  if (counter == NULL) return TPM_SIZE;\n  /* verify authorization */\n  res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);\n  if (res != TPM_SUCCESS) return res;\n  auth1->continueAuthSession = FALSE;\n  session = tpm_get_auth(auth1->authHandle);\n  if ((session->type != TPM_ST_OSAP) && (session->type != TPM_ST_DSAP))\n    return TPM_AUTHFAIL;\n  /* decrypt authorization secret */\n  tpm_decrypt_auth_secret(*authData, session->sharedSecret, \n    &session->lastNonceEven, counter->usageAuth);\n  /* setup counter */\n  counter->tag = TPM_TAG_COUNTER_VALUE;\n  memcpy(counter->label, label, 4);\n  counter->counter = get_max_counter_value() + 1;\n  memcpy(counterValue, counter, sizeof(TPM_COUNTER_VALUE));\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_IncrementCounter(TPM_COUNT_ID countID, TPM_AUTH *auth1,\n                                TPM_COUNTER_VALUE *count)\n{\n  TPM_RESULT res;\n  TPM_COUNTER_VALUE *counter;\n  info(\"TPM_IncrementCounter()\");\n  /* get counter */\n  counter = tpm_get_counter(countID);\n  if (counter == NULL) return TPM_BAD_COUNTER;\n  /* verify authorization */\n  res = tpm_verify_auth(auth1, counter->usageAuth, countID);\n  if (res != TPM_SUCCESS) return res;\n  /* verify counter selection and increment counter */\n  if (tpm_get_counter(tpmData.stclear.data.countID) != NULL\n      && tpmData.stclear.data.countID != countID) return TPM_BAD_COUNTER;\n  tpmData.stclear.data.countID = countID;\n  counter->counter++;\n  memcpy(count, counter, sizeof(TPM_COUNTER_VALUE));\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_ReadCounter(TPM_COUNT_ID countID, TPM_COUNTER_VALUE *count)\n{\n  TPM_COUNTER_VALUE *counter;\n  info(\"TPM_ReadCounter()\");\n  /* get counter */\n  counter = tpm_get_counter(countID);\n  if (counter == NULL) return TPM_BAD_COUNTER;\n  memcpy(count, counter, sizeof(TPM_COUNTER_VALUE));\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_ReleaseCounter(TPM_COUNT_ID countID, TPM_AUTH *auth1)\n{\n  TPM_RESULT res;\n  TPM_COUNTER_VALUE *counter;\n  info(\"TPM_ReleaseCounter()\");\n  /* get counter */\n  counter = tpm_get_counter(countID);\n  if (counter == NULL) return TPM_BAD_COUNTER;\n  /* verify authorization */\n  res = tpm_verify_auth(auth1, counter->usageAuth, countID);\n  if (res != TPM_SUCCESS) return res;\n  /* release counter */\n  if (tpmData.stclear.data.countID == countID)\n    tpmData.stclear.data.countID = TPM_INVALID_HANDLE;\n  memset(counter, 0, sizeof(TPM_COUNTER_VALUE));\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_ReleaseCounterOwner(TPM_COUNT_ID countID, TPM_AUTH *auth1)\n{\n  TPM_RESULT res;\n  TPM_COUNTER_VALUE *counter;\n  info(\"TPM_ReleaseCounterOwner()\");\n  /* get counter */\n  counter = tpm_get_counter(countID);\n  if (counter == NULL) return TPM_BAD_COUNTER;\n  /* verify authorization */\n  res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);\n  if (res != TPM_SUCCESS) return res;\n  /* release counter */\n  if (tpmData.stclear.data.countID == countID)\n    tpmData.stclear.data.countID = TPM_INVALID_HANDLE;\n  memset(counter, 0, sizeof(TPM_COUNTER_VALUE));\n  return TPM_SUCCESS;\n}\n\n"
  },
  {
    "path": "tpm/tpm_credentials.c",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: tpm_credentials.c 364 2010-02-11 10:24:45Z mast $\n */\n\n#include \"tpm_emulator.h\"\n#include \"tpm_commands.h\"\n#include \"tpm_marshalling.h\"\n#include \"tpm_data.h\"\n#include \"crypto/sha1.h\"\n\n/*\n * Credential Handling ([TPM_Part3], Section 14)\n * There are two create EK commands. The first matches the 1.1 functionality. \n * The second provides the mechanism to enable revokeEK and provides \n * FIPS 140-2 compatibility. \n */\n\nTPM_RESULT tpm_get_pubek(TPM_PUBKEY *pubEndorsementKey)\n{\n  UINT32 key_length;\n  if (!tpmData.permanent.data.endorsementKey.size) return TPM_NO_ENDORSEMENT;\n  /* setup TPM_PUBKEY structure */\n  key_length = tpmData.permanent.data.endorsementKey.size;\n  pubEndorsementKey->pubKey.keyLength = key_length >> 3;\n  pubEndorsementKey->pubKey.key = tpm_malloc(pubEndorsementKey->pubKey.keyLength);\n  if (pubEndorsementKey->pubKey.key == NULL) return TPM_FAIL;\n  tpm_rsa_export_modulus(&tpmData.permanent.data.endorsementKey,\n                     pubEndorsementKey->pubKey.key, NULL);\n  pubEndorsementKey->algorithmParms.algorithmID = TPM_ALG_RSA;\n  pubEndorsementKey->algorithmParms.encScheme = TPM_ES_RSAESOAEP_SHA1_MGF1;\n  pubEndorsementKey->algorithmParms.sigScheme = TPM_SS_NONE;\n  pubEndorsementKey->algorithmParms.parms.rsa.keyLength = key_length;\n  pubEndorsementKey->algorithmParms.parms.rsa.numPrimes = 2;\n  pubEndorsementKey->algorithmParms.parms.rsa.exponentSize = 0;\n  pubEndorsementKey->algorithmParms.parms.rsa.exponent = NULL;\n  pubEndorsementKey->algorithmParms.parmSize = 12;\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_CreateEndorsementKeyPair(TPM_NONCE *antiReplay,\n                                        TPM_KEY_PARMS *keyInfo, \n                                        TPM_PUBKEY *pubEndorsementKey, \n                                        TPM_DIGEST *checksum)\n{\n  info(\"TPM_CreateEndorsementKeyPair()\");\n  return TPM_DISABLED_CMD;\n}\n\nTPM_RESULT TPM_CreateRevocableEK(TPM_NONCE *antiReplay, TPM_KEY_PARMS *keyInfo,\n                                 BOOL generateReset, TPM_NONCE *inputEKreset,  \n                                 TPM_PUBKEY *pubEndorsementKey, \n                                 TPM_DIGEST *checksum, \n                                 TPM_NONCE *outputEKreset)\n{\n  TPM_RESULT res;\n  info(\"TPM_CreateRevocableEK()\");\n  /* verify key parameters */\n  if (tpmData.permanent.data.endorsementKey.size > 0) return TPM_DISABLED_CMD;\n  if (keyInfo->algorithmID != TPM_ALG_RSA\n      || keyInfo->encScheme != TPM_ES_RSAESOAEP_SHA1_MGF1\n      || keyInfo->sigScheme != TPM_SS_NONE\n      || keyInfo->parmSize == 0\n      || keyInfo->parms.rsa.keyLength != 2048\n      || keyInfo->parms.rsa.numPrimes != 2\n      || keyInfo->parms.rsa.exponentSize != 0) return TPM_BAD_KEY_PROPERTY;\n  /* create endorsement key */\n  if (tpm_rsa_generate_key(&tpmData.permanent.data.endorsementKey, \n      keyInfo->parms.rsa.keyLength)) return TPM_FAIL;\n  /* return PUBEK */\n  res = tpm_get_pubek(pubEndorsementKey);\n  if (res != TPM_SUCCESS) {\n    tpm_rsa_release_private_key(&tpmData.permanent.data.endorsementKey);\n    tpmData.permanent.data.endorsementKey.size = 0;\n    return res;\n  }\n  /* compute checksum */\n  if (tpm_compute_pubkey_checksum(antiReplay, pubEndorsementKey, checksum)) {\n    tpm_free(pubEndorsementKey->pubKey.key);\n    tpm_rsa_release_private_key(&tpmData.permanent.data.endorsementKey);\n    tpmData.permanent.data.endorsementKey.size = 0;\n    return TPM_FAIL;\n  }\n  tpmData.permanent.flags.enableRevokeEK = TRUE;\n  tpmData.permanent.flags.CEKPUsed = TRUE;\n  if (generateReset) {\n    tpm_get_random_bytes(tpmData.permanent.data.ekReset.nonce, \n      sizeof(tpmData.permanent.data.ekReset.nonce));\n  } else {\n    memcpy(&tpmData.permanent.data.ekReset, inputEKreset, sizeof(TPM_NONCE));\n  }\n  memcpy(outputEKreset, &tpmData.permanent.data.ekReset, sizeof(TPM_NONCE));\n  /* Create TPM_PERMANENT_DATA->TPM_DAA_TPM_SEED from the TPM RNG */\n  tpm_get_random_bytes(tpmData.permanent.data.tpmDAASeed.nonce, \n    sizeof(tpmData.permanent.data.tpmDAASeed.nonce));\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_RevokeTrust(TPM_NONCE *ekReset)\n{\n  info(\"TPM_RevokeTrust()\");\n  if (!tpmData.permanent.flags.enableRevokeEK) return TPM_FAIL;\n  if (!tpm_get_physical_presence()) return TPM_BAD_PRESENCE;\n  if (memcmp(ekReset, &tpmData.permanent.data.ekReset, \n             sizeof(TPM_NONCE))) return TPM_AUTHFAIL;\n  tpm_owner_clear();\n  tpm_rsa_release_private_key(&tpmData.permanent.data.endorsementKey);\n  tpmData.permanent.data.endorsementKey.size = 0;\n  /* Invalidate TPM_PERMANENT_DATA->tpmDAASeed */\n  memset(tpmData.permanent.data.tpmDAASeed.nonce, 0, \n    sizeof(tpmData.permanent.data.tpmDAASeed.nonce));\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_ReadPubek(TPM_NONCE *antiReplay, TPM_PUBKEY *pubEndorsementKey, \n                         TPM_DIGEST *checksum)\n{\n  TPM_RESULT res;\n  info(\"TPM_ReadPubek()\");\n  if (!tpmData.permanent.flags.readPubek) return TPM_DISABLED_CMD;\n  /* get PUBEK */\n  res = tpm_get_pubek(pubEndorsementKey);\n  if (res != TPM_SUCCESS) return res; \n  /* compute checksum */\n  if (tpm_compute_pubkey_checksum(antiReplay, pubEndorsementKey, checksum)) {\n    tpm_free(pubEndorsementKey->pubKey.key);\n    return TPM_FAIL;\n  }\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_DisablePubekRead(TPM_AUTH *auth1)\n{\n  TPM_RESULT res;\n  info(\"TPM_DisablePubekRead()\");\n  /* verify authorization */\n  res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);\n  if (res != TPM_SUCCESS) return res;\n  tpmData.permanent.flags.readPubek = FALSE;\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_OwnerReadInternalPub(TPM_KEY_HANDLE keyHandle, TPM_AUTH *auth1,  \n                                    TPM_PUBKEY *publicPortion)\n{\n  TPM_RESULT res;\n  TPM_KEY_DATA *srk = &tpmData.permanent.data.srk;\n  info(\"TPM_OwnerReadInternalPub()\");\n  /* verify authorization */\n  res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);\n  if (res != TPM_SUCCESS) return res;\n  if (keyHandle == TPM_KH_EK) {\n    return tpm_get_pubek(publicPortion);\n  } else if (keyHandle == TPM_KH_SRK) {\n    publicPortion->pubKey.keyLength = srk->key.size >> 3;\n    publicPortion->pubKey.key = tpm_malloc(publicPortion->pubKey.keyLength);\n    if (publicPortion->pubKey.key == NULL) return TPM_FAIL;\n    tpm_rsa_export_modulus(&srk->key, publicPortion->pubKey.key, NULL);\n    publicPortion->algorithmParms.algorithmID = TPM_ALG_RSA;\n    publicPortion->algorithmParms.encScheme = srk->encScheme;\n    publicPortion->algorithmParms.sigScheme = srk->sigScheme;\n    publicPortion->algorithmParms.parms.rsa.keyLength = srk->key.size;\n    publicPortion->algorithmParms.parms.rsa.numPrimes = 2;\n    publicPortion->algorithmParms.parms.rsa.exponentSize = 0;\n    publicPortion->algorithmParms.parms.rsa.exponent = NULL;\n    publicPortion->algorithmParms.parmSize = 12;\n    return TPM_SUCCESS;\n  } else {\n    return TPM_BAD_PARAMETER;\n  }\n}\n"
  },
  {
    "path": "tpm/tpm_crypto.c",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: tpm_crypto.c 444 2010-06-12 09:14:18Z mast $\n */\n\n#include \"tpm_emulator.h\"\n#include \"tpm_commands.h\"\n#include \"tpm_data.h\"\n#include \"tpm_handles.h\"\n#include \"crypto/sha1.h\"\n#include \"crypto/hmac.h\"\n#include \"crypto/rc4.h\"\n#include \"tpm_marshalling.h\"\n\n/*\n * Cryptographic Functions ([TPM_Part3], Section 13)\n */\n\nstatic tpm_sha1_ctx_t sha1_ctx;\nstatic BOOL sha1_ctx_valid = FALSE;\n\nTPM_RESULT TPM_SHA1Start(UINT32 *maxNumBytes)\n{\n  info(\"TPM_SHA1Start()\");\n  tpm_sha1_init(&sha1_ctx);\n  sha1_ctx_valid = TRUE;\n  /* this limit was arbitrarily chosen */\n  *maxNumBytes = 2048;\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_SHA1Update(UINT32 numBytes, BYTE *hashData)\n{\n  info(\"TPM_SHA1Update()\");\n  if (!sha1_ctx_valid) return TPM_SHA_THREAD;\n  tpm_sha1_update(&sha1_ctx, hashData, numBytes);\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_SHA1Complete(UINT32 hashDataSize, BYTE *hashData, \n                            TPM_DIGEST *hashValue)\n{\n  info(\"TPM_SHA1Complete()\");\n  if (!sha1_ctx_valid) return TPM_SHA_THREAD;\n  sha1_ctx_valid = FALSE;\n  tpm_sha1_update(&sha1_ctx, hashData, hashDataSize);\n  tpm_sha1_final(&sha1_ctx, hashValue->digest);\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_SHA1CompleteExtend(TPM_PCRINDEX pcrNum, UINT32 hashDataSize, \n                                  BYTE *hashData, TPM_DIGEST *hashValue, \n                                  TPM_PCRVALUE *outDigest)\n{\n  TPM_RESULT res;\n  info(\"TPM_SHA1CompleteExtend()\");\n  res = TPM_SHA1Complete(hashDataSize, hashData, hashValue);\n  if (res != TPM_SUCCESS) return res;\n  return TPM_Extend(pcrNum, hashValue, outDigest);\n}\n\nTPM_RESULT tpm_verify(TPM_PUBKEY_DATA *key, TPM_AUTH *auth, BOOL isInfo,\n                      BYTE *data, UINT32 dataSize, BYTE *sig, UINT32 sigSize)\n{\n  if (sigSize != key->key.size >> 3) return TPM_BAD_SIGNATURE;\n  if (key->sigScheme == TPM_SS_RSASSAPKCS1v15_SHA1) {\n    /* use signature scheme PKCS1_SHA1_RAW */\n    if (dataSize != 20) return TPM_BAD_PARAMETER;\n    if (tpm_rsa_verify(&key->key, RSA_SSA_PKCS1_SHA1_RAW,\n         data, dataSize, sig) != 0)  return TPM_BAD_SIGNATURE;\n  } else if (key->sigScheme == TPM_SS_RSASSAPKCS1v15_DER) {\n    /* use signature scheme PKCS1_DER */\n    if ((dataSize + 11) > (UINT32)(key->key.size >> 3)\n        || dataSize == 0) return TPM_BAD_PARAMETER;\n    if (tpm_rsa_verify(&key->key, RSA_SSA_PKCS1_DER,\n        data, dataSize, sig) != 0)  return TPM_BAD_SIGNATURE;\n  } else if (key->sigScheme == TPM_SS_RSASSAPKCS1v15_INFO && !isInfo) {\n    /* use signature scheme PKCS1_SHA1 and TPM_SIGN_INFO container */\n    BYTE buf[dataSize + 30];\n    if ((dataSize + 30) > (UINT32)(key->key.size >> 3)\n        || dataSize == 0) return TPM_BAD_PARAMETER;\n    /* setup TPM_SIGN_INFO structure */\n    memcpy(&buf[0], \"\\x00\\x05SIGN\", 6);\n    memcpy(&buf[6], auth->nonceOdd.nonce, 20);\n    buf[26] = (dataSize >> 24) & 0xff;\n    buf[27] = (dataSize >> 16) & 0xff;\n    buf[28] = (dataSize >>  8) & 0xff;\n    buf[29] = (dataSize      ) & 0xff;\n    memcpy(&buf[30], data, dataSize);\n    if (tpm_rsa_verify(&key->key, RSA_SSA_PKCS1_SHA1,\n        data, dataSize, sig) != 0)  return TPM_BAD_SIGNATURE;\n  } else if (key->sigScheme == TPM_SS_RSASSAPKCS1v15_INFO && isInfo) {\n    /* TPM_SIGN_INFO structure is already set up */\n    if (dataSize > (UINT32)(key->key.size >> 3)\n        || dataSize == 0) return TPM_BAD_PARAMETER;\n    if (tpm_rsa_verify(&key->key, RSA_SSA_PKCS1_SHA1,\n        data, dataSize, sig) != 0)  return TPM_BAD_SIGNATURE;\n  } else {\n    return TPM_INVALID_KEYUSAGE;\n  }\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT tpm_sign(TPM_KEY_DATA *key, TPM_AUTH *auth, BOOL isInfo,\n                    BYTE *areaToSign, UINT32 areaToSignSize, \n                    BYTE **sig, UINT32 *sigSize)\n{  \n  if (key->sigScheme == TPM_SS_RSASSAPKCS1v15_SHA1) {\n    /* use signature scheme PKCS1_SHA1_RAW */ \n    if (areaToSignSize != 20) return TPM_BAD_PARAMETER;\n    *sigSize = key->key.size >> 3;\n    *sig = tpm_malloc(*sigSize);\n    if (*sig == NULL || tpm_rsa_sign(&key->key, RSA_SSA_PKCS1_SHA1_RAW, \n        areaToSign, areaToSignSize, *sig)) {\n      tpm_free(*sig);\n      return TPM_FAIL;\n    }\n  } else if (key->sigScheme == TPM_SS_RSASSAPKCS1v15_DER) {\n    /* use signature scheme PKCS1_DER */ \n    if ((areaToSignSize + 11) > (UINT32)(key->key.size >> 3)\n        || areaToSignSize == 0) return TPM_BAD_PARAMETER;\n    *sigSize = key->key.size >> 3;\n    *sig = tpm_malloc(*sigSize);\n    if (*sig == NULL || tpm_rsa_sign(&key->key, RSA_SSA_PKCS1_DER, \n        areaToSign, areaToSignSize, *sig)) {\n      tpm_free(*sig);\n      return TPM_FAIL;\n    }\n  } else if (key->sigScheme == TPM_SS_RSASSAPKCS1v15_INFO && !isInfo) {\n    /* use signature scheme PKCS1_SHA1 and TPM_SIGN_INFO container */\n    BYTE buf[areaToSignSize + 30];\n    if ((areaToSignSize + 30) > (UINT32)(key->key.size >> 3)\n        || areaToSignSize == 0) return TPM_BAD_PARAMETER;\n    *sigSize = key->key.size >> 3;\n    *sig = tpm_malloc(*sigSize);\n    if (*sig == NULL) return TPM_FAIL; \n    /* setup TPM_SIGN_INFO structure */\n    memcpy(&buf[0], \"\\x00\\x05SIGN\", 6);\n    memcpy(&buf[6], auth->nonceOdd.nonce, 20);\n    buf[26] = (areaToSignSize >> 24) & 0xff;\n    buf[27] = (areaToSignSize >> 16) & 0xff;\n    buf[28] = (areaToSignSize >>  8) & 0xff;\n    buf[29] = (areaToSignSize      ) & 0xff;\n    memcpy(&buf[30], areaToSign, areaToSignSize);\n    if (tpm_rsa_sign(&key->key, RSA_SSA_PKCS1_SHA1, \n        buf, areaToSignSize + 30, *sig)) {\n      tpm_free(*sig);\n      return TPM_FAIL;\n    }\n  } else if (key->sigScheme == TPM_SS_RSASSAPKCS1v15_INFO && isInfo) {\n    /* TPM_SIGN_INFO structure is already set up */\n    if (areaToSignSize > (UINT32)(key->key.size >> 3)\n        || areaToSignSize == 0) return TPM_BAD_PARAMETER;\n    *sigSize = key->key.size >> 3;\n    *sig = tpm_malloc(*sigSize);\n    if (*sig == NULL) return TPM_FAIL; \n    if (tpm_rsa_sign(&key->key, RSA_SSA_PKCS1_SHA1, \n        areaToSign, areaToSignSize, *sig)) {\n      tpm_free(*sig);\n      return TPM_FAIL;\n    }    \n  } else {\n    return TPM_INVALID_KEYUSAGE;\n  }\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_Sign(TPM_KEY_HANDLE keyHandle, UINT32 areaToSignSize, \n                    BYTE *areaToSign, TPM_AUTH *auth1,  \n                    UINT32 *sigSize, BYTE **sig)\n{\n  TPM_RESULT res;\n  TPM_KEY_DATA *key;\n  info(\"TPM_Sign()\");\n  /* get key */\n  key = tpm_get_key(keyHandle);\n  if (key == NULL) return TPM_INVALID_KEYHANDLE;\n  /* verify authorization */ \n  if (auth1->authHandle != TPM_INVALID_HANDLE\n      || key->authDataUsage != TPM_AUTH_NEVER) {\n    res = tpm_verify_auth(auth1, key->usageAuth, keyHandle);\n    if (res != TPM_SUCCESS) return res;\n  }\n  if (key->keyUsage != TPM_KEY_SIGNING && key->keyUsage != TPM_KEY_LEGACY) \n    return TPM_INVALID_KEYUSAGE;\n  /* sign data */\n  return tpm_sign(key, auth1, FALSE, areaToSign, areaToSignSize, sig, sigSize);\n}\n\nvoid tpm_get_random_bytes(void *buf, size_t nbytes)\n{\n  if (tpmConf & TPM_CONF_USE_INTERNAL_PRNG) {\n    tpm_rc4_ctx_t ctx;\n    tpm_rc4_init(&ctx, tpmData.permanent.data.rngState,\n      sizeof(tpmData.permanent.data.rngState));\n    tpm_rc4_crypt(&ctx, buf, buf, nbytes);\n    tpm_rc4_crypt(&ctx, tpmData.permanent.data.rngState,\n      tpmData.permanent.data.rngState, sizeof(tpmData.permanent.data.rngState));\n  } else {\n    tpm_get_extern_random_bytes(buf, nbytes);\n  }\n}\n\nTPM_RESULT TPM_GetRandom(UINT32 bytesRequested, UINT32 *randomBytesSize, \n                         BYTE **randomBytes)\n{\n  info(\"TPM_GetRandom()\");\n  *randomBytesSize = (bytesRequested < 2048) ? bytesRequested : 2048;\n  *randomBytes = tpm_malloc(*randomBytesSize);\n  if (*randomBytes == NULL) return TPM_SIZE;\n  tpm_get_random_bytes(*randomBytes, *randomBytesSize);\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_StirRandom(UINT32 dataSize, BYTE *inData)\n{\n  info(\"TPM_StirRandom()\");\n  UINT32 i, length = sizeof(tpmData.permanent.data.rngState);\n  while (dataSize > length) {\n    for (i = 0; i < length; i++) {\n        tpmData.permanent.data.rngState[i] ^= *inData++;\n    }\n    dataSize -= length;\n  }\n  for (i = 0; i < dataSize; i++) {\n    tpmData.permanent.data.rngState[i] ^= *inData++;\n  }\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_CertifyKey(TPM_KEY_HANDLE certHandle, TPM_KEY_HANDLE keyHandle,\n                          TPM_NONCE *antiReplay, TPM_AUTH *auth1, \n                          TPM_AUTH *auth2, TPM_CERTIFY_INFO *certifyInfo,\n                          UINT32 *outDataSize, BYTE **outData)\n{\n  TPM_RESULT res;\n  TPM_KEY_DATA *cert, *key;\n  tpm_sha1_ctx_t sha1_ctx;\n  BYTE *buf, *p;\n  UINT32 length;\n  info(\"TPM_CertifyKey()\");\n  /* get keys */\n  cert = tpm_get_key(certHandle);\n  if (cert == NULL) return TPM_INVALID_KEYHANDLE;\n  key = tpm_get_key(keyHandle);\n  if (key == NULL) return TPM_INVALID_KEYHANDLE;\n  /* verify authorization */ \n  if (auth2->authHandle != TPM_INVALID_HANDLE\n      || cert->authDataUsage != TPM_AUTH_NEVER) {\n    res = tpm_verify_auth(auth1, cert->usageAuth, certHandle);\n    if (res != TPM_SUCCESS) return res;\n  }\n  if (auth1->authHandle != TPM_INVALID_HANDLE\n      || key->authDataUsage != TPM_AUTH_NEVER) {\n    res = tpm_verify_auth(auth2, key->usageAuth, keyHandle);\n    if (res != TPM_SUCCESS) return (res == TPM_AUTHFAIL) ? TPM_AUTH2FAIL : res;\n  }\n  /* verify key usage */\n  if (cert->sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1 \n      && cert->sigScheme != TPM_SS_RSASSAPKCS1v15_INFO) return TPM_BAD_SCHEME;\n  if (cert->keyUsage == TPM_KEY_IDENTITY \n      && (key->keyFlags & TPM_KEY_FLAG_MIGRATABLE)\n      && !(key->keyFlags & TPM_KEY_FLAG_AUTHORITY)) return TPM_MIGRATEFAIL;\n  if (key->keyFlags & TPM_KEY_FLAG_HAS_PCR) {\n    if (!(key->keyFlags & TPM_KEY_FLAG_PCR_IGNORE)) {\n      TPM_DIGEST digest;\n      res = tpm_compute_pcr_digest(&key->pcrInfo.releasePCRSelection, \n        &digest, NULL);\n      if (res != TPM_SUCCESS) return res;\n      if (memcmp(&digest, &key->pcrInfo.digestAtRelease, sizeof(TPM_DIGEST)))\n        return TPM_WRONGPCRVAL;\n      if (key->pcrInfo.tag == TPM_TAG_PCR_INFO_LONG\n        && !(key->pcrInfo.localityAtRelease\n             & (1 << tpmData.stany.flags.localityModifier)))\n        return TPM_BAD_LOCALITY;\n    } \n    /* if sizeOfSelect is two use a TPM_CERTIFY_INFO structure ... */\n    if (key->pcrInfo.releasePCRSelection.sizeOfSelect == 2) {\n      certifyInfo->tag = 0x0101;\n      certifyInfo->fill = 0x0000;\n      certifyInfo->migrationAuthoritySize = 0;\n      memcpy(&certifyInfo->PCRInfo, &key->pcrInfo, sizeof(TPM_PCR_INFO));\n      memset(&certifyInfo->PCRInfo.digestAtCreation, 0, sizeof(TPM_DIGEST));\n      certifyInfo->PCRInfoSize = sizeof(TPM_PCR_INFO);\n    /* ... otherwise use a TPM_CERTIFY_INFO2 structure */\n    } else {\n      certifyInfo->tag = TPM_TAG_CERTIFY_INFO2;\n      certifyInfo->fill = 0x0000;\n      certifyInfo->migrationAuthoritySize = 0;\n      memcpy(&certifyInfo->PCRInfo, &key->pcrInfo, sizeof(TPM_PCR_INFO));\n      certifyInfo->PCRInfoSize = sizeof(TPM_PCR_INFO);\n    } \n  } else {\n    /* setup TPM_CERTIFY_INFO structure */\n    certifyInfo->tag = 0x0101;\n    certifyInfo->fill = 0x0000;\n    certifyInfo->migrationAuthoritySize = 0;\n    certifyInfo->PCRInfoSize = 0;\n  }\n  /* setup CERTIFY_INFO[2] structure */\n  certifyInfo->keyUsage = key->keyUsage;\n  certifyInfo->keyFlags = key->keyFlags & TPM_KEY_FLAG_MASK;\n  certifyInfo->authDataUsage = key->authDataUsage;\n  certifyInfo->parentPCRStatus = key->parentPCRStatus;\n  if (tpm_setup_key_parms(key, &certifyInfo->algorithmParms)) return TPM_FAIL;\n  memcpy(&certifyInfo->data, antiReplay, sizeof(TPM_NONCE));\n  /* compute pubKeyDigest */\n  length = key->key.size >> 3;\n  buf = tpm_malloc(length);\n  if (buf == NULL) {\n    free_TPM_KEY_PARMS(certifyInfo->algorithmParms);\n    return TPM_FAIL;\n  }\n  tpm_rsa_export_modulus(&key->key, buf, NULL);\n  tpm_sha1_init(&sha1_ctx);\n  tpm_sha1_update(&sha1_ctx, buf, length);\n  tpm_sha1_final(&sha1_ctx, certifyInfo->pubkeyDigest.digest);\n  tpm_free(buf);\n  /* compute the digest of the CERTIFY_INFO[2] structure and sign it */\n  length = sizeof_TPM_CERTIFY_INFO((*certifyInfo));\n  p = buf = tpm_malloc(length);\n  if (buf == NULL\n      || tpm_marshal_TPM_CERTIFY_INFO(&p, &length, certifyInfo)) {\n    free_TPM_KEY_PARMS(certifyInfo->algorithmParms);\n    return TPM_FAIL;\n  }\n  length = sizeof_TPM_CERTIFY_INFO((*certifyInfo));\n  tpm_sha1_init(&sha1_ctx);\n  tpm_sha1_update(&sha1_ctx, buf, length);\n  tpm_sha1_final(&sha1_ctx, buf);\n  res = tpm_sign(cert, auth1, FALSE, buf, SHA1_DIGEST_LENGTH, outData, outDataSize);\n  tpm_free(buf);\n  if (res != TPM_SUCCESS) {\n    free_TPM_KEY_PARMS(certifyInfo->algorithmParms);\n    return res;\n  }\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_CertifyKey2(TPM_KEY_HANDLE keyHandle, TPM_KEY_HANDLE certHandle,\n                           TPM_DIGEST *migrationPubDigest, \n                           TPM_NONCE *antiReplay, TPM_AUTH *auth1, \n                           TPM_AUTH *auth2, TPM_CERTIFY_INFO *certifyInfo,\n                           UINT32 *outDataSize, BYTE **outData)\n{\n  TPM_RESULT res;\n  TPM_KEY_DATA *cert, *key;\n  tpm_sha1_ctx_t sha1_ctx;\n  BYTE *buf, *p;\n  UINT32 length;\n  info(\"TPM_CertifyKey2()\");\n  /* get keys */\n  key = tpm_get_key(keyHandle);\n  if (key == NULL) return TPM_INVALID_KEYHANDLE;\n  cert = tpm_get_key(certHandle);\n  if (cert == NULL) return TPM_INVALID_KEYHANDLE;\n  /* verify authorization */ \n  if (auth2->authHandle != TPM_INVALID_HANDLE\n      || cert->authDataUsage != TPM_AUTH_NEVER) {\n    res = tpm_verify_auth(auth2, cert->usageAuth, certHandle);\n    if (res != TPM_SUCCESS) return res;\n  }\n  if (auth1->authHandle != TPM_INVALID_HANDLE\n      || key->authDataUsage != TPM_AUTH_NEVER) {\n    res = tpm_verify_auth(auth1, key->usageAuth, keyHandle);\n    if (res != TPM_SUCCESS) return (res == TPM_AUTHFAIL) ? TPM_AUTH2FAIL : res;\n  }\n  /* verify key usage */\n  if (cert->sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1) return TPM_BAD_SCHEME;\n  if (cert->keyUsage == TPM_KEY_IDENTITY \n      && (key->keyFlags & TPM_KEY_FLAG_MIGRATABLE)\n      && !(key->keyFlags & TPM_KEY_FLAG_AUTHORITY)) return TPM_MIGRATEFAIL;\n  if (key->keyFlags & TPM_KEY_FLAG_HAS_PCR) {\n    if (!(key->keyFlags & TPM_KEY_FLAG_PCR_IGNORE)) {\n      TPM_DIGEST digest;\n      res = tpm_compute_pcr_digest(&key->pcrInfo.releasePCRSelection, \n        &digest, NULL);\n      if (res != TPM_SUCCESS) return res;\n      if (memcmp(&digest, &key->pcrInfo.digestAtRelease, sizeof(TPM_DIGEST)))\n        return TPM_WRONGPCRVAL;\n      if (key->pcrInfo.tag == TPM_TAG_PCR_INFO_LONG\n        && !(key->pcrInfo.localityAtRelease\n             & (1 << tpmData.stany.flags.localityModifier)))\n        return TPM_BAD_LOCALITY;\n    }\n    memcpy(&certifyInfo->PCRInfo, &key->pcrInfo, sizeof(TPM_PCR_INFO));\n    certifyInfo->PCRInfoSize = sizeof(certifyInfo->PCRInfo);\n  } else {\n    certifyInfo->PCRInfoSize = 0;\n  }\n  /* setup migration authority values */\n  if (key->payload == TPM_PT_MIGRATE_RESTRICTED\n      || key->payload == TPM_PT_MIGRATE_EXTERNAL) {\n    TPM_PUBKEY pubKey;\n    TPM_DIGEST keyDigest;\n    BYTE buf[SHA1_DIGEST_LENGTH];\n    tpm_hmac_ctx_t hmac_ctx;\n    tpm_sha1_ctx_t sha1_ctx;\n    /* compute digest of public key */\n    if (tpm_extract_pubkey(key, &pubKey) != 0) {\n      debug(\"tpm_extract_pubkey() failed\");\n      return TPM_FAIL;\n    }\n    if (tpm_compute_pubkey_digest(&pubKey, &keyDigest) != 0) {\n      debug(\"tpm_compute_pubkey_digest() failed.\");\n      free_TPM_PUBKEY(pubKey);\n      return TPM_FAIL;\n    }\n    free_TPM_PUBKEY(pubKey);\n    /* verify migration authorization */\n    buf[0] = (TPM_TAG_CMK_MIGAUTH >> 8) & 0xff;\n    buf[1] = TPM_TAG_CMK_MIGAUTH & 0xff;\n    tpm_hmac_init(&hmac_ctx, tpmData.permanent.data.tpmProof.nonce, sizeof(TPM_NONCE));\n    tpm_hmac_update(&hmac_ctx, buf, 2);\n    tpm_hmac_update(&hmac_ctx, migrationPubDigest->digest, sizeof(TPM_DIGEST));\n    tpm_hmac_update(&hmac_ctx, keyDigest.digest, sizeof(TPM_DIGEST));\n    tpm_hmac_final(&hmac_ctx, buf);\n    if (memcmp(key->migrationAuth, buf, sizeof(TPM_SECRET)) != 0) return TPM_MA_SOURCE;\n    /* compute migrationAuthority */\n    certifyInfo->migrationAuthoritySize = SHA1_DIGEST_LENGTH;\n    certifyInfo->migrationAuthority = tpm_malloc(certifyInfo->migrationAuthoritySize);\n    if (certifyInfo->migrationAuthority == NULL) return TPM_NOSPACE;\n    tpm_sha1_init(&sha1_ctx);\n    tpm_sha1_update(&sha1_ctx, migrationPubDigest->digest, sizeof(TPM_DIGEST));\n    buf[0] = key->payload;\n    tpm_sha1_update(&sha1_ctx, buf, 1);\n    tpm_sha1_final(&sha1_ctx, certifyInfo->migrationAuthority);\n    certifyInfo->payloadType = key->payload;\n  } else {\n    certifyInfo->migrationAuthoritySize = 0;\n    certifyInfo->migrationAuthority = 0;\n    certifyInfo->payloadType = TPM_PT_ASYM;\n  }\n  /* setup CERTIFY_INFO2 structure */\n  certifyInfo->tag = TPM_TAG_CERTIFY_INFO2;\n  certifyInfo->fill = 0x0000; \n  certifyInfo->keyUsage = key->keyUsage;\n  certifyInfo->keyFlags = key->keyFlags & TPM_KEY_FLAG_MASK;\n  certifyInfo->authDataUsage = key->authDataUsage;\n  certifyInfo->parentPCRStatus = key->parentPCRStatus;\n  if (tpm_setup_key_parms(key, &certifyInfo->algorithmParms)) return TPM_FAIL;\n  memcpy(&certifyInfo->data, antiReplay, sizeof(TPM_NONCE));\n  /* compute pubKeyDigest */\n  length = key->key.size >> 3;\n  buf = tpm_malloc(length);\n  if (buf == NULL) {\n    free_TPM_KEY_PARMS(certifyInfo->algorithmParms);\n    return TPM_FAIL;\n  }\n  tpm_rsa_export_modulus(&key->key, buf, NULL);\n  tpm_sha1_init(&sha1_ctx);\n  tpm_sha1_update(&sha1_ctx, buf, length);\n  tpm_sha1_final(&sha1_ctx, certifyInfo->pubkeyDigest.digest);\n  tpm_free(buf);\n  /* compute the digest of the CERTIFY_INFO[2] structure and sign it */\n  length = sizeof_TPM_CERTIFY_INFO((*certifyInfo));\n  p = buf = tpm_malloc(length);\n  if (buf == NULL\n      || tpm_marshal_TPM_CERTIFY_INFO(&p, &length, certifyInfo)) {\n    free_TPM_KEY_PARMS(certifyInfo->algorithmParms);\n    return TPM_FAIL;\n  }\n  length = sizeof_TPM_CERTIFY_INFO((*certifyInfo));\n  tpm_sha1_init(&sha1_ctx);\n  tpm_sha1_update(&sha1_ctx, buf, length);\n  tpm_sha1_final(&sha1_ctx, buf);\n  res = tpm_sign(cert, auth2, FALSE, buf, SHA1_DIGEST_LENGTH, outData, outDataSize);\n  tpm_free(buf);\n  if (res != TPM_SUCCESS) {\n    free_TPM_KEY_PARMS(certifyInfo->algorithmParms);\n    return res;\n  }\n  return TPM_SUCCESS;\n}\n\n"
  },
  {
    "path": "tpm/tpm_daa.c",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *               2005-2008 Heiko Stamer <stamer@gaos.org> \n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: tpm_daa.c 452 2010-07-19 19:05:05Z mast $\n */\n\n#include \"tpm_emulator.h\"\n#include \"tpm_commands.h\"\n#include \"tpm_data.h\"\n#include \"tpm_handles.h\"\n#include \"tpm_marshalling.h\"\n#include \"crypto/sha1.h\"\n#include \"crypto/rsa.h\"\n#include \"crypto/rc4.h\"\n#include \"crypto/hmac.h\"\n\n#define DAA_LABEL_00 ((uint8_t*)\"\\x00\")\n#define DAA_LABEL_01 ((uint8_t*)\"\\x01\")\n#define DAA_LABEL_r0 ((uint8_t*)\"r0\")\n#define DAA_LABEL_r1 ((uint8_t*)\"r1\")\n#define DAA_LABEL_r2 ((uint8_t*)\"r2\")\n\nUINT32 tpm_get_free_daa_session(void)\n{\n  UINT32 i;\n  \n  for (i = 0; i < TPM_MAX_SESSIONS_DAA; i++) {\n    if (tpmData.stany.data.sessionsDAA[i].type == TPM_ST_INVALID) {\n      tpmData.stany.data.sessionsDAA[i].type = TPM_ST_DAA;\n      tpmData.stany.data.sessionsDAA[i].handle = INDEX_TO_DAA_HANDLE(i);\n      return INDEX_TO_DAA_HANDLE(i);\n    }\n  }\n  return TPM_INVALID_HANDLE;\n}\n\n/* Verify that DAA_session->DAA_digestContext == \n * SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error on mismatch */\nstatic TPM_RESULT tpm_daa_verify_digestContext(TPM_DAA_SESSION_DATA *session, \n                                               tpm_sha1_ctx_t *sha1)\n{\n  TPM_DIGEST dgt;\n  UINT32 size, len;\n  BYTE *buf, *ptr;\n  \n  tpm_sha1_init(sha1);\n  \n  size = len = sizeof(TPM_DAA_TPM);\n  buf = ptr = tpm_malloc(size);\n  if (buf == NULL)\n    return -1;\n  memset(buf, 0, size);\n  if (tpm_marshal_TPM_DAA_TPM(&ptr, &len, &session->DAA_tpmSpecific)) {\n    tpm_free(buf);\n    return -1;\n  }\n  tpm_sha1_update(sha1, buf, size);\n  tpm_free(buf);\n  \n  size = len = sizeof(TPM_DAA_JOINDATA);\n  buf = ptr = tpm_malloc(size);\n  if (buf == NULL)\n    return -1;\n  memset(buf, 0, size);\n  if (tpm_marshal_TPM_DAA_JOINDATA(&ptr, &len, &session->DAA_joinSession)) {\n    tpm_free(buf);\n    return -1;\n  }\n  tpm_sha1_update(sha1, buf, size);\n  tpm_free(buf);\n  \n  tpm_sha1_final(sha1, dgt.digest);\n  \n  return memcmp(dgt.digest, session->DAA_session.DAA_digestContext.digest, \n    sizeof(TPM_DIGEST));\n}\n\n/* Set DAA_session->DAA_digestContext = SHA-1(DAA_tpmSpecific || \n * DAA_joinSession) */\nstatic void tpm_daa_update_digestContext(TPM_DAA_SESSION_DATA *session,\n                                         tpm_sha1_ctx_t *sha1)\n{\n  UINT32 size, len;\n  BYTE *buf, *ptr;\n  \n  tpm_sha1_init(sha1);\n  \n  /* DAA_tpmSpecific */\n  size = len = sizeof(TPM_DAA_TPM);\n  buf = ptr = tpm_malloc(size);\n  if (buf == NULL)\n    return;\n  memset(buf, 0, size);\n  if (tpm_marshal_TPM_DAA_TPM(&ptr, &len, &session->DAA_tpmSpecific)) {\n    tpm_free(buf);\n    return;\n  }\n  tpm_sha1_update(sha1, buf, size);\n  tpm_free(buf);\n  \n  /* DAA_joinSession */\n  size = len = sizeof(TPM_DAA_JOINDATA);\n  buf = ptr = tpm_malloc(size);\n  if (buf == NULL)\n    return;\n  memset(buf, 0, size);\n  if (tpm_marshal_TPM_DAA_JOINDATA(&ptr, &len, &session->DAA_joinSession)) {\n    tpm_free(buf);\n    return;\n  }\n  tpm_sha1_update(sha1, buf, size);\n  tpm_free(buf);\n  \n  tpm_sha1_final(sha1, session->DAA_session.DAA_digestContext.digest);\n}\n\n/* Verify that DAA_session->DAA_digestContext == SHA-1(DAA_tpmSpecific) and \n * return error on mismatch */\nstatic TPM_RESULT tpm_daa_verify_digestContext_sign(TPM_DAA_SESSION_DATA *session,\n                                                    tpm_sha1_ctx_t *sha1)\n{\n  TPM_DIGEST dgt;\n  UINT32 size, len;\n  BYTE *buf, *ptr;\n  \n  tpm_sha1_init(sha1);\n  \n  size = len = sizeof(TPM_DAA_TPM);\n  buf = ptr = tpm_malloc(size);\n  if (buf == NULL)\n    return -1;\n  memset(buf, 0, size);\n  if (tpm_marshal_TPM_DAA_TPM(&ptr, &len, &session->DAA_tpmSpecific)) {\n    tpm_free(buf);\n    return -1;\n  }\n  tpm_sha1_update(sha1, buf, size);\n  tpm_free(buf);\n  \n  tpm_sha1_final(sha1, dgt.digest);\n  \n  return memcmp(dgt.digest, session->DAA_session.DAA_digestContext.digest, \n    sizeof(TPM_DIGEST));\n}\n\n/* Set DAA_session->DAA_digestContext = SHA-1(DAA_tpmSpecific) */\nstatic void tpm_daa_update_digestContext_sign(TPM_DAA_SESSION_DATA *session,\n                                              tpm_sha1_ctx_t *sha1)\n{\n  UINT32 size, len;\n  BYTE *buf, *ptr;\n  \n  tpm_sha1_init(sha1);\n  \n  size = len = sizeof(TPM_DAA_TPM);\n  buf = ptr = tpm_malloc(size);\n  if (buf == NULL)\n    return;\n  memset(buf, 0, size);\n  if (tpm_marshal_TPM_DAA_TPM(&ptr, &len, &session->DAA_tpmSpecific)) {\n    tpm_free(buf);\n    return;\n  }\n  tpm_sha1_update(sha1, buf, size);\n  tpm_free(buf);\n  \n  tpm_sha1_final(sha1, session->DAA_session.DAA_digestContext.digest);\n}\n\n/* Verify that DAA_tpmSpecific->DAA_digestIssuer == \n * SHA-1(DAA_issuerSettings) and return error on mismatch */\nstatic TPM_RESULT tpm_daa_verify_digestIssuer(TPM_DAA_SESSION_DATA *session,\n                                              tpm_sha1_ctx_t *sha1)\n{\n  TPM_DIGEST dgt;\n  UINT32 size, len;\n  BYTE *buf, *ptr;\n  \n  tpm_sha1_init(sha1);\n  \n  size = len = sizeof(TPM_DAA_ISSUER);\n  buf = ptr = tpm_malloc(size);\n  if (buf == NULL)\n    return -1;\n  memset(buf, 0, size);\n  if (tpm_marshal_TPM_DAA_ISSUER(&ptr, &len, &session->DAA_issuerSettings)) {\n    tpm_free(buf);\n    return -1;\n  }\n  tpm_sha1_update(sha1, buf, size);\n  tpm_free(buf);\n  \n  tpm_sha1_final(sha1, dgt.digest);\n  \n  return memcmp(dgt.digest, session->DAA_tpmSpecific.DAA_digestIssuer.digest, \n    sizeof(TPM_DIGEST));\n}\n\n/* Set DAA_tpmSpecific->DAA_digestIssuer == SHA-1(DAA_issuerSettings) */\nstatic void tpm_daa_update_digestIssuer(TPM_DAA_SESSION_DATA *session,\n                                        tpm_sha1_ctx_t *sha1)\n{\n  UINT32 size, len;\n  BYTE *buf, *ptr;\n  \n  tpm_sha1_init(sha1);\n  \n  size = len = sizeof(TPM_DAA_ISSUER);\n  buf = ptr = tpm_malloc(size);\n  if (buf == NULL)\n    return;\n  memset(buf, 0, size);\n  if (tpm_marshal_TPM_DAA_ISSUER(&ptr, &len, &session->DAA_issuerSettings)) {\n    tpm_free(buf);\n    return;\n  }\n  tpm_sha1_update(sha1, buf, size);\n  tpm_free(buf);\n  \n  tpm_sha1_final(sha1, session->DAA_tpmSpecific.DAA_digestIssuer.digest);\n}\n\n/* Verify that SHA-1(input) == digest and return error !TPM_SUCCESS \n * on mismatch */\nstatic TPM_RESULT tpm_daa_verify_generic(TPM_DIGEST digest, BYTE *input, \n                                         UINT32 inputSize, tpm_sha1_ctx_t *sha1)\n{\n  TPM_DIGEST dgt;\n  \n  tpm_sha1_init(sha1);\n  tpm_sha1_update(sha1, input, inputSize);\n  tpm_sha1_final(sha1, dgt.digest);\n  return memcmp(dgt.digest, digest.digest, sizeof(TPM_DIGEST));\n}\n\n/* Encryption and decryption of the TPM_DAA_SENSITIVE structure */\nstatic int encrypt_daa(BYTE *iv, UINT32 iv_size, TPM_DAA_SENSITIVE *sensitive, \n                       BYTE **enc, UINT32 *enc_size)\n{\n  UINT32 len;\n  BYTE *ptr;\n  tpm_rc4_ctx_t rc4_ctx;\n  BYTE key[TPM_SYM_KEY_SIZE + iv_size];\n  \n  /* marshal sensitive */\n  *enc_size = len = sizeof_TPM_DAA_SENSITIVE((*sensitive));\n  *enc = ptr = tpm_malloc(len);\n  if (*enc == NULL)\n    return -1;\n  if (tpm_marshal_TPM_DAA_SENSITIVE(&ptr, &len, sensitive)) {\n    tpm_free(*enc);\n    return -1;\n  }\n  \n  /* encrypt sensitive */\n  memcpy(key, tpmData.permanent.data.daaKey, TPM_SYM_KEY_SIZE);\n  memcpy(&key[TPM_SYM_KEY_SIZE], iv, iv_size);\n  tpm_rc4_init(&rc4_ctx, key, sizeof(key));\n  tpm_rc4_crypt(&rc4_ctx, *enc, *enc, *enc_size);\n  \n  return 0;\n}\n\nstatic int decrypt_daa(BYTE *iv, UINT32 iv_size, BYTE *enc, UINT32 enc_size, \n                       TPM_DAA_SENSITIVE *sensitive, BYTE **buf)\n{\n  UINT32 len;\n  BYTE *ptr;\n  tpm_rc4_ctx_t rc4_ctx;\n  BYTE key[TPM_SYM_KEY_SIZE + iv_size];\n  \n  /* decrypt sensitive */\n  len = enc_size, *buf = ptr = tpm_malloc(len);\n  if (ptr == NULL)\n    return -1;\n  memcpy(key, tpmData.permanent.data.daaKey, TPM_SYM_KEY_SIZE);\n  memcpy(&key[TPM_SYM_KEY_SIZE], iv, iv_size);\n  tpm_rc4_init(&rc4_ctx, key, sizeof(key));\n  tpm_rc4_crypt(&rc4_ctx, enc, ptr, enc_size);\n  \n  /* unmarshal sensitive */\n  if (tpm_unmarshal_TPM_DAA_SENSITIVE(&ptr, &len, sensitive)) {\n    tpm_free(*buf);\n    return -1;\n  }\n  \n  return 0;\n}\n\n/* Computation of the HMAC which protects the integrity of the TPM_DAA_BLOB */\nstatic int compute_daa_digest(TPM_DAA_BLOB *daaBlob, TPM_DIGEST *digest)\n{\n  BYTE *buf, *ptr;\n  UINT32 len;\n  tpm_hmac_ctx_t hmac_ctx;\n  \n  len = sizeof_TPM_DAA_BLOB((*daaBlob));\n  buf = ptr = tpm_malloc(len);\n  if (buf == NULL)\n    return -1;\n  if (tpm_marshal_TPM_DAA_BLOB(&ptr, &len, daaBlob)) {\n    tpm_free(buf);\n    return -1;\n  }\n  memset(&buf[22], 0, sizeof(TPM_DIGEST));\n  tpm_hmac_init(&hmac_ctx, tpmData.permanent.data.daaProof.nonce,\n    sizeof(tpmData.permanent.data.daaProof.nonce));\n  tpm_hmac_update(&hmac_ctx, buf, sizeof_TPM_DAA_BLOB((*daaBlob)));\n  tpm_hmac_final(&hmac_ctx, digest->digest);\n  tpm_free(buf);\n  return 0;\n}\n\n/*\n * DAA commands ([TPM_Part3], Section 26)\n * Operations that are necessary to setup a TPM for DAA, execute the \n * JOIN process, and execute the SIGN process.\n */\n\n#define SCRATCH_SIZE 256\n\nTPM_RESULT TPM_DAA_Join(TPM_HANDLE handle, BYTE stage, UINT32 inputSize0,\n                        BYTE *inputData0, UINT32 inputSize1,\n                        BYTE *inputData1, TPM_AUTH *auth1,\n                        TPM_COMMAND_CODE *ordinal, UINT32 *outputSize,\n                        BYTE **outputData)\n{\n  BYTE scratch[SCRATCH_SIZE];\n  TPM_DAA_SESSION_DATA *session = NULL;\n  \n  TPM_RESULT res;\n  UINT32 cnt, len;\n  tpm_sha1_ctx_t sha1;\n  tpm_rsa_public_key_t key;\n  BYTE *signedData = NULL, *signatureValue = NULL, *DAA_generic_gamma = NULL,\n    *DAA_generic_R0 = NULL, *DAA_generic_R1 = NULL, *DAA_generic_n = NULL,\n    *DAA_generic_S0 = NULL, *DAA_generic_S1 = NULL, *ptr;\n  tpm_bn_t X, Y, Z, n, f, q, f0, f1, w1, w, gamma, r0, r1, r2, r3, r, s0, s1, \n    s12, s2, s3, E, E1, u2, u3, v0, v10, v1, tmp;\n  size_t size;\n  BYTE mgf1_seed[2 + sizeof(TPM_DIGEST)];\n  TPM_DAA_BLOB blob;\n  TPM_DAA_SENSITIVE sensitive;\n  \n  info(\"TPM_DAA_Join()\");\n  debug(\"handle = %.8x, stage = %d\", handle, stage);\n  debug(\"stany.data.currentDAA = %.8x\", tpmData.stany.data.currentDAA);\n  \n  /* Initalize internal scratch pad */\n  memset(scratch, 0, SCRATCH_SIZE);\n  \n  /* Verify authorization */\n  res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);\n  if (res != TPM_SUCCESS) return res;\n  \n  /* Verify and initalize the session, for all stages greater than zero. */\n  if (stage > 0) {\n    if ((HANDLE_TO_INDEX(handle) >= TPM_MAX_SESSIONS_DAA) ||\n      (tpmData.stany.data.sessionsDAA[HANDLE_TO_INDEX(handle)].type != \n        TPM_ST_DAA) ||\n      (tpmData.stany.data.sessionsDAA[HANDLE_TO_INDEX(handle)].handle != \n      handle)) {\n        /* Probe, whether the handle from stany.data.currentDAA is valid. */\n        handle = tpmData.stany.data.currentDAA;\n        if ((HANDLE_TO_INDEX(handle) >= TPM_MAX_SESSIONS_DAA) ||\n          (tpmData.stany.data.sessionsDAA[HANDLE_TO_INDEX(handle)].type != \n            TPM_ST_DAA) ||\n          (tpmData.stany.data.sessionsDAA[HANDLE_TO_INDEX(handle)].handle != \n            handle))\n              return TPM_BAD_HANDLE;\n    }\n    session = &tpmData.stany.data.sessionsDAA[HANDLE_TO_INDEX(handle)];\n  }\n  \n  /* TPM_DAA_JOIN [TPM_Part3], Section 26.1, Rev. 85 */\n  switch (stage) {\n    case 0:\n    {\n      /* Determine that sufficient resources are available to perform a\n       * DAA_Join. Assign session handle for this DAA_Join. */\n      handle = tpm_get_free_daa_session();\n      if (handle == TPM_INVALID_HANDLE)\n        return TPM_RESOURCES;\n      session = &tpmData.stany.data.sessionsDAA[HANDLE_TO_INDEX(handle)];\n      /* Set all fields in DAA_issuerSettings = NULL */\n      memset(&session->DAA_issuerSettings, 0, sizeof(TPM_DAA_ISSUER));\n      session->DAA_issuerSettings.tag = TPM_TAG_DAA_ISSUER;\n      /* Set all fields in DAA_tpmSpecific = NULL */\n      memset(&session->DAA_tpmSpecific, 0, sizeof(TPM_DAA_TPM));\n      session->DAA_tpmSpecific.tag = TPM_TAG_DAA_TPM;\n      /* Set all fields in DAA_session = NULL */\n      memset(&session->DAA_session, 0, sizeof(TPM_DAA_CONTEXT));\n      session->DAA_session.tag = TPM_TAG_DAA_CONTEXT;\n      /* Set all fields in DAA_joinSession = NULL */\n      memset(&session->DAA_joinSession, 0, sizeof(TPM_DAA_JOINDATA));\n      /* Verify that sizeOf(inputData0) == sizeOf(DAA_tpmSpecific->DAA_count)\n       * and return error TPM_DAA_INPUT_DATA0 on mismatch */\n      if (inputSize0 != sizeof(session->DAA_tpmSpecific.DAA_count)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_INPUT_DATA0;\n      }\n      /* Verify that inputData0 > 0, and return TPM_DAA_INPUT_DATA0 on\n       * mismatch */\n      ptr = inputData0, len = inputSize0;\n      if (tpm_unmarshal_UINT32(&ptr, &len, &cnt) || (len != 0)) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA0;\n      }\n      if (cnt <= 0) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_INPUT_DATA0;\n      }\n      /* Set DAA_tpmSpecific->DAA_count = inputData0 */\n      debug(\"TPM_DAA_Join() -- set DAA_count := %d\", cnt);\n      session->DAA_tpmSpecific.DAA_count = cnt;\n      /* Set DAA_session->DAA_digestContext = SHA-1(DAA_tpmSpecific ||\n       * DAA_joinSession) */\n      tpm_daa_update_digestContext(session, &sha1);\n      /* Set DAA_session->DAA_stage = 1 */\n      session->DAA_session.DAA_stage = 1;\n      /* Assign session handle for DAA_Join */\n      tpmData.stany.data.currentDAA = handle;\n      debug(\"TPM_DAA_Join() -- set handle := %.8x\", handle);\n      /* Set outputData = new session handle */\n      *outputSize = sizeof(TPM_HANDLE);\n      if ((*outputData = tpm_malloc(*outputSize)) != NULL) {\n        ptr = *outputData, len = *outputSize;\n        if (tpm_marshal_TPM_HANDLE(&ptr, &len, handle)) {\n          debug(\"TPM_DAA_Join(): tpm_marshal_TPM_HANDLE() failed.\");\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_FAIL;\n        }\n      } else {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_NOSPACE;\n      }\n      /* Return TPM_SUCCESS */\n      return TPM_SUCCESS;\n    }\n    case 1:\n    {\n      /* Verify that DAA_session->DAA_stage == 1. Return TPM_DAA_STAGE\n       * and flush handle on mismatch */\n      if (session->DAA_session.DAA_stage != 1) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_STAGE;\n      }\n      /* Verify that DAA_session->DAA_digestContext == \n       * SHA-1(DAA_tpmSpecific || DAA_joinSession) and return \n       * TPM_DAA_TPM_SETTINGS on mismatch */\n      if (tpm_daa_verify_digestContext(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_TPM_SETTINGS;\n      }\n      /* Verify that sizeOf(inputData0) == DAA_SIZE_issuerModulus and\n       * return error TPM_DAA_INPUT_DATA0 on mismatch */\n      if (inputSize0 != DAA_SIZE_issuerModulus) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_INPUT_DATA0;\n      }\n      /* If DAA_session->DAA_scratch == NULL: */\n      if (!memcmp(scratch, session->DAA_session.DAA_scratch, \n        sizeof(session->DAA_session.DAA_scratch))) {\n          /* Set DAA_session->DAA_scratch = inputData0 */\n          memset(session->DAA_session.DAA_scratch, 0, \n            sizeof(session->DAA_session.DAA_scratch));\n          memcpy(session->DAA_session.DAA_scratch, inputData0, inputSize0);\n          /* Set DAA_joinSession->DAA_digest_n0 = \n           * SHA-1(DAA_session->DAA_scratch) */\n          tpm_sha1_init(&sha1);\n          tpm_sha1_update(&sha1, session->DAA_session.DAA_scratch, \n            sizeof(session->DAA_session.DAA_scratch));\n          tpm_sha1_final(&sha1, (BYTE*) &session->DAA_joinSession.DAA_digest_n0);\n          /* Set DAA_tpmSpecific->DAA_rekey = SHA-1(TPM_DAA_TPM_SEED || \n           * DAA_joinSession->DAA_digest_n0) */\n          tpm_sha1_init(&sha1);\n          tpm_sha1_update(&sha1, (BYTE*) &tpmData.permanent.data.tpmDAASeed, \n            sizeof(tpmData.permanent.data.tpmDAASeed));\n          tpm_sha1_update(&sha1, (BYTE*) &session->DAA_joinSession.DAA_digest_n0, \n            sizeof(session->DAA_joinSession.DAA_digest_n0));\n          tpm_sha1_final(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_rekey);\n      /* Else (If DAA_session->DAA_scratch != NULL): */\n      } else {\n        /* Set signedData = inputData0 */\n        signedData = inputData0;\n        /* Verify that sizeOf(inputData1) == DAA_SIZE_issuerModulus and \n         * return error TPM_DAA_INPUT_DATA1 on mismatch */\n        if (inputSize1 != DAA_SIZE_issuerModulus) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA1;\n        }\n        /* Set signatureValue = inputData1 */\n        signatureValue = inputData1;\n        /* Use the RSA key == [DAA_session->DAA_scratch] to verify that \n         * signatureValue is a signature on signedData, and return error \n         * TPM_DAA_ISSUER_VALIDITY on mismatch */\n        if (tpm_rsa_import_public_key(&key, RSA_MSB_FIRST, \n          session->DAA_session.DAA_scratch, DAA_SIZE_issuerModulus, NULL, 0)) {\n            memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n            return TPM_DAA_ISSUER_VALIDITY;\n        }\n        if (tpm_rsa_verify(&key, RSA_SSA_PKCS1_SHA1, signedData, inputSize0, \n          signatureValue)) {\n            memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n            return TPM_DAA_ISSUER_VALIDITY;\n        }\n        tpm_rsa_release_public_key(&key);\n        /* Set DAA_session->DAA_scratch = signedData */\n        memset(session->DAA_session.DAA_scratch, 0, \n          sizeof(session->DAA_session.DAA_scratch));\n        memcpy(session->DAA_session.DAA_scratch, inputData0, inputSize0);\n      }\n      /* Decrement DAA_tpmSpecific->DAA_count by 1 (unity) */\n      session->DAA_tpmSpecific.DAA_count--;\n      /* If DAA_tpmSpecific->DAA_count == 0: */\n      if (session->DAA_tpmSpecific.DAA_count == 0) {\n        /* Increment DAA_Session->DAA_stage by 1 */\n        session->DAA_session.DAA_stage++;\n      }\n      /* Set DAA_session->DAA_digestContext = SHA-1(DAA_tpmSpecific || \n       * DAA_joinSession) */\n      tpm_daa_update_digestContext(session, &sha1);\n      /* Set outputData = NULL */\n      *outputSize = 0, *outputData = NULL;\n      /* Return TPM_SUCCESS */\n      return TPM_SUCCESS;\n    }\n    case 2:\n    {\n      /* Verify that DAA_session->DAA_stage == 2. Return TPM_DAA_STAGE \n       * and flush handle on mismatch */\n      if (session->DAA_session.DAA_stage != 2) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_STAGE;\n      }\n      /* Verify that DAA_session->DAA_digestContext == \n       * SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error\n       * TPM_DAA_TPM_SETTINGS on mismatch */\n      if (tpm_daa_verify_digestContext(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_TPM_SETTINGS;\n      }\n      /* Verify that sizeOf(inputData0) == sizeOf(TPM_DAA_ISSUER) and \n       * return error TPM_DAA_INPUT_DATA0 on mismatch */\n      if (inputSize0 != sizeof(TPM_DAA_ISSUER)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_INPUT_DATA0;\n      }\n      /* Set DAA_issuerSettings = inputData0. Verify that all fields in \n       * DAA_issuerSettings are present and return error\n       * TPM_DAA_INPUT_DATA0 if not. */\n      ptr = inputData0, len = inputSize0;\n      if (tpm_unmarshal_TPM_DAA_ISSUER(&ptr, &len, \n        &session->DAA_issuerSettings) || (len != 0) || \n        !(session->DAA_issuerSettings.tag == TPM_TAG_DAA_ISSUER)) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA0;\n      }\n      /* Verify that sizeOf(inputData1) == DAA_SIZE_issuerModulus and \n       * return error TPM_DAA_INPUT_DATA1 on mismatch */\n      if (inputSize1 != DAA_SIZE_issuerModulus) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_INPUT_DATA1;\n      }\n      /* Set signatureValue = inputData1 */\n      signatureValue = inputData1;\n      /* Set signedData = (DAA_joinSession->DAA_digest_n0 || \n       * DAA_issuerSettings) */\n      memcpy(scratch, &session->DAA_joinSession.DAA_digest_n0, \n        sizeof(TPM_DIGEST));\n      memcpy(scratch + sizeof(TPM_DIGEST), inputData0, inputSize0);\n      signedData = scratch;\n      /* Use the RSA key [DAA_session->DAA_scratch] to verify that \n       * signatureValue is a signature on signedData, and return error \n       * TPM_DAA_ISSUER_VALIDITY on mismatch */\n      if (tpm_rsa_import_public_key(&key, RSA_MSB_FIRST, \n        session->DAA_session.DAA_scratch, DAA_SIZE_issuerModulus, NULL, 0)) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_ISSUER_VALIDITY;\n      }\n      if (tpm_rsa_verify(&key, RSA_SSA_PKCS1_SHA1, signedData, \n        sizeof(TPM_DIGEST) + inputSize0, signatureValue)) {\n          tpm_rsa_release_public_key(&key);\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_ISSUER_VALIDITY;\n      }\n      tpm_rsa_release_public_key(&key);\n      /* Set DAA_tpmSpecific->DAA_digestIssuer == SHA-1(DAA_issuerSettings) */\n      tpm_daa_update_digestIssuer(session, &sha1);\n      /* Set DAA_session->DAA_digestContext = SHA-1(DAA_tpmSpecific || \n       * DAA_joinSession) */\n      tpm_daa_update_digestContext(session, &sha1);\n      /* Set DAA_session->DAA_scratch = NULL */\n      memset(session->DAA_session.DAA_scratch, 0, \n        sizeof(session->DAA_session.DAA_scratch));\n      /* Set outputData = NULL */\n      *outputSize = 0;\n      *outputData = NULL;\n      /* Increment DAA_session->DAA_stage by 1 */\n      session->DAA_session.DAA_stage++;\n      /* Return TPM_SUCCESS */\n      return TPM_SUCCESS;\n    }\n    case 3:\n    {\n      /* Verify that DAA_session->DAA_stage == 3. Return TPM_DAA_STAGE \n       * and flush handle on mismatch */\n      if (session->DAA_session.DAA_stage != 3) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_STAGE;\n      }\n      /* Verify that DAA_tpmSpecific->DAA_digestIssuer == \n       * SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS \n       * on mismatch */\n      if (tpm_daa_verify_digestIssuer(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_ISSUER_SETTINGS;\n      }\n      /* Verify that DAA_session->DAA_digestContext == \n       * SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error \n       * TPM_DAA_TPM_SETTINGS on mismatch */\n      if (tpm_daa_verify_digestContext(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_TPM_SETTINGS;\n      }\n      /* Verify that sizeOf(inputData0) == sizeOf(DAA_tpmSpecific->DAA_count)\n       * and return error TPM_DAA_INPUT_DATA0 on mismatch */\n      if (inputSize0 != sizeof(session->DAA_tpmSpecific.DAA_count)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_INPUT_DATA0;\n      }\n      /* Set DAA_tpmSpecific->DAA_count = inputData0 */\n      ptr = inputData0, len = inputSize0;\n      if (tpm_unmarshal_UINT32(&ptr, &len, \n        &session->DAA_tpmSpecific.DAA_count) || (len != 0)) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA0;\n      }\n      /* Obtain random data from the RNG and store it as \n       * DAA_joinSession->DAA_join_u0 */\n      tpm_get_random_bytes(session->DAA_joinSession.DAA_join_u0, \n        sizeof(session->DAA_joinSession.DAA_join_u0));\n      /* Obtain random data from the RNG and store it as \n       * DAA_joinSession->DAA_join_u1 */\n      tpm_get_random_bytes(session->DAA_joinSession.DAA_join_u1, \n        sizeof(session->DAA_joinSession.DAA_join_u1));\n      /* Set outputData = NULL */\n      *outputSize = 0, *outputData = NULL;\n      /* Increment DAA_session->DAA_stage by 1 */\n      session->DAA_session.DAA_stage++;\n      /* Set DAA_session->DAA_digestContext = SHA-1(DAA_tpmSpecific || \n       * DAA_joinSession) */\n      tpm_daa_update_digestContext(session, &sha1);\n      /* Return TPM_SUCCESS */\n      return TPM_SUCCESS;\n    }\n    case 4:\n    {\n      /* Verify that DAA_session->DAA_stage == 4. Return TPM_DAA_STAGE \n       * and flush handle on mismatch */\n      if (session->DAA_session.DAA_stage != 4) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_STAGE;\n      }\n      /* Verify that DAA_tpmSpecific->DAA_digestIssuer == \n       * SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS \n       * on mismatch */\n      if (tpm_daa_verify_digestIssuer(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_ISSUER_SETTINGS;\n      }\n      /* Verify that DAA_session->DAA_digestContext == \n       * SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error \n       * TPM_DAA_TPM_SETTINGS on mismatch */\n      if (tpm_daa_verify_digestContext(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_TPM_SETTINGS;\n      }\n      /* Set DAA_generic_R0 = inputData0 */\n      DAA_generic_R0 = inputData0;\n      /* Verify that SHA-1(DAA_generic_R0) == \n       * DAA_issuerSettings->DAA_digest_R0 and return error \n       * TPM_DAA_INPUT_DATA0 on mismatch */\n      if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_R0, \n        DAA_generic_R0, inputSize0, &sha1)) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA0;\n      }\n      /* Set DAA_generic_n = inputData1 */\n      DAA_generic_n = inputData1;\n      /* Verify that SHA-1(DAA_generic_n) == DAA_issuerSettings->DAA_digest_n \n       * and return error TPM_DAA_INPUT_DATA1 on mismatch */\n      if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_n, \n        DAA_generic_n, inputSize1, &sha1)) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA1;\n      }\n      /* Set X = DAA_generic_R0 */\n      tpm_bn_init(X);\n      tpm_bn_import(X, inputSize0, 1, DAA_generic_R0);\n      /* Set n = DAA_generic_n */\n      tpm_bn_init(n);\n      tpm_bn_import(n, inputSize1, 1, DAA_generic_n);\n      /* Set f = SHA1(DAA_tpmSpecific->DAA_rekey || \n       * DAA_tpmSpecific->DAA_count || 0 ) || \n       * SHA1(DAA_tpmSpecific->DAA_rekey || DAA_tpmSpecific->DAA_count || \n       * 1 ) mod DAA_issuerSettings->DAA_generic_q */\n      tpm_sha1_init(&sha1);\n      tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_rekey, \n          sizeof(session->DAA_tpmSpecific.DAA_rekey));\n      tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count, \n          sizeof(session->DAA_tpmSpecific.DAA_count));\n      tpm_sha1_update(&sha1, DAA_LABEL_00, 1);\n      tpm_sha1_final(&sha1, scratch);\n      tpm_sha1_init(&sha1);\n      tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_rekey, \n          sizeof(session->DAA_tpmSpecific.DAA_rekey));\n      tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count, \n          sizeof(session->DAA_tpmSpecific.DAA_count));\n      tpm_sha1_update(&sha1, DAA_LABEL_01, 1);\n      tpm_sha1_final(&sha1, scratch + SHA1_DIGEST_LENGTH);\n      tpm_bn_init(f), tpm_bn_init(q);\n      tpm_bn_import(f, 2 * SHA1_DIGEST_LENGTH, 1, scratch);\n      tpm_bn_import(q, sizeof(session->DAA_issuerSettings.DAA_generic_q), \n        1, session->DAA_issuerSettings.DAA_generic_q);\n      tpm_bn_mod(f, f, q);\n      /* Set f0  = f mod 2^DAA_power0 (erase all but the lowest DAA_power0 \n       * bits of f) */\n      tpm_bn_init(f0), tpm_bn_init(tmp);\n      tpm_bn_ui_pow_ui(tmp, 2, DAA_power0);\n      tpm_bn_mod(f0, f, tmp);\n      /* Set DAA_session->DAA_scratch = (X^f0) mod n */\n      memset(session->DAA_session.DAA_scratch, 0, \n        sizeof(session->DAA_session.DAA_scratch));\n      tpm_bn_powm(tmp, X, f0, n);\n      tpm_bn_export(session->DAA_session.DAA_scratch, NULL, -1, tmp);\n      tpm_bn_clear(f), tpm_bn_clear(q), tpm_bn_clear(f0), tpm_bn_clear(tmp);\n      tpm_bn_clear(X), tpm_bn_clear(n);\n      /* Set outputData = NULL */\n      *outputSize = 0, *outputData = NULL;\n      /* Increment DAA_session->DAA_stage by 1 */\n      session->DAA_session.DAA_stage++;\n      /* Return TPM_SUCCESS */\n      return TPM_SUCCESS;\n    }\n    case 5:\n    {\n      /* Verify that DAA_session->DAA_stage == 5. Return TPM_DAA_STAGE \n       * and flush handle on mismatch */\n      if (session->DAA_session.DAA_stage != 5) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_STAGE;\n      }\n      /* Verify that DAA_tpmSpecific->DAA_digestIssuer == \n       * SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS \n       * on mismatch */\n      if (tpm_daa_verify_digestIssuer(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_ISSUER_SETTINGS;\n      }\n      /* Verify that DAA_session->DAA_digestContext == \n       * SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error \n       * TPM_DAA_TPM_SETTINGS on mismatch */\n      if (tpm_daa_verify_digestContext(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_TPM_SETTINGS;\n      }\n      /* Set DAA_generic_R1 = inputData0 */\n      DAA_generic_R1 = inputData0;\n      /* Verify that SHA-1(DAA_generic_R1) == \n       * DAA_issuerSettings->DAA_digest_R1 and return error \n       * TPM_DAA_INPUT_DATA0 on mismatch */\n      if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_R1, \n        DAA_generic_R1, inputSize0, &sha1)) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA0;\n      }\n      /* Set DAA_generic_n = inputData1 */\n      DAA_generic_n = inputData1;\n      /* Verify that SHA-1(DAA_generic_n) == DAA_issuerSettings->DAA_digest_n \n       * and return error TPM_DAA_INPUT_DATA1 on mismatch */\n      if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_n, \n        DAA_generic_n, inputSize1, &sha1)) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA1;\n      }\n      /* Set X = DAA_generic_R1 */\n      tpm_bn_init(X);\n      tpm_bn_import(X, inputSize0, 1, DAA_generic_R1);\n      /* Set n = DAA_generic_n */\n      tpm_bn_init(n);\n      tpm_bn_import(n, inputSize1, 1, DAA_generic_n);\n      /* Set f = SHA1(DAA_tpmSpecific->DAA_rekey || \n       * DAA_tpmSpecific->DAA_count || 0 ) || \n       * SHA1(DAA_tpmSpecific->DAA_rekey || DAA_tpmSpecific->DAA_count || \n       * 1 ) mod DAA_issuerSettings->DAA_generic_q */\n      tpm_sha1_init(&sha1);\n      tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_rekey, \n          sizeof(session->DAA_tpmSpecific.DAA_rekey));\n      tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count, \n          sizeof(session->DAA_tpmSpecific.DAA_count));\n      tpm_sha1_update(&sha1, DAA_LABEL_00, 1);\n      tpm_sha1_final(&sha1, scratch);\n      tpm_sha1_init(&sha1);\n      tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_rekey, \n          sizeof(session->DAA_tpmSpecific.DAA_rekey));\n      tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count, \n          sizeof(session->DAA_tpmSpecific.DAA_count));\n      tpm_sha1_update(&sha1, DAA_LABEL_01, 1);\n      tpm_sha1_final(&sha1, scratch + SHA1_DIGEST_LENGTH);\n      tpm_bn_init(f), tpm_bn_init(q);\n      tpm_bn_import(f, 2 * SHA1_DIGEST_LENGTH, 1, scratch);\n      tpm_bn_import(q, sizeof(session->DAA_issuerSettings.DAA_generic_q), \n        1, session->DAA_issuerSettings.DAA_generic_q);\n      tpm_bn_mod(f, f, q);\n      /* Shift f right by DAA_power0 bits (discard the lowest DAA_power0 \n       * bits) and label the result f1 */\n      tpm_bn_init(f1);\n      tpm_bn_fdiv_q_2exp(f1, f, DAA_power0);\n      /* Set Z = DAA_session->DAA_scratch */\n      tpm_bn_init(Z);\n      tpm_bn_import(Z, sizeof(session->DAA_session.DAA_scratch), -1, \n        session->DAA_session.DAA_scratch);\n      /* Set DAA_session->DAA_scratch = Z*(X^f1) mod n */\n      memset(session->DAA_session.DAA_scratch, 0, \n        sizeof(session->DAA_session.DAA_scratch));\n      tpm_bn_init(tmp);\n      tpm_bn_powm(tmp, X, f1, n);\n      tpm_bn_mul(tmp, tmp, Z);\n      tpm_bn_mod(tmp, tmp, n);\n      tpm_bn_export(session->DAA_session.DAA_scratch, NULL, -1, tmp);\n      tpm_bn_clear(f), tpm_bn_clear(q), tpm_bn_clear(f1), tpm_bn_clear(tmp);\n      tpm_bn_clear(X), tpm_bn_clear(n), tpm_bn_clear(Z);\n      /* Set outputData = NULL */\n      *outputSize = 0, *outputData = NULL;\n      /* Increment DAA_session->DAA_stage by 1 */\n      session->DAA_session.DAA_stage++;\n      /* Return TPM_SUCCESS */\n      return TPM_SUCCESS;\n    }\n    case 6:\n    {\n      /* Verify that DAA_session->DAA_stage == 6. Return TPM_DAA_STAGE \n       * and flush handle on mismatch */\n      if (session->DAA_session.DAA_stage != 6) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_STAGE;\n      }\n      /* Verify that DAA_tpmSpecific->DAA_digestIssuer == \n       * SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS \n       * on mismatch */\n      if (tpm_daa_verify_digestIssuer(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_ISSUER_SETTINGS;\n      }\n      /* Verify that DAA_session->DAA_digestContext == \n       * SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error \n       * TPM_DAA_TPM_SETTINGS on mismatch */\n      if (tpm_daa_verify_digestContext(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_TPM_SETTINGS;\n      }\n      /* Set DAA_generic_S0 = inputData0 */\n      DAA_generic_S0 = inputData0;\n      /* Verify that SHA-1(DAA_generic_S0) == \n       * DAA_issuerSettings->DAA_digest_S0 and return error \n       * TPM_DAA_INPUT_DATA0 on mismatch */\n      if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_S0, \n        DAA_generic_S0, inputSize0, &sha1)) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA0;\n      }\n      /* Set DAA_generic_n = inputData1 */\n      DAA_generic_n = inputData1;\n      /* Verify that SHA-1(DAA_generic_n) == DAA_issuerSettings->DAA_digest_n \n       * and return error TPM_DAA_INPUT_DATA1 on mismatch */\n      if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_n, \n        DAA_generic_n, inputSize1, &sha1)) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA1;\n      }\n      /* Set X = DAA_generic_S0 */\n      tpm_bn_init(X);\n      tpm_bn_import(X, inputSize0, 1, DAA_generic_S0);\n      /* Set n = DAA_generic_n */\n      tpm_bn_init(n);\n      tpm_bn_import(n, inputSize1, 1, DAA_generic_n);\n      /* Set Z = DAA_session->DAA_scratch */\n      tpm_bn_init(Z);\n      tpm_bn_import(Z, sizeof(session->DAA_session.DAA_scratch), -1, \n        session->DAA_session.DAA_scratch);\n      /* Set Y = DAA_joinSession->DAA_join_u0 */\n      tpm_bn_init(Y);\n      tpm_bn_import(Y, sizeof(session->DAA_joinSession.DAA_join_u0), 1, \n        session->DAA_joinSession.DAA_join_u0);\n      /* Set DAA_session->DAA_scratch = Z*(X^Y) mod n */\n      memset(session->DAA_session.DAA_scratch, 0, \n        sizeof(session->DAA_session.DAA_scratch));\n      tpm_bn_init(tmp);\n      tpm_bn_powm(tmp, X, Y, n);\n      tpm_bn_mul(tmp, tmp, Z);\n      tpm_bn_mod(tmp, tmp, n);\n      tpm_bn_export(session->DAA_session.DAA_scratch, NULL, -1, tmp);\n      tpm_bn_clear(X), tpm_bn_clear(Y), tpm_bn_clear(Z), tpm_bn_clear(n), tpm_bn_clear(tmp);\n      /* Set outputData = NULL */\n      *outputSize = 0, *outputData = NULL;\n      /* Increment DAA_session->DAA_stage by 1 */\n      session->DAA_session.DAA_stage++;\n      /* Return TPM_SUCCESS */\n      return TPM_SUCCESS;\n    }\n    case 7:\n    {\n      /* Verify that DAA_session->DAA_stage == 7. Return TPM_DAA_STAGE \n       * and flush handle on mismatch */\n      if (session->DAA_session.DAA_stage != 7) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_STAGE;\n      }\n      /* Verify that DAA_tpmSpecific->DAA_digestIssuer == \n       * SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS \n       * on mismatch */\n      if (tpm_daa_verify_digestIssuer(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_ISSUER_SETTINGS;\n      }\n      /* Verify that DAA_session->DAA_digestContext == \n       * SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error \n       * TPM_DAA_TPM_SETTINGS on mismatch */\n      if (tpm_daa_verify_digestContext(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_TPM_SETTINGS;\n      }\n      /* Set DAA_generic_S1 = inputData0 */\n      DAA_generic_S1 = inputData0;\n      /* Verify that SHA-1(DAA_generic_S1) == \n       * DAA_issuerSettings->DAA_digest_S1 and return error \n       * TPM_DAA_INPUT_DATA0 on mismatch */\n      if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_S1, \n        DAA_generic_S1, inputSize0, &sha1)) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA0;\n      }\n      /* Set DAA_generic_n = inputData1 */\n      DAA_generic_n = inputData1;\n      /* Verify that SHA-1(DAA_generic_n) == DAA_issuerSettings->DAA_digest_n \n       * and return error TPM_DAA_INPUT_DATA1 on mismatch */\n      if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_n, \n        DAA_generic_n, inputSize1, &sha1)) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA1;\n      }\n      /* Set X = DAA_generic_S1 */\n      tpm_bn_init(X);\n      tpm_bn_import(X, inputSize0, 1, DAA_generic_S1);\n      /* Set n = DAA_generic_n */\n      tpm_bn_init(n);\n      tpm_bn_import(n, inputSize1, 1, DAA_generic_n);\n      /* Set Y = DAA_joinSession->DAA_join_u1 */\n      tpm_bn_init(Y);\n      tpm_bn_import(Y, sizeof(session->DAA_joinSession.DAA_join_u1), 1, \n        session->DAA_joinSession.DAA_join_u1);\n      /* Set Z = DAA_session->DAA_scratch */\n      tpm_bn_init(Z);\n      tpm_bn_import(Z, sizeof(session->DAA_session.DAA_scratch), -1, \n        session->DAA_session.DAA_scratch);\n      /* Set DAA_session->DAA_scratch = Z*(X^Y) mod n */\n      memset(session->DAA_session.DAA_scratch, 0, \n        sizeof(session->DAA_session.DAA_scratch));\n      tpm_bn_init(tmp);\n      tpm_bn_powm(tmp, X, Y, n);\n      tpm_bn_mul(tmp, tmp, Z);\n      tpm_bn_mod(tmp, tmp, n);\n      tpm_bn_export(session->DAA_session.DAA_scratch, &size, 1, tmp);\n      memset(session->DAA_session.DAA_scratch, 0, \n        sizeof(session->DAA_session.DAA_scratch));\n      tpm_bn_export(session->DAA_session.DAA_scratch + \n        (sizeof(session->DAA_session.DAA_scratch) - size),\n        &size, 1, tmp);\n      tpm_bn_clear(X), tpm_bn_clear(Y), tpm_bn_clear(Z), tpm_bn_clear(n), tpm_bn_clear(tmp);\n      /* Set DAA_session->DAA_digest to the SHA-1(DAA_session->DAA_scratch || \n       * DAA_tpmSpecific->DAA_count || DAA_joinSession->DAA_digest_n0) */\n      tpm_sha1_init(&sha1);\n      tpm_sha1_update(&sha1, session->DAA_session.DAA_scratch, \n        sizeof(session->DAA_session.DAA_scratch));\n      ptr = scratch, len = sizeof(scratch);\n      if (tpm_marshal_UINT32(&ptr, &len, session->DAA_tpmSpecific.DAA_count)) {\n        debug(\"TPM_DAA_Join(): tpm_marshal_UINT32() failed.\");\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_FAIL;\n      }\n      tpm_sha1_update(&sha1, scratch, sizeof(UINT32));\n      tpm_sha1_update(&sha1, session->DAA_joinSession.DAA_digest_n0.digest, \n        sizeof(session->DAA_joinSession.DAA_digest_n0.digest));\n      tpm_sha1_final(&sha1, session->DAA_session.DAA_digest.digest);\n      /* Set outputData = DAA_session->DAA_scratch */\n      *outputSize = sizeof(session->DAA_session.DAA_scratch);\n      if ((*outputData = tpm_malloc(*outputSize)) != NULL) {\n        memcpy(*outputData, session->DAA_session.DAA_scratch, *outputSize);\n      } else {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_NOSPACE;\n      }\n      /* Set DAA_session->DAA_scratch = NULL */\n      memset(session->DAA_session.DAA_scratch, 0, \n        sizeof(session->DAA_session.DAA_scratch));\n      /* Increment DAA_session->DAA_stage by 1 */\n      session->DAA_session.DAA_stage++;\n      /* Return TPM_SUCCESS */\n      return TPM_SUCCESS;\n    }\n    case 8:\n    {\n      /* Verify that DAA_session->DAA_stage == 8. Return TPM_DAA_STAGE \n       * and flush handle on mismatch */\n      if (session->DAA_session.DAA_stage != 8) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_STAGE;\n      }\n      /* Verify that DAA_tpmSpecific->DAA_digestIssuer == \n       * SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS \n       * on mismatch */\n      if (tpm_daa_verify_digestIssuer(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_ISSUER_SETTINGS;\n      }\n      /* Verify that DAA_session->DAA_digestContext == \n       * SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error \n       * TPM_DAA_TPM_SETTINGS on mismatch */\n      if (tpm_daa_verify_digestContext(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_TPM_SETTINGS;\n      }\n      /* Verify inputSize0 == DAA_SIZE_NE and return error \n       * TPM_DAA_INPUT_DATA0 on mismatch */\n      if (inputSize0 != DAA_SIZE_NE) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_INPUT_DATA0;\n      }\n      /* Set NE = decrypt(inputData0, privEK) */\n      memset(scratch, 0, sizeof(scratch));\n      if (tpm_rsa_decrypt(&tpmData.permanent.data.endorsementKey, \n        RSA_ES_OAEP_SHA1, inputData0, inputSize0, scratch, &size)) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DECRYPT_ERROR;\n      }\n      /* Set outputData = SHA-1(DAA_session->DAA_digest || NE) */\n      *outputSize = SHA1_DIGEST_LENGTH;\n      if ((*outputData = tpm_malloc(*outputSize)) == NULL) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_NOSPACE;\n      }\n      tpm_sha1_init(&sha1);\n      tpm_sha1_update(&sha1, session->DAA_session.DAA_digest.digest, \n        sizeof(session->DAA_session.DAA_digest.digest));\n      tpm_sha1_update(&sha1, scratch, size);\n      tpm_sha1_final(&sha1, *outputData);\n      /* Set DAA_session->DAA_digest = NULL */\n      memset(&session->DAA_session.DAA_digest, 0, \n        sizeof(session->DAA_session.DAA_digest));\n      /* Increment DAA_session->DAA_stage by 1 */\n      session->DAA_session.DAA_stage++;\n      /* Return TPM_SUCCESS */\n      return TPM_SUCCESS;\n    }\n    case 9:\n    {\n      /* Verify that DAA_session->DAA_stage == 9. Return TPM_DAA_STAGE \n       * and flush handle on mismatch */\n      if (session->DAA_session.DAA_stage != 9) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_STAGE;\n      }\n      /* Verify that DAA_tpmSpecific->DAA_digestIssuer == \n       * SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS \n       * on mismatch */\n      if (tpm_daa_verify_digestIssuer(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_ISSUER_SETTINGS;\n      }\n      /* Verify that DAA_session->DAA_digestContext == \n       * SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error \n       * TPM_DAA_TPM_SETTINGS on mismatch */\n      if (tpm_daa_verify_digestContext(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_TPM_SETTINGS;\n      }\n      /* Set DAA_generic_R0 = inputData0 */\n      DAA_generic_R0 = inputData0;\n      /* Verify that SHA-1(DAA_generic_R0) == \n       * DAA_issuerSettings->DAA_digest_R0 and return error \n       * TPM_DAA_INPUT_DATA0 on mismatch */\n      if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_R0, \n        DAA_generic_R0, inputSize0, &sha1)) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA0;\n      }\n      /* Set DAA_generic_n = inputData1 */\n      DAA_generic_n = inputData1;\n      /* Verify that SHA-1(DAA_generic_n) == DAA_issuerSettings->DAA_digest_n \n       * and return error TPM_DAA_INPUT_DATA1 on mismatch */\n      if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_n, \n        DAA_generic_n, inputSize1, &sha1)) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA1;\n      }\n      /* Obtain random data from the RNG and store it as \n       * DAA_session->DAA_contextSeed */\n      tpm_get_random_bytes(session->DAA_session.DAA_contextSeed.nonce, \n        sizeof(TPM_NONCE));\n      /* Obtain DAA_SIZE_r0 bits from MGF1(\"r0\", \n       * DAA_session->DAA_contextSeed), and label them Y */\n      memset(scratch, 0, sizeof(scratch));\n      memcpy(mgf1_seed, \"r0\", 2);\n      memcpy(mgf1_seed + 2, session->DAA_session.DAA_contextSeed.nonce, \n        sizeof(TPM_NONCE));\n      tpm_rsa_mask_generation(mgf1_seed, sizeof(mgf1_seed), scratch, DAA_SIZE_r0);\n      tpm_bn_init(Y);\n      tpm_bn_import(Y, DAA_SIZE_r0, 1, scratch);\n      /* Set X = DAA_generic_R0 */\n      tpm_bn_init(X);\n      tpm_bn_import(X, inputSize0, 1, DAA_generic_R0);\n      /* Set n = DAA_generic_n */\n      tpm_bn_init(n);\n      tpm_bn_import(n, inputSize1, 1, DAA_generic_n);\n      /* Set DAA_session->DAA_scratch = (X^Y) mod n */\n      memset(session->DAA_session.DAA_scratch, 0, \n        sizeof(session->DAA_session.DAA_scratch));\n      tpm_bn_init(tmp);\n      tpm_bn_powm(tmp, X, Y, n);\n      tpm_bn_export(session->DAA_session.DAA_scratch, NULL, -1, tmp);\n      tpm_bn_clear(X), tpm_bn_clear(Y), tpm_bn_clear(n), tpm_bn_clear(tmp);\n      /* Set outputData = NULL */\n      *outputSize = 0, *outputData = NULL;\n      /* Increment DAA_session->DAA_stage by 1 */\n      session->DAA_session.DAA_stage++;\n      /* Return TPM_SUCCESS */\n      return TPM_SUCCESS;\n    }\n    case 10:\n    {\n      /* Verify that DAA_session->DAA_stage == 10. Return TPM_DAA_STAGE \n       * and flush handle on mismatch */\n      if (session->DAA_session.DAA_stage != 10) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_STAGE;\n      }\n      /* Verify that DAA_tpmSpecific->DAA_digestIssuer == \n       * SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS \n       * on mismatch */\n      if (tpm_daa_verify_digestIssuer(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_ISSUER_SETTINGS;\n      }\n      /* Verify that DAA_session->DAA_digestContext == \n       * SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error \n       * TPM_DAA_TPM_SETTINGS on mismatch */\n      if (tpm_daa_verify_digestContext(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_TPM_SETTINGS;\n      }\n      /* Set DAA_generic_R1 = inputData0 */\n      DAA_generic_R1 = inputData0;\n      /* Verify that SHA-1(DAA_generic_R1) == \n       * DAA_issuerSettings->DAA_digest_R1 and return error \n       * TPM_DAA_INPUT_DATA0 on mismatch */\n      if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_R1, \n        DAA_generic_R1, inputSize0, &sha1)) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA0;\n      }\n      /* Set DAA_generic_n = inputData1 */\n      DAA_generic_n = inputData1;\n      /* Verify that SHA-1(DAA_generic_n) == DAA_issuerSettings->DAA_digest_n \n       * and return error TPM_DAA_INPUT_DATA1 on mismatch */\n      if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_n, \n        DAA_generic_n, inputSize1, &sha1)) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA1;\n      }\n      /* Obtain DAA_SIZE_r1 bits from MGF1(\"r1\", \n       * DAA_session->DAA_contextSeed), and label them Y */\n      memset(scratch, 0, sizeof(scratch));\n      memcpy(mgf1_seed, \"r1\", 2);\n      memcpy(mgf1_seed + 2, session->DAA_session.DAA_contextSeed.nonce, \n        sizeof(TPM_NONCE));\n      tpm_rsa_mask_generation(mgf1_seed, sizeof(mgf1_seed), scratch, DAA_SIZE_r1);\n      tpm_bn_init(Y);\n      tpm_bn_import(Y, DAA_SIZE_r1, 1, scratch);\n      /* Set X = DAA_generic_R1 */\n      tpm_bn_init(X);\n      tpm_bn_import(X, inputSize0, 1, DAA_generic_R1);\n      /* Set n = DAA_generic_n */\n      tpm_bn_init(n);\n      tpm_bn_import(n, inputSize1, 1, DAA_generic_n);\n      /* Set Z = DAA_session->DAA_scratch */\n      tpm_bn_init(Z);\n      tpm_bn_import(Z, sizeof(session->DAA_session.DAA_scratch), -1, \n        session->DAA_session.DAA_scratch);\n      /* Set DAA_session->DAA_scratch = Z*(X^Y) mod n */\n      memset(session->DAA_session.DAA_scratch, 0, \n        sizeof(session->DAA_session.DAA_scratch));\n      tpm_bn_init(tmp);\n      tpm_bn_powm(tmp, X, Y, n);\n      tpm_bn_mul(tmp, tmp, Z);\n      tpm_bn_mod(tmp, tmp, n);\n      tpm_bn_export(session->DAA_session.DAA_scratch, NULL, -1, tmp);\n      tpm_bn_clear(X), tpm_bn_clear(Y), tpm_bn_clear(Z), tpm_bn_clear(n), tpm_bn_clear(tmp);\n      /* Set outputData = NULL */\n      *outputSize = 0, *outputData = NULL;\n      /* Increment DAA_session->DAA_stage by 1 */\n      session->DAA_session.DAA_stage++;\n      /* Return TPM_SUCCESS */\n      return TPM_SUCCESS;\n    }\n    case 11:\n    {\n      /* Verify that DAA_session->DAA_stage == 11. Return TPM_DAA_STAGE \n       * and flush handle on mismatch */\n      if (session->DAA_session.DAA_stage != 11) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_STAGE;\n      }\n      /* Verify that DAA_tpmSpecific->DAA_digestIssuer == \n       * SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS \n       * on mismatch */\n      if (tpm_daa_verify_digestIssuer(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_ISSUER_SETTINGS;\n      }\n      /* Verify that DAA_session->DAA_digestContext == \n       * SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error \n       * TPM_DAA_TPM_SETTINGS on mismatch */\n      if (tpm_daa_verify_digestContext(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_TPM_SETTINGS;\n      }\n      /* Set DAA_generic_S0 = inputData0 */\n      DAA_generic_S0 = inputData0;\n      /* Verify that SHA-1(DAA_generic_S0) == \n       * DAA_issuerSettings->DAA_digest_S0 and return error \n       * TPM_DAA_INPUT_DATA0 on mismatch */\n      if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_S0, \n        DAA_generic_S0, inputSize0, &sha1)) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA0;\n      }\n      /* Set DAA_generic_n = inputData1 */\n      DAA_generic_n = inputData1;\n      /* Verify that SHA-1(DAA_generic_n) == DAA_issuerSettings->DAA_digest_n \n       * and return error TPM_DAA_INPUT_DATA1 on mismatch */\n      if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_n, \n        DAA_generic_n, inputSize1, &sha1)) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA1;\n      }\n      /* Obtain DAA_SIZE_r2 bits from MGF1(\"r2\", \n       * DAA_session->DAA_contextSeed), and label them Y */\n      memset(scratch, 0, sizeof(scratch));\n      memcpy(mgf1_seed, \"r2\", 2);\n      memcpy(mgf1_seed + 2, session->DAA_session.DAA_contextSeed.nonce, \n        sizeof(TPM_NONCE));\n      tpm_rsa_mask_generation(mgf1_seed, sizeof(mgf1_seed), scratch, DAA_SIZE_r2);\n      tpm_bn_init(Y);\n      tpm_bn_import(Y, DAA_SIZE_r2, 1, scratch);\n      /* Set X = DAA_generic_S0 */\n      tpm_bn_init(X);\n      tpm_bn_import(X, inputSize0, 1, DAA_generic_S0);\n      /* Set n = DAA_generic_n */\n      tpm_bn_init(n);\n      tpm_bn_import(n, inputSize1, 1, DAA_generic_n);\n      /* Set Z = DAA_session->DAA_scratch */\n      tpm_bn_init(Z);\n      tpm_bn_import(Z, sizeof(session->DAA_session.DAA_scratch), -1, \n        session->DAA_session.DAA_scratch);\n      /* Set DAA_session->DAA_scratch = Z*(X^Y) mod n */\n      memset(session->DAA_session.DAA_scratch, 0, \n        sizeof(session->DAA_session.DAA_scratch));\n      tpm_bn_init(tmp);\n      tpm_bn_powm(tmp, X, Y, n);\n      tpm_bn_mul(tmp, tmp, Z);\n      tpm_bn_mod(tmp, tmp, n);\n      tpm_bn_export(session->DAA_session.DAA_scratch, NULL, -1, tmp);\n      tpm_bn_clear(X), tpm_bn_clear(Y), tpm_bn_clear(Z), tpm_bn_clear(n), tpm_bn_clear(tmp);\n      /* Set outputData = NULL */\n      *outputSize = 0, *outputData = NULL;\n      /* Increment DAA_session->DAA_stage by 1 */\n      session->DAA_session.DAA_stage++;\n      /* Return TPM_SUCCESS */\n      return TPM_SUCCESS;\n    }\n    case 12:\n    {\n      /* Verify that DAA_session->DAA_stage == 12. Return TPM_DAA_STAGE \n       * and flush handle on mismatch */\n      if (session->DAA_session.DAA_stage != 12) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_STAGE;\n      }\n      /* Verify that DAA_tpmSpecific->DAA_digestIssuer == \n       * SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS \n       * on mismatch */\n      if (tpm_daa_verify_digestIssuer(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_ISSUER_SETTINGS;\n      }\n      /* Verify that DAA_session->DAA_digestContext == \n       * SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error \n       * TPM_DAA_TPM_SETTINGS on mismatch */\n      if (tpm_daa_verify_digestContext(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_TPM_SETTINGS;\n      }\n      /* Set DAA_generic_S1 = inputData0 */\n      DAA_generic_S1 = inputData0;\n      /* Verify that SHA-1(DAA_generic_S1) == \n       * DAA_issuerSettings->DAA_digest_S1 and return error \n       * TPM_DAA_INPUT_DATA0 on mismatch */\n      if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_S1, \n        DAA_generic_S1, inputSize0, &sha1)) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA0;\n      }\n      /* Set DAA_generic_n = inputData1 */\n      DAA_generic_n = inputData1;\n      /* Verify that SHA-1(DAA_generic_n) == DAA_issuerSettings->DAA_digest_n \n       * and return error TPM_DAA_INPUT_DATA1 on mismatch */\n      if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_n, \n        DAA_generic_n, inputSize1, &sha1)) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA1;\n      }\n      /* Obtain DAA_SIZE_r3 bits from MGF1(\"r3\", \n       * DAA_session->DAA_contextSeed), and label them Y */\n      memset(scratch, 0, sizeof(scratch));\n      memcpy(mgf1_seed, \"r3\", 2);\n      memcpy(mgf1_seed + 2, session->DAA_session.DAA_contextSeed.nonce, \n        sizeof(TPM_NONCE));\n      tpm_rsa_mask_generation(mgf1_seed, sizeof(mgf1_seed), scratch, DAA_SIZE_r3);\n      tpm_bn_init(Y);\n      tpm_bn_import(Y, DAA_SIZE_r3, 1, scratch);\n      /* Set X = DAA_generic_S1 */\n      tpm_bn_init(X);\n      tpm_bn_import(X, inputSize0, 1, DAA_generic_S1);\n      /* Set n = DAA_generic_n */\n      tpm_bn_init(n);\n      tpm_bn_import(n, inputSize1, 1, DAA_generic_n);\n      /* Set Z = DAA_session->DAA_scratch */\n      tpm_bn_init(Z);\n      tpm_bn_import(Z, sizeof(session->DAA_session.DAA_scratch), -1, \n        session->DAA_session.DAA_scratch);\n      /* Set DAA_session->DAA_scratch = Z*(X^Y) mod n */\n      memset(session->DAA_session.DAA_scratch, 0, \n        sizeof(session->DAA_session.DAA_scratch));\n      tpm_bn_init(tmp);\n      tpm_bn_powm(tmp, X, Y, n);\n      tpm_bn_mul(tmp, tmp, Z);\n      tpm_bn_mod(tmp, tmp, n);\n      tpm_bn_export(session->DAA_session.DAA_scratch, &size, 1, tmp);\n      *outputSize = (uint32_t)size;\n      tpm_bn_clear(X), tpm_bn_clear(Y), tpm_bn_clear(Z), tpm_bn_clear(n), tpm_bn_clear(tmp);\n      /* Set outputData = DAA_session->DAA_scratch */\n      if ((*outputData = tpm_malloc(*outputSize)) != NULL)\n        memcpy(*outputData, session->DAA_session.DAA_scratch, *outputSize);\n      else {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_NOSPACE;\n      }\n      /* Set DAA_session->DAA_scratch = NULL */\n      memset(session->DAA_session.DAA_scratch, 0, \n        sizeof(session->DAA_session.DAA_scratch));\n      /* Increment DAA_session->DAA_stage by 1 */\n      session->DAA_session.DAA_stage++;\n      /* Return TPM_SUCCESS */\n      return TPM_SUCCESS;\n    }\n    case 13:\n    {\n      /* Verify that DAA_session->DAA_stage == 13. Return TPM_DAA_STAGE \n       * and flush handle on mismatch */\n      if (session->DAA_session.DAA_stage != 13) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_STAGE;\n      }\n      /* Verify that DAA_tpmSpecific->DAA_digestIssuer == \n       * SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS \n       * on mismatch */\n      if (tpm_daa_verify_digestIssuer(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_ISSUER_SETTINGS;\n      }\n      /* Verify that DAA_session->DAA_digestContext == \n       * SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error \n       * TPM_DAA_TPM_SETTINGS on mismatch */\n      if (tpm_daa_verify_digestContext(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_TPM_SETTINGS;\n      }\n      /* Set DAA_generic_gamma = inputData0 */\n      DAA_generic_gamma = inputData0;\n      /* Verify that SHA-1(DAA_generic_gamma) == \n       * DAA_issuerSettings->DAA_digest_gamma and return error \n       * TPM_DAA_INPUT_DATA0 on mismatch */\n      if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_gamma, \n        DAA_generic_gamma, inputSize0, &sha1)) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA0;\n      }\n      /* Verify that inputSize1 == DAA_SIZE_w and return error \n       * TPM_DAA_INPUT_DATA1 on mismatch */\n      if (inputSize1 != DAA_SIZE_w) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_INPUT_DATA1;\n      }\n      /* Set w = inputData1 */\n      tpm_bn_init(w);\n      tpm_bn_import(w, inputSize1, 1, inputData1);\n      /* Set w1 = w^(DAA_issuerSettings->DAA_generic_q) mod \n       * (DAA_generic_gamma) */\n      tpm_bn_init(gamma);\n      tpm_bn_import(gamma, inputSize0, 1, DAA_generic_gamma);\n      tpm_bn_init(q);\n      tpm_bn_import(q, sizeof(session->DAA_issuerSettings.DAA_generic_q), \n        1, session->DAA_issuerSettings.DAA_generic_q);\n      tpm_bn_init(w1);\n      tpm_bn_powm(w1, w, q, gamma);\n      /* If w1 != 1 (unity), return error TPM_DAA_WRONG_W */\n      if (tpm_bn_cmp_ui(w1, 1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_WRONG_W;\n      }\n      /* Set DAA_session->DAA_scratch = w */\n      memset(session->DAA_session.DAA_scratch, 0, \n        sizeof(session->DAA_session.DAA_scratch));\n      tpm_bn_export(session->DAA_session.DAA_scratch, NULL, -1, w);\n      tpm_bn_clear(w), tpm_bn_clear(gamma), tpm_bn_clear(w1), tpm_bn_clear(q);\n      /* Set outputData = NULL */\n      *outputSize = 0, *outputData = NULL;\n      /* Increment DAA_session->DAA_stage by 1 */\n      session->DAA_session.DAA_stage++;\n      /* Return TPM_SUCCESS */\n      return TPM_SUCCESS;\n    }\n    case 14:\n    {\n      /* Verify that DAA_session->DAA_stage == 14. Return TPM_DAA_STAGE \n       * and flush handle on mismatch */\n      if (session->DAA_session.DAA_stage != 14) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_STAGE;\n      }\n      /* Verify that DAA_tpmSpecific->DAA_digestIssuer == \n       * SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS \n       * on mismatch */\n      if (tpm_daa_verify_digestIssuer(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_ISSUER_SETTINGS;\n      }\n      /* Verify that DAA_session->DAA_digestContext == \n       * SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error \n       * TPM_DAA_TPM_SETTINGS on mismatch */\n      if (tpm_daa_verify_digestContext(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_TPM_SETTINGS;\n      }\n      /* Set DAA_generic_gamma = inputData0 */\n      DAA_generic_gamma = inputData0;\n      /* Verify that SHA-1(DAA_generic_gamma) == \n       * DAA_issuerSettings->DAA_digest_gamma and return error \n       * TPM_DAA_INPUT_DATA0 on mismatch */\n      if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_gamma, \n        DAA_generic_gamma, inputSize0, &sha1)) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA0;\n      }\n      /* Set f = SHA-1(DAA_tpmSpecific->DAA_rekey || \n       * DAA_tpmSpecific->DAA_count || 0) || SHA-1(DAA_tpmSpecific->DAA_rekey \n       * || DAA_tpmSpecific->DAA_count || 1) mod \n       * DAA_issuerSettings->DAA_generic_q. */\n      tpm_sha1_init(&sha1);\n      tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_rekey, \n          sizeof(session->DAA_tpmSpecific.DAA_rekey));\n      tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count, \n          sizeof(session->DAA_tpmSpecific.DAA_count));\n      tpm_sha1_update(&sha1, DAA_LABEL_00, 1);\n      tpm_sha1_final(&sha1, scratch);\n      tpm_sha1_init(&sha1);\n      tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_rekey, \n          sizeof(session->DAA_tpmSpecific.DAA_rekey));\n      tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count, \n          sizeof(session->DAA_tpmSpecific.DAA_count));\n      tpm_sha1_update(&sha1, DAA_LABEL_01, 1);\n      tpm_sha1_final(&sha1, scratch + SHA1_DIGEST_LENGTH);\n      tpm_bn_init(f), tpm_bn_init(q);\n      tpm_bn_import(f, 2 * SHA1_DIGEST_LENGTH, 1, scratch);\n      tpm_bn_import(q, sizeof(session->DAA_issuerSettings.DAA_generic_q), \n        1, session->DAA_issuerSettings.DAA_generic_q);\n      tpm_bn_mod(f, f, q);\n      /* Set E = ((DAA_session->DAA_scratch)^f) mod (DAA_generic_gamma).*/\n      tpm_bn_init(gamma);\n      tpm_bn_import(gamma, inputSize0, 1, DAA_generic_gamma);\n      tpm_bn_init(w);\n      tpm_bn_import(w, sizeof(session->DAA_session.DAA_scratch), -1, \n        session->DAA_session.DAA_scratch);\n      tpm_bn_init(E);\n      tpm_bn_powm(E, w, f, gamma);\n      /* Set outputData = E */\n      tpm_bn_export(scratch, &size, 1, E);\n      *outputSize = (uint32_t)size;\n      tpm_bn_clear(f), tpm_bn_clear(q), tpm_bn_clear(gamma), tpm_bn_clear(w), tpm_bn_clear(E);\n      if ((*outputData = tpm_malloc(*outputSize)) != NULL)\n        memcpy(*outputData, scratch, *outputSize);\n      else {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_NOSPACE;\n      }\n      /* Increment DAA_session->DAA_stage by 1 */\n      session->DAA_session.DAA_stage++;\n      /* Return TPM_SUCCESS */\n      return TPM_SUCCESS;\n    }\n    case 15:\n    {\n      /* Verify that DAA_session->DAA_stage == 15. Return TPM_DAA_STAGE \n       * and flush handle on mismatch */\n      if (session->DAA_session.DAA_stage != 15) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_STAGE;\n      }\n      /* Verify that DAA_tpmSpecific->DAA_digestIssuer == \n       * SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS \n       * on mismatch */\n      if (tpm_daa_verify_digestIssuer(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_ISSUER_SETTINGS;\n      }\n      /* Verify that DAA_session->DAA_digestContext == \n       * SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error \n       * TPM_DAA_TPM_SETTINGS on mismatch */\n      if (tpm_daa_verify_digestContext(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_TPM_SETTINGS;\n      }\n      /* Set DAA_generic_gamma = inputData0 */\n      DAA_generic_gamma = inputData0;\n      /* Verify that SHA-1(DAA_generic_gamma) == \n       * DAA_issuerSettings->DAA_digest_gamma and return error \n       * TPM_DAA_INPUT_DATA0 on mismatch */\n      if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_gamma, \n        DAA_generic_gamma, inputSize0, &sha1)) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA0;\n      }\n      /* Obtain DAA_SIZE_r0 bits from MGF1(\"r0\", \n       * DAA_session->DAA_contextSeed), and label them r0 */\n      memset(scratch, 0, sizeof(scratch));\n      memcpy(mgf1_seed, \"r0\", 2);\n      memcpy(mgf1_seed + 2, session->DAA_session.DAA_contextSeed.nonce, \n        sizeof(TPM_NONCE));\n      tpm_rsa_mask_generation(mgf1_seed, sizeof(mgf1_seed), scratch, DAA_SIZE_r0);\n      tpm_bn_init(r0);\n      tpm_bn_import(r0, DAA_SIZE_r0, 1, scratch);\n      /* Obtain DAA_SIZE_r1 bits from MGF1(\"r1\", \n       * DAA_session->DAA_contextSeed), and label them r1 */\n      memset(scratch, 0, sizeof(scratch));\n      memcpy(mgf1_seed, \"r1\", 2);\n      memcpy(mgf1_seed + 2, session->DAA_session.DAA_contextSeed.nonce, \n        sizeof(TPM_NONCE));\n      tpm_rsa_mask_generation(mgf1_seed, sizeof(mgf1_seed), scratch, DAA_SIZE_r1);\n      tpm_bn_init(r1);\n      tpm_bn_import(r1, DAA_SIZE_r1, 1, scratch);\n      /* Set r = r0 + 2^DAA_power0 * r1 mod \n       * (DAA_issuerSettings->DAA_generic_q). */\n      tpm_bn_init(q);\n      tpm_bn_import(q, sizeof(session->DAA_issuerSettings.DAA_generic_q), \n        1, session->DAA_issuerSettings.DAA_generic_q);\n      tpm_bn_init(r);\n      tpm_bn_ui_pow_ui(r, 2, DAA_power0);\n      tpm_bn_mul(r, r, r1);\n      tpm_bn_mod(r, r, q);\n      tpm_bn_add(r, r, r0);\n      tpm_bn_mod(r, r, q);\n      /* Set E1 = ((DAA_session->DAA_scratch)^r) mod (DAA_generic_gamma). */\n      tpm_bn_init(gamma);\n      tpm_bn_import(gamma, inputSize0, 1, DAA_generic_gamma);\n      tpm_bn_init(w);\n      tpm_bn_import(w, sizeof(session->DAA_session.DAA_scratch), -1, \n        session->DAA_session.DAA_scratch);\n      tpm_bn_init(E1);\n      tpm_bn_powm(E1, w, r, gamma);\n      /* Set DAA_session->DAA_scratch = NULL */\n      memset(session->DAA_session.DAA_scratch, 0, \n        sizeof(session->DAA_session.DAA_scratch));\n      /* Set outputData = E1 */\n      tpm_bn_export(scratch, &size, 1, E1);\n      *outputSize = (uint32_t)size;\n      tpm_bn_clear(r0), tpm_bn_clear(r1), tpm_bn_clear(q), tpm_bn_clear(r);\n      tpm_bn_clear(gamma), tpm_bn_clear(w), tpm_bn_clear(E1);\n      if ((*outputData = tpm_malloc(*outputSize)) != NULL)\n        memcpy(*outputData, scratch, *outputSize);\n      else {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_NOSPACE;\n      }\n      /* Increment DAA_session->DAA_stage by 1 */\n      session->DAA_session.DAA_stage++;\n      /* Return TPM_SUCCESS */\n      return TPM_SUCCESS;\n    }\n    case 16:\n    {\n      BYTE *NT = NULL;\n      \n      /* Verify that DAA_session->DAA_stage == 16. Return TPM_DAA_STAGE \n       * and flush handle on mismatch */\n      if (session->DAA_session.DAA_stage != 16) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_STAGE;\n      }\n      /* Verify that DAA_tpmSpecific->DAA_digestIssuer == \n       * SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS \n       * on mismatch */\n      if (tpm_daa_verify_digestIssuer(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_ISSUER_SETTINGS;\n      }\n      /* Verify that DAA_session->DAA_digestContext == \n       * SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error \n       * TPM_DAA_TPM_SETTINGS on mismatch */\n      if (tpm_daa_verify_digestContext(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_TPM_SETTINGS;\n      }\n      /* Verify that inputSize0 == sizeOf(TPM_DIGEST) and return error \n       * TPM_DAA_INPUT_DATA0 on mismatch */\n      if (inputSize0 != sizeof(TPM_DIGEST)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_INPUT_DATA0;\n      }\n      /* Set DAA_session->DAA_digest = inputData0 */\n      memcpy(session->DAA_session.DAA_digest.digest, inputData0, inputSize0);\n      /* Obtain DAA_SIZE_NT bits from the RNG and label them NT */\n      if ((NT = tpm_malloc(DAA_SIZE_NT)) == NULL) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_NOSPACE;\n      }\n      tpm_get_random_bytes(NT, DAA_SIZE_NT);\n      /* Set DAA_session->DAA_digest to the SHA-1(DAA_session->DAA_digest || \n       * NT)*/\n      tpm_sha1_init(&sha1);\n      tpm_sha1_update(&sha1, (BYTE*) session->DAA_session.DAA_digest.digest, \n          sizeof(session->DAA_session.DAA_digest.digest));\n      tpm_sha1_update(&sha1, NT, DAA_SIZE_NT);\n      tpm_sha1_final(&sha1, session->DAA_session.DAA_digest.digest);\n      /* Set outputData = NT */\n      *outputSize = DAA_SIZE_NT;\n      if ((*outputData = tpm_malloc(*outputSize)) != NULL)\n        memcpy(*outputData, NT, *outputSize);\n      else {\n        tpm_free(NT);\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_NOSPACE;\n      }\n      tpm_free(NT);\n      /* Increment DAA_session->DAA_stage by 1 */\n      session->DAA_session.DAA_stage++;\n      /* Return TPM_SUCCESS */\n      return TPM_SUCCESS;\n    }\n    case 17:\n    {\n      /* Verify that DAA_session->DAA_stage == 17. Return TPM_DAA_STAGE \n       * and flush handle on mismatch */\n      if (session->DAA_session.DAA_stage != 17) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_STAGE;\n      }\n      /* Verify that DAA_tpmSpecific->DAA_digestIssuer == \n       * SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS \n       * on mismatch */\n      if (tpm_daa_verify_digestIssuer(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_ISSUER_SETTINGS;\n      }\n      /* Verify that DAA_session->DAA_digestContext == \n       * SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error \n       * TPM_DAA_TPM_SETTINGS on mismatch */\n      if (tpm_daa_verify_digestContext(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_TPM_SETTINGS;\n      }\n      /* Obtain DAA_SIZE_r0 bits from MGF1(\"r0\", \n       * DAA_session->DAA_contextSeed), and label them r0 */\n      memset(scratch, 0, sizeof(scratch));\n      memcpy(mgf1_seed, \"r0\", 2);\n      memcpy(mgf1_seed + 2, session->DAA_session.DAA_contextSeed.nonce, \n        sizeof(TPM_NONCE));\n      tpm_rsa_mask_generation(mgf1_seed, sizeof(mgf1_seed), scratch, DAA_SIZE_r0);\n      tpm_bn_init(r0);\n      tpm_bn_import(r0, DAA_SIZE_r0, 1, scratch);\n      /* Set f = SHA1(DAA_tpmSpecific->DAA_rekey || \n       * DAA_tpmSpecific->DAA_count || 0 ) || \n       * SHA1(DAA_tpmSpecific->DAA_rekey || DAA_tpmSpecific->DAA_count || \n       * 1 ) mod DAA_issuerSettings->DAA_generic_q */\n      tpm_sha1_init(&sha1);\n      tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_rekey, \n          sizeof(session->DAA_tpmSpecific.DAA_rekey));\n      tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count, \n          sizeof(session->DAA_tpmSpecific.DAA_count));\n      tpm_sha1_update(&sha1, DAA_LABEL_00, 1);\n      tpm_sha1_final(&sha1, scratch);\n      tpm_sha1_init(&sha1);\n      tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_rekey, \n          sizeof(session->DAA_tpmSpecific.DAA_rekey));\n      tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count, \n          sizeof(session->DAA_tpmSpecific.DAA_count));\n      tpm_sha1_update(&sha1, DAA_LABEL_01, 1);\n      tpm_sha1_final(&sha1, scratch + SHA1_DIGEST_LENGTH);\n      tpm_bn_init(f), tpm_bn_init(q);\n      tpm_bn_import(f, 2 * SHA1_DIGEST_LENGTH, 1, scratch);\n      tpm_bn_import(q, sizeof(session->DAA_issuerSettings.DAA_generic_q), \n        1, session->DAA_issuerSettings.DAA_generic_q);\n      tpm_bn_mod(f, f, q);\n      /* Set f0 = f mod 2^DAA_power0 (erase all but the lowest DAA_power0 \n       * bits of f) */\n      tpm_bn_init(f0);\n      tpm_bn_init(tmp);\n      tpm_bn_ui_pow_ui(tmp, 2, DAA_power0);\n      tpm_bn_mod(f0, f, tmp);\n      /* Set s0 = r0 + (DAA_session->DAA_digest) * f0 in Z */\n      tpm_bn_init(s0);\n      tpm_bn_import(tmp, sizeof(session->DAA_session.DAA_digest.digest), \n        1, session->DAA_session.DAA_digest.digest);\n      tpm_bn_mul(s0, tmp, f0);\n      tpm_bn_add(s0, r0, s0);\n      /* Set outputData = s0 */\n      tpm_bn_export(scratch, &size, 1, s0);\n      *outputSize = (uint32_t)size;\n      tpm_bn_clear(r0), tpm_bn_clear(f), tpm_bn_clear(q), tpm_bn_clear(f0);\n      tpm_bn_clear(s0), tpm_bn_clear(tmp);\n      if ((*outputData = tpm_malloc(*outputSize)) != NULL)\n        memcpy(*outputData, scratch, *outputSize);\n      else {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_NOSPACE;\n      }\n      /* Increment DAA_session->DAA_stage by 1 */\n      session->DAA_session.DAA_stage++;\n      /* Return TPM_SUCCESS */\n      return TPM_SUCCESS;\n    }\n    case 18:\n    {\n      /* Verify that DAA_session->DAA_stage == 18. Return TPM_DAA_STAGE \n       * and flush handle on mismatch */\n      if (session->DAA_session.DAA_stage != 18) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_STAGE;\n      }\n      /* Verify that DAA_tpmSpecific->DAA_digestIssuer == \n       * SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS \n       * on mismatch */\n      if (tpm_daa_verify_digestIssuer(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_ISSUER_SETTINGS;\n      }\n      /* Verify that DAA_session->DAA_digestContext == \n       * SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error \n       * TPM_DAA_TPM_SETTINGS on mismatch */\n      if (tpm_daa_verify_digestContext(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_TPM_SETTINGS;\n      }\n      /* Obtain DAA_SIZE_r1 bits from MGF1(\"r1\", \n       * DAA_session->DAA_contextSeed), and label them r1 */\n      memset(scratch, 0, sizeof(scratch));\n      memcpy(mgf1_seed, \"r1\", 2);\n      memcpy(mgf1_seed + 2, session->DAA_session.DAA_contextSeed.nonce, \n        sizeof(TPM_NONCE));\n      tpm_rsa_mask_generation(mgf1_seed, sizeof(mgf1_seed), scratch, DAA_SIZE_r1);\n      tpm_bn_init(r1);\n      tpm_bn_import(r1, DAA_SIZE_r1, 1, scratch);\n      /* Set f = SHA1(DAA_tpmSpecific->DAA_rekey || \n       * DAA_tpmSpecific->DAA_count || 0 ) || \n       * SHA1(DAA_tpmSpecific->DAA_rekey || DAA_tpmSpecific->DAA_count || \n       * 1 ) mod DAA_issuerSettings->DAA_generic_q */\n      tpm_sha1_init(&sha1);\n      tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_rekey, \n          sizeof(session->DAA_tpmSpecific.DAA_rekey));\n      tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count, \n          sizeof(session->DAA_tpmSpecific.DAA_count));\n      tpm_sha1_update(&sha1, DAA_LABEL_00, 1);\n      tpm_sha1_final(&sha1, scratch);\n      tpm_sha1_init(&sha1);\n      tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_rekey, \n          sizeof(session->DAA_tpmSpecific.DAA_rekey));\n      tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count, \n          sizeof(session->DAA_tpmSpecific.DAA_count));\n      tpm_sha1_update(&sha1, DAA_LABEL_01, 1);\n      tpm_sha1_final(&sha1, scratch + SHA1_DIGEST_LENGTH);\n      tpm_bn_init(f), tpm_bn_init(q);\n      tpm_bn_import(f, 2 * SHA1_DIGEST_LENGTH, 1, scratch);\n      tpm_bn_import(q, sizeof(session->DAA_issuerSettings.DAA_generic_q), \n        1, session->DAA_issuerSettings.DAA_generic_q);\n      tpm_bn_mod(f, f, q);\n      /* Shift f right by DAA_power0 bits (discard the lowest DAA_power0 \n       * bits) and label the result f1 */\n      tpm_bn_init(f1);\n      tpm_bn_fdiv_q_2exp(f1, f, DAA_power0);\n      /* Set s1 = r1 + (DAA_session->DAA_digest) * f1 in Z */\n      tpm_bn_init(s1);\n      tpm_bn_init(tmp);\n      tpm_bn_import(tmp, sizeof(session->DAA_session.DAA_digest.digest), \n        1, session->DAA_session.DAA_digest.digest);\n      tpm_bn_mul(s1, tmp, f1);\n      tpm_bn_add(s1, r1, s1);\n      /* Set outputData = s1 */\n      tpm_bn_export(scratch, &size, 1, s1);\n      *outputSize = (uint32_t)size;\n      tpm_bn_clear(r1), tpm_bn_clear(f), tpm_bn_clear(q), tpm_bn_clear(f1);\n      tpm_bn_clear(s1), tpm_bn_clear(tmp);\n      if ((*outputData = tpm_malloc(*outputSize)) != NULL)\n        memcpy(*outputData, scratch, *outputSize);\n      else {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_NOSPACE;\n      }\n      /* Increment DAA_session->DAA_stage by 1 */\n      session->DAA_session.DAA_stage++;\n      /* Return TPM_SUCCESS */\n      return TPM_SUCCESS;\n    }\n    case 19:\n    {\n      /* Verify that DAA_session->DAA_stage == 19. Return TPM_DAA_STAGE \n       * and flush handle on mismatch */\n      if (session->DAA_session.DAA_stage != 19) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_STAGE;\n      }\n      /* Verify that DAA_tpmSpecific->DAA_digestIssuer == \n       * SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS \n       * on mismatch */\n      if (tpm_daa_verify_digestIssuer(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_ISSUER_SETTINGS;\n      }\n      /* Verify that DAA_session->DAA_digestContext == \n       * SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error \n       * TPM_DAA_TPM_SETTINGS on mismatch */\n      if (tpm_daa_verify_digestContext(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_TPM_SETTINGS;\n      }\n      /* Obtain DAA_SIZE_r2 bits from MGF1(\"r2\", \n       * DAA_session->DAA_contextSeed), and label them r2 */\n      memset(scratch, 0, sizeof(scratch));\n      memcpy(mgf1_seed, \"r2\", 2);\n      memcpy(mgf1_seed + 2, session->DAA_session.DAA_contextSeed.nonce, \n        sizeof(TPM_NONCE));\n      tpm_rsa_mask_generation(mgf1_seed, sizeof(mgf1_seed), scratch, DAA_SIZE_r2);\n      tpm_bn_init(r2);\n      tpm_bn_import(r2, DAA_SIZE_r2, 1, scratch);\n      /* Set s2 = r2 + (DAA_session->DAA_digest) * \n       * (DAA_joinSession->DAA_join_u0) mod 2^DAA_power1 \n       * (Erase all but the lowest DAA_power1 bits of s2) */\n      tpm_bn_init(s2);\n      tpm_bn_import(s2, sizeof(session->DAA_joinSession.DAA_join_u0), \n        1, session->DAA_joinSession.DAA_join_u0);\n      tpm_bn_init(tmp);\n      tpm_bn_import(tmp, sizeof(session->DAA_session.DAA_digest.digest), \n        1, session->DAA_session.DAA_digest.digest);\n      tpm_bn_mul(s2, tmp, s2);\n      tpm_bn_add(s2, r2, s2);\n      tpm_bn_ui_pow_ui(tmp, 2, DAA_power1);\n      tpm_bn_mod(s2, s2, tmp);\n      /* Set DAA_session->DAA_scratch = s2 */\n      memset(session->DAA_session.DAA_scratch, 0, \n        sizeof(session->DAA_session.DAA_scratch));\n      tpm_bn_export(session->DAA_session.DAA_scratch, NULL, -1, s2);\n      /* Set outputData = s2 */\n      tpm_bn_export(scratch, &size, 1, s2);\n      *outputSize = (uint32_t)size;\n      tpm_bn_clear(r2), tpm_bn_clear(s2), tpm_bn_clear(tmp);\n      if ((*outputData = tpm_malloc(*outputSize)) != NULL)\n        memcpy(*outputData, scratch, *outputSize);\n      else {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_NOSPACE;\n      }\n      /* Increment DAA_session->DAA_stage by 1 */\n      session->DAA_session.DAA_stage++;\n      /* Return TPM_SUCCESS */\n      return TPM_SUCCESS;\n    }\n    case 20:\n    {\n      /* Verify that DAA_session->DAA_stage == 20. Return TPM_DAA_STAGE \n       * and flush handle on mismatch */\n      if (session->DAA_session.DAA_stage != 20) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_STAGE;\n      }\n      /* Verify that DAA_tpmSpecific->DAA_digestIssuer == \n       * SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS \n       * on mismatch */\n      if (tpm_daa_verify_digestIssuer(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_ISSUER_SETTINGS;\n      }\n      /* Verify that DAA_session->DAA_digestContext == \n       * SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error \n       * TPM_DAA_TPM_SETTINGS on mismatch */\n      if (tpm_daa_verify_digestContext(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_TPM_SETTINGS;\n      }\n      /* Obtain DAA_SIZE_r2 bits from MGF1(\"r2\", \n       * DAA_session->DAA_contextSeed), and label them r2 */\n      memset(scratch, 0, sizeof(scratch));\n      memcpy(mgf1_seed, \"r2\", 2);\n      memcpy(mgf1_seed + 2, session->DAA_session.DAA_contextSeed.nonce, \n        sizeof(TPM_NONCE));\n      tpm_rsa_mask_generation(mgf1_seed, sizeof(mgf1_seed), scratch, DAA_SIZE_r2);\n      tpm_bn_init(r2);\n      tpm_bn_import(r2, DAA_SIZE_r2, 1, scratch);\n      /* Set s12 = r2 + (DAA_session->DAA_digest) * \n       * (DAA_joinSession->DAA_join_u0) */\n      tpm_bn_init(s12);\n      tpm_bn_import(s12, sizeof(session->DAA_joinSession.DAA_join_u0), \n        1, session->DAA_joinSession.DAA_join_u0);\n      tpm_bn_init(tmp);\n      tpm_bn_import(tmp, sizeof(session->DAA_session.DAA_digest.digest), \n        1, session->DAA_session.DAA_digest.digest);\n      tpm_bn_mul(s12, tmp, s12);\n      tpm_bn_add(s12, r2, s12);\n      /* Shift s12 right by DAA_power1 bit (discard the lowest DAA_power1 \n       * bits). */\n      tpm_bn_fdiv_q_2exp(s12, s12, DAA_power1);\n      /* Set DAA_session->DAA_scratch = s12 */\n      memset(session->DAA_session.DAA_scratch, 0, \n        sizeof(session->DAA_session.DAA_scratch));\n      tpm_bn_export(session->DAA_session.DAA_scratch, NULL, -1, s12);\n      tpm_bn_clear(r2), tpm_bn_clear(s12), tpm_bn_clear(tmp);\n      /* Set outputData = DAA_session->DAA_digest */\n      *outputSize = sizeof(session->DAA_session.DAA_digest.digest);\n      if ((*outputData = tpm_malloc(*outputSize)) != NULL)\n        memcpy(*outputData, session->DAA_session.DAA_digest.digest, \n          *outputSize);\n      else {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_NOSPACE;\n      }\n      /* Increment DAA_session->DAA_stage by 1 */\n      session->DAA_session.DAA_stage++;\n      /* Return TPM_SUCCESS */\n      return TPM_SUCCESS;\n    }\n    case 21:\n    {\n      /* Verify that DAA_session->DAA_stage == 21. Return TPM_DAA_STAGE \n       * and flush handle on mismatch */\n      if (session->DAA_session.DAA_stage != 21) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_STAGE;\n      }\n      /* Verify that DAA_tpmSpecific->DAA_digestIssuer == \n       * SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS \n       * on mismatch */\n      if (tpm_daa_verify_digestIssuer(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_ISSUER_SETTINGS;\n      }\n      /* Verify that DAA_session->DAA_digestContext == \n       * SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error \n       * TPM_DAA_TPM_SETTINGS on mismatch */\n      if (tpm_daa_verify_digestContext(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_TPM_SETTINGS;\n      }\n      /* Obtain DAA_SIZE_r3 bits from MGF1(\"r3\", \n       * DAA_session->DAA_contextSeed), and label them r3 */\n      memset(scratch, 0, sizeof(scratch));\n      memcpy(mgf1_seed, \"r3\", 2);\n      memcpy(mgf1_seed + 2, session->DAA_session.DAA_contextSeed.nonce, \n        sizeof(TPM_NONCE));\n      tpm_rsa_mask_generation(mgf1_seed, sizeof(mgf1_seed), scratch, DAA_SIZE_r3);\n      tpm_bn_init(r3);\n      tpm_bn_import(r3, DAA_SIZE_r3, 1, scratch);\n      /* Set s3 = r3 + (DAA_session->DAA_digest) * \n       * (DAA_joinSession->DAA_join_u1) + (DAA_session->DAA_scratch). */\n      tpm_bn_init(s3);\n      tpm_bn_import(s3, sizeof(session->DAA_joinSession.DAA_join_u1), \n        1, session->DAA_joinSession.DAA_join_u1);\n      tpm_bn_init(tmp);\n      tpm_bn_import(tmp, sizeof(session->DAA_session.DAA_digest.digest), \n        1, session->DAA_session.DAA_digest.digest);\n      tpm_bn_mul(s3, tmp, s3);\n      tpm_bn_add(s3, r3, s3);\n      tpm_bn_import(tmp, sizeof(session->DAA_session.DAA_scratch), \n        -1, session->DAA_session.DAA_scratch);\n      tpm_bn_add(s3, s3, tmp);\n      /* Set DAA_session->DAA_scratch = NULL */\n      memset(session->DAA_session.DAA_scratch, 0, \n        sizeof(session->DAA_session.DAA_scratch));\n      /* Set outputData = s3 */\n      tpm_bn_export(scratch, &size, 1, s3);\n      *outputSize = (uint32_t)size;\n      tpm_bn_clear(r3), tpm_bn_clear(s3), tpm_bn_clear(tmp);\n      if ((*outputData = tpm_malloc(*outputSize)) != NULL)\n        memcpy(*outputData, scratch, *outputSize);\n      else {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_NOSPACE;\n      }\n      /* Increment DAA_session->DAA_stage by 1 */\n      session->DAA_session.DAA_stage++;\n      /* Return TPM_SUCCESS */\n      return TPM_SUCCESS;\n    }\n    case 22:\n    {\n      /* Verify that DAA_session->DAA_stage == 22. Return TPM_DAA_STAGE \n       * and flush handle on mismatch */\n      if (session->DAA_session.DAA_stage != 22) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_STAGE;\n      }\n      /* Verify that DAA_tpmSpecific->DAA_digestIssuer == \n       * SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS \n       * on mismatch */\n      if (tpm_daa_verify_digestIssuer(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_ISSUER_SETTINGS;\n      }\n      /* Verify that DAA_session->DAA_digestContext == \n       * SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error \n       * TPM_DAA_TPM_SETTINGS on mismatch */\n      if (tpm_daa_verify_digestContext(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_TPM_SETTINGS;\n      }\n      /* Verify inputSize0 == DAA_SIZE_v0 and return error \n       * TPM_DAA_INPUT_DATA0 on mismatch */\n      if (inputSize0 != DAA_SIZE_v0) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_INPUT_DATA0;\n      }\n      /* Set u2 = inputData0 */\n      tpm_bn_init(u2);\n      tpm_bn_import(u2, DAA_SIZE_v0, 1, inputData0);\n      /* Set v0 = u2 + (DAA_joinSession->DAA_join_u0) mod 2^DAA_power1 \n       * (Erase all but the lowest DAA_power1 bits of v0). */\n      tpm_bn_init(v0);\n      tpm_bn_import(v0, sizeof(session->DAA_joinSession.DAA_join_u0), \n        1, session->DAA_joinSession.DAA_join_u0);\n      tpm_bn_add(v0, u2, v0);\n      tpm_bn_init(tmp);\n      tpm_bn_ui_pow_ui(tmp, 2, DAA_power1);\n      tpm_bn_mod(v0, v0, tmp);\n      /* Set DAA_tpmSpecific->DAA_digest_v0 = SHA-1(v0) */\n      tpm_bn_export(scratch, &size, 1, v0);\n      tpm_sha1_init(&sha1);\n      tpm_sha1_update(&sha1, (BYTE*) scratch, size);\n      tpm_sha1_final(&sha1, session->DAA_tpmSpecific.DAA_digest_v0.digest);\n      /* Set v10 = u2 + (DAA_joinSession->DAA_join_u0) in Z */\n      tpm_bn_init(v10);\n      tpm_bn_import(v10, sizeof(session->DAA_joinSession.DAA_join_u0), \n        1, session->DAA_joinSession.DAA_join_u0);\n      tpm_bn_add(v10, u2, v10);\n      /* Shift v10 right by DAA_power1 bits (erase the lowest DAA_power1 \n       * bits). */\n      tpm_bn_fdiv_q_2exp(v10, v10, DAA_power1);\n      /* Set DAA_session->DAA_scratch = v10 */\n      memset(session->DAA_session.DAA_scratch, 0, \n        sizeof(session->DAA_session.DAA_scratch));\n      tpm_bn_export(session->DAA_session.DAA_scratch, NULL, -1, v10);\n      tpm_bn_clear(u2), tpm_bn_clear(v0), tpm_bn_clear(tmp), tpm_bn_clear(v10);\n      /* Set outputData */\n        memset(&blob, 0, sizeof(blob));\n        /* Fill in TPM_DAA_BLOB with a type of TPM_RT_DAA_V0 and encrypt \n         * the v0 parameters */\n        blob.tag = TPM_TAG_DAA_BLOB;\n        blob.resourceType = TPM_RT_DAA_V0;\n        memset(blob.label, 0, sizeof(blob.label));\n        memset(&blob.blobIntegrity, 0, sizeof(TPM_DIGEST));\n        blob.additionalSize = TPM_SYM_KEY_SIZE;\n        blob.additionalData = tpm_malloc(blob.additionalSize);\n        if (blob.additionalData == NULL) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_NOSPACE;\n        }\n        tpm_get_random_bytes(blob.additionalData, blob.additionalSize);\n        sensitive.tag = TPM_TAG_DAA_SENSITIVE;\n        sensitive.internalSize = size;\n        sensitive.internalData = scratch;\n        if (encrypt_daa(blob.additionalData, blob.additionalSize,\n          &sensitive, &blob.sensitiveData, &blob.sensitiveSize)) {\n            tpm_free(blob.additionalData);\n            memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n            return TPM_ENCRYPT_ERROR;\n        }\n        if (compute_daa_digest(&blob, &blob.blobIntegrity)) {\n          debug(\"TPM_DAA_Join(): compute_daa_digest() failed.\");\n          tpm_free(blob.sensitiveData);\n          tpm_free(blob.additionalData);\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_FAIL;\n        }\n        /* Set outputData to the encrypted TPM_DAA_BLOB */\n        *outputSize = sizeof_TPM_DAA_BLOB(blob);\n        if ((*outputData = tpm_malloc(*outputSize)) == NULL) {\n          tpm_free(blob.sensitiveData);\n          tpm_free(blob.additionalData);\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_NOSPACE;\n        }\n        len = *outputSize;\n        ptr = *outputData;\n        if (tpm_marshal_TPM_DAA_BLOB(&ptr, &len, &blob)) {\n          debug(\"TPM_DAA_Join(): tpm_marshal_TPM_DAA_BLOB() failed.\");\n          tpm_free(blob.sensitiveData);\n          tpm_free(blob.additionalData);\n          tpm_free(*outputData);\n          *outputSize = 0;\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_FAIL;\n        }\n        tpm_free(blob.sensitiveData);\n        tpm_free(blob.additionalData);\n      /* Increment DAA_session->DAA_stage by 1 */\n      session->DAA_session.DAA_stage++;\n      /* Set DAA_session->DAA_digestContext = SHA-1(DAA_tpmSpecific || \n       * DAA_joinSession) */\n      tpm_daa_update_digestContext(session, &sha1);\n      /* Return TPM_SUCCESS */\n      return TPM_SUCCESS;\n    }\n    case 23:\n    {\n      /* Verify that DAA_session->DAA_stage == 23. Return TPM_DAA_STAGE \n       * and flush handle on mismatch */\n      if (session->DAA_session.DAA_stage != 23) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_STAGE;\n      }\n      /* Verify that DAA_tpmSpecific->DAA_digestIssuer == \n       * SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS \n       * on mismatch */\n      if (tpm_daa_verify_digestIssuer(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_ISSUER_SETTINGS;\n      }\n      /* Verify that DAA_session->DAA_digestContext == \n       * SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error \n       * TPM_DAA_TPM_SETTINGS on mismatch */\n      if (tpm_daa_verify_digestContext(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_TPM_SETTINGS;\n      }\n      /* Verify inputSize0 == DAA_SIZE_v1 and return error \n       * TPM_DAA_INPUT_DATA0 on mismatch */\n      if (inputSize0 != DAA_SIZE_v1) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_INPUT_DATA0;\n      }\n      /* Set u3 = inputData0 */\n      tpm_bn_init(u3);\n      tpm_bn_import(u3, DAA_SIZE_v1, 1, inputData0);\n      /* Set v1 = u3 + DAA_joinSession->DAA_join_u1 + \n       * DAA_session->DAA_scratch */\n      tpm_bn_init(v1);\n      tpm_bn_import(v1, sizeof(session->DAA_joinSession.DAA_join_u1), \n        1, session->DAA_joinSession.DAA_join_u1);\n      tpm_bn_init(tmp);\n      tpm_bn_import(tmp, sizeof(session->DAA_session.DAA_scratch), \n        -1, session->DAA_session.DAA_scratch);\n      tpm_bn_add(v1, v1, tmp);\n      tpm_bn_add(v1, u3, v1);\n      /* Set DAA_tpmSpecific->DAA_digest_v1 = SHA-1(v1) */\n      tpm_bn_export(scratch, &size, 1, v1);\n      tpm_bn_clear(u3), tpm_bn_clear(v1), tpm_bn_clear(tmp);\n      tpm_sha1_init(&sha1);\n      tpm_sha1_update(&sha1, (BYTE*) scratch, size);\n      tpm_sha1_final(&sha1, session->DAA_tpmSpecific.DAA_digest_v1.digest);\n      /* Set outputData */\n        memset(&blob, 0, sizeof(blob));\n        /* Fill in TPM_DAA_BLOB with a type of TPM_RT_DAA_V1 and encrypt \n         * the v1 parameters */\n        blob.tag = TPM_TAG_DAA_BLOB;\n        blob.resourceType = TPM_RT_DAA_V1;\n        memset(blob.label, 0, sizeof(blob.label));\n        memset(&blob.blobIntegrity, 0, sizeof(TPM_DIGEST));\n        blob.additionalSize = TPM_SYM_KEY_SIZE;\n        blob.additionalData = tpm_malloc(blob.additionalSize);\n        if (blob.additionalData == NULL) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_NOSPACE;\n        }\n        tpm_get_random_bytes(blob.additionalData, blob.additionalSize);\n        sensitive.tag = TPM_TAG_DAA_SENSITIVE;\n        sensitive.internalSize = size;\n        sensitive.internalData = scratch;\n        if (encrypt_daa(blob.additionalData, blob.additionalSize,\n          &sensitive, &blob.sensitiveData, &blob.sensitiveSize)) {\n            tpm_free(blob.additionalData);\n            memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n            return TPM_ENCRYPT_ERROR;\n        }\n        if (compute_daa_digest(&blob, &blob.blobIntegrity)) {\n          debug(\"TPM_DAA_Join(): compute_daa_digest() failed.\");\n          tpm_free(blob.sensitiveData);\n          tpm_free(blob.additionalData);\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_FAIL;\n        }\n        /* Set outputData to the encrypted TPM_DAA_BLOB */\n        *outputSize = sizeof_TPM_DAA_BLOB(blob);\n        if ((*outputData = tpm_malloc(*outputSize)) == NULL) {\n          tpm_free(blob.sensitiveData);\n          tpm_free(blob.additionalData);\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_NOSPACE;\n        }\n        len = *outputSize;\n        ptr = *outputData;\n        if (tpm_marshal_TPM_DAA_BLOB(&ptr, &len, &blob)) {\n          debug(\"TPM_DAA_Join(): tpm_marshal_TPM_DAA_BLOB() failed.\");\n          tpm_free(blob.sensitiveData);\n          tpm_free(blob.additionalData);\n          tpm_free(*outputData);\n          *outputSize = 0;\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_FAIL;\n        }\n        tpm_free(blob.sensitiveData);\n        tpm_free(blob.additionalData);\n      /* Set DAA_session->DAA_scratch = NULL */\n      memset(session->DAA_session.DAA_scratch, 0, \n        sizeof(session->DAA_session.DAA_scratch));\n      /* Increment DAA_session->DAA_stage by 1 */\n      session->DAA_session.DAA_stage++;\n      /* Set DAA_session->DAA_digestContext = SHA-1(DAA_tpmSpecific || \n       * DAA_joinSession) */\n      tpm_daa_update_digestContext(session, &sha1);\n      /* Return TPM_SUCCESS */\n      return TPM_SUCCESS;\n    }\n    case 24:\n    {\n      /* Verify that DAA_session->DAA_stage == 24. Return TPM_DAA_STAGE \n       * and flush handle on mismatch */\n      if (session->DAA_session.DAA_stage != 24) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_STAGE;\n      }\n      /* Verify that DAA_tpmSpecific->DAA_digestIssuer == \n       * SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS \n       * on mismatch */\n      if (tpm_daa_verify_digestIssuer(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_ISSUER_SETTINGS;\n      }\n      /* Verify that DAA_session->DAA_digestContext == \n       * SHA-1(DAA_tpmSpecific || DAA_joinSession) and return error \n       * TPM_DAA_TPM_SETTINGS on mismatch */\n      if (tpm_daa_verify_digestContext(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_TPM_SETTINGS;\n      }\n      /* Set outputData = enc(DAA_tpmSpecific) */\n      memset(&blob, 0, sizeof(blob));\n      blob.tag = TPM_TAG_DAA_BLOB;\n      blob.resourceType = TPM_RT_DAA_TPM;\n      memcpy(blob.label, \"DAA_tpmSpecific\", 15);\n      memset(&blob.blobIntegrity, 0, sizeof(TPM_DIGEST));\n      blob.additionalSize = TPM_SYM_KEY_SIZE;\n      blob.additionalData = tpm_malloc(blob.additionalSize);\n      if (blob.additionalData == NULL) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_NOSPACE;\n      }\n      tpm_get_random_bytes(blob.additionalData, blob.additionalSize);\n      sensitive.tag = TPM_TAG_DAA_SENSITIVE;\n      sensitive.internalSize = len = sizeof(TPM_DAA_TPM);\n      sensitive.internalData = ptr = tpm_malloc(sensitive.internalSize);\n      if (sensitive.internalData == NULL) {\n        tpm_free(blob.additionalData);\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_NOSPACE;\n      }\n      if (tpm_marshal_TPM_DAA_TPM(&ptr, &len, &session->DAA_tpmSpecific)) {\n        debug(\"TPM_DAA_Join(): tpm_marshal_TPM_DAA_TPM() failed.\");\n        tpm_free(blob.additionalData);\n        tpm_free(sensitive.internalData);\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_FAIL;\n      }\n      if (encrypt_daa(blob.additionalData, blob.additionalSize,\n        &sensitive, &blob.sensitiveData, &blob.sensitiveSize)) {\n          tpm_free(blob.additionalData);\n          tpm_free(sensitive.internalData);\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_ENCRYPT_ERROR;\n      }\n      if (compute_daa_digest(&blob, &blob.blobIntegrity)) {\n        debug(\"TPM_DAA_Join(): compute_daa_digest() failed.\");\n        tpm_free(blob.sensitiveData);\n        tpm_free(sensitive.internalData);\n        tpm_free(blob.additionalData);\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_FAIL;\n      }\n      *outputSize = sizeof_TPM_DAA_BLOB(blob);\n      if ((*outputData = tpm_malloc(*outputSize)) == NULL) {\n        tpm_free(blob.sensitiveData);\n        tpm_free(sensitive.internalData);\n        tpm_free(blob.additionalData);\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_NOSPACE;\n      }\n      len = *outputSize;\n      ptr = *outputData;\n      if (tpm_marshal_TPM_DAA_BLOB(&ptr, &len, &blob)) {\n        debug(\"TPM_DAA_Join(): tpm_marshal_TPM_DAA_BLOB() failed.\");\n        tpm_free(blob.sensitiveData);\n        tpm_free(sensitive.internalData);\n        tpm_free(blob.additionalData);\n        tpm_free(*outputData);\n        *outputSize = 0;\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_FAIL;\n      }\n      tpm_free(blob.sensitiveData);\n      tpm_free(sensitive.internalData);\n      tpm_free(blob.additionalData);\n      /* Terminate the DAA session and all resources assoociated with the\n       * DAA sign session handle. */\n      memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n      /* Return TPM_SUCCESS */\n      return TPM_SUCCESS;\n    }\n    default:\n      return TPM_DAA_STAGE;\n  }\n}\n\nTPM_RESULT TPM_DAA_Sign(TPM_HANDLE handle, BYTE stage, UINT32 inputSize0,\n                        BYTE *inputData0, UINT32 inputSize1,\n                        BYTE *inputData1, TPM_AUTH *auth1,\n                        TPM_COMMAND_CODE *ordinal, UINT32 *outputSize,\n                        BYTE **outputData)\n{\n  BYTE scratch[SCRATCH_SIZE];\n  TPM_DAA_SESSION_DATA *session = NULL;\n  \n  TPM_RESULT res;\n  tpm_sha1_ctx_t sha1;\n  BYTE *ptr, *buf;\n  UINT32 len;\n  TPM_DAA_BLOB blob;\n  TPM_DAA_SENSITIVE sensitive;\n  TPM_DIGEST digest;\n  BYTE *DAA_generic_R0 = NULL, *DAA_generic_R1 = NULL, *DAA_generic_n = NULL, \n    *DAA_generic_S0 = NULL, *DAA_generic_S1 = NULL, *DAA_generic_gamma = NULL;\n  BYTE mgf1_seed[2 + sizeof(TPM_DIGEST)];\n  tpm_bn_t X, Y, Z, n, w1, w, gamma, q, f, E, r0, r1, r, E1, f0, s0, f1, s1, \n    r2, s2, s12, r4, s3, tmp;\n  BYTE selector;\n  size_t size;\n  TPM_KEY_DATA *aikData;\n  TPM_KEY_HANDLE aikHandle;\n  \n  info(\"TPM_DAA_Sign()\");\n  debug(\"handle = %.8x, stage = %d\", handle, stage);\n  debug(\"stany.data.currentDAA = %.8x\", tpmData.stany.data.currentDAA);\n  \n  /* Initalize internal scratch pad */\n  memset(scratch, 0, SCRATCH_SIZE);\n  \n  /* Verify authorization */\n  res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);\n  if (res != TPM_SUCCESS) return res;\n  \n  /* Verify and initalize the session, for all stages greater than zero. */\n  if (stage > 0) {\n    if ((HANDLE_TO_INDEX(handle) >= TPM_MAX_SESSIONS_DAA) ||\n      (tpmData.stany.data.sessionsDAA[HANDLE_TO_INDEX(handle)].type != \n        TPM_ST_DAA) ||\n      (tpmData.stany.data.sessionsDAA[HANDLE_TO_INDEX(handle)].handle != \n      handle)) {\n        /* Probe, whether the handle from stany.data.currentDAA is valid. */\n        handle = tpmData.stany.data.currentDAA;\n        if ((HANDLE_TO_INDEX(handle) >= TPM_MAX_SESSIONS_DAA) ||\n          (tpmData.stany.data.sessionsDAA[HANDLE_TO_INDEX(handle)].type != \n            TPM_ST_DAA) ||\n          (tpmData.stany.data.sessionsDAA[HANDLE_TO_INDEX(handle)].handle != \n            handle))\n              return TPM_BAD_HANDLE;\n    }\n    session = &tpmData.stany.data.sessionsDAA[HANDLE_TO_INDEX(handle)];\n  }\n  \n  /* TPM_DAA_SIGN [TPM_Part3], Section 26.2, Rev. 85 */\n  switch (stage) {\n    case 0:\n    {\n      /* Determine that sufficient resources are available to perform a \n       * DAA_Sign. Assign session handle for this DAA_Sign. */\n      handle = tpm_get_free_daa_session();\n      if (handle == TPM_INVALID_HANDLE)\n        return TPM_RESOURCES;\n      session = &tpmData.stany.data.sessionsDAA[HANDLE_TO_INDEX(handle)];\n      /* Verify that sizeOf(inputData0) == sizeOf(TPM_DAA_ISSUER)\n       * and return error TPM_DAA_INPUT_DATA0 on mismatch */\n      if (inputSize0 != sizeof(TPM_DAA_ISSUER)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_INPUT_DATA0;\n      }\n      /* Set DAA_issuerSettings = inputData0. */\n      /* Verify that all fields in DAA_issuerSettings are present and \n       * return error TPM_DAA_INPUT_DATA0 if not. */\n      ptr = inputData0, len = inputSize0;\n      if (tpm_unmarshal_TPM_DAA_ISSUER(&ptr, &len, \n        &session->DAA_issuerSettings) || (len != 0) || \n        (session->DAA_issuerSettings.tag != TPM_TAG_DAA_ISSUER)) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA0;\n      }\n      /* Set all fields in DAA_session = NULL */\n      memset(&session->DAA_session, 0, sizeof(TPM_DAA_CONTEXT));\n      /* Assign new handle for session */\n      tpmData.stany.data.currentDAA = handle;\n      debug(\"TPM_DAA_Sign() -- set handle := %.8x\", handle);\n      /* Set outputData to new handle */\n      *outputSize = sizeof(TPM_HANDLE);\n      if ((*outputData = tpm_malloc(*outputSize)) != NULL) {\n        ptr = *outputData, len = *outputSize;\n        if (tpm_marshal_TPM_HANDLE(&ptr, &len, handle)) {\n          debug(\"TPM_DAA_Sign(): tpm_marshal_TPM_HANDLE() failed.\");\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_FAIL;\n        }\n      } else {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_NOSPACE;\n      }\n      /* Set DAA_session->DAA_stage = 1 */\n      session->DAA_session.DAA_stage = 1;\n      /* Return TPM_SUCCESS */\n      return TPM_SUCCESS;\n    }\n    case 1:\n    {\n      /* Verify that DAA_session->DAA_stage == 1. Return TPM_DAA_STAGE and \n       * flush handle on mismatch */\n      if (session->DAA_session.DAA_stage != 1) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_STAGE;\n      }\n      /* Set DAA_tpmSpecific = unwrap(inputData0) */\n      ptr = inputData0, len = inputSize0;\n      if (tpm_unmarshal_TPM_DAA_BLOB(&ptr, &len, &blob) || (len != 0)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_INPUT_DATA0;\n      }\n      sensitive.internalData = scratch;\n      if (decrypt_daa(blob.additionalData, blob.additionalSize, \n        blob.sensitiveData, blob.sensitiveSize, &sensitive, &buf)) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DECRYPT_ERROR;\n      }\n      if (compute_daa_digest(&blob, &digest) || \n        memcmp(&digest, &blob.blobIntegrity, sizeof(TPM_DIGEST))) {\n          tpm_free(buf);\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA0;\n      }\n      if ((blob.resourceType != TPM_RT_DAA_TPM) || \n        (sensitive.tag != TPM_TAG_DAA_SENSITIVE || \n        (sensitive.internalSize != sizeof(TPM_DAA_TPM)))) {\n          tpm_free(buf);\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA0;\n      }\n      if (tpm_unmarshal_TPM_DAA_TPM(&sensitive.internalData,\n        &sensitive.internalSize, &session->DAA_tpmSpecific)) {\n          tpm_free(buf);\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA0;\n      }\n      tpm_free(buf);\n      \n      /* Verify that DAA_tpmSpecific->DAA_digestIssuer == \n       * SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS \n       * on mismatch */\n      if (tpm_daa_verify_digestIssuer(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_ISSUER_SETTINGS;\n      }\n      /* Set DAA_session->DAA_digestContext = SHA-1(DAA_tpmSpecific) */\n      tpm_daa_update_digestContext_sign(session, &sha1);\n      /* Obtain random data from the RNG and store it as \n       * DAA_session->DAA_contextSeed */\n      tpm_get_random_bytes(session->DAA_session.DAA_contextSeed.nonce, \n        sizeof(TPM_NONCE));\n      /* Set outputData = NULL */\n      *outputSize = 0, *outputData = NULL;\n      /* Set DAA_session->DAA_stage = 2 */\n      session->DAA_session.DAA_stage = 2;\n      /* Return TPM_SUCCESS */\n      return TPM_SUCCESS;\n    }\n    case 2:\n    {\n      /* Verify that DAA_session->DAA_stage == 2. Return TPM_DAA_STAGE and \n       * flush handle on mismatch */\n      if (session->DAA_session.DAA_stage != 2) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_STAGE;\n      }\n      /* Verify that DAA_tpmSpecific->DAA_digestIssuer == \n       * SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS \n       * on mismatch */\n      if (tpm_daa_verify_digestIssuer(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_ISSUER_SETTINGS;\n      }\n      /* Verify that DAA_session->DAA_digestContext == SHA-1(DAA_tpmSpecific) \n       * and return error TPM_DAA_TPM_SETTINGS on mismatch */\n      if (tpm_daa_verify_digestContext_sign(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_TPM_SETTINGS;\n      }\n      /* Set DAA_generic_R0 = inputData0 */\n      DAA_generic_R0 = inputData0;\n      /* Verify that SHA-1(DAA_generic_R0) == \n       * DAA_issuerSettings->DAA_digest_R0 and return error \n       * TPM_DAA_INPUT_DATA0 on mismatch */\n      if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_R0, \n        DAA_generic_R0, inputSize0, &sha1)) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA0;\n      }\n      /* Set DAA_generic_n = inputData1 */\n      DAA_generic_n = inputData1;\n      /* Verify that SHA-1(DAA_generic_n) == DAA_issuerSettings->DAA_digest_n \n       * and return error TPM_DAA_INPUT_DATA1 on mismatch */\n      if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_n, \n        DAA_generic_n, inputSize1, &sha1)) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA1;\n      }\n      /* Obtain DAA_SIZE_r0 bits from MGF1(\"r0\", \n       * DAA_session->DAA_contextSeed), and label them Y */\n      memset(scratch, 0, sizeof(scratch));\n      memcpy(mgf1_seed, \"r0\", 2);\n      memcpy(mgf1_seed + 2, session->DAA_session.DAA_contextSeed.nonce, \n        sizeof(TPM_NONCE));\n      tpm_rsa_mask_generation(mgf1_seed, sizeof(mgf1_seed), scratch, DAA_SIZE_r0);\n      tpm_bn_init(Y);\n      tpm_bn_import(Y, DAA_SIZE_r0, 1, scratch);\n      /* Set X = DAA_generic_R0 */\n      tpm_bn_init(X);\n      tpm_bn_import(X, inputSize0, 1, DAA_generic_R0);\n      /* Set n = DAA_generic_n */\n      tpm_bn_init(n);\n      tpm_bn_import(n, inputSize1, 1, DAA_generic_n);\n      /* Set DAA_session->DAA_scratch = (X^Y) mod n */\n      memset(session->DAA_session.DAA_scratch, 0, \n        sizeof(session->DAA_session.DAA_scratch));\n      tpm_bn_init(tmp);\n      tpm_bn_powm(tmp, X, Y, n);\n      tpm_bn_export(session->DAA_session.DAA_scratch, NULL, -1, tmp);\n      tpm_bn_clear(X), tpm_bn_clear(Y), tpm_bn_clear(n), tpm_bn_clear(tmp);\n      /* Set outputData = NULL */\n      *outputSize = 0, *outputData = NULL;\n      /* Increment DAA_session->DAA_stage by 1 */\n      session->DAA_session.DAA_stage++;\n      /* Return TPM_SUCCESS */\n      return TPM_SUCCESS;\n    }\n    case 3:\n    {\n      /* Verify that DAA_session->DAA_stage == 3. Return TPM_DAA_STAGE \n       * and flush handle on mismatch */\n      if (session->DAA_session.DAA_stage != 3) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_STAGE;\n      }\n      /* Verify that DAA_tpmSpecific->DAA_digestIssuer == \n       * SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS \n       * on mismatch */\n      if (tpm_daa_verify_digestIssuer(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_ISSUER_SETTINGS;\n      }\n      /* Verify that DAA_session->DAA_digestContext == SHA-1(DAA_tpmSpecific) \n       * and return error TPM_DAA_TPM_SETTINGS on mismatch */\n      if (tpm_daa_verify_digestContext_sign(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_TPM_SETTINGS;\n      }\n      /* Set DAA_generic_R1 = inputData0 */\n      DAA_generic_R1 = inputData0;\n      /* Verify that SHA-1(DAA_generic_R1) == \n       * DAA_issuerSettings->DAA_digest_R1 and return error \n       * TPM_DAA_INPUT_DATA0 on mismatch */\n      if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_R1, \n        DAA_generic_R1, inputSize0, &sha1)) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA0;\n      }\n      /* Set DAA_generic_n = inputData1 */\n      DAA_generic_n = inputData1;\n      /* Verify that SHA-1(DAA_generic_n) == DAA_issuerSettings->DAA_digest_n \n       * and return error TPM_DAA_INPUT_DATA1 on mismatch */\n      if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_n, \n        DAA_generic_n, inputSize1, &sha1)) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA1;\n      }\n      /* Obtain DAA_SIZE_r1 bits from MGF1(\"r1\", \n       * DAA_session->DAA_contextSeed), and label them Y */\n      memset(scratch, 0, sizeof(scratch));\n      memcpy(mgf1_seed, \"r1\", 2);\n      memcpy(mgf1_seed + 2, session->DAA_session.DAA_contextSeed.nonce, \n        sizeof(TPM_NONCE));\n      tpm_rsa_mask_generation(mgf1_seed, sizeof(mgf1_seed), scratch, DAA_SIZE_r1);\n      tpm_bn_init(Y);\n      tpm_bn_import(Y, DAA_SIZE_r1, 1, scratch);\n      /* Set X = DAA_generic_R1 */\n      tpm_bn_init(X);\n      tpm_bn_import(X, inputSize0, 1, DAA_generic_R1);\n      /* Set n = DAA_generic_n */\n      tpm_bn_init(n);\n      tpm_bn_import(n, inputSize1, 1, DAA_generic_n);\n      /* Set Z = DAA_session->DAA_scratch */\n      tpm_bn_init(Z);\n      tpm_bn_import(Z, sizeof(session->DAA_session.DAA_scratch), -1, \n        session->DAA_session.DAA_scratch);\n      /* Set DAA_session->DAA_scratch = Z*(X^Y) mod n */\n      memset(session->DAA_session.DAA_scratch, 0, \n        sizeof(session->DAA_session.DAA_scratch));\n      tpm_bn_init(tmp);\n      tpm_bn_powm(tmp, X, Y, n);\n      tpm_bn_mul(tmp, tmp, Z);\n      tpm_bn_mod(tmp, tmp, n);\n      tpm_bn_export(session->DAA_session.DAA_scratch, NULL, -1, tmp);\n      tpm_bn_clear(X), tpm_bn_clear(Y), tpm_bn_clear(Z), tpm_bn_clear(n), tpm_bn_clear(tmp);\n      /* Set outputData = NULL */\n      *outputSize = 0, *outputData = NULL;\n      /* Increment DAA_session->DAA_stage by 1 */\n      session->DAA_session.DAA_stage++;\n      /* Return TPM_SUCCESS */\n      return TPM_SUCCESS;\n    }\n    case 4:\n    {\n      /* Verify that DAA_session->DAA_stage == 4. Return TPM_DAA_STAGE \n       * and flush handle on mismatch */\n      if (session->DAA_session.DAA_stage != 4) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_STAGE;\n      }\n      /* Verify that DAA_tpmSpecific->DAA_digestIssuer == \n       * SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS \n       * on mismatch */\n      if (tpm_daa_verify_digestIssuer(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_ISSUER_SETTINGS;\n      }\n      /* Verify that DAA_session->DAA_digestContext == SHA-1(DAA_tpmSpecific) \n       * and return error TPM_DAA_TPM_SETTINGS on mismatch */\n      if (tpm_daa_verify_digestContext_sign(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_TPM_SETTINGS;\n      }\n      /* Set DAA_generic_S0 = inputData0 */\n      DAA_generic_S0 = inputData0;\n      /* Verify that SHA-1(DAA_generic_S0) == \n       * DAA_issuerSettings->DAA_digest_S0 and return error \n       * TPM_DAA_INPUT_DATA0 on mismatch */\n      if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_S0, \n        DAA_generic_S0, inputSize0, &sha1)) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA0;\n      }\n      /* Set DAA_generic_n = inputData1 */\n      DAA_generic_n = inputData1;\n      /* Verify that SHA-1(DAA_generic_n) == DAA_issuerSettings->DAA_digest_n \n       * and return error TPM_DAA_INPUT_DATA1 on mismatch */\n      if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_n, \n        DAA_generic_n, inputSize1, &sha1)) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA1;\n      }\n      /* Obtain DAA_SIZE_r2 bits from MGF1(\"r2\", \n       * DAA_session->DAA_contextSeed), and label them Y */\n      memset(scratch, 0, sizeof(scratch));\n      memcpy(mgf1_seed, \"r2\", 2);\n      memcpy(mgf1_seed + 2, session->DAA_session.DAA_contextSeed.nonce, \n        sizeof(TPM_NONCE));\n      tpm_rsa_mask_generation(mgf1_seed, sizeof(mgf1_seed), scratch, DAA_SIZE_r2);\n      tpm_bn_init(Y);\n      tpm_bn_import(Y, DAA_SIZE_r2, 1, scratch);\n      /* Set X = DAA_generic_S0 */\n      tpm_bn_init(X);\n      tpm_bn_import(X, inputSize0, 1, DAA_generic_S0);\n      /* Set n = DAA_generic_n */\n      tpm_bn_init(n);\n      tpm_bn_import(n, inputSize1, 1, DAA_generic_n);\n      /* Set Z = DAA_session->DAA_scratch */\n      tpm_bn_init(Z);\n      tpm_bn_import(Z, sizeof(session->DAA_session.DAA_scratch), -1, \n        session->DAA_session.DAA_scratch);\n      /* Set DAA_session->DAA_scratch = Z*(X^Y) mod n */\n      memset(session->DAA_session.DAA_scratch, 0, \n        sizeof(session->DAA_session.DAA_scratch));\n      tpm_bn_init(tmp);\n      tpm_bn_powm(tmp, X, Y, n);\n      tpm_bn_mul(tmp, tmp, Z);\n      tpm_bn_mod(tmp, tmp, n);\n      tpm_bn_export(session->DAA_session.DAA_scratch, NULL, -1, tmp);\n      tpm_bn_clear(X), tpm_bn_clear(Y), tpm_bn_clear(Z), tpm_bn_clear(n), tpm_bn_clear(tmp);\n      /* Set outputData = NULL */\n      *outputSize = 0, *outputData = NULL;\n      /* Increment DAA_session->DAA_stage by 1 */\n      session->DAA_session.DAA_stage++;\n      /* Return TPM_SUCCESS */\n      return TPM_SUCCESS;\n    }\n    case 5:\n    {\n      /* Verify that DAA_session->DAA_stage == 5. Return TPM_DAA_STAGE \n       * and flush handle on mismatch */\n      if (session->DAA_session.DAA_stage != 5) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_STAGE;\n      }\n      /* Verify that DAA_tpmSpecific->DAA_digestIssuer == \n       * SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS \n       * on mismatch */\n      if (tpm_daa_verify_digestIssuer(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_ISSUER_SETTINGS;\n      }\n      /* Verify that DAA_session->DAA_digestContext == SHA-1(DAA_tpmSpecific) \n       * and return error TPM_DAA_TPM_SETTINGS on mismatch */\n      if (tpm_daa_verify_digestContext_sign(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_TPM_SETTINGS;\n      }\n      /* Set DAA_generic_S1 = inputData0 */\n      DAA_generic_S1 = inputData0;\n      /* Verify that SHA-1(DAA_generic_S1) == \n       * DAA_issuerSettings->DAA_digest_S1 and return error \n       * TPM_DAA_INPUT_DATA0 on mismatch */\n      if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_S1, \n        DAA_generic_S1, inputSize0, &sha1)) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA0;\n      }\n      /* Set DAA_generic_n = inputData1 */\n      DAA_generic_n = inputData1;\n      /* Verify that SHA-1(DAA_generic_n) == DAA_issuerSettings->DAA_digest_n \n       * and return error TPM_DAA_INPUT_DATA1 on mismatch */\n      if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_n, \n        DAA_generic_n, inputSize1, &sha1)) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA1;\n      }\n      /* Obtain DAA_SIZE_r4 bits from MGF1(\"r4\", \n       * DAA_session->DAA_contextSeed), and label them Y */\n      memset(scratch, 0, sizeof(scratch));\n      memcpy(mgf1_seed, \"r4\", 2);\n      memcpy(mgf1_seed + 2, session->DAA_session.DAA_contextSeed.nonce, \n        sizeof(TPM_NONCE));\n      tpm_rsa_mask_generation(mgf1_seed, sizeof(mgf1_seed), scratch, DAA_SIZE_r4);\n      tpm_bn_init(Y);\n      tpm_bn_import(Y, DAA_SIZE_r4, 1, scratch);\n      /* Set X = DAA_generic_S1 */\n      tpm_bn_init(X);\n      tpm_bn_import(X, inputSize0, 1, DAA_generic_S1);\n      /* Set n = DAA_generic_n */\n      tpm_bn_init(n);\n      tpm_bn_import(n, inputSize1, 1, DAA_generic_n);\n      /* Set Z = DAA_session->DAA_scratch */\n      tpm_bn_init(Z);\n      tpm_bn_import(Z, sizeof(session->DAA_session.DAA_scratch), -1, \n        session->DAA_session.DAA_scratch);\n      /* Set DAA_session->DAA_scratch = Z*(X^Y) mod n */\n      memset(session->DAA_session.DAA_scratch, 0, \n        sizeof(session->DAA_session.DAA_scratch));\n      tpm_bn_init(tmp);\n      tpm_bn_powm(tmp, X, Y, n);\n      tpm_bn_mul(tmp, tmp, Z);\n      tpm_bn_mod(tmp, tmp, n);\n      tpm_bn_export(session->DAA_session.DAA_scratch, &size, 1, tmp);\n      *outputSize = (uint32_t)size;\n      tpm_bn_clear(X), tpm_bn_clear(Y), tpm_bn_clear(Z), tpm_bn_clear(n), tpm_bn_clear(tmp);\n      /* Set outputData = DAA_session->DAA_scratch */\n      if ((*outputData = tpm_malloc(*outputSize)) != NULL)\n        memcpy(*outputData, session->DAA_session.DAA_scratch, *outputSize);\n      else {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_NOSPACE;\n      }\n      /* Set DAA_session->DAA_scratch = NULL */\n      memset(session->DAA_session.DAA_scratch, 0, \n        sizeof(session->DAA_session.DAA_scratch));\n      /* Increment DAA_session->DAA_stage by 1 */\n      session->DAA_session.DAA_stage++;\n      /* Return TPM_SUCCESS */\n      return TPM_SUCCESS;\n    }\n    case 6:\n    {\n      /* Verify that DAA_session->DAA_stage == 6. Return TPM_DAA_STAGE \n       * and flush handle on mismatch */\n      if (session->DAA_session.DAA_stage != 6) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_STAGE;\n      }\n      /* Verify that DAA_tpmSpecific->DAA_digestIssuer == \n       * SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS \n       * on mismatch */\n      if (tpm_daa_verify_digestIssuer(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_ISSUER_SETTINGS;\n      }\n      /* Verify that DAA_session->DAA_digestContext == SHA-1(DAA_tpmSpecific) \n       * and return error TPM_DAA_TPM_SETTINGS on mismatch */\n      if (tpm_daa_verify_digestContext_sign(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_TPM_SETTINGS;\n      }\n      /* Set DAA_generic_gamma = inputData0 */\n      DAA_generic_gamma = inputData0;\n      /* Verify that SHA-1(DAA_generic_gamma) == \n       * DAA_issuerSettings->DAA_digest_gamma and return error \n       * TPM_DAA_INPUT_DATA0 on mismatch */\n      if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_gamma, \n        DAA_generic_gamma, inputSize0, &sha1)) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA0;\n      }\n      /* Verify that inputSize1 == DAA_SIZE_w and return error \n       * TPM_DAA_INPUT_DATA1 on mismatch */\n      if (inputSize1 != DAA_SIZE_w) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_INPUT_DATA1;\n      }\n      /* Set w = inputData1 */\n      tpm_bn_init(w);\n      tpm_bn_import(w, inputSize1, 1, inputData1);\n      /* Set w1 = w^(DAA_issuerSettings->DAA_generic_q) mod \n       * (DAA_generic_gamma) */\n      tpm_bn_init(gamma);\n      tpm_bn_import(gamma, inputSize0, 1, DAA_generic_gamma);\n      tpm_bn_init(q);\n      tpm_bn_import(q, sizeof(session->DAA_issuerSettings.DAA_generic_q), \n        1, session->DAA_issuerSettings.DAA_generic_q);\n      tpm_bn_init(w1);\n      tpm_bn_powm(w1, w, q, gamma);\n      /* If w1 != 1 (unity), return error TPM_DAA_WRONG_W */\n      if (tpm_bn_cmp_ui(w1, 1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_WRONG_W;\n      }\n      /* Set DAA_session->DAA_scratch = w */\n      memset(session->DAA_session.DAA_scratch, 0, \n        sizeof(session->DAA_session.DAA_scratch));\n      tpm_bn_export(session->DAA_session.DAA_scratch, NULL, -1, w);\n      tpm_bn_clear(w), tpm_bn_clear(gamma), tpm_bn_clear(w1), tpm_bn_clear(q);\n      /* Set outputData = NULL */\n      *outputSize = 0, *outputData = NULL;\n      /* Increment DAA_session->DAA_stage by 1 */\n      session->DAA_session.DAA_stage++;\n      /* Return TPM_SUCCESS */\n      return TPM_SUCCESS;\n    }\n    case 7:\n    {\n      /* Verify that DAA_session->DAA_stage == 7. Return TPM_DAA_STAGE \n       * and flush handle on mismatch */\n      if (session->DAA_session.DAA_stage != 7) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_STAGE;\n      }\n      /* Verify that DAA_tpmSpecific->DAA_digestIssuer == \n       * SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS \n       * on mismatch */\n      if (tpm_daa_verify_digestIssuer(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_ISSUER_SETTINGS;\n      }\n      /* Verify that DAA_session->DAA_digestContext == SHA-1(DAA_tpmSpecific) \n       * and return error TPM_DAA_TPM_SETTINGS on mismatch */\n      if (tpm_daa_verify_digestContext_sign(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_TPM_SETTINGS;\n      }\n      /* Set DAA_generic_gamma = inputData0 */\n      DAA_generic_gamma = inputData0;\n      /* Verify that SHA-1(DAA_generic_gamma) == \n       * DAA_issuerSettings->DAA_digest_gamma and return error \n       * TPM_DAA_INPUT_DATA0 on mismatch */\n      if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_gamma, \n        DAA_generic_gamma, inputSize0, &sha1)) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA0;\n      }\n      /* Set f = SHA-1(DAA_tpmSpecific->DAA_rekey || \n       * DAA_tpmSpecific->DAA_count || 0) || SHA-1(DAA_tpmSpecific->DAA_rekey \n       * || DAA_tpmSpecific->DAA_count || 1) mod \n       * DAA_issuerSettings->DAA_generic_q. */\n      tpm_sha1_init(&sha1);\n      tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_rekey, \n          sizeof(session->DAA_tpmSpecific.DAA_rekey));\n      tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count, \n          sizeof(session->DAA_tpmSpecific.DAA_count));\n      tpm_sha1_update(&sha1, DAA_LABEL_00, 1);\n      tpm_sha1_final(&sha1, scratch);\n      tpm_sha1_init(&sha1);\n      tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_rekey, \n          sizeof(session->DAA_tpmSpecific.DAA_rekey));\n      tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count, \n          sizeof(session->DAA_tpmSpecific.DAA_count));\n      tpm_sha1_update(&sha1, DAA_LABEL_01, 1);\n      tpm_sha1_final(&sha1, scratch + SHA1_DIGEST_LENGTH);\n      tpm_bn_init(f), tpm_bn_init(q);\n      tpm_bn_import(f, 2 * SHA1_DIGEST_LENGTH, 1, scratch);\n      tpm_bn_import(q, sizeof(session->DAA_issuerSettings.DAA_generic_q), \n        1, session->DAA_issuerSettings.DAA_generic_q);\n      tpm_bn_mod(f, f, q);\n      /* Set E = ((DAA_session->DAA_scratch)^f) mod (DAA_generic_gamma).*/\n      tpm_bn_init(gamma);\n      tpm_bn_import(gamma, inputSize0, 1, DAA_generic_gamma);\n      tpm_bn_init(w);\n      tpm_bn_import(w, sizeof(session->DAA_session.DAA_scratch), -1, \n        session->DAA_session.DAA_scratch);\n      tpm_bn_init(E);\n      tpm_bn_powm(E, w, f, gamma);\n      /* Set outputData = E */\n      tpm_bn_export(scratch, &size, 1, E);\n      *outputSize = (uint32_t)size;\n      tpm_bn_clear(f), tpm_bn_clear(q), tpm_bn_clear(gamma), tpm_bn_clear(w), tpm_bn_clear(E);\n      if ((*outputData = tpm_malloc(*outputSize)) != NULL)\n        memcpy(*outputData, scratch, *outputSize);\n      else {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_NOSPACE;\n      }\n      /* Increment DAA_session->DAA_stage by 1 */\n      session->DAA_session.DAA_stage++;\n      /* Return TPM_SUCCESS */\n      return TPM_SUCCESS;\n    }\n    case 8:\n    {\n      /* Verify that DAA_session->DAA_stage == 8. Return TPM_DAA_STAGE \n       * and flush handle on mismatch */\n      if (session->DAA_session.DAA_stage != 8) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_STAGE;\n      }\n      /* Verify that DAA_tpmSpecific->DAA_digestIssuer == \n       * SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS \n       * on mismatch */\n      if (tpm_daa_verify_digestIssuer(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_ISSUER_SETTINGS;\n      }\n      /* Verify that DAA_session->DAA_digestContext == SHA-1(DAA_tpmSpecific) \n       * and return error TPM_DAA_TPM_SETTINGS on mismatch */\n      if (tpm_daa_verify_digestContext_sign(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_TPM_SETTINGS;\n      }\n      /* Set DAA_generic_gamma = inputData0 */\n      DAA_generic_gamma = inputData0;\n      /* Verify that SHA-1(DAA_generic_gamma) == \n       * DAA_issuerSettings->DAA_digest_gamma and return error \n       * TPM_DAA_INPUT_DATA0 on mismatch */\n      if (tpm_daa_verify_generic(session->DAA_issuerSettings.DAA_digest_gamma, \n        DAA_generic_gamma, inputSize0, &sha1)) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA0;\n      }\n      /* Obtain DAA_SIZE_r0 bits from MGF1(\"r0\", \n       * DAA_session->DAA_contextSeed), and label them r0 */\n      memset(scratch, 0, sizeof(scratch));\n      memcpy(mgf1_seed, \"r0\", 2);\n      memcpy(mgf1_seed + 2, session->DAA_session.DAA_contextSeed.nonce, \n        sizeof(TPM_NONCE));\n      tpm_rsa_mask_generation(mgf1_seed, sizeof(mgf1_seed), scratch, DAA_SIZE_r0);\n      tpm_bn_init(r0);\n      tpm_bn_import(r0, DAA_SIZE_r0, 1, scratch);\n      /* Obtain DAA_SIZE_r1 bits from MGF1(\"r1\", \n       * DAA_session->DAA_contextSeed), and label them r1 */\n      memset(scratch, 0, sizeof(scratch));\n      memcpy(mgf1_seed, \"r1\", 2);\n      memcpy(mgf1_seed + 2, session->DAA_session.DAA_contextSeed.nonce, \n        sizeof(TPM_NONCE));\n      tpm_rsa_mask_generation(mgf1_seed, sizeof(mgf1_seed), scratch, DAA_SIZE_r1);\n      tpm_bn_init(r1);\n      tpm_bn_import(r1, DAA_SIZE_r1, 1, scratch);\n      /* Set r = r0 + 2^DAA_power0 * r1 mod \n       * (DAA_issuerSettings->DAA_generic_q). */\n      tpm_bn_init(q);\n      tpm_bn_import(q, sizeof(session->DAA_issuerSettings.DAA_generic_q), \n        1, session->DAA_issuerSettings.DAA_generic_q);\n      tpm_bn_init(r);\n      tpm_bn_ui_pow_ui(r, 2, DAA_power0);\n      tpm_bn_mul(r, r, r1);\n      tpm_bn_mod(r, r, q);\n      tpm_bn_add(r, r, r0);\n      tpm_bn_mod(r, r, q);\n      /* Set E1 = ((DAA_session->DAA_scratch)^r) mod (DAA_generic_gamma). */\n      tpm_bn_init(gamma);\n      tpm_bn_import(gamma, inputSize0, 1, DAA_generic_gamma);\n      tpm_bn_init(w);\n      tpm_bn_import(w, sizeof(session->DAA_session.DAA_scratch), -1, \n        session->DAA_session.DAA_scratch);\n      tpm_bn_init(E1);\n      tpm_bn_powm(E1, w, r, gamma);\n      /* Set DAA_session->DAA_scratch = NULL */\n      memset(session->DAA_session.DAA_scratch, 0, \n        sizeof(session->DAA_session.DAA_scratch));\n      /* Set outputData = E1 */\n      tpm_bn_export(scratch, &size, 1, E1);\n      *outputSize = (uint32_t)size;\n      tpm_bn_clear(r0), tpm_bn_clear(r1), tpm_bn_clear(q), tpm_bn_clear(r);\n      tpm_bn_clear(gamma), tpm_bn_clear(w), tpm_bn_clear(E1);\n      if ((*outputData = tpm_malloc(*outputSize)) != NULL)\n        memcpy(*outputData, scratch, *outputSize);\n      else {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_NOSPACE;\n      }\n      /* Increment DAA_session->DAA_stage by 1 */\n      session->DAA_session.DAA_stage++;\n      /* Return TPM_SUCCESS */\n      return TPM_SUCCESS;\n    }\n    case 9:\n    {\n      BYTE *NT = NULL;\n      \n      /* Verify that DAA_session->DAA_stage == 9. Return TPM_DAA_STAGE \n       * and flush handle on mismatch */\n      if (session->DAA_session.DAA_stage != 9) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_STAGE;\n      }\n      /* Verify that DAA_tpmSpecific->DAA_digestIssuer == \n       * SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS \n       * on mismatch */\n      if (tpm_daa_verify_digestIssuer(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_ISSUER_SETTINGS;\n      }\n      /* Verify that DAA_session->DAA_digestContext == SHA-1(DAA_tpmSpecific) \n       * and return error TPM_DAA_TPM_SETTINGS on mismatch */\n      if (tpm_daa_verify_digestContext_sign(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_TPM_SETTINGS;\n      }\n      /* Verify that inputSize0 == sizeOf(TPM_DIGEST) and return error \n       * TPM_DAA_INPUT_DATA0 on mismatch */\n      if (inputSize0 != sizeof(TPM_DIGEST)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_INPUT_DATA0;\n      }\n      /* Set DAA_session->DAA_digest = inputData0 */\n      memcpy(&session->DAA_session.DAA_digest, inputData0, inputSize0);\n      /* Obtain DAA_SIZE_NT bytes from the RNG and label them NT */\n      if ((NT = tpm_malloc(DAA_SIZE_NT)) == NULL) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_NOSPACE;\n      }\n      tpm_get_random_bytes(NT, DAA_SIZE_NT);\n      /* Set DAA_session->DAA_digest to the SHA-1(DAA_session->DAA_digest || \n       * NT)*/\n      tpm_sha1_init(&sha1);\n      tpm_sha1_update(&sha1, (BYTE*) &session->DAA_session.DAA_digest, \n          sizeof(session->DAA_session.DAA_digest));\n      tpm_sha1_update(&sha1, NT, DAA_SIZE_NT);\n      tpm_sha1_final(&sha1, session->DAA_session.DAA_digest.digest);\n      /* Set outputData = NT */\n      *outputSize = DAA_SIZE_NT;\n      if ((*outputData = tpm_malloc(*outputSize)) != NULL)\n        memcpy(*outputData, NT, *outputSize);\n      else {\n        tpm_free(NT);\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_NOSPACE;\n      }\n      tpm_free(NT);\n      /* Increment DAA_session->DAA_stage by 1 */\n      session->DAA_session.DAA_stage++;\n      /* Return TPM_SUCCESS */\n      return TPM_SUCCESS;\n    }\n    case 10:\n    {\n      /* Verify that DAA_session->DAA_stage == 10. Return TPM_DAA_STAGE \n       * and flush handle on mismatch */\n      if (session->DAA_session.DAA_stage != 10) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_STAGE;\n      }\n      /* Verify that DAA_tpmSpecific->DAA_digestIssuer == \n       * SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS \n       * on mismatch */\n      if (tpm_daa_verify_digestIssuer(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_ISSUER_SETTINGS;\n      }\n      /* Verify that DAA_session->DAA_digestContext == SHA-1(DAA_tpmSpecific) \n       * and return error TPM_DAA_TPM_SETTINGS on mismatch */\n      if (tpm_daa_verify_digestContext_sign(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_TPM_SETTINGS;\n      }\n      /* Set selector = inputData0, verify that selector == 0 or 1, and \n       * return error TPM_DAA_INPUT_DATA0 on mismatch */\n      if (inputSize0 != sizeof(selector)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_INPUT_DATA0;\n      }\n      memcpy(&selector, inputData0, sizeof(selector));\n      if ((selector != '\\x00') && (selector != '\\x01')) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_INPUT_DATA0;\n      }\n      /* If selector == 1, verify that inputSize1 == sizeOf(TPM_DIGEST), and */\n      if (selector == '\\x01') {\n        debug(\"DAA_Sign(): selector == 1\");\n        if (inputSize1 != sizeof(TPM_DIGEST)) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA1;\n        }\n        /* Set DAA_session->DAA_digest to SHA-1(DAA_session->DAA_digest || \n         * 1 || inputData1) */\n        tpm_sha1_init(&sha1);\n        tpm_sha1_update(&sha1, (BYTE*) &session->DAA_session.DAA_digest, \n          sizeof(session->DAA_session.DAA_digest));\n        tpm_sha1_update(&sha1, DAA_LABEL_01, 1);\n        tpm_sha1_update(&sha1, inputData1, inputSize1);\n        tpm_sha1_final(&sha1, (BYTE*) &session->DAA_session.DAA_digest);\n      }\n      /* If selector == 0, verify that inputData1 is a handle to a TPM \n       * identity key (AIK), and */\n      if (selector == '\\x00') {\n        debug(\"DAA_Sign(): selector == 0\");\n        if (tpm_unmarshal_TPM_KEY_HANDLE(&inputData1, &inputSize1, \n          &aikHandle) || (inputSize1 != 0))\n        {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA1;\n        }\n        debug(\"DAA_Sign(): aikHandle == %.8x\", aikHandle);\n        aikData = tpm_get_key(aikHandle);\n        if (aikData == NULL) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA1;\n        }\n        if (aikData->keyUsage != TPM_KEY_IDENTITY) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA1;\n        }\n        /* Set DAA_session->DAA_digest to SHA-1(DAA_session->DAA_digest || \n         * 0 || n2) where n2 is the modulus of the AIK */\n        tpm_sha1_init(&sha1);\n        tpm_sha1_update(&sha1, (BYTE*) &session->DAA_session.DAA_digest, \n          sizeof(session->DAA_session.DAA_digest));\n        tpm_sha1_update(&sha1, DAA_LABEL_00, 1);\n        tpm_rsa_export_modulus(&aikData->key, scratch, &size);\n        tpm_sha1_update(&sha1, scratch, size);\n        tpm_sha1_final(&sha1, (BYTE*) &session->DAA_session.DAA_digest);\n      }\n      /* Set outputData = DAA_session->DAA_digest */\n      *outputSize = sizeof(session->DAA_session.DAA_digest);\n      if ((*outputData = tpm_malloc(*outputSize)) != NULL)\n        memcpy(*outputData, &session->DAA_session.DAA_digest, *outputSize);\n      else {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_NOSPACE;\n      }\n      /* Increment DAA_session->DAA_stage by 1 */\n      session->DAA_session.DAA_stage++;\n      /* Return TPM_SUCCESS */\n      return TPM_SUCCESS;\n    }\n    case 11:\n    {\n      /* Verify that DAA_session->DAA_stage == 11. Return TPM_DAA_STAGE \n       * and flush handle on mismatch */\n      if (session->DAA_session.DAA_stage != 11) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_STAGE;\n      }\n      /* Verify that DAA_tpmSpecific->DAA_digestIssuer == \n       * SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS \n       * on mismatch */\n      if (tpm_daa_verify_digestIssuer(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_ISSUER_SETTINGS;\n      }\n      /* Verify that DAA_session->DAA_digestContext == SHA-1(DAA_tpmSpecific) \n       * and return error TPM_DAA_TPM_SETTINGS on mismatch */\n      if (tpm_daa_verify_digestContext_sign(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_TPM_SETTINGS;\n      }\n      /* Obtain DAA_SIZE_r0 bits from MGF1(\"r0\", \n       * DAA_session->DAA_contextSeed), and label them r0 */\n      memset(scratch, 0, sizeof(scratch));\n      memcpy(mgf1_seed, \"r0\", 2);\n      memcpy(mgf1_seed + 2, session->DAA_session.DAA_contextSeed.nonce, \n        sizeof(TPM_NONCE));\n      tpm_rsa_mask_generation(mgf1_seed, sizeof(mgf1_seed), scratch, DAA_SIZE_r0);\n      tpm_bn_init(r0);\n      tpm_bn_import(r0, DAA_SIZE_r0, 1, scratch);\n      /* Set f = SHA1(DAA_tpmSpecific->DAA_rekey || \n       * DAA_tpmSpecific->DAA_count || 0 ) || \n       * SHA1(DAA_tpmSpecific->DAA_rekey || DAA_tpmSpecific->DAA_count || \n       * 1 ) mod DAA_issuerSettings->DAA_generic_q */\n      tpm_sha1_init(&sha1);\n      tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_rekey, \n          sizeof(session->DAA_tpmSpecific.DAA_rekey));\n      tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count, \n          sizeof(session->DAA_tpmSpecific.DAA_count));\n      tpm_sha1_update(&sha1, DAA_LABEL_00, 1);\n      tpm_sha1_final(&sha1, scratch);\n      tpm_sha1_init(&sha1);\n      tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_rekey, \n          sizeof(session->DAA_tpmSpecific.DAA_rekey));\n      tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count, \n          sizeof(session->DAA_tpmSpecific.DAA_count));\n      tpm_sha1_update(&sha1, DAA_LABEL_01, 1);\n      tpm_sha1_final(&sha1, scratch + SHA1_DIGEST_LENGTH);\n      tpm_bn_init(f), tpm_bn_init(q);\n      tpm_bn_import(f, 2 * SHA1_DIGEST_LENGTH, 1, scratch);\n      tpm_bn_import(q, sizeof(session->DAA_issuerSettings.DAA_generic_q), \n        1, session->DAA_issuerSettings.DAA_generic_q);\n      tpm_bn_mod(f, f, q);\n      /* Set f0 = f mod 2^DAA_power0 (erase all but the lowest DAA_power0 \n       * bits of f) */\n      tpm_bn_init(f0);\n      tpm_bn_init(tmp);\n      tpm_bn_ui_pow_ui(tmp, 2, DAA_power0);\n      tpm_bn_mod(f0, f, tmp);\n      /* Set s0 = r0 + (DAA_session->DAA_digest) * (f0) */\n      tpm_bn_init(s0);\n      tpm_bn_import(tmp, sizeof(session->DAA_session.DAA_digest.digest), \n        1, session->DAA_session.DAA_digest.digest);\n      tpm_bn_mul(s0, tmp, f0);\n      tpm_bn_add(s0, r0, s0);\n      /* Set outputData = s0 */\n      tpm_bn_export(scratch, &size, 1, s0);\n      *outputSize = (uint32_t)size;\n      tpm_bn_clear(r0), tpm_bn_clear(f), tpm_bn_clear(q), tpm_bn_clear(f0);\n      tpm_bn_clear(s0), tpm_bn_clear(tmp);\n      if ((*outputData = tpm_malloc(*outputSize)) != NULL)\n        memcpy(*outputData, scratch, *outputSize);\n      else {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_NOSPACE;\n      }\n      /* Increment DAA_session->DAA_stage by 1 */\n      session->DAA_session.DAA_stage++;\n      /* Return TPM_SUCCESS */\n      return TPM_SUCCESS;\n    }\n    case 12:\n    {\n      /* Verify that DAA_session->DAA_stage == 12. Return TPM_DAA_STAGE \n       * and flush handle on mismatch */\n      if (session->DAA_session.DAA_stage != 12) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_STAGE;\n      }\n      /* Verify that DAA_tpmSpecific->DAA_digestIssuer == \n       * SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS \n       * on mismatch */\n      if (tpm_daa_verify_digestIssuer(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_ISSUER_SETTINGS;\n      }\n      /* Verify that DAA_session->DAA_digestContext == SHA-1(DAA_tpmSpecific) \n       * and return error TPM_DAA_TPM_SETTINGS on mismatch */\n      if (tpm_daa_verify_digestContext_sign(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_TPM_SETTINGS;\n      }\n      /* Obtain DAA_SIZE_r1 bits from MGF1(\"r1\", \n       * DAA_session->DAA_contextSeed), and label them r1 */\n      memset(scratch, 0, sizeof(scratch));\n      memcpy(mgf1_seed, \"r1\", 2);\n      memcpy(mgf1_seed + 2, session->DAA_session.DAA_contextSeed.nonce, \n        sizeof(TPM_NONCE));\n      tpm_rsa_mask_generation(mgf1_seed, sizeof(mgf1_seed), scratch, DAA_SIZE_r1);\n      tpm_bn_init(r1);\n      tpm_bn_import(r1, DAA_SIZE_r1, 1, scratch);\n      /* Set f = SHA1(DAA_tpmSpecific->DAA_rekey || \n       * DAA_tpmSpecific->DAA_count || 0 ) || \n       * SHA1(DAA_tpmSpecific->DAA_rekey || DAA_tpmSpecific->DAA_count || \n       * 1 ) mod DAA_issuerSettings->DAA_generic_q */\n      tpm_sha1_init(&sha1);\n      tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_rekey, \n          sizeof(session->DAA_tpmSpecific.DAA_rekey));\n      tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count, \n          sizeof(session->DAA_tpmSpecific.DAA_count));\n      tpm_sha1_update(&sha1, DAA_LABEL_00, 1);\n      tpm_sha1_final(&sha1, scratch);\n      tpm_sha1_init(&sha1);\n      tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_rekey, \n          sizeof(session->DAA_tpmSpecific.DAA_rekey));\n      tpm_sha1_update(&sha1, (BYTE*) &session->DAA_tpmSpecific.DAA_count, \n          sizeof(session->DAA_tpmSpecific.DAA_count));\n      tpm_sha1_update(&sha1, DAA_LABEL_01, 1);\n      tpm_sha1_final(&sha1, scratch + SHA1_DIGEST_LENGTH);\n      tpm_bn_init(f), tpm_bn_init(q);\n      tpm_bn_import(f, 2 * SHA1_DIGEST_LENGTH, 1, scratch);\n      tpm_bn_import(q, sizeof(session->DAA_issuerSettings.DAA_generic_q), \n        1, session->DAA_issuerSettings.DAA_generic_q);\n      tpm_bn_mod(f, f, q);\n      /* Shift f right by DAA_power0 bits (discard the lowest DAA_power0 \n       * bits) and label the result f1 */\n      tpm_bn_init(f1);\n      tpm_bn_fdiv_q_2exp(f1, f, DAA_power0);\n      /* Set s1 = r1 + (DAA_session->DAA_digest) * (f1) */\n      tpm_bn_init(s1);\n      tpm_bn_init(tmp);\n      tpm_bn_import(tmp, sizeof(session->DAA_session.DAA_digest.digest), \n        1, session->DAA_session.DAA_digest.digest);\n      tpm_bn_mul(s1, tmp, f1);\n      tpm_bn_add(s1, r1, s1);\n      /* Set outputData = s1 */\n      tpm_bn_export(scratch, &size, 1, s1);\n      *outputSize = (uint32_t)size;\n      tpm_bn_clear(r1), tpm_bn_clear(f), tpm_bn_clear(q), tpm_bn_clear(f1);\n      tpm_bn_clear(s1), tpm_bn_clear(tmp);\n      if ((*outputData = tpm_malloc(*outputSize)) != NULL)\n        memcpy(*outputData, scratch, *outputSize);\n      else {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_NOSPACE;\n      }\n      /* Increment DAA_session->DAA_stage by 1 */\n      session->DAA_session.DAA_stage++;\n      /* Return TPM_SUCCESS */\n      return TPM_SUCCESS;\n    }\n    case 13:\n    {\n      BYTE *DAA_private_v0 = NULL;\n      \n      /* Verify that DAA_session->DAA_stage == 13. Return TPM_DAA_STAGE \n       * and flush handle on mismatch */\n      if (session->DAA_session.DAA_stage != 13) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_STAGE;\n      }\n      /* Verify that DAA_tpmSpecific->DAA_digestIssuer == \n       * SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS \n       * on mismatch */\n      if (tpm_daa_verify_digestIssuer(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_ISSUER_SETTINGS;\n      }\n      /* Verify that DAA_session->DAA_digestContext == SHA-1(DAA_tpmSpecific) \n       * and return error TPM_DAA_TPM_SETTINGS on mismatch */\n      if (tpm_daa_verify_digestContext_sign(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_TPM_SETTINGS;\n      }\n      /* Set DAA_private_v0 = unwrap(inputData0) */\n      ptr = inputData0, len = inputSize0;\n      if (tpm_unmarshal_TPM_DAA_BLOB(&ptr, &len, &blob) || (len != 0)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_INPUT_DATA0;\n      }\n      sensitive.internalData = scratch;\n      if (decrypt_daa(blob.additionalData, blob.additionalSize, \n        blob.sensitiveData, blob.sensitiveSize, &sensitive, &buf)) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DECRYPT_ERROR;\n      }\n      if (compute_daa_digest(&blob, &digest) || \n        memcmp(&digest, &blob.blobIntegrity, sizeof(TPM_DIGEST))) {\n          tpm_free(buf);\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA0;\n      }\n      if ((blob.resourceType != TPM_RT_DAA_V0) || \n        (sensitive.tag != TPM_TAG_DAA_SENSITIVE || \n        (sensitive.internalSize == 0) || \n        (sensitive.internalSize > DAA_SIZE_v0))) {\n          tpm_free(buf);\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA0;\n      }\n      if ((DAA_private_v0 = tpm_malloc(DAA_SIZE_v0)) == NULL) {\n        tpm_free(buf);\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_NOSPACE;\n      }\n      memcpy(DAA_private_v0, sensitive.internalData, sensitive.internalSize);\n      tpm_free(buf);\n      /* Verify that SHA-1(DAA_private_v0) == DAA_tpmSpecific->DAA_digest_v0 \n       * and return error TPM_DAA_INPUT_DATA0 on mismatch */\n      tpm_sha1_init(&sha1);\n      tpm_sha1_update(&sha1, DAA_private_v0, sensitive.internalSize);\n      tpm_sha1_final(&sha1, (BYTE*) &digest);\n      if (memcmp(&digest, &session->DAA_tpmSpecific.DAA_digest_v0, \n        sizeof(TPM_DIGEST))) {\n          tpm_free(DAA_private_v0);\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA0;\n      }\n      /* Obtain DAA_SIZE_r2 bits from MGF1(\"r2\", \n       * DAA_session->DAA_contextSeed), and label them r2 */\n      memset(scratch, 0, sizeof(scratch));\n      memcpy(mgf1_seed, \"r2\", 2);\n      memcpy(mgf1_seed + 2, session->DAA_session.DAA_contextSeed.nonce, \n        sizeof(TPM_NONCE));\n      tpm_rsa_mask_generation(mgf1_seed, sizeof(mgf1_seed), scratch, DAA_SIZE_r2);\n      tpm_bn_init(r2);\n      tpm_bn_import(r2, DAA_SIZE_r2, 1, scratch);\n      /* Set s2 = r2 + (DAA_session->DAA_digest) * \n       * (DAA_private_v0) mod 2^DAA_power1 \n       * (Erase all but the lowest DAA_power1 bits of s2) */\n      tpm_bn_init(s2);\n      tpm_bn_import(s2, sensitive.internalSize, 1, DAA_private_v0);\n      tpm_free(DAA_private_v0);\n      tpm_bn_init(tmp);\n      tpm_bn_import(tmp, sizeof(session->DAA_session.DAA_digest.digest), \n        1, session->DAA_session.DAA_digest.digest);\n      tpm_bn_mul(s2, tmp, s2);\n      tpm_bn_add(s2, r2, s2);\n      tpm_bn_ui_pow_ui(tmp, 2, DAA_power1);\n      tpm_bn_mod(s2, s2, tmp);\n      /* Set DAA_session->DAA_scratch = s2 */\n      memset(session->DAA_session.DAA_scratch, 0, \n        sizeof(session->DAA_session.DAA_scratch));\n      tpm_bn_export(session->DAA_session.DAA_scratch, NULL, -1, s2);\n      /* Set outputData = s2 */\n      tpm_bn_export(scratch, &size, 1, s2);\n      *outputSize = (uint32_t)size;\n      tpm_bn_clear(r2), tpm_bn_clear(s2), tpm_bn_clear(tmp);\n      if ((*outputData = tpm_malloc(*outputSize)) != NULL)\n        memcpy(*outputData, scratch, *outputSize);\n      else {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_NOSPACE;\n      }\n      /* Increment DAA_session->DAA_stage by 1 */\n      session->DAA_session.DAA_stage++;\n      /* Return TPM_SUCCESS */\n      return TPM_SUCCESS;\n    }\n    case 14:\n    {\n      BYTE *DAA_private_v0 = NULL;\n      \n      /* Verify that DAA_session->DAA_stage == 14. Return TPM_DAA_STAGE \n       * and flush handle on mismatch */\n      if (session->DAA_session.DAA_stage != 14) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_STAGE;\n      }\n      /* Verify that DAA_tpmSpecific->DAA_digestIssuer == \n       * SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS \n       * on mismatch */\n      if (tpm_daa_verify_digestIssuer(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_ISSUER_SETTINGS;\n      }\n      /* Verify that DAA_session->DAA_digestContext == SHA-1(DAA_tpmSpecific) \n       * and return error TPM_DAA_TPM_SETTINGS on mismatch */\n      if (tpm_daa_verify_digestContext_sign(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_TPM_SETTINGS;\n      }\n      /* Set DAA_private_v0 = unwrap(inputData0) */\n      ptr = inputData0, len = inputSize0;\n      if (tpm_unmarshal_TPM_DAA_BLOB(&ptr, &len, &blob) || (len != 0)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_INPUT_DATA0;\n      }\n      sensitive.internalData = scratch;\n      if (decrypt_daa(blob.additionalData, blob.additionalSize, \n        blob.sensitiveData, blob.sensitiveSize, &sensitive, &buf)) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DECRYPT_ERROR;\n      }\n      if (compute_daa_digest(&blob, &digest) || \n        memcmp(&digest, &blob.blobIntegrity, sizeof(TPM_DIGEST))) {\n          tpm_free(buf);\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA0;\n      }\n      if ((blob.resourceType != TPM_RT_DAA_V0) || \n        (sensitive.tag != TPM_TAG_DAA_SENSITIVE || \n        (sensitive.internalSize == 0) || \n        (sensitive.internalSize > DAA_SIZE_v0))) {\n          tpm_free(buf);\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA0;\n      }\n      if ((DAA_private_v0 = tpm_malloc(DAA_SIZE_v0)) == NULL) {\n        tpm_free(buf);\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_NOSPACE;\n      }\n      memcpy(DAA_private_v0, sensitive.internalData, sensitive.internalSize);\n      tpm_free(buf);\n      /* Verify that SHA-1(DAA_private_v0) == DAA_tpmSpecific->DAA_digest_v0 \n       * and return error TPM_DAA_INPUT_DATA0 on mismatch */\n      tpm_sha1_init(&sha1);\n      tpm_sha1_update(&sha1, DAA_private_v0, sensitive.internalSize);\n      tpm_sha1_final(&sha1, (BYTE*) &digest);\n      if (memcmp(&digest, &session->DAA_tpmSpecific.DAA_digest_v0, \n        sizeof(TPM_DIGEST))) {\n          tpm_free(DAA_private_v0);\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA0;\n      }\n      /* Obtain DAA_SIZE_r2 bits from MGF1(\"r2\", \n       * DAA_session->DAA_contextSeed), and label them r2 */\n      memset(scratch, 0, sizeof(scratch));\n      memcpy(mgf1_seed, \"r2\", 2);\n      memcpy(mgf1_seed + 2, session->DAA_session.DAA_contextSeed.nonce, \n        sizeof(TPM_NONCE));\n      tpm_rsa_mask_generation(mgf1_seed, sizeof(mgf1_seed), scratch, DAA_SIZE_r2);\n      tpm_bn_init(r2);\n      tpm_bn_import(r2, DAA_SIZE_r2, 1, scratch);\n      /* Set s12 = r2 + (DAA_session->DAA_digest) * (DAA_private_v0). */\n      tpm_bn_init(s12);\n      tpm_bn_import(s12, sensitive.internalSize, 1, DAA_private_v0);\n      tpm_free(DAA_private_v0);\n      tpm_bn_init(tmp);\n      tpm_bn_import(tmp, sizeof(session->DAA_session.DAA_digest.digest), \n        1, session->DAA_session.DAA_digest.digest);\n      tpm_bn_mul(s12, tmp, s12);\n      tpm_bn_add(s12, r2, s12);\n      /* Shift s12 right by DAA_power1 bits (erase the lowest DAA_power1 \n       * bits). */\n      tpm_bn_fdiv_q_2exp(s12, s12, DAA_power1);\n      /* Set DAA_session->DAA_scratch = s12 */\n      memset(session->DAA_session.DAA_scratch, 0, \n        sizeof(session->DAA_session.DAA_scratch));\n      tpm_bn_export(session->DAA_session.DAA_scratch, NULL, -1, s12);\n      tpm_bn_clear(r2), tpm_bn_clear(s12), tpm_bn_clear(tmp);\n      /* Set outputData = NULL */\n      *outputSize = 0, *outputData = NULL;\n      /* Increment DAA_session->DAA_stage by 1 */\n      session->DAA_session.DAA_stage++;\n      /* Return TPM_SUCCESS */\n      return TPM_SUCCESS;\n    }\n    case 15:\n    {\n      BYTE *DAA_private_v1 = NULL;\n      \n      /* Verify that DAA_session->DAA_stage == 15. Return TPM_DAA_STAGE \n       * and flush handle on mismatch */\n      if (session->DAA_session.DAA_stage != 15) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_STAGE;\n      }\n      /* Verify that DAA_tpmSpecific->DAA_digestIssuer == \n       * SHA-1(DAA_issuerSettings) and return error TPM_DAA_ISSUER_SETTINGS \n       * on mismatch */\n      if (tpm_daa_verify_digestIssuer(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_ISSUER_SETTINGS;\n      }\n      /* Verify that DAA_session->DAA_digestContext == SHA-1(DAA_tpmSpecific) \n       * and return error TPM_DAA_TPM_SETTINGS on mismatch */\n      if (tpm_daa_verify_digestContext_sign(session, &sha1)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_TPM_SETTINGS;\n      }\n      /* Set DAA_private_v1 = unwrap(inputData0) */\n      ptr = inputData0, len = inputSize0;\n      if (tpm_unmarshal_TPM_DAA_BLOB(&ptr, &len, &blob) || (len != 0)) {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_DAA_INPUT_DATA0;\n      }\n      sensitive.internalData = scratch;\n      if (decrypt_daa(blob.additionalData, blob.additionalSize, \n        blob.sensitiveData, blob.sensitiveSize, &sensitive, &buf)) {\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DECRYPT_ERROR;\n      }\n      if (compute_daa_digest(&blob, &digest) || \n        memcmp(&digest, &blob.blobIntegrity, sizeof(TPM_DIGEST))) {\n          tpm_free(buf);\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA0;\n      }\n      if ((blob.resourceType != TPM_RT_DAA_V1) || \n        (sensitive.tag != TPM_TAG_DAA_SENSITIVE || \n        (sensitive.internalSize == 0) || \n        (sensitive.internalSize > DAA_SIZE_v1))) {\n          tpm_free(buf);\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA0;\n      }\n      if ((DAA_private_v1 = tpm_malloc(DAA_SIZE_v1)) == NULL) {\n        tpm_free(buf);\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_NOSPACE;\n      }\n      memcpy(DAA_private_v1, sensitive.internalData, sensitive.internalSize);\n      tpm_free(buf);\n      /* Verify that SHA-1(DAA_private_v1) == DAA_tpmSpecific->DAA_digest_v1 \n       * and return error TPM_DAA_INPUT_DATA0 on mismatch */\n      tpm_sha1_init(&sha1);\n      tpm_sha1_update(&sha1, DAA_private_v1, sensitive.internalSize);\n      tpm_sha1_final(&sha1, (BYTE*) &digest);\n      if (memcmp(&digest, &session->DAA_tpmSpecific.DAA_digest_v1, \n        sizeof(TPM_DIGEST))) {\n          tpm_free(DAA_private_v1);\n          memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n          return TPM_DAA_INPUT_DATA0;\n      }\n      /* Obtain DAA_SIZE_r4 bits from MGF1(\"r4\", \n       * DAA_session->DAA_contextSeed), and label them r4 */\n      memset(scratch, 0, sizeof(scratch));\n      memcpy(mgf1_seed, \"r4\", 2);\n      memcpy(mgf1_seed + 2, session->DAA_session.DAA_contextSeed.nonce, \n        sizeof(TPM_NONCE));\n      tpm_rsa_mask_generation(mgf1_seed, sizeof(mgf1_seed), scratch, DAA_SIZE_r4);\n      tpm_bn_init(r4);\n      tpm_bn_import(r4, DAA_SIZE_r4, 1, scratch);\n      /* Set s3 = r4 + (DAA_session->DAA_digest) * (DAA_private_v1) + \n       * (DAA_session->DAA_scratch). */\n      tpm_bn_init(s3);\n      tpm_bn_import(s3, sensitive.internalSize, 1, DAA_private_v1);\n      tpm_free(DAA_private_v1);\n      tpm_bn_init(tmp);\n      tpm_bn_import(tmp, sizeof(session->DAA_session.DAA_digest.digest), \n        1, session->DAA_session.DAA_digest.digest);\n      tpm_bn_mul(s3, tmp, s3);\n      tpm_bn_add(s3, r4, s3);\n      tpm_bn_import(tmp, sizeof(session->DAA_session.DAA_scratch), \n        -1, session->DAA_session.DAA_scratch);\n      tpm_bn_add(s3, s3, tmp);\n      /* Set DAA_session->DAA_scratch = NULL */\n      memset(session->DAA_session.DAA_scratch, 0, \n        sizeof(session->DAA_session.DAA_scratch));\n      /* Set outputData = s3 */\n      tpm_bn_export(scratch, &size, 1, s3);\n      *outputSize = (uint32_t)size;\n      tpm_bn_clear(r4), tpm_bn_clear(s3), tpm_bn_clear(tmp);\n      if ((*outputData = tpm_malloc(*outputSize)) != NULL)\n        memcpy(*outputData, scratch, *outputSize);\n      else {\n        memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n        return TPM_NOSPACE;\n      }\n      /* Terminate the DAA session and all resources assoociated with the\n       * DAA sign session handle. */\n      memset(session, 0, sizeof(TPM_DAA_SESSION_DATA));\n      /* Return TPM_SUCCESS */\n      return TPM_SUCCESS;\n    }\n    default:\n      return TPM_DAA_STAGE;\n  }\n}\n"
  },
  {
    "path": "tpm/tpm_data.c",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: tpm_data.c 372 2010-02-15 12:52:00Z mast $\n */\n\n#include \"tpm_emulator.h\"\n#include \"tpm_structures.h\"\n#include \"tpm_marshalling.h\"\n#include \"tpm_commands.h\"\n#include \"tpm_data.h\"\n\nTPM_DATA tpmData;\nUINT32 tpmConf;\n\n#ifdef MTM_EMULATOR\n#include \"mtm/mtm_data.h\"\n#include \"mtm/mtm_marshalling.h\"\n#endif\n\nstatic TPM_VERSION tpm_version = { 1, 2, VERSION_MAJOR, VERSION_MINOR };\n\nBOOL tpm_get_physical_presence(void)\n{\n  return (tpmData.stclear.flags.physicalPresence || TRUE);\n}\n\nstatic inline void init_pcr_attr(int pcr, BOOL reset, BYTE rl, BYTE el)\n{\n  tpmData.permanent.data.pcrAttrib[pcr].pcrReset = reset;\n  tpmData.permanent.data.pcrAttrib[pcr].pcrResetLocal = rl;\n  tpmData.permanent.data.pcrAttrib[pcr].pcrExtendLocal = el;\n}\n\nstatic void init_nv_storage(void)\n{\n    TPM_NV_DATA_SENSITIVE *nv;\n    memset(tpmData.permanent.data.nvData, 0xff, TPM_MAX_NV_SIZE);\n    /* init TPM_NV_INDEX_DIR */\n    nv = &tpmData.permanent.data.nvStorage[0];\n    memset(nv, 0, sizeof(TPM_NV_DATA_SENSITIVE));\n    nv->tag = TPM_TAG_NV_DATA_SENSITIVE;\n    nv->pubInfo.tag = TPM_TAG_NV_DATA_PUBLIC;\n    nv->pubInfo.nvIndex = TPM_NV_INDEX_DIR;\n    nv->pubInfo.pcrInfoRead.localityAtRelease = 0x1f;\n    nv->pubInfo.pcrInfoWrite.localityAtRelease = 0x1f;\n    nv->pubInfo.permission.tag = TPM_TAG_NV_ATTRIBUTES;\n    nv->pubInfo.permission.attributes = TPM_NV_PER_OWNERWRITE \n                                        | TPM_NV_PER_WRITEALL;\n    nv->pubInfo.dataSize = 20;\n    nv->dataIndex = 0;\n    nv->valid = TRUE;\n    /* set NV data size */\n    tpmData.permanent.data.nvDataSize = 20;\n}\n\nstatic void init_timeouts(void)\n{\n  /* for the timeouts we use the PC platform defaults */\n  tpmData.permanent.data.tis_timeouts[0] = 750;\n  tpmData.permanent.data.tis_timeouts[1] = 2000;\n  tpmData.permanent.data.tis_timeouts[2] = 750;\n  tpmData.permanent.data.tis_timeouts[3] = 750;\n  tpmData.permanent.data.cmd_durations[0] = 1;\n  tpmData.permanent.data.cmd_durations[1] = 10;\n  tpmData.permanent.data.cmd_durations[2] = 1000;\n}\n\nvoid tpm_init_data(void)\n{\n  /* endorsement key */\n  uint8_t ek_n[] =  \"\\xa8\\xdb\\xa9\\x42\\xa8\\xf3\\xb8\\x06\\x85\\x90\\x76\\x93\\xad\\xf7\"\n    \"\\x74\\xec\\x3f\\xd3\\x3d\\x9d\\xe8\\x2e\\xff\\x15\\xed\\x0e\\xce\\x5f\\x93\"\n    \"\\x92\\xeb\\xd1\\x96\\x2b\\x72\\x18\\x81\\x79\\x12\\x9d\\x9c\\x40\\xd7\\x1a\"\n    \"\\x21\\xda\\x5f\\x56\\xe0\\xc9\\x48\\x31\\xdd\\x96\\xdc\\xbb\\x45\\xc6\\x8e\"\n    \"\\xad\\x58\\x23\\xcb\\xbe\\xbb\\x13\\x2d\\x6b\\x86\\xc5\\x57\\xf5\\xdd\\x48\"\n    \"\\xc1\\x3d\\xcd\\x4d\\xda\\x81\\xc4\\x43\\x17\\xaa\\x05\\x40\\x33\\x62\\x0a\"\n    \"\\x59\\xdb\\x28\\xcd\\xb5\\x08\\x31\\xbb\\x06\\xf5\\xf7\\x71\\xae\\x21\\xa8\"\n    \"\\xf2\\x2f\\x0e\\x17\\x80\\x5d\\x9c\\xdf\\xaa\\xe9\\x89\\x09\\x54\\x65\\x2b\"\n    \"\\x46\\xfb\\x9d\\xb2\\x00\\x70\\x63\\x0d\\x9a\\x6d\\x3d\\x5e\\x11\\x78\\x65\"\n    \"\\x90\\xe6\\x26\\xee\\x77\\xbe\\x08\\xff\\x07\\x60\\x5a\\xcc\\xf1\\x0a\\xbd\"\n    \"\\x44\\x92\\x6b\\xca\\xb6\\xce\\x66\\xf9\\x93\\x40\\xae\\xf3\\x3e\\x53\\x02\"\n    \"\\x3c\\xa6\\x81\\xb3\\xbe\\xad\\x6e\\x6c\\xa6\\xf0\\xeb\\xdf\\xe9\\xa2\\x83\"\n    \"\\x36\\x0e\\x52\\x0d\\x64\\x17\\xd9\\xff\\xa1\\x74\\x7c\\x2b\\xbc\\x6a\\xcc\"\n    \"\\xe5\\x4e\\xb4\\x52\\xd9\\xec\\x43\\xbd\\x26\\x6a\\x2b\\x19\\x19\\x6e\\x97\"\n    \"\\xb8\\x1d\\x9f\\x7b\\xe7\\x32\\x2d\\xdd\\x7c\\x51\\xc8\\xe4\\xf3\\x02\\xd4\"\n    \"\\x7c\\x90\\x44\\xa0\\x33\\x72\\x81\\x75\\xa9\\x16\\x27\\x5c\\x00\\x1d\\x07\"\n    \"\\x81\\xd4\\xf7\\xac\\xcb\\xfe\\xd6\\x60\\x03\\x6f\\x7a\\xcc\\x00\\xd1\\xc4\"\n    \"\\x85\\x37\";\n  uint8_t ek_e[] = \"\\x01\\x00\\x01\";\n  uint8_t ek_p[] = \"\\xd7\\xea\\x61\\x15\\x8b\\xa3\\x71\\xdf\\xa8\\x74\\x77\\xca\\x88\\x95\"\n    \"\\xd0\\x76\\x17\\x43\\x2c\\xf6\\x23\\x27\\x44\\xb9\\x0e\\x18\\x35\\x7e\\xe4\"\n    \"\\xc3\\xcb\\x13\\x6e\\xfc\\x38\\x02\\x1e\\x77\\x26\\x40\\x9d\\x17\\xb2\\x39\"\n    \"\\x9c\\x7f\\x5f\\x98\\xe6\\xf2\\x55\\x0c\\x12\\x05\\x4c\\xb3\\x51\\xae\\x29\"\n    \"\\xe7\\xcd\\xce\\x41\\x0b\\x28\\x4d\\x97\\x13\\x4b\\x60\\xc8\\xd8\\x70\\x81\"\n    \"\\xf9\\x1c\\x12\\x44\\xdf\\x53\\x0a\\x87\\x9d\\x33\\x92\\x4a\\x34\\x69\\xf0\"\n    \"\\x70\\x5e\\x1b\\x5d\\x65\\xc7\\x84\\x90\\xa2\\x62\\xdf\\x83\\x14\\x10\\x69\"\n    \"\\xe2\\xa7\\x18\\x43\\xd7\\x1f\\x60\\xc9\\x03\\x8f\\xd6\\xa4\\xce\\xb2\\x9d\"\n    \"\\x40\\x37\\x70\\x17\\x4c\\xe3\\x69\\xd4\\x59\";\n  uint8_t ek_q[] = \"\\xc8\\x34\\xd2\\xd0\\x7c\\xfa\\xdc\\x68\\xe2\\x72\\xd7\\x92\\xe2\\x50\"\n    \"\\x93\\xfc\\xbb\\x72\\x55\\x4d\\x6b\\x7a\\x0c\\x0b\\xcf\\x87\\x66\\x1f\\x81\"\n    \"\\x71\\xf3\\x50\\xcb\\xaa\\xe6\\x43\\x7e\\xbe\\x11\\xc4\\xec\\x00\\x53\\xf4\"\n    \"\\x78\\x13\\x2b\\x59\\x26\\x4a\\x9f\\x91\\x61\\x8f\\xa7\\x07\\x64\\x11\\x5a\"\n    \"\\xf4\\xaf\\x9c\\x9b\\x5a\\x5d\\x69\\x20\\x17\\x55\\x74\\xba\\xd8\\xe4\\x59\"\n    \"\\x39\\x1a\\x0a\\x7b\\x4a\\x30\\xf0\\xc8\\x7f\\xd9\\xaf\\x72\\xc5\\xb6\\x71\"\n    \"\\xd1\\xc0\\x8b\\x5b\\xa2\\x2e\\xa7\\x15\\xca\\x50\\x75\\x10\\x48\\x9c\\x2b\"\n    \"\\x18\\xb9\\x67\\x8f\\x5d\\x64\\xc3\\x28\\x9f\\x2f\\x16\\x2f\\x08\\xda\\x47\"\n    \"\\xec\\x86\\x43\\x0c\\x80\\x99\\x07\\x34\\x0f\";\n  int i;\n  info(\"initializing TPM data to default values\");\n  /* reset all data to NULL, FALSE or 0 */\n  memset(&tpmData, 0, sizeof(tpmData));\n  tpmData.permanent.data.tag = TPM_TAG_PERMANENT_DATA;\n  /* set permanent flags */\n  tpmData.permanent.flags.tag = TPM_TAG_PERMANENT_FLAGS;\n  tpmData.permanent.flags.disable = FALSE;\n  tpmData.permanent.flags.deactivated = FALSE;\n  tpmData.permanent.flags.ownership = TRUE;\n  tpmData.permanent.flags.readPubek = TRUE;\n  tpmData.permanent.flags.allowMaintenance = TRUE;\n  tpmData.permanent.flags.enableRevokeEK = TRUE;\n  tpmData.permanent.flags.readSRKPub = TRUE;\n  tpmData.permanent.flags.nvLocked = TRUE;\n  /* set TPM vision */\n  memcpy(&tpmData.permanent.data.version, \n         &tpm_version, sizeof(TPM_VERSION));\n  /* seed PRNG */\n  tpm_get_extern_random_bytes(&tpmData.permanent.data.rngState,\n    sizeof(tpmData.permanent.data.rngState));\n  /* setup PCR attributes */\n  for (i = 0; i < TPM_NUM_PCR && i < 16; i++) {\n    init_pcr_attr(i, FALSE, 0x00, 0x1f);\n  }\n  if (TPM_NUM_PCR >= 24) {\n    init_pcr_attr(16, TRUE, 0x1f, 0x1f);\n    init_pcr_attr(17, TRUE, 0x10, 0x1c);\n    init_pcr_attr(18, TRUE, 0x10, 0x1c);\n    init_pcr_attr(19, TRUE, 0x10, 0x0c);\n    init_pcr_attr(20, TRUE, 0x14, 0x0e);\n    init_pcr_attr(21, TRUE, 0x04, 0x04);\n    init_pcr_attr(22, TRUE, 0x04, 0x04);\n    init_pcr_attr(23, TRUE, 0x1f, 0x1f);\n  }\n#if TPM_NUM_PCR > 24\n  for (i = 24; i < TPM_NUM_PCR; i++) {\n    init_pcr_attr(i, TRUE, 0x00, 0x00);\n  }\n#endif\n  if (tpmConf & TPM_CONF_GENERATE_EK) {\n    /* generate a new endorsement key */\n    tpm_rsa_generate_key(&tpmData.permanent.data.endorsementKey, 2048);\n  } else {\n    /* setup endorsement key */\n    tpm_rsa_import_key(&tpmData.permanent.data.endorsementKey, \n      RSA_MSB_FIRST, ek_n, 256, ek_e, 3, ek_p, ek_q);\n  }\n  if (tpmConf & TPM_CONF_GENERATE_SEED_DAA) {\n    /* generate the DAA seed */\n    tpm_get_random_bytes(tpmData.permanent.data.tpmDAASeed.nonce, \n      sizeof(tpmData.permanent.data.tpmDAASeed.nonce));\n  } else {\n    /* setup DAA seed */\n    memcpy(tpmData.permanent.data.tpmDAASeed.nonce, \n      \"\\x77\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\"\n      \"\\x00\\x00\\x00\\x77\", sizeof(TPM_NONCE));\n  }\n  memcpy(tpmData.permanent.data.ekReset.nonce, \"\\xde\\xad\\xbe\\xef\", 4);\n  /* initialize predefined non-volatile storage */\n  init_nv_storage();\n  /* set the timeout and duration values */\n  init_timeouts();\n#ifdef MTM_EMULATOR\n  mtm_init_data();\n#endif\n}\n\nvoid tpm_release_data(void)\n{\n  free_TPM_DATA(tpmData);\n#ifdef MTM_EMULATOR\n  free_MTM_DATA(mtmData);\n#endif\n}\n\nint tpm_store_permanent_data(void)\n{\n  uint8_t *buf, *ptr;\n  size_t buf_length;\n  uint32_t len;\n\n  /* marshal data */\n  buf_length = len = sizeof_TPM_VERSION(tpmData.permanent.data.version)\n#ifdef MTM_EMULATOR\n                     + sizeof_TPM_DATA(tpmData) + sizeof_MTM_DATA(mtmData);\n#else\n                     + sizeof_TPM_DATA(tpmData);\n#endif\n  debug(\"size of permanent data: %d\", buf_length);\n  buf = ptr = tpm_malloc(buf_length);\n  if (buf == NULL\n      || tpm_marshal_TPM_VERSION(&ptr, &len, &tpmData.permanent.data.version)\n#ifdef MTM_EMULATOR\n      || tpm_marshal_TPM_DATA(&ptr, &len, &tpmData)\n      || tpm_marshal_MTM_DATA(&ptr, &len, &mtmData)) {\n#else\n      || tpm_marshal_TPM_DATA(&ptr, &len, &tpmData)) {\n#endif\n    tpm_free(buf);\n    return -1;\n  }\n  if (len != 0) debug(\"warning: buffer was too large, %d bytes left\", len);\n  if (tpm_write_to_storage(buf, buf_length - len)) {\n    tpm_free(buf);\n    return -1; \n  }\n  tpm_free(buf);\n  return 0;\n}\n\nint tpm_restore_permanent_data(void)\n{\n  uint8_t *buf, *ptr;\n  size_t buf_length;\n  uint32_t len;\n  TPM_VERSION ver;\n\n  /* read data */\n  if (tpm_read_from_storage(&buf, &buf_length)) return -1;\n  ptr = buf;\n  len = buf_length;\n  /* unmarshal data */\n  if (tpm_unmarshal_TPM_VERSION(&ptr, &len, &ver)\n      || memcmp(&ver, &tpm_version, sizeof(TPM_VERSION))\n      || tpm_unmarshal_TPM_DATA(&ptr, &len, &tpmData)\n#ifdef MTM_EMULATOR\n      || tpm_unmarshal_MTM_DATA(&ptr, &len, &mtmData)\n#endif\n      || len > 0) {\n    tpm_free(buf);\n    return -1;\n  }\n  tpm_free(buf);\n  tpmData.permanent.flags.dataRestored = TRUE;\n  return 0;\n}\n\nint tpm_erase_permanent_data(void)\n{\n  uint8_t d[1];\n  int res = tpm_write_to_storage(d, 0);\n  return res;\n}\n\n"
  },
  {
    "path": "tpm/tpm_data.h",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: tpm_data.h 368 2010-02-15 09:26:37Z mast $\n */\n\n#ifndef _TPM_DATA_H_\n#define _TPM_DATA_H_\n\n#include \"tpm_structures.h\"\n\nextern TPM_DATA tpmData;\nextern UINT32 tpmConf;\n\nBOOL tpm_get_physical_presence(void);\n\nvoid tpm_init_data(void);\n\nvoid tpm_release_data(void);\n\nint tpm_store_permanent_data(void);\n\nint tpm_restore_permanent_data(void);\n\nint tpm_erase_permanent_data(void);\n\n#endif /* _TPM_DATA_H_ */\n"
  },
  {
    "path": "tpm/tpm_delegation.c",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: tpm_delegation.c 367 2010-02-13 15:52:18Z mast $\n */\n\n#include \"tpm_emulator.h\"\n#include \"tpm_commands.h\"\n#include \"tpm_marshalling.h\"\n#include \"tpm_data.h\"\n#include \"tpm_handles.h\"\n#include \"crypto/hmac.h\"\n#include \"crypto/rc4.h\"\n\n/*\n * Delegation Commands ([TPM_Part3], Section 19)\n */\n\nTPM_FAMILY_TABLE_ENTRY *tpm_get_family_row(TPM_FAMILY_ID id)\n{\n  UINT32 i;\n  for (i = 0; i < TPM_NUM_FAMILY_TABLE_ENTRY; i++) {\n    if (tpmData.permanent.data.familyTable.famRow[i].valid\n        && tpmData.permanent.data.familyTable.famRow[i].familyID == id)\n      return &tpmData.permanent.data.familyTable.famRow[i];\n  }\n  return NULL;\n}\n\nTPM_DELEGATE_TABLE_ROW *tpm_get_delegate_row(UINT32 row)\n{\n  if (row < TPM_NUM_DELEGATE_TABLE_ENTRY\n      && tpmData.permanent.data.delegateTable.delRow[row].valid)\n    return &tpmData.permanent.data.delegateTable.delRow[row];\n  return NULL;\n}\n\nvoid tpm_compute_owner_blob_digest(TPM_DELEGATE_OWNER_BLOB *blob,\n                                   TPM_DIGEST *digest)\n{\n  tpm_hmac_ctx_t ctx;\n  BYTE buf[sizeof_TPM_DELEGATE_OWNER_BLOB((*blob))];\n  BYTE *ptr = buf;\n  UINT32 length = sizeof(buf);\n  tpm_marshal_TPM_DELEGATE_OWNER_BLOB(&ptr, &length, blob);\n  memset(&buf[2 + sizeof_TPM_DELEGATE_PUBLIC(blob->pub)], 0, 20);\n  tpm_hmac_init(&ctx, tpmData.permanent.data.tpmProof.nonce,\n    sizeof(tpmData.permanent.data.tpmProof.nonce));\n  tpm_hmac_update(&ctx, buf, sizeof(buf) - length);\n  tpm_hmac_final(&ctx, digest->digest);\n}\n\nvoid tpm_compute_key_blob_digest(TPM_DELEGATE_KEY_BLOB *blob,\n                                 TPM_DIGEST *digest)\n{\n  tpm_hmac_ctx_t ctx;\n  BYTE buf[sizeof_TPM_DELEGATE_KEY_BLOB((*blob))];\n  BYTE *ptr = buf;\n  UINT32 length = sizeof(buf);\n  tpm_marshal_TPM_DELEGATE_KEY_BLOB(&ptr, &length, blob);\n  memset(&buf[2 + sizeof_TPM_DELEGATE_PUBLIC(blob->pub)], 0, 20);\n  tpm_hmac_init(&ctx, tpmData.permanent.data.tpmProof.nonce,\n    sizeof(tpmData.permanent.data.tpmProof.nonce));\n  tpm_hmac_update(&ctx, buf, sizeof(buf) - length);\n  tpm_hmac_final(&ctx, digest->digest);\n}\n\nint tpm_encrypt_sensitive(BYTE *iv, UINT32 iv_size,\n                          TPM_DELEGATE_SENSITIVE *sensitive,\n                          BYTE **enc, UINT32 *enc_size)\n{\n  UINT32 len;\n  BYTE *ptr;\n  tpm_rc4_ctx_t rc4_ctx;\n  BYTE key[TPM_SYM_KEY_SIZE + iv_size];\n  /* marshal context */\n  *enc_size = len = sizeof_TPM_DELEGATE_SENSITIVE((*sensitive));\n  *enc = ptr = tpm_malloc(len);\n  if (*enc == NULL) return -1;\n  if (tpm_marshal_TPM_DELEGATE_SENSITIVE(&ptr, &len, sensitive)) {\n    tpm_free(*enc);\n    return -1;\n  }\n  /* encrypt context */\n  memcpy(key, tpmData.permanent.data.delegateKey, TPM_SYM_KEY_SIZE);\n  memcpy(&key[TPM_SYM_KEY_SIZE], iv, iv_size);\n  tpm_rc4_init(&rc4_ctx, key, sizeof(key));\n  tpm_rc4_crypt(&rc4_ctx, *enc, *enc, *enc_size);\n  return 0;\n}\n\nint tpm_decrypt_sensitive(BYTE *iv, UINT32 iv_size, BYTE *enc, UINT32 enc_size,\n                          TPM_DELEGATE_SENSITIVE *sensitive, BYTE **buf)\n{\n  UINT32 len;\n  BYTE *ptr;\n  tpm_rc4_ctx_t rc4_ctx;\n  BYTE key[TPM_SYM_KEY_SIZE + iv_size];\n  len = enc_size;\n  *buf = ptr = tpm_malloc(len);\n  if (*buf == NULL) return -1;\n  /* decrypt context */\n  memcpy(key, tpmData.permanent.data.delegateKey, TPM_SYM_KEY_SIZE);\n  memcpy(&key[TPM_SYM_KEY_SIZE], iv, iv_size);\n  tpm_rc4_init(&rc4_ctx, key, sizeof(key));\n  tpm_rc4_crypt(&rc4_ctx, enc, *buf, enc_size);\n  /* unmarshal context */\n  if (tpm_unmarshal_TPM_DELEGATE_SENSITIVE(&ptr, &len, sensitive)) {\n    tpm_free(*buf);\n    return -1;\n  }\n  return 0;\n}\n\nstatic TPM_FAMILY_TABLE_ENTRY *tpm_get_free_family_row(void) {\n  UINT32 i;\n  for(i = 0; i < TPM_NUM_FAMILY_TABLE_ENTRY; i++) {\n    if(!tpmData.permanent.data.familyTable.famRow[i].valid) {\n      tpmData.permanent.data.familyTable.famRow[i].valid = TRUE;\n      return &tpmData.permanent.data.familyTable.famRow[i];\n    }\n  }\n  return NULL;\n}\n\nTPM_RESULT TPM_Delegate_Manage(TPM_FAMILY_ID familyID,\n                               TPM_FAMILY_OPERATION opFlag,\n                               UINT32 opDataSize, BYTE *opData,\n                               TPM_AUTH *auth1,\n                               UINT32 *retDataSize, BYTE **retData)\n{\n  TPM_RESULT res;\n  TPM_SESSION_DATA *session;\n  TPM_FAMILY_TABLE_ENTRY *fr;\n  UINT32 i;\n\n  info(\"[TPM_Delegate_Manage]\");\n  /* if no new family row is to be created, get the existing one */\n  if (opFlag != TPM_FAMILY_CREATE) {\n    fr = tpm_get_family_row(familyID);\n    if (fr == NULL) return TPM_BADINDEX;\n  } else {\n    fr = NULL;\n  }\n  /* verify authorization */\n  session = tpm_get_auth(auth1->authHandle);\n  if (session == NULL) return TPM_AUTHFAIL;\n  if (auth1->authHandle != TPM_INVALID_AUTHHANDLE) {\n    res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);\n    if (res != TPM_SUCCESS) return res;\n    if (session->type == TPM_ST_DSAP) {\n      if (session->familyID != familyID) return TPM_DELEGATE_FAMILY;\n      auth1->continueAuthSession = FALSE;\n    }\n  } else {\n    if (tpmData.permanent.flags.owned) return TPM_AUTHFAIL;\n    /* check delegate admin lock */\n    if (fr != NULL && (fr->flags & TPM_DELEGATE_ADMIN_LOCK)) {\n      debug(\"delegate admin lock is set\");\n      return TPM_DELEGATE_LOCK;\n    }\n    /* verify maximal number of writes without an owner */\n    if (tpmData.permanent.data.noOwnerNVWrite >= TPM_MAX_NV_WRITE_NOOWNER)\n      return TPM_MAXNVWRITES;\n    tpmData.permanent.data.noOwnerNVWrite++;\n  }\n  /* invalidate all but this auth session */\n  for (i = 0; i < TPM_MAX_SESSIONS; i++) {\n    TPM_SESSION_DATA *s = &tpmData.stany.data.sessions[i];\n    if (s->type != TPM_ST_TRANSPORT && s != session) memset(s, 0, sizeof(*s));\n  }\n  tpmData.stclear.data.ownerReference = TPM_KH_OWNER;\n  /* perform requested operation */\n  if (opFlag == TPM_FAMILY_CREATE) {\n    BYTE *ptr;\n    UINT32 length;\n    debug(\"ofFlag = TPM_FAMILY_CREATE\");\n    if (opDataSize != 1) return TPM_BAD_PARAM_SIZE;\n    /* get a free family row */\n    fr = tpm_get_free_family_row();\n    if (fr == NULL)  return TPM_NOSPACE;\n    /* initialize the new row */\n    fr->tag = TPM_TAG_FAMILY_TABLE_ENTRY;\n    fr->familyLabel.label = *opData;\n    tpmData.permanent.data.lastFamilyID++;\n    fr->familyID = tpmData.permanent.data.lastFamilyID;\n    fr->verificationCount = 1;\n    fr->flags = 0;\n    /* return the familyID */\n    length = *retDataSize = 4;\n    ptr = *retData = tpm_malloc(*retDataSize);\n    if (*retData == NULL) {\n      debug(\"tpm_malloc() failed.\");\n      fr->valid = FALSE;\n      return TPM_FAIL;\n    }\n    if (tpm_marshal_UINT32(&ptr, &length, fr->familyID) != 0) {\n      debug(\"tpm_marshal_UINT32() failed.\");\n      tpm_free(*retData);\n      fr->valid = FALSE;\n      return TPM_FAIL;\n    }\n  } else if (opFlag == TPM_FAMILY_ADMIN) {\n    debug(\"opFlag = TPM_FAMILY_ADMIN\");\n    if (opDataSize != 1) return TPM_BAD_PARAM_SIZE;\n    if (*opData)fr->flags |= TPM_DELEGATE_ADMIN_LOCK;\n    else fr->flags &= ~TPM_DELEGATE_ADMIN_LOCK;\n    *retDataSize = 0;\n  } else if (opFlag == TPM_FAMILY_ENABLE) {\n    debug(\"opFlag = TPM_FAMFLAG_ENABLED\");\n    if (opDataSize != 1) return TPM_BAD_PARAM_SIZE;\n    if (*opData)fr->flags |= TPM_FAMFLAG_ENABLED;\n    else fr->flags &= ~TPM_FAMFLAG_ENABLED;\n    *retDataSize = 0;\n    return TPM_SUCCESS;\n  } else if (opFlag == TPM_FAMILY_INVALIDATE) {\n    debug(\"opFlag = TPM_FAMILY_INVALIDATE\");\n    /* invalidate all family data */\n    memset(fr, 0, sizeof(*fr));\n    fr->valid = FALSE;\n    *retDataSize = 0;\n  } else {\n    debug(\"unknown opFlag value: %d\", opFlag);\n    return TPM_BAD_PARAMETER;\n  }\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_Delegate_CreateKeyDelegation(TPM_KEY_HANDLE keyHandle,\n                                            TPM_DELEGATE_PUBLIC *publicInfo,\n                                            TPM_ENCAUTH *delAuth,\n                                            TPM_AUTH *auth1,\n                                            TPM_DELEGATE_KEY_BLOB *blob)\n{\n  TPM_RESULT res;\n  TPM_SESSION_DATA *session;\n  TPM_FAMILY_TABLE_ENTRY *fr;\n  TPM_SECRET secret;\n  TPM_KEY_DATA *key;\n  TPM_PUBKEY pubKey;\n  TPM_DELEGATE_SENSITIVE sensitive;\n  info(\"TPM_Delegate_CreateKeyDelegation()\");\n  /* get key */\n  key = tpm_get_key(keyHandle);\n  if (key == NULL) return TPM_INVALID_KEYHANDLE;\n  /* verify authorization */\n  session = tpm_get_auth(auth1->authHandle);\n  if (session == NULL) return TPM_FAIL;\n  if (session->type != TPM_ST_OSAP && session->type != TPM_ST_DSAP) {\n    debug(\"session is neither of type OSAP nor DSAP\");\n    return TPM_INVALID_AUTHHANDLE;\n  }\n  res = tpm_verify_auth(auth1, key->usageAuth, keyHandle);\n  if (res != TPM_SUCCESS) return res;\n  auth1->continueAuthSession = FALSE;\n  /* get specified family entry */\n  fr = tpm_get_family_row(publicInfo->familyID);\n  if (fr == NULL) return TPM_BADINDEX;\n  /* check delegation type */\n  if (publicInfo->permissions.delegateType != TPM_DEL_KEY_BITS) {\n    debug(\"invalid delegation type: %d\", publicInfo->permissions.delegateType);\n    return TPM_BAD_PARAMETER;\n  }\n  blob->tag = TPM_TAG_DELEGATE_KEY_BLOB;\n  /* verify permissions if the access was delegated */\n  if (session->type == TPM_ST_DSAP) {\n    if (!(fr->flags & TPM_FAMFLAG_ENABLED)) return TPM_DISABLED_CMD;\n    if (session->familyID != publicInfo->familyID) return TPM_DELEGATE_FAMILY;\n    if (((session->permissions.per1 | publicInfo->permissions.per1)\n          != session->permissions.per1)\n        || ((session->permissions.per2 | publicInfo->permissions.per2)\n             != session->permissions.per2)) return TPM_AUTHFAIL;\n  }\n  /* decrypt delegation secret */\n  tpm_decrypt_auth_secret(*delAuth, session->sharedSecret,\n                          &session->lastNonceEven, secret);\n  /* compute key digest */\n  if (tpm_extract_pubkey(key, &pubKey)) {\n    debug(\"tpm_extraxt_pubkey() failed.\");\n    return TPM_FAIL;\n  }\n  if (tpm_compute_pubkey_digest(&pubKey, &blob->pubKeyDigest)) {\n    debug(\"tpm_compute_pubkey_digest() failed\");\n    free_TPM_PUBKEY(pubKey);\n    return TPM_FAIL;\n  }\n  free_TPM_PUBKEY(pubKey);\n  /* create a delegate sensitive structure */\n  sensitive.tag = TPM_TAG_DELEGATE_SENSITIVE;\n  memcpy(&sensitive.authValue, &secret, sizeof(TPM_SECRET));\n  /* generate IV and encrypt sensitive area */\n  blob->additionalSize = TPM_SYM_KEY_SIZE;\n  blob->additionalArea = tpm_malloc(blob->additionalSize);\n  if (blob->additionalArea == NULL) {\n    debug(\"tpm_malloc() failed.\");\n    return TPM_NOSPACE;\n  }\n  tpm_get_random_bytes(blob->additionalArea, blob->additionalSize);\n  if (tpm_encrypt_sensitive(blob->additionalArea, blob->additionalSize,\n        &sensitive, &blob->sensitiveArea, &blob->sensitiveSize)) {\n    debug(\"tpm_encrypt_sensitive() failed.\");\n    tpm_free(blob->additionalArea);\n    return TPM_ENCRYPT_ERROR;\n  }\n  /* copy public delegation information */\n  memcpy(&blob->pub, publicInfo, sizeof(TPM_DELEGATE_PUBLIC));\n  blob->pub.verificationCount = fr->verificationCount;\n  /* compute integrity digest */\n  tpm_compute_key_blob_digest(blob, &blob->integrityDigest);\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_Delegate_CreateOwnerDelegation(BOOL increment,\n                                              TPM_DELEGATE_PUBLIC *publicInfo,\n                                              TPM_ENCAUTH *delAuth,\n                                              TPM_AUTH *auth1,\n                                              TPM_DELEGATE_OWNER_BLOB *blob)\n{\n  TPM_RESULT res;\n  TPM_SESSION_DATA *session;\n  TPM_FAMILY_TABLE_ENTRY *fr;\n  TPM_SECRET secret;\n  TPM_DELEGATE_SENSITIVE sensitive;\n  info(\"[TPM_Delegate_CreateOwnerDelegation]\");\n  /* verify authorization */\n  session = tpm_get_auth(auth1->authHandle);\n  if (session == NULL) return TPM_FAIL;\n  if (session->type != TPM_ST_OSAP && session->type != TPM_ST_DSAP) {\n    debug(\"session is neither of type OSAP nor DSAP\");\n    return TPM_INVALID_AUTHHANDLE;\n  }\n  res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);\n  if (res != TPM_SUCCESS) return res;\n  auth1->continueAuthSession = FALSE;\n  /* get specified family entry */\n  fr = tpm_get_family_row(publicInfo->familyID);\n  if (fr == NULL) return TPM_BADINDEX;\n  /* check delegation type */\n  if (publicInfo->permissions.delegateType != TPM_DEL_OWNER_BITS) {\n    debug(\"invalid delegation type: %d\", publicInfo->permissions.delegateType);\n    return TPM_BAD_PARAMETER;\n  }\n  blob->tag = TPM_TAG_DELEGATE_OWNER_BLOB;\n  /* verify permissions if the access was delegated */\n  if (session->type == TPM_ST_DSAP) {\n  if (!(fr->flags & TPM_FAMFLAG_ENABLED)) return TPM_DISABLED_CMD;\n  if (session->familyID != publicInfo->familyID) return TPM_DELEGATE_FAMILY;\n  if (((session->permissions.per1 | publicInfo->permissions.per1)\n        != session->permissions.per1)\n      || ((session->permissions.per2 | publicInfo->permissions.per2)\n           != session->permissions.per2)) return TPM_AUTHFAIL;\n  }\n  /* increment verification count if required */\n  if (increment) {\n    UINT32 i;\n    fr->verificationCount++;\n    debug(\"incrementing verificationCount to %d\", fr->verificationCount);\n    tpmData.stclear.data.ownerReference = TPM_KH_OWNER;\n    /* invalidate all but this session */\n    for (i = 0; i < TPM_MAX_SESSIONS; i++) {\n      TPM_SESSION_DATA *s = &tpmData.stany.data.sessions[i];\n      if (s->type != TPM_ST_TRANSPORT && s != session) memset(s, 0, sizeof(*s));\n    }\n  }\n  /* decrypt delegation secret */\n  tpm_decrypt_auth_secret(*delAuth, session->sharedSecret,\n                          &session->lastNonceEven, secret);\n  /* create a delegate sensitive structure */\n  sensitive.tag = TPM_TAG_DELEGATE_SENSITIVE;\n  memcpy(&sensitive.authValue, &secret, sizeof(TPM_SECRET));\n  /* generate IV and encrypt sensitive area */\n  blob->additionalSize = TPM_SYM_KEY_SIZE;\n  blob->additionalArea = tpm_malloc(blob->additionalSize);\n  if (blob->additionalArea == NULL) {\n    debug(\"tpm_malloc() failed.\");\n    return TPM_NOSPACE;\n  }\n  tpm_get_random_bytes(blob->additionalArea, blob->additionalSize);\n  if (tpm_encrypt_sensitive(blob->additionalArea, blob->additionalSize,\n      &sensitive, &blob->sensitiveArea, &blob->sensitiveSize)) {\n    debug(\"tpm_encrypt_sensitive() failed.\");\n    tpm_free(blob->additionalArea);\n    return TPM_ENCRYPT_ERROR;\n  }\n  /* copy public delegation information */\n  memcpy(&blob->pub, publicInfo, sizeof(TPM_DELEGATE_PUBLIC));\n  blob->pub.verificationCount = fr->verificationCount;\n  /* compute integrity digest */\n  tpm_compute_owner_blob_digest(blob, &blob->integrityDigest);\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_Delegate_LoadOwnerDelegation(TPM_DELEGATE_INDEX index,\n                                            TPM_DELEGATE_OWNER_BLOB *blob,\n                                            TPM_AUTH *auth1)\n{\n  TPM_RESULT res;\n  TPM_SESSION_DATA *session;\n  TPM_FAMILY_TABLE_ENTRY *fr;\n  TPM_DIGEST blobDigest;\n  TPM_DELEGATE_SENSITIVE sensitive;\n  TPM_DELEGATE_TABLE_ROW *dr;\n  BYTE *sens_buf;\n  UINT32 i;\n  info(\"TPM_Delegate_LoadOwnerDelegation()\");\n  /* get specified family entry */\n  fr = tpm_get_family_row(blob->pub.familyID);\n  if (fr == NULL) return TPM_BADINDEX;\n  /* verify authorization */\n  session = tpm_get_auth(auth1->authHandle);\n  if (session == NULL) return TPM_AUTHFAIL;\n  if (auth1->authHandle != TPM_INVALID_AUTHHANDLE) {\n    res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);\n    if (res != TPM_SUCCESS) return res;\n    if (session->type == TPM_ST_DSAP) {\n      if (session->familyID != blob->pub.familyID) return TPM_DELEGATE_FAMILY;\n      auth1->continueAuthSession = FALSE;\n    }\n  } else {\n    if (tpmData.permanent.flags.owned) return TPM_AUTHFAIL;\n    /* check delegate admin lock */\n    if (fr != NULL && (fr->flags & TPM_DELEGATE_ADMIN_LOCK)) {\n      debug(\"delegate admin lock is set\");\n      return TPM_DELEGATE_LOCK;\n    }\n    /* verify maximal number of writes without an owner */\n    if (tpmData.permanent.data.noOwnerNVWrite >= TPM_MAX_NV_WRITE_NOOWNER)\n    return TPM_MAXNVWRITES;\n    tpmData.permanent.data.noOwnerNVWrite++;\n  }\n  /* verify the integrity of the blob and decode/decrypt the sensitive data */\n  if (!(fr->flags & TPM_FAMFLAG_ENABLED)) return TPM_DISABLED_CMD;\n  if (tpmData.permanent.flags.owned) {\n    tpm_compute_owner_blob_digest(blob, &blobDigest);\n    if (memcmp(&blob->integrityDigest, &blobDigest, sizeof(TPM_DIGEST)) != 0)\n      return TPM_AUTHFAIL;\n    /* decrypt sensitive data */\n    if (tpm_decrypt_sensitive(blob->additionalArea, blob->additionalSize,\n      blob->sensitiveArea, blob->sensitiveSize, &sensitive, &sens_buf)) {\n      debug(\"tpm_decrypt_sensitive() failed\");\n      return TPM_DECRYPT_ERROR;\n    }\n  } else {\n    BYTE *ptr = blob->sensitiveArea;\n    UINT32 length = blob->sensitiveSize;\n    if (tpm_unmarshal_TPM_DELEGATE_SENSITIVE(&ptr, &length, &sensitive) != 0) {\n      debug(\"tpm_unmarshal_TPM_DELEGATE_SENSITIVE()\");\n      return TPM_FAIL;\n    }\n    sens_buf = NULL;\n  }\n  if (sensitive.tag != TPM_TAG_DELEGATE_SENSITIVE) {\n    tpm_free(sens_buf);\n    return TPM_INVALID_STRUCTURE;\n  }\n  /* check that index is valid and copy data */\n  debug(\"index = %d\", index);\n  if (index >= TPM_NUM_DELEGATE_TABLE_ENTRY) {\n    tpm_free(sens_buf);\n    return TPM_BADINDEX;\n  }\n  dr = &tpmData.permanent.data.delegateTable.delRow[index];\n  dr->valid = TRUE;\n  dr->tag = TPM_TAG_DELEGATE_TABLE_ROW;\n  memcpy(&dr->authValue, &sensitive.authValue, sizeof(TPM_SECRET));\n  memcpy(&dr->pub, &blob->pub, sizeof(TPM_DELEGATE_PUBLIC));\n  tpm_free(sens_buf);\n  /* invalidate all but this session */\n  for (i = 0; i < TPM_MAX_SESSIONS; i++) {\n    TPM_SESSION_DATA *s = &tpmData.stany.data.sessions[i];\n     if (s->type != TPM_ST_TRANSPORT && s != session) memset(s, 0, sizeof(*s));\n  }\n  tpmData.stclear.data.ownerReference = TPM_KH_OWNER;\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_Delegate_ReadTable(UINT32 *familyTableSize, BYTE **familyTable,\n                                  UINT32 *delegateTableSize,\n                                  BYTE **delegateTable)\n{\n  UINT32 i, length;\n  BYTE *ptr;\n  info(\"TPM_Delegate_ReadTable\");\n  /* compute the size of the family table */\n  *familyTableSize = 0;\n  *familyTable = NULL;\n  for (i = 0; i < TPM_NUM_FAMILY_TABLE_ENTRY; i++) {\n    if (tpmData.permanent.data.familyTable.famRow[i].valid) {\n      *familyTableSize += sizeof_TPM_FAMILY_TABLE_ENTRY(\n        tpmData.permanent.data.familyTable.famRow[i]);\n    }\n  }\n  debug(\"family table size: %d\", *familyTableSize);\n  /* allocate the table buffer and copy the family table */\n  if (*familyTableSize > 0) {\n    length = *familyTableSize;\n    ptr = *familyTable = tpm_malloc(*familyTableSize);\n    if (*familyTable == NULL) return TPM_RESOURCES;\n    for (i = 0; i < TPM_NUM_FAMILY_TABLE_ENTRY; i++) {\n      if (tpmData.permanent.data.familyTable.famRow[i].valid) {\n        debug(\"writing table row %d\", i);\n        if (tpm_marshal_TPM_FAMILY_TABLE_ENTRY(&ptr, &length,\n            &tpmData.permanent.data.familyTable.famRow[i])) {\n          debug(\"tpm_marshal_TPM_FAMILY_TABLE_ENTRY() failed.\");\n          tpm_free(*familyTable);\n          return TPM_FAIL;\n        }\n      }\n    }\n  }\n  /* computing the size of the delegation table */\n  *delegateTableSize = 0;\n  *delegateTable = NULL;\n  for (i = 0; i < TPM_NUM_DELEGATE_TABLE_ENTRY; i++) {\n    if (tpmData.permanent.data.delegateTable.delRow[i].valid) {\n      *delegateTableSize += sizeof_TPM_DELEGATE_PUBLIC(\n        tpmData.permanent.data.delegateTable.delRow[i].pub) + 4;\n    }\n  }\n  debug(\"delegation table size: %d\", *delegateTableSize);\n  /* allocate the table buffer and copy the delegation table */\n  if (*delegateTableSize > 0) {\n    length = *delegateTableSize;\n    ptr = *delegateTable = tpm_malloc(*delegateTableSize);\n    if (*delegateTable == NULL) {\n      tpm_free(*familyTable);\n      return TPM_RESOURCES;\n    }\n    for (i = 0; i < TPM_NUM_DELEGATE_TABLE_ENTRY; i++) {\n      if (tpmData.permanent.data.delegateTable.delRow[i].valid) {\n        debug(\"writing delegate row %d\", i);\n        if (tpm_marshal_TPM_DELEGATE_INDEX(&ptr, &length, i)\n            || tpm_marshal_TPM_DELEGATE_PUBLIC(&ptr, &length,\n                 &tpmData.permanent.data.delegateTable.delRow[i].pub)) {\n          debug(\"tpm_marshal_UINT32 or -TPM_DELEGATE_PUBLIC failed.\");\n          tpm_free(*familyTable);\n          tpm_free(*delegateTable);\n          return TPM_FAIL;\n        }\n      }\n    }\n  }\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_Delegate_UpdateVerification(UINT32 inputSize, BYTE *inputData,\n                                           TPM_AUTH *auth1, UINT32 *outputSize,\n                                           BYTE **outputData)\n{\n  TPM_RESULT res;\n  TPM_SESSION_DATA *session;\n  info(\"TPM_Delegate_UpdateVerification()\");\n  /* verify authorization */\n  session = tpm_get_auth(auth1->authHandle);\n  if (session == NULL) return TPM_AUTHFAIL;\n  res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);\n  if (res != TPM_SUCCESS) return res;\n  /* determine the type of the input data */\n  if (inputSize == 4) {\n    TPM_DELEGATE_INDEX index;\n    TPM_DELEGATE_TABLE_ROW *dr;\n    TPM_FAMILY_TABLE_ENTRY *fr;\n    debug(\"TPM_DELEGATE_TABLE_ROW\");\n    /* unmarshal delegate index */\n    if (tpm_unmarshal_TPM_DELEGATE_INDEX(&inputData, &inputSize, &index)) {\n      debug(\"tpm_unmarshal_TPM_DELEGATE_INDEX() failed.\");\n      return TPM_FAIL;\n    }\n    /* get delegate and family row */\n    dr = tpm_get_delegate_row(index);\n    if (dr == NULL) return TPM_BADINDEX;\n    fr = tpm_get_family_row(dr->pub.familyID);\n    if (fr == NULL) return TPM_BADINDEX;\n    /* verify permissions if the access was delegated */\n    if (session->type == TPM_ST_DSAP) {\n      if (!(fr->flags & TPM_FAMFLAG_ENABLED)) return TPM_DISABLED_CMD;\n      if (session->familyID != fr->familyID) return TPM_DELEGATE_FAMILY;\n    }\n    /* update verification count */\n    dr->pub.verificationCount = fr->verificationCount;\n    *outputSize = 0;\n    *outputData = NULL;\n  } else if (inputData[0] == (TPM_TAG_DELEGATE_OWNER_BLOB >> 8)\n             && inputData[1] == (TPM_TAG_DELEGATE_OWNER_BLOB & 0xff)) {\n    TPM_DELEGATE_OWNER_BLOB blob;\n    TPM_DIGEST blobDigest;\n    TPM_FAMILY_TABLE_ENTRY *fr;\n    UINT32 length;\n    BYTE *ptr;\n    debug(\"TPM_DELEGATE_OWNER_BLOB\");\n    /* unmarshal the blob */\n    if (tpm_unmarshal_TPM_DELEGATE_OWNER_BLOB(&inputData, &inputSize, &blob)) {\n      debug(\"tpm_unmarshal_TPM_DELEGATE_OWNER_BLOB() failed.\");\n      return TPM_FAIL;\n    }\n    /* validate the integrity of the blob */\n    tpm_compute_owner_blob_digest(&blob, &blobDigest);\n    if (memcmp(&blob.integrityDigest, &blobDigest, sizeof(TPM_DIGEST)) != 0)\n      return TPM_AUTHFAIL;\n    /* get family row */\n    fr = tpm_get_family_row(blob.pub.familyID);\n    if (fr == NULL) return TPM_BADINDEX;\n    /* verify permissions if the access was delegated */\n    if (session->type == TPM_ST_DSAP) {\n      if (!(fr->flags & TPM_FAMFLAG_ENABLED)) return TPM_DISABLED_CMD;\n      if (session->familyID != fr->familyID) return TPM_DELEGATE_FAMILY;\n    }\n    /* update verification count */\n    blob.pub.verificationCount = fr->verificationCount;\n    /* update the blob digest */\n    tpm_compute_owner_blob_digest(&blob, &blobDigest);\n    /* marshal the blob */\n    length = *outputSize = sizeof_TPM_DELEGATE_OWNER_BLOB(blob);\n    ptr = *outputData = tpm_malloc(*outputSize);\n    if (ptr == NULL) {\n      debug(\"tpm_malloc() failed.\");\n      return TPM_NOSPACE;\n    }\n    if (tpm_marshal_TPM_DELEGATE_OWNER_BLOB(&ptr, &length, &blob) != 0) {\n      debug(\"tpm_marshal_TPM_DELEGATE_OWNER_BLOB() failed.\");\n      tpm_free(*outputData);\n      return TPM_FAIL;\n    }\n  } else if (inputData[0] == (TPM_TAG_DELEGATE_KEY_BLOB >> 8)\n               && inputData[1] == (TPM_TAG_DELEGATE_KEY_BLOB & 0xff)) {\n    TPM_DELEGATE_KEY_BLOB blob;\n    TPM_DIGEST blobDigest;\n    TPM_FAMILY_TABLE_ENTRY *fr;\n    UINT32 length;\n    BYTE *ptr;\n    debug(\"TPM_DELEGATE_KEY_BLOB\");\n    /* unmarshal the blob */\n    if (tpm_unmarshal_TPM_DELEGATE_KEY_BLOB(&inputData, &inputSize, &blob)) {\n      debug(\"tpm_unmarshal_TPM_DELEGATE_KEY_BLOB() failed.\");\n      return TPM_FAIL;\n    }\n    /* validate the integrity of the blob */\n    tpm_compute_key_blob_digest(&blob, &blobDigest);\n    if (memcmp(&blob.integrityDigest, &blobDigest, sizeof(TPM_DIGEST)) != 0)\n      return TPM_AUTHFAIL;\n    /* get family row */\n    fr = tpm_get_family_row(blob.pub.familyID);\n    if (fr == NULL) return TPM_BADINDEX;\n    /* verify permissions if the access was delegated */\n    if (session->type == TPM_ST_DSAP) {\n      if (!(fr->flags & TPM_FAMFLAG_ENABLED)) return TPM_DISABLED_CMD;\n      if (session->familyID != fr->familyID) return TPM_DELEGATE_FAMILY;\n    }\n    /* update verification count */\n    blob.pub.verificationCount = fr->verificationCount;\n    /* update the blob digest */\n    tpm_compute_key_blob_digest(&blob, &blobDigest);\n    /* marshal the blob */\n    length = *outputSize = sizeof_TPM_DELEGATE_KEY_BLOB(blob);\n    ptr = *outputData = tpm_malloc(*outputSize);\n    if (ptr == NULL) {\n      debug(\"tpm_malloc() failed.\");\n      return TPM_NOSPACE;\n    }\n    if (tpm_marshal_TPM_DELEGATE_KEY_BLOB(&ptr, &length, &blob) != 0) {\n      debug(\"tpm_marshal_TPM_DELEGATE_KEY_BLOB() failed.\");\n      tpm_free(*outputData);\n      return TPM_FAIL;\n    }\n  } else {\n    debug(\"unsupported input structure: %02x%02x\", inputData[0], inputData[1]);\n    return TPM_BAD_PARAMETER;\n  }\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_Delegate_VerifyDelegation(UINT32 delegateSize, BYTE *delegation)\n{\n  info(\"TPM_Delegate_VerifyDelegation()\");\n  if (delegation[0] == (TPM_TAG_DELEGATE_OWNER_BLOB >> 8)\n      && delegation[1] == (TPM_TAG_DELEGATE_OWNER_BLOB & 0xff)) {\n    TPM_DELEGATE_OWNER_BLOB blob;\n    TPM_DIGEST blobDigest;\n    TPM_FAMILY_TABLE_ENTRY *fr;\n    TPM_DELEGATE_SENSITIVE sensitive;\n    BYTE *sens_buf;\n    debug(\"TPM_DELEGATE_OWNER_BLOB\");\n    /* unmarshal the blob */\n    if (tpm_unmarshal_TPM_DELEGATE_OWNER_BLOB(&delegation, &delegateSize, &blob)) {\n      debug(\"tpm_unmarshal_TPM_DELEGATE_OWNER_BLOB() failed.\");\n      return TPM_FAIL;\n    }\n    /* validate the integrity of the blob */\n    tpm_compute_owner_blob_digest(&blob, &blobDigest);\n    if (memcmp(&blob.integrityDigest, &blobDigest, sizeof(TPM_DIGEST)) != 0)\n      return TPM_AUTHFAIL;\n    /* get family row */\n    fr = tpm_get_family_row(blob.pub.familyID);\n    if (fr == NULL) return TPM_BADINDEX;\n    if (!(fr->flags & TPM_FAMFLAG_ENABLED)) return TPM_DISABLED_CMD;\n    /* verify verification count */\n    if (blob.pub.verificationCount != fr->verificationCount)\n      return TPM_FAMILYCOUNT;\n    /* decrypt and verify sensitive area */\n    if (tpm_decrypt_sensitive(blob.additionalArea, blob.additionalSize,\n        blob.sensitiveArea, blob.sensitiveSize, &sensitive, &sens_buf)) {\n      debug(\"tpm_decrypt_sensitive() failed\");\n      return TPM_DECRYPT_ERROR;\n    }\n    tpm_free(sens_buf);\n    if (sensitive.tag != TPM_TAG_DELEGATE_SENSITIVE) return TPM_BAD_PARAMETER;\n  } else if (delegation[0] == (TPM_TAG_DELEGATE_KEY_BLOB >> 8)\n          && delegation[1] == (TPM_TAG_DELEGATE_KEY_BLOB & 0xff)) {\n    TPM_DELEGATE_KEY_BLOB blob;\n    TPM_DIGEST blobDigest;\n    TPM_FAMILY_TABLE_ENTRY *fr;\n    TPM_DELEGATE_SENSITIVE sensitive;\n    BYTE *sens_buf;\n    debug(\"TPM_DELEGATE_KEY_BLOB\");\n    /* unmarshal the blob */\n    if (tpm_unmarshal_TPM_DELEGATE_KEY_BLOB(&delegation, &delegateSize, &blob)) {\n      debug(\"tpm_unmarshal_TPM_DELEGATE_OWNER_BLOB() failed.\");\n      return TPM_FAIL;\n    }\n    /* validate the integrity of the blob */\n    tpm_compute_key_blob_digest(&blob, &blobDigest);\n    if (memcmp(&blob.integrityDigest, &blobDigest, sizeof(TPM_DIGEST)) != 0)\n      return TPM_AUTHFAIL;\n    /* get family row */\n    fr = tpm_get_family_row(blob.pub.familyID);\n    if (fr == NULL) return TPM_BADINDEX;\n    if (!(fr->flags & TPM_FAMFLAG_ENABLED)) return TPM_DISABLED_CMD;\n    /* verify verification count */\n    if (blob.pub.verificationCount != fr->verificationCount)\n      return TPM_FAMILYCOUNT;\n    /* decrypt and verify sensitive area */\n    if (tpm_decrypt_sensitive(blob.additionalArea, blob.additionalSize,\n        blob.sensitiveArea, blob.sensitiveSize, &sensitive, &sens_buf)) {\n      debug(\"tpm_decrypt_sensitive() failed\");\n      return TPM_DECRYPT_ERROR;\n    }\n    tpm_free(sens_buf);\n    if (sensitive.tag != TPM_TAG_DELEGATE_SENSITIVE) return TPM_BAD_PARAMETER;\n  } else {\n    debug(\"unsupported input structure: %02x%02x\", delegation[0], delegation[1]);\n    return TPM_BAD_PARAMETER;\n  }\n  return TPM_SUCCESS;\n}\n\n"
  },
  {
    "path": "tpm/tpm_deprecated.c",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *               2005-2008 Heiko Stamer <stamer@gaos.org>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: tpm_deprecated.c 452 2010-07-19 19:05:05Z mast $\n */\n\n#include \"tpm_emulator.h\"\n#include \"tpm_commands.h\"\n#include \"tpm_data.h\"\n#include \"tpm_handles.h\"\n#include \"tpm_marshalling.h\"\n#include \"crypto/rsa.h\"\n#include \"crypto/sha1.h\"\n#include \"crypto/hmac.h\"\n\n#define SAVE_KEY_CONTEXT_LABEL  ((uint8_t*)\"SaveKeyContext..\")\n#define SAVE_AUTH_CONTEXT_LABEL ((uint8_t*)\"SaveAuthContext.\")\n\n/*\n * Deprecated commands ([TPM_Part3], Section 28)\n * This section covers the commands that were in version 1.1 but now have \n * new functionality in other functions. The deprecated commands are still \n * available in 1.2 but all new software should use the new functionality. \n * There is no requirement that the deprecated commands work with new \n * structures.\n */\n\nTPM_RESULT TPM_EvictKey(TPM_KEY_HANDLE evictHandle)\n{\n  info(\"TPM_EvictKey()\");\n  return TPM_FlushSpecific(evictHandle, TPM_RT_KEY);\n}\n\nTPM_RESULT TPM_Terminate_Handle(TPM_AUTHHANDLE handle)\n{\n  info(\"TPM_Terminate_Handle()\");\n  return TPM_FlushSpecific(handle, TPM_RT_AUTH);\n}\n\nTPM_RESULT TPM_SaveKeyContext(TPM_KEY_HANDLE keyHandle,  \n                              UINT32 *keyContextSize, BYTE **keyContextBlob)\n{\n  TPM_RESULT res;\n  TPM_CONTEXT_BLOB contextBlob;\n  BYTE *ptr;\n  UINT32 len;\n  info(\"TPM_SaveKeyContext()\");\n  res = TPM_SaveContext(keyHandle, TPM_RT_KEY, SAVE_KEY_CONTEXT_LABEL,\n                        keyContextSize, &contextBlob);\n  if (res != TPM_SUCCESS) return res;\n  len = *keyContextSize;\n  *keyContextBlob = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_CONTEXT_BLOB(&ptr, &len, &contextBlob)) res = TPM_FAIL;\n  else res = TPM_SUCCESS;\n  free_TPM_CONTEXT_BLOB(contextBlob);\n  return res;\n}\n\nTPM_RESULT TPM_LoadKeyContext(UINT32 keyContextSize,\n                              BYTE *keyContextBlob, TPM_KEY_HANDLE *keyHandle)\n{\n  TPM_CONTEXT_BLOB contextBlob;\n  UINT32 len = keyContextSize;\n  info(\"TPM_LoadKeyContext()\");\n  if (tpm_unmarshal_TPM_CONTEXT_BLOB(&keyContextBlob, \n      &len, &contextBlob)) return TPM_FAIL;\n  return TPM_LoadContext(TPM_INVALID_HANDLE, FALSE, keyContextSize, \n                         &contextBlob, keyHandle);\n}\n\nTPM_RESULT TPM_SaveAuthContext(TPM_AUTHHANDLE authHandle,  \n                               UINT32 *authContextSize, BYTE **authContextBlob)\n{\n  TPM_RESULT res;\n  TPM_CONTEXT_BLOB contextBlob;\n  BYTE *ptr;\n  UINT32 len;\n  info(\"TPM_SaveAuthContext()\");\n  res = TPM_SaveContext(authHandle, TPM_RT_KEY, SAVE_AUTH_CONTEXT_LABEL,\n                        authContextSize, &contextBlob);\n  if (res != TPM_SUCCESS) return res;\n  len = *authContextSize;\n  *authContextBlob = ptr = tpm_malloc(len);\n  if (ptr == NULL\n      || tpm_marshal_TPM_CONTEXT_BLOB(&ptr, &len, &contextBlob)) res = TPM_FAIL;\n  else res = TPM_SUCCESS;\n  free_TPM_CONTEXT_BLOB(contextBlob);\n  return res;\n}\n\nTPM_RESULT TPM_LoadAuthContext(UINT32 authContextSize, BYTE *authContextBlob, \n                               TPM_KEY_HANDLE *authHandle)\n{\n  TPM_CONTEXT_BLOB contextBlob;\n  UINT32 len = authContextSize;\n  info(\"TPM_LoadAuthContext()\");\n  if (tpm_unmarshal_TPM_CONTEXT_BLOB(&authContextBlob, \n      &len, &contextBlob)) return TPM_FAIL;\n  return TPM_LoadContext(TPM_INVALID_HANDLE, FALSE, authContextSize, \n                         &contextBlob, authHandle);\n}\n\nTPM_RESULT TPM_DirWriteAuth(TPM_DIRINDEX dirIndex, \n                            TPM_DIRVALUE *newContents, TPM_AUTH *auth1)\n{\n  TPM_RESULT res;\n  info(\"TPM_DirWriteAuth()\");\n  res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);\n  if (res != TPM_SUCCESS) return res;\n  if (dirIndex != 0) return TPM_BADINDEX;\n  memcpy(tpmData.permanent.data.nvData\n         + tpmData.permanent.data.nvStorage[0].dataIndex,\n         newContents, sizeof(TPM_DIRVALUE));\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_DirRead(TPM_DIRINDEX dirIndex, TPM_DIRVALUE *dirContents)\n{\n  info(\"TPM_DirRead()\");\n  if (dirIndex != 0) return TPM_BADINDEX;\n  memcpy(dirContents, tpmData.permanent.data.nvData\n         + tpmData.permanent.data.nvStorage[0].dataIndex,\n         sizeof(TPM_DIRVALUE));\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_ChangeAuthAsymStart(TPM_KEY_HANDLE idHandle,\n                                   TPM_NONCE *antiReplay,\n                                   TPM_KEY_PARMS *inTempKey,\n                                   TPM_AUTH *auth1,\n                                   TPM_CERTIFY_INFO *certifyInfo,\n                                   UINT32 *sigSize, BYTE **sig,\n                                   TPM_KEY_HANDLE *ephHandle,\n                                   TPM_KEY *outTempKey)\n{\n  TPM_RESULT res;\n  TPM_KEY_DATA *idKey;\n  tpm_rsa_private_key_t k1;\n  UINT32 key_length;\n  TPM_STORE_ASYMKEY store;\n  TPM_KEY ephKey;\n  UINT32 len, size;\n  BYTE *ptr, *buf;\n  \n  info(\"TPM_ChangeAuthAsymStart()\");\n  /* 1. The TPM SHALL verify the AuthData to use the TPM identity key held in\n        idHandle. The TPM MUST verify that the key is a TPM identity key. */\n    /* get identity key */\n    idKey = tpm_get_key(idHandle);\n    if (idKey == NULL) return TPM_INVALID_KEYHANDLE;\n    /* verify authorization */\n    if (auth1->authHandle != TPM_INVALID_HANDLE \n      || idKey->authDataUsage != TPM_AUTH_NEVER) {\n        res = tpm_verify_auth(auth1, idKey->usageAuth, idHandle);\n        if (res != TPM_SUCCESS) return res;\n    }\n    /* verify key parameters */\n    if (idKey->keyUsage != TPM_KEY_IDENTITY) return TPM_INVALID_KEYUSAGE;\n  /* 2. The TPM SHALL validate the algorithm parameters for the key to create\n        from the tempKey parameter. */\n  /* 3. Recommended key type is RSA */\n  /* 4. Minimum RSA key size MUST is 512 bits, recommended RSA key size \n        is 1024 */\n  /* 5. For other key types the minimum key size strength MUST be\n        comparable to RSA 512 */\n  /* 6. If the TPM is not designed to create a key of the requested type,\n        return the error code TPM_BAD_KEY_PROPERTY */\n  if (inTempKey->algorithmID != TPM_ALG_RSA\n      || inTempKey->encScheme != TPM_ES_RSAESOAEP_SHA1_MGF1\n      || inTempKey->parmSize == 0\n      || inTempKey->parms.rsa.keyLength < 512\n      || inTempKey->parms.rsa.numPrimes != 2\n      || inTempKey->parms.rsa.exponentSize != 0)\n    return TPM_BAD_KEY_PROPERTY;\n  /* 7. The TPM SHALL create a new key (k1) in accordance with the\n        algorithm parameter.\n        The newly created key is pointed to by ephHandle. */\n    /* generate key */\n    key_length = inTempKey->parms.rsa.keyLength;\n    if (tpm_rsa_generate_key(&k1, key_length)) {\n      debug(\"TPM_ChangeAuthAsymStart(): tpm_rsa_generate_key() failed.\");\n      return TPM_FAIL;\n    }\n    /* setup private key store */\n    store.payload = TPM_PT_ASYM;\n    memcpy(store.usageAuth, tpmData.permanent.data.tpmProof.nonce, \n      sizeof(TPM_SECRET));\n    memcpy(store.migrationAuth, tpmData.permanent.data.tpmProof.nonce, \n      sizeof(TPM_SECRET));\n    store.privKey.keyLength = key_length >> 4;\n    store.privKey.key = tpm_malloc(store.privKey.keyLength);\n    if (store.privKey.key == NULL) {\n      tpm_rsa_release_private_key(&k1);\n      return TPM_NOSPACE;\n    }\n    tpm_rsa_export_prime1(&k1, store.privKey.key, NULL);\n    /* setup ephKey */\n    ephKey.tag = 0x0101;\n    ephKey.fill = 0x0000;\n    ephKey.keyUsage = TPM_KEY_AUTHCHANGE;\n    ephKey.keyFlags = TPM_KEY_FLAG_VOLATILE;\n    ephKey.authDataUsage = TPM_AUTH_NEVER;\n    ephKey.algorithmParms.algorithmID = inTempKey->algorithmID;\n    ephKey.algorithmParms.encScheme = inTempKey->encScheme;\n    ephKey.algorithmParms.sigScheme = inTempKey->sigScheme;\n    ephKey.algorithmParms.parmSize = inTempKey->parmSize;\n    switch (ephKey.algorithmParms.algorithmID) {\n      case TPM_ALG_RSA:\n        ephKey.algorithmParms.parms.rsa.keyLength =\n          inTempKey->parms.rsa.keyLength;\n        ephKey.algorithmParms.parms.rsa.numPrimes =\n          inTempKey->parms.rsa.numPrimes;\n        ephKey.algorithmParms.parms.rsa.exponentSize =\n          inTempKey->parms.rsa.exponentSize;\n        break;\n      default:\n        tpm_rsa_release_private_key(&k1);\n        return TPM_BAD_KEY_PROPERTY;\n    }\n    ephKey.PCRInfoSize = 0;\n    ephKey.pubKey.keyLength = key_length >> 3;\n    ephKey.pubKey.key = tpm_malloc(ephKey.pubKey.keyLength);\n    if (ephKey.pubKey.key == NULL) {\n      tpm_rsa_release_private_key(&k1);\n      tpm_free(store.privKey.key);\n      return TPM_NOSPACE;\n    }\n    tpm_rsa_export_modulus(&k1, ephKey.pubKey.key, NULL);\n    tpm_rsa_release_private_key(&k1);\n    ephKey.encDataSize = key_length >> 3;\n    ephKey.encData = tpm_malloc(ephKey.encDataSize);\n    if (ephKey.encData == NULL) {\n      tpm_free(store.privKey.key);\n      tpm_free(ephKey.pubKey.key);\n      return TPM_NOSPACE;\n    }\n    if (tpm_compute_key_digest(&ephKey, &store.pubDataDigest)) {\n      tpm_free(store.privKey.key);\n      tpm_free(ephKey.pubKey.key);\n      tpm_free(ephKey.encData);\n      debug(\"TPM_ChangeAuthAsymStart(): tpm_compute_key_digest() failed.\");\n      return TPM_FAIL;\n    }\n    if (tpm_encrypt_private_key(&tpmData.permanent.data.srk, &store, \n      ephKey.encData, &ephKey.encDataSize)) {\n      tpm_free(store.privKey.key);\n      tpm_free(ephKey.pubKey.key);\n      tpm_free(ephKey.encData);\n      debug(\"TPM_ChangeAuthAsymStart(): tpm_encrypt_private_key() failed.\");\n      return TPM_ENCRYPT_ERROR;\n    }\n    tpm_free(store.privKey.key);\n    /* assign a handle and store ephKey by calling internal_TPM_LoadKey() */\n    res = internal_TPM_LoadKey(&ephKey, ephHandle);\n    if (res != TPM_SUCCESS) {\n      tpm_free(ephKey.pubKey.key);\n      tpm_free(ephKey.encData);\n      return res;\n    }\n    tpm_free(ephKey.pubKey.key);\n    tpm_free(ephKey.encData);\n  /* 8. The TPM SHALL fill in all fields in tempKey using k1 for the\n        information. The TPM_KEY->encSize MUST be 0. */\n  outTempKey->tag = ephKey.tag;\n  outTempKey->fill = ephKey.fill;\n  outTempKey->keyUsage = ephKey.keyUsage;\n  outTempKey->keyFlags = ephKey.keyFlags;\n  outTempKey->authDataUsage = ephKey.authDataUsage;\n  outTempKey->algorithmParms.algorithmID = ephKey.algorithmParms.algorithmID;\n  outTempKey->algorithmParms.encScheme = ephKey.algorithmParms.encScheme;\n  outTempKey->algorithmParms.sigScheme = ephKey.algorithmParms.sigScheme;\n  outTempKey->algorithmParms.parmSize = ephKey.algorithmParms.parmSize;\n  outTempKey->algorithmParms.parms.rsa.keyLength = \n    ephKey.algorithmParms.parms.rsa.keyLength;\n  outTempKey->algorithmParms.parms.rsa.numPrimes = \n    ephKey.algorithmParms.parms.rsa.numPrimes;\n  outTempKey->algorithmParms.parms.rsa.exponentSize = \n    ephKey.algorithmParms.parms.rsa.exponentSize;\n  outTempKey->PCRInfoSize = ephKey.PCRInfoSize;\n  outTempKey->pubKey.keyLength = ephKey.pubKey.keyLength;\n  outTempKey->pubKey.key = tpm_malloc(outTempKey->pubKey.keyLength);\n  if (outTempKey->pubKey.key == NULL) return TPM_NOSPACE;\n  memcpy(outTempKey->pubKey.key, ephKey.pubKey.key, outTempKey->pubKey.keyLength);\n  outTempKey->encDataSize = 0;\n  outTempKey->encData = NULL;\n  /* 9. The TPM SHALL fill in certifyInfo using k1 for the information.\n        The certifyInfo->data field is supplied by the antiReplay. */\n    /* \"Version\" field is set according to the deprecated TPM_VERSION\n       structure from the old v1.1 specification. */\n    memcpy(&certifyInfo->tag, &tpmData.permanent.data.version, 2);\n    memcpy(&certifyInfo->fill, &tpmData.permanent.data.version + 2, 1);\n    memcpy(&certifyInfo->payloadType, &tpmData.permanent.data.version + 3, 1);\n    /* Other fields are filled according to Section 27.4.1 [TPM, Part 3]. */\n    certifyInfo->keyUsage = ephKey.keyUsage;\n    certifyInfo->keyFlags = ephKey.keyFlags;\n    certifyInfo->authDataUsage = ephKey.authDataUsage;\n    certifyInfo->algorithmParms.algorithmID = ephKey.algorithmParms.algorithmID;\n    certifyInfo->algorithmParms.encScheme = ephKey.algorithmParms.encScheme;\n    certifyInfo->algorithmParms.sigScheme = ephKey.algorithmParms.sigScheme;\n    certifyInfo->algorithmParms.parmSize = ephKey.algorithmParms.parmSize;\n    certifyInfo->algorithmParms.parms.rsa.keyLength = \n      ephKey.algorithmParms.parms.rsa.keyLength;\n    certifyInfo->algorithmParms.parms.rsa.numPrimes = \n      ephKey.algorithmParms.parms.rsa.numPrimes;\n    certifyInfo->algorithmParms.parms.rsa.exponentSize = \n      ephKey.algorithmParms.parms.rsa.exponentSize;\n    memcpy(&certifyInfo->pubkeyDigest, &store.pubDataDigest, sizeof(TPM_DIGEST));\n    memcpy(&certifyInfo->data, antiReplay, sizeof(TPM_NONCE));\n    certifyInfo->parentPCRStatus = FALSE;\n    certifyInfo->PCRInfoSize = 0;\n  /* 10. The TPM then signs the certifyInfo parameter using the key\n         pointed to by idHandle. The resulting signed blob is returned\n         in sig parameter. */\n  size = len = sizeof_TPM_CERTIFY_INFO((*certifyInfo));\n  buf = ptr = tpm_malloc(size);\n  if (buf == NULL) {\n    return TPM_NOSPACE;\n  }\n  if (tpm_marshal_TPM_CERTIFY_INFO(&ptr, &len, certifyInfo) || (len != 0)) {\n    debug(\"TPM_ChangeAuthAsymStart(): tpm_marshal_TPM_CERTIFY_INFO() failed.\");\n    tpm_free(buf);\n    return TPM_FAIL;\n  }\n  res = tpm_sign(idKey, auth1, FALSE, buf, size, sig, sigSize);\n  tpm_free(buf);\n  return res;\n}\n\nTPM_RESULT TPM_ChangeAuthAsymFinish(TPM_KEY_HANDLE parentHandle,\n                                    TPM_KEY_HANDLE ephHandle,\n                                    TPM_ENTITY_TYPE entityType,\n                                    TPM_HMAC *newAuthLink,\n                                    UINT32 newAuthSize, BYTE *encNewAuth,\n                                    UINT32 encDataSize, BYTE *encData,\n                                    TPM_AUTH *auth1,\n                                    UINT32 *outDataSize, BYTE **outData,\n                                    TPM_NONCE *saltNonce,\n                                    TPM_DIGEST *changeProof)\n{\n  TPM_RESULT res;\n  TPM_KEY_DATA *parentKey, *ephKey;\n  TPM_SEALED_DATA e1_seal;\n  TPM_STORE_ASYMKEY e1_store;\n  BYTE *e1_seal_buf, *e1_key_buf;\n  int scheme;\n  TPM_CHANGEAUTH_VALIDATE a1;\n  tpm_hmac_ctx_t hmac_ctx;\n  UINT32 len;\n  size_t size;\n  BYTE *ptr, *buf;\n  TPM_SECRET oldAuthSecret;\n  TPM_HMAC b1;\n  \n  \n  info(\"TPM_ChangeAuthAsymFinish()\");\n  /* 1. The TPM SHALL validate that the authHandle parameter authorizes\n        use of the key in parentHandle. */\n    /* get parent key */\n    parentKey = tpm_get_key(parentHandle);\n    if (parentKey == NULL) return TPM_INVALID_KEYHANDLE;\n    /* verify authorization */\n    if (auth1->authHandle != TPM_INVALID_HANDLE \n      || parentKey->authDataUsage != TPM_AUTH_NEVER) {\n        res = tpm_verify_auth(auth1, parentKey->usageAuth, parentHandle);\n        if (res != TPM_SUCCESS) return res;\n    }\n    /* get ephemeral key */\n    ephKey = tpm_get_key(ephHandle);\n    if (ephKey == NULL) return TPM_INVALID_KEYHANDLE;\n  /* 2. The encData field MUST be the encData field from TPM_STORED_DATA\n        or TPM_KEY. */\n    if (encDataSize != (parentKey->key.size >> 3))\n      return TPM_BAD_PARAMETER;\n  /* 3. The TPM SHALL create e1 by decrypting the entity held in the\n        encData parameter. */\n  switch (entityType) {\n    case TPM_ET_DATA:\n      /* decrypt seal data */\n      if (tpm_decrypt_sealed_data(parentKey, encData, encDataSize,\n          &e1_seal, &e1_seal_buf)) return TPM_DECRYPT_ERROR;\n      memcpy(oldAuthSecret, e1_seal.authData, sizeof(TPM_SECRET));\n      tpm_free(e1_seal_buf);\n      break;\n    case TPM_ET_KEY:\n      /* decrypt key data */\n      if (tpm_decrypt_private_key(parentKey, encData, encDataSize,\n        &e1_store, &e1_key_buf, NULL)) return TPM_DECRYPT_ERROR;\n      memcpy(oldAuthSecret, e1_store.usageAuth, sizeof(TPM_SECRET));\n      tpm_free(e1_key_buf);\n      break;\n    default:\n      return TPM_BAD_PARAMETER;\n  }\n  /* 4. The TPM SHALL create a1 by decrypting encNewAuth using the\n        ephHandle->TPM_KEY_AUTHCHANGE private key. a1 is a structure\n        of type TPM_CHANGEAUTH_VALIDATE. */\n  switch (ephKey->encScheme) {\n    case TPM_ES_RSAESOAEP_SHA1_MGF1: scheme = RSA_ES_OAEP_SHA1; break;\n    case TPM_ES_RSAESPKCSv15: scheme = RSA_ES_PKCSV15; break;\n    default: return TPM_BAD_PARAMETER;\n  }\n  len = newAuthSize;\n  buf = ptr = tpm_malloc(len);\n  if (buf == NULL) return TPM_NOSPACE;\n  if (tpm_rsa_decrypt(&ephKey->key, scheme, encNewAuth, newAuthSize, \n    buf, &size)\n    || (len = size) == 0\n    || tpm_unmarshal_TPM_CHANGEAUTH_VALIDATE(&ptr, &len, &a1)) {\n    debug(\"TPM_ChangeAuthAsymFinish(): tpm_rsa_decrypt() failed.\");\n    tpm_free(buf);\n    return TPM_DECRYPT_ERROR;\n  }\n  tpm_free(buf);\n  /* 5. The TPM SHALL create b1 by performing the following HMAC\n        calculation: b1 = HMAC(a1->newAuthSecret). The secret for\n        this calculation is encData->currentAuth. This means that\n        b1 is a value built from the current AuthData value\n        (encData->currentAuth) and the new AuthData value\n        (a1->newAuthSecret). */\n  tpm_hmac_init(&hmac_ctx, oldAuthSecret, sizeof(TPM_SECRET));\n  tpm_hmac_update(&hmac_ctx, a1.newAuthSecret, sizeof(TPM_SECRET));\n  tpm_hmac_final(&hmac_ctx, b1.digest);\n  /* 6. The TPM SHALL compare b1 with newAuthLink. The TPM SHALL\n        indicate a failure if the values do not match. */\n  if (memcmp(&b1, newAuthLink, sizeof(TPM_HMAC))) {\n    debug(\"TPM_ChangeAuthAsymFinish(): newAuthLink value does not match.\");\n    return TPM_FAIL;\n  }\n  /* 7. The TPM SHALL replace e1->authData with a1->newAuthSecret */\n  switch (entityType) {\n    case TPM_ET_DATA:\n      memcpy(e1_seal.authData, a1.newAuthSecret, sizeof(TPM_SECRET));\n      break;\n    case TPM_ET_KEY:\n      memcpy(e1_store.usageAuth, a1.newAuthSecret, sizeof(TPM_SECRET));\n      break;\n  }\n  /* 8. The TPM SHALL encrypt e1 using the appropriate functions for\n        the entity type. The key to encrypt with is parentHandle. */\n  switch (entityType) {\n    case TPM_ET_DATA:\n      if (tpm_encrypt_sealed_data(parentKey, &e1_seal, \n        *outData, outDataSize)) {\n          tpm_free(outData);\n          return TPM_ENCRYPT_ERROR;\n      }\n      break;\n    case TPM_ET_KEY:\n      if (tpm_encrypt_private_key(parentKey, &e1_store, \n        *outData, outDataSize)) {\n          tpm_free(outData);\n          return TPM_ENCRYPT_ERROR;\n      }\n      break;\n  }\n  /* 9. The TPM SHALL create slatNonce by taking the next 20 bytes\n        from the TPM RNG. */\n  tpm_get_random_bytes(saltNonce->nonce, sizeof(TPM_NONCE));\n  /* 10. The TPM SHALL create changeProof a HMAC of (saltNonce\n         concatenated with a1->n1) using a1->newAuthSecret as the\n         HMAC secret. */\n  tpm_hmac_init(&hmac_ctx, a1.newAuthSecret, sizeof(a1.newAuthSecret));\n  tpm_hmac_update(&hmac_ctx, saltNonce->nonce, sizeof(TPM_NONCE));\n  tpm_hmac_update(&hmac_ctx, a1.n1.nonce, sizeof(TPM_NONCE));\n  tpm_hmac_final(&hmac_ctx, changeProof->digest);\n  /* 11. The TPM MUST destroy the TPM_KEY_AUTHCHANGE key associated\n         with the authorization session. */\n  tpm_rsa_release_private_key(&ephKey->key);\n  memset(ephKey, 0, sizeof(*ephKey));\n  tpm_invalidate_sessions(ephHandle);\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_Reset()\n{\n  int i;\n  info(\"TPM_Reset()\");\n  /* invalidate all authorization sessions */\n  for (i = 0; i < TPM_MAX_SESSIONS; i++) {\n    TPM_SESSION_DATA *session = &tpmData.stany.data.sessions[i]; \n    if (session->type == TPM_ST_OIAP || session->type == TPM_ST_OSAP)\n      memset(session, 0, sizeof(*session));\n  }\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_CertifySelfTest(TPM_KEY_HANDLE keyHandle, TPM_NONCE *antiReplay,\n                               TPM_AUTH *auth1, UINT32 *sigSize, BYTE **sig)\n{\n  TPM_RESULT res;\n  TPM_KEY_DATA *key;\n  BYTE buf[35];\n  info(\"TPM_CertifySelfTest()\");\n  key = tpm_get_key(keyHandle);\n  if (key == NULL) return TPM_INVALID_KEYHANDLE;\n  /* perform self test */\n  res = TPM_SelfTestFull();\n  if (res != TPM_SUCCESS) return res;\n  /* verify authorization */ \n  if (auth1->authHandle != TPM_INVALID_HANDLE\n      || key->authDataUsage != TPM_AUTH_NEVER) {\n    res = tpm_verify_auth(auth1, key->usageAuth, keyHandle);\n    if (res != TPM_SUCCESS) return res;\n  }\n  if (key->keyUsage != TPM_KEY_SIGNING && key->keyUsage != TPM_KEY_LEGACY\n      && key->keyUsage != TPM_KEY_IDENTITY) return TPM_INVALID_KEYUSAGE;\n  /* not neccessary, because a vendor specific signature is allowed\n  if (key->sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1)\n    return TPM_BAD_SCHEME;\n  */\n  /* setup and sign result */\n  memcpy(&buf, \"Test Passed\", 11);\n  memcpy(&buf[11], antiReplay->nonce, sizeof(TPM_NONCE));\n  memcpy(&buf[31], \"\\x52\\x00\\x00\\x00\", 4);\n  return tpm_sign(key, auth1, FALSE, buf, sizeof(buf), sig, sigSize);\n}\n\nTPM_RESULT TPM_OwnerReadPubek(TPM_AUTH *auth1, TPM_PUBKEY *pubEndorsementKey)\n{\n  TPM_RESULT res;\n  info(\"TPM_OwnerReadPubek()\");\n  /* verify authorization */\n  res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);\n  if (res != TPM_SUCCESS) return res;\n  res = tpm_get_pubek(pubEndorsementKey);\n  if (res != TPM_SUCCESS) return res; \n  return TPM_SUCCESS;\n}\n"
  },
  {
    "path": "tpm/tpm_emulator.h",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: tpm_emulator.h 463 2011-06-08 14:25:04Z mast $\n */\n\n#ifndef _TPM_EMULATOR_H_\n#define _TPM_EMULATOR_H_\n\n#include \"config.h\"\n#include \"tpm_emulator_extern.h\"\n\n#define TPM_MANUFACTURER 0x4554485A /* 'ETHZ' */        \n\n/**\n * configuration flags\n */\n#define TPM_CONF_STRONG_PERSISTENCE            0x01\n#define TPM_CONF_GENERATE_EK                   0x02\n#define TPM_CONF_GENERATE_SEED_DAA             0x04\n#define TPM_CONF_USE_INTERNAL_PRNG             0x08\n#define TPM_CONF_ALLOW_PRNG_STATE_SETTING      0x10\n\n/**\n * tpm_emulator_init - initialises and starts the TPM emulator\n * @startup: [in] startup mode\n * @conf: [in] tpm configuration flags\n * @Returns: 0 on success, -1 otherwise\n */\nint tpm_emulator_init(uint32_t startup, uint32_t conf);\n\n/**\n * tpm_emulator_shutdown - shuts the TPM emulator down\n */\nvoid tpm_emulator_shutdown(void);\n\n/**\n * tpm_handle_command - handles (i.e., executes) TPM commands\n * @in: [in] incoming TPM command\n * @in_size: [in] total number of input bytes\n * @out: [inout] outgoing TPM result\n * @out_size: [inout] total number of output bytes\n * @Returns: 0 on success, -1 otherwise\n *\n * Description: Handles (i.e., executes) TPM commands. The parameters\n * out and out_size determine the output buffer and its capacity,\n * respectively. If out is NULL, the required memory is allocated\n * internally and has to be released by means of tpm_free() after\n * its usage. In case of an error, all internally allocated memory\n * is released and the the state of out and out_size is unspecified.\n */ \nint tpm_handle_command(const uint8_t *in, uint32_t in_size, uint8_t **out, uint32_t *out_size);\n\n#endif /* _TPM_EMULATOR_H_ */\n\n"
  },
  {
    "path": "tpm/tpm_emulator_extern.c",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: tpm_emulator_extern.c 477 2012-04-28 09:15:26Z mast $\n */\n\n#include \"tpm_emulator_extern.h\"\n#include \"config.h\"\n\n#ifndef TPM_NO_EXTERN\n\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <fcntl.h>\n#include <unistd.h>\n#include <errno.h>\n#include <stdio.h>\n#include <stdarg.h>\n#include <sys/time.h>\n#include <time.h>\n\nconst char *tpm_storage_file = TPM_STORAGE_NAME;\nconst char *tpm_log_file = TPM_LOG_FILE;\nconst char *tpm_random_device = \"/dev/urandom\";\n\nstatic int mkdirs(const char *path)\n{\n  char *copy = strdup(path);\n  char *p = strchr(copy + 1, '/');\n  while (p != NULL) {\n    *p = '\\0';\n#if defined(_WIN32) || defined(_WIN64)\n    if ((mkdir(copy) == -1) && (errno != EEXIST)) {\n#else\n    if ((mkdir(copy, 0755) == -1) && (errno != EEXIST)) {\n#endif\n      free(copy);\n      return errno;\n    }\n    *p = '/';\n    p = strchr(p + 1, '/');\n  }\n  free(copy);\n  return 0;\n}\n\n#if defined(_WIN32) || defined(_WIN64)\n\n#include <windows.h>\n#include <wincrypt.h>\n\nstatic HCRYPTPROV rand_ch;\n\nstatic int _tpm_extern_init()\n{\n  info(\"_tpm_extern_init()\");\n  mkdirs(tpm_storage_file);\n  mkdirs(tpm_log_file);\n  debug(\"initializing crypto context for RNG\");\n  BOOL res = CryptAcquireContext(&rand_ch, NULL, NULL,\n                                 PROV_RSA_FULL, CRYPT_SILENT);\n  if (!res) {\n    /* try it again with CRYPT_NEWKEYSET enabled */\n    res = CryptAcquireContext(&rand_ch, NULL, NULL,\n                              PROV_RSA_FULL, CRYPT_SILENT | CRYPT_NEWKEYSET);\n  }\n  if (!res) {\n    error(\"CryptAcquireContext() failed: %d\", GetLastError());\n    return -1;\n  }\n  return 0;\n}\n\nvoid _tpm_extern_release()\n{\n  info(\"_tpm_extern_release()\");\n  CryptReleaseContext(rand_ch, 0);\n}\n\nvoid _tpm_get_extern_random_bytes(void *buf, size_t nbytes)\n{\n  CryptGenRandom(rand_ch, nbytes, (BYTE*)buf);\n}\n\n#else\n\nstatic int rand_fh = -1;\n\nstatic int _tpm_extern_init()\n{\n  info(\"_tpm_extern_init()\");\n  mkdirs(tpm_storage_file);\n  mkdirs(tpm_log_file);\n  debug(\"openening random device %s\", tpm_random_device);\n  rand_fh = open(tpm_random_device, O_RDONLY);\n  if (rand_fh < 0) {\n    error(\"open(%s) failed: %s\", tpm_random_device, strerror(errno));\n    return -1;\n  }\n  return 0;\n}\n\nstatic void _tpm_extern_release()\n{\n  info(\"_tpm_extern_release()\");\n  if (rand_fh != -1) close(rand_fh);\n}\n\nstatic void _tpm_get_extern_random_bytes(void *buf, size_t nbytes)\n{\n  uint8_t *p = (uint8_t*)buf;\n  ssize_t res;\n  while (nbytes > 0) {\n    res = read(rand_fh, p, nbytes);\n    if (res > 0) {\n      nbytes -= res;\n      p += res;\n    }\n  }\n}\n\n#endif\n\nstatic void *_tpm_malloc(size_t size)\n{\n  return malloc(size);\n}\n\nstatic void _tpm_free(/*const*/ void *ptr)\n{\n  if (ptr != NULL) free((void*)ptr);\n}\n\nstatic void _tpm_log(int priority, const char *fmt, ...)\n{\n  FILE *fh;\n  va_list ap;\n  time_t tv;\n  struct tm t;\n  va_start(ap, fmt);\n  fh = fopen(tpm_log_file, \"a\");\n  if (fh != NULL) {\n    time(&tv);\n#if defined(_WIN32) || defined(_WIN64)\n    memcpy(&t, localtime(&tv), sizeof(t));\n#else\n    localtime_r(&tv, &t);\n#endif\n    fprintf(fh, \"%04d-%02d-%02d %02d:%02d:%02d \",\n            t.tm_year + 1900, t.tm_mon + 1, t.tm_mday,\n            t.tm_hour, t.tm_min, t.tm_sec);\n    vfprintf(fh, fmt, ap);\n    fclose(fh);\n  }\n  va_end(ap);\n}\n\nstatic uint64_t _tpm_get_ticks(void)\n{\n  static uint64_t old_t = 0;\n  uint64_t new_t, res_t;\n  struct timeval tv;\n  gettimeofday(&tv, NULL);\n  new_t = (uint64_t)tv.tv_sec * 1000000 + (uint64_t)tv.tv_usec;\n  res_t = (old_t > 0) ? new_t - old_t : 0;\n  old_t = new_t;\n  return res_t;\n}\n\nstatic int _tpm_write_to_storage(uint8_t *data, size_t data_length)\n{\n  int fh;\n  ssize_t res;\n\n#if defined(_WIN32) || defined(_WIN64)\n  fh = open(tpm_storage_file, O_WRONLY | O_TRUNC | O_CREAT | O_BINARY, S_IRUSR | S_IWUSR); \n#else\n  fh = open(tpm_storage_file, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR);\n#endif\n  if (fh < 0) return -1;\n  while (data_length > 0) {\n    res = write(fh, data, data_length);\n    if (res < 0) {\n      close(fh);\n      return -1;\n    }\n    data_length -= res; \n    data += res;\n  }\n  close(fh);\n  return 0;\n}\n\nstatic int _tpm_read_from_storage(uint8_t **data, size_t *data_length)\n{\n  int fh;\n  ssize_t res;\n  size_t total_length;\n\n#if defined(_WIN32) || defined(_WIN64)\n  fh = open(tpm_storage_file, O_RDONLY | O_BINARY); \n#else\n  fh = open(tpm_storage_file, O_RDONLY);\n#endif\n  if (fh < 0) return -1;\n  total_length = lseek(fh, 0, SEEK_END);\n  lseek(fh, 0, SEEK_SET);\n  *data = tpm_malloc(total_length);\n  if (*data == NULL) {\n    close(fh);\n    return -1;\n  }\n  *data_length = 0;\n  while (total_length > 0) {\n    res = read(fh, &(*data)[*data_length], total_length);\n    if (res < 0) {\n      close(fh);\n      tpm_free(*data);\n      return -1;\n    }\n    if (res == 0) break;\n    *data_length += res;\n    total_length -= res;\n  }\n  close(fh);\n  return 0;\n}\n\nint (*tpm_extern_init)(void)                                      = _tpm_extern_init;\nvoid (*tpm_extern_release)(void)                                  = _tpm_extern_release;\nvoid* (*tpm_malloc)(size_t size)                                  = _tpm_malloc;\nvoid (*tpm_free)(/*const*/ void *ptr)                             = _tpm_free;\nvoid (*tpm_log)(int priority, const char *fmt, ...)               = _tpm_log;\nvoid (*tpm_get_extern_random_bytes)(void *buf, size_t nbytes)     = _tpm_get_extern_random_bytes;\nuint64_t (*tpm_get_ticks)(void)                                   = _tpm_get_ticks;\nint (*tpm_write_to_storage)(uint8_t *data, size_t data_length)    = _tpm_write_to_storage;\nint (*tpm_read_from_storage)(uint8_t **data, size_t *data_length) = _tpm_read_from_storage;\n\n#else /* TPM_NO_EXTERN */\n\nint (*tpm_extern_init)(void)                                      = NULL;\nvoid (*tpm_extern_release)(void)                                  = NULL;\nvoid* (*tpm_malloc)(size_t size)                                  = NULL;\nvoid (*tpm_free)(/*const*/ void *ptr)                             = NULL;\nvoid (*tpm_log)(int priority, const char *fmt, ...)               = NULL;\nvoid (*tpm_get_extern_random_bytes)(void *buf, size_t nbytes)     = NULL;\nuint64_t (*tpm_get_ticks)(void)                                   = NULL;\nint (*tpm_write_to_storage)(uint8_t *data, size_t data_length)    = NULL;\nint (*tpm_read_from_storage)(uint8_t **data, size_t *data_length) = NULL;\n\n#endif /* TPM_NO_EXTERN */\n\n"
  },
  {
    "path": "tpm/tpm_emulator_extern.h",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: tpm_emulator_extern.h 440 2010-03-17 22:53:07Z mast $\n */\n\n#ifndef _TPM_EMULATOR_EXTERN_H_\n#define _TPM_EMULATOR_EXTERN_H_\n\n#include <inttypes.h>\n#include <stdlib.h>\n#include <string.h>\n\n/* log functions */\n\nenum {\n  TPM_LOG_DEBUG,\n  TPM_LOG_INFO,\n  TPM_LOG_ERROR\n};\n\nvoid (*tpm_log)(int priority, const char *fmt, ...);\n\n#if defined(_WIN32) || defined(_WIN64)\n#define __BFILE__ ((strrchr(__FILE__, '\\\\') ? : __FILE__ - 1) + 1)\n#else\n#define __BFILE__ ((strrchr(__FILE__, '/') ? : __FILE__ - 1) + 1)\n#endif\n\n#define debug(fmt, ...) tpm_log(TPM_LOG_DEBUG, \"%s:%d: Debug: \" fmt \"\\n\", \\\n                                __BFILE__, __LINE__, ## __VA_ARGS__)\n#define info(fmt, ...)  tpm_log(TPM_LOG_INFO, \"%s:%d: Info: \" fmt \"\\n\", \\\n                                __BFILE__, __LINE__, ## __VA_ARGS__)\n#define error(fmt, ...) tpm_log(TPM_LOG_ERROR, \"%s:%d: Error: \" fmt \"\\n\", \\\n                                __BFILE__, __LINE__, ## __VA_ARGS__)\n/* initialization */\nint (*tpm_extern_init)(void);\nvoid (*tpm_extern_release)(void);\n\n/* memory allocation */\n\nvoid* (*tpm_malloc)(size_t size);\n\nvoid (*tpm_free)(/*const*/ void *ptr);\n\n/* random numbers */\n\nvoid (*tpm_get_extern_random_bytes)(void *buf, size_t nbytes);\n\n/* usec since last call */\n\nuint64_t (*tpm_get_ticks)(void);\n\n/* file handling */\n\nint (*tpm_write_to_storage)(uint8_t *data, size_t data_length);\nint (*tpm_read_from_storage)(uint8_t **data, size_t *data_length);\n\n#endif /* _TPM_EMULATOR_EXTERN_H_ */\n\n"
  },
  {
    "path": "tpm/tpm_error.c",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: tpm_error.c 364 2010-02-11 10:24:45Z mast $\n */\n\n#include \"tpm_emulator.h\"\n#include \"tpm_structures.h\"\n\nconst char *tpm_error_to_string(TPM_RESULT res)\n{\n  switch (res) {\n    case TPM_SUCCESS:\n      return \"Successful completion of the operation.\";\n    case TPM_AUTHFAIL:\n      return \"Authentication failed.\";\n    case TPM_BADINDEX:\n      return \"The index to a PCR, DIR or other register is incorrect.\";\n    case TPM_BAD_PARAMETER:\n      return \"One or more parameter is bad.\";\n    case TPM_AUDITFAILURE:\n      return \"An operation completed successfully but the auditing of \"\n\t\"that operation failed.\";\n    case TPM_CLEAR_DISABLED:\n      return \"The clear disable flag is set and all clear operations now \"\n\t\"require physical access.\";\n    case TPM_DEACTIVATED:\n      return \"The TPM is deactivated.\";\n    case TPM_DISABLED:\n      return \"The TPM is disabled.\";\n    case TPM_DISABLED_CMD:\n      return \"The target command has been disabled.\";\n    case TPM_FAIL:\n      return \"The operation failed.\";\n    case TPM_BAD_ORDINAL:\n      return \"The ordinal was unknown or inconsistent.\";\n    case TPM_INSTALL_DISABLED:\n      return \"The ability to install an owner is disabled.\";\n    case TPM_INVALID_KEYHANDLE:\n      return \"The key handle can not be interpreted.\";\n    case TPM_KEYNOTFOUND:\n      return \"The key handle points to an invalid key.\";\n    case TPM_INAPPROPRIATE_ENC:\n      return \"Unacceptable encryption scheme.\";\n    case TPM_MIGRATEFAIL:\n      return \"Migration authorization failed.\";\n    case TPM_INVALID_PCR_INFO:\n      return \"PCR information could not be interpreted.\";\n    case TPM_NOSPACE:\n      return \"No room to load key.\";\n    case TPM_NOSRK:\n      return \"There is no SRK set.\";\n    case TPM_NOTSEALED_BLOB:\n      return \"An encrypted blob is invalid or was not created by this TPM.\";\n    case TPM_OWNER_SET:\n      return \"There is already an Owner.\";\n    case TPM_RESOURCES:\n      return \"The TPM has insufficient internal resources to perform the \"\n\t\"requested action.\";\n    case TPM_SHORTRANDOM:\n      return \"A random string was too short.\";\n    case TPM_SIZE:\n      return \"The TPM does not have the space to perform the operation.\";\n    case TPM_WRONGPCRVAL:\n      return \"The named PCR value does not match the current PCR value.\";\n    case TPM_BAD_PARAM_SIZE:\n      return \"The paramSize argument to the command has the incorrect value.\";\n    case TPM_SHA_THREAD:\n      return \"There is no existing SHA-1 thread.\";\n    case TPM_SHA_ERROR:\n      return \"The calculation is unable to proceed because the existing SHA-1 \"\n\t\"thread has already encountered an error.\";\n    case TPM_FAILEDSELFTEST:\n      return \"Self-test has failed and the TPM has shutdown.\";\n    case TPM_AUTH2FAIL:\n      return \"The authorization for the second key in a 2 key function failed \"\n\t\"authorization.\";\n    case TPM_BADTAG:\n      return \"The tag value sent to for a command is invalid.\";\n    case TPM_IOERROR:\n      return \"An IO error occurred transmitting information to the TPM.\";\n    case TPM_ENCRYPT_ERROR:\n      return \"The encryption process had a problem.\";\n    case TPM_DECRYPT_ERROR:\n      return \"The decryption process did not complete.\";\n    case TPM_INVALID_AUTHHANDLE:\n      return \"An invalid handle was used.\";\n    case TPM_NO_ENDORSEMENT:\n      return \"The TPM does not a EK installed.\";\n    case TPM_INVALID_KEYUSAGE:\n      return \"The usage of a key is not allowed.\";\n    case TPM_WRONG_ENTITYTYPE:\n      return \"The submitted entity type is not allowed.\";\n    case TPM_INVALID_POSTINIT:\n      return \"The command was received in the wrong sequence relative to \"\n\t\"TPM_Init and a subsequent TPM_Startup.\";\n    case TPM_INAPPROPRIATE_SIG:\n      return \"Signed data cannot include additional DER information.\";\n    case TPM_BAD_KEY_PROPERTY:\n      return \"The key properties in TPM_KEY_PARMs are not supported \"\n\t\"by this TPM.\";\n    case TPM_BAD_MIGRATION:\n      return \"The migration properties of this key are incorrect.\";\n    case TPM_BAD_SCHEME:\n      return \"The signature or encryption scheme for this key is incorrect \"\n\t\"or not permitted in this situation.\";\n    case TPM_BAD_DATASIZE:\n      return \"The size of the data (or blob) parameter is bad or \"\n        \"inconsistent with the referenced key.\";\n    case TPM_BAD_MODE:\n      return \"A mode parameter is bad, such as capArea or subCapArea for \"\n\t\"TPM_GetCapability, physicalPresence parameter for \"\n\t\"TPM_PhysicalPresence, or migrationType for TPM_CreateMigrationBlob.\";\n    case TPM_BAD_PRESENCE:\n      return \"Either the physicalPresence or physicalPresenceLock bits \"\n\t\"have the wrong value.\";\n    case TPM_BAD_VERSION:\n      return \"The TPM cannot perform this version of the capability.\";\n    case TPM_NO_WRAP_TRANSPORT:\n      return \"The TPM does not allow for wrapped transport sessions.\";\n    case TPM_AUDITFAIL_UNSUCCESSFUL:\n      return \"TPM audit construction failed and the underlying command was \"\n\t\"returning a failure code also.\";\n    case TPM_AUDITFAIL_SUCCESSFUL:\n      return \"TPM audit construction failed and the underlying command was \"\n\t\"returning success.\";\n    case TPM_NOTRESETABLE:\n      return \"Attempt to reset a PCR register that does not have the \"\n\t\"resettable attribute.\";\n    case TPM_NOTLOCAL:\n      return \"Attempt to reset a PCR register that requires locality and \"\n\t\"locality modifier not part of command transport.\";\n    case TPM_BAD_TYPE:\n      return \"Make identity blob not properly typed.\";\n    case TPM_INVALID_RESOURCE:\n      return \"When saving context identified resource type does not match \"\n\t\"actual resource.\";\n    case TPM_NOTFIPS:\n      return \"The TPM is attempting to execute a command only available \"\n\t\"when in FIPS mode.\";\n    case TPM_INVALID_FAMILY:\n      return \"The command is attempting to use an invalid family ID.\";\n    case TPM_NO_NV_PERMISSION:\n      return \"The permission to manipulate the NV storage is not available.\";\n    case TPM_REQUIRES_SIGN:\n      return \"The operation requires a signed command.\";\n    case TPM_KEY_NOTSUPPORTED:\n      return \"Wrong operation to load an NV key.\";\n    case TPM_AUTH_CONFLICT:\n      return \"NV_LoadKey blob requires both owner and blob authorization.\";\n    case TPM_AREA_LOCKED:\n      return \"The NV area is locked and not writable.\";\n    case TPM_BAD_LOCALITY:\n      return \"The locality is incorrect for the attempted operation.\";\n    case TPM_READ_ONLY:\n      return \"The NV area is read only and can't be written to.\";\n    case TPM_PER_NOWRITE:\n      return \"There is no protection on the write to the NV area.\";\n    case TPM_FAMILYCOUNT:\n      return \"The family count value does not match.\";\n    case TPM_WRITE_LOCKED:\n      return \"The NV area has already been written to.\";\n    case TPM_BAD_ATTRIBUTES:\n      return \"The NV area attributes conflict.\";\n    case TPM_INVALID_STRUCTURE:\n      return \"The structure tag and version are invalid or inconsistent.\";\n    case TPM_KEY_OWNER_CONTROL:\n      return \"The key is under control of the TPM Owner and can only be \"\n\t\"evicted by the TPM Owner.\";\n    case TPM_BAD_COUNTER:\n      return \"The counter handle is incorrect.\";\n    case TPM_NOT_FULLWRITE:\n      return \"The write is not a complete write of the area.\";\n    case TPM_CONTEXT_GAP:\n      return \"The gap between saved context counts is too large.\";\n    case TPM_MAXNVWRITES:\n      return \"The maximum number of NV writes without an \"\n\t\"owner has been exceeded.\";\n    case TPM_NOOPERATOR:\n      return \"No operator AuthData value is set.\";\n    case TPM_RESOURCEMISSING:\n      return \"The resource pointed to by context is not loaded.\";\n    case TPM_DELEGATE_LOCK:\n      return \"The delegate administration is locked.\";\n    case TPM_DELEGATE_FAMILY:\n      return \"Attempt to manage a family other then the delegated family.\";\n    case TPM_DELEGATE_ADMIN:\n      return \"Delegation table management not enabled.\";\n    case TPM_TRANSPORT_NOTEXCLUSIVE:\n      return \"There was a command executed outside of an exclusive \"\n\t\"transport session.\";\n    case TPM_OWNER_CONTROL:\n      return \"Attempt to context save a owner evict controlled key.\";\n    case TPM_DAA_RESOURCES:\n      return \"The DAA command has no resources available to \"\n\t\"execute the command.\";\n    case TPM_DAA_INPUT_DATA0:\n      return \"The consistency check on DAA parameter inputData0 has failed.\";\n    case TPM_DAA_INPUT_DATA1:\n      return \"The consistency check on DAA parameter inputData1 has failed.\";\n    case TPM_DAA_ISSUER_SETTINGS:\n      return \"The consistency check on DAA_issuerSettings has failed.\";\n    case TPM_DAA_TPM_SETTINGS:\n      return \"The consistency check on DAA_tpmSpecific has failed.\";\n    case TPM_DAA_STAGE:\n      return \"The atomic process indicated by the submitted DAA command \"\n\t\"is not the expected process.\";\n    case TPM_DAA_ISSUER_VALIDITY:\n      return \"The issuer's validity check has detected an inconsistency.\";\n    case TPM_DAA_WRONG_W:\n      return \"The consistency check on w has failed.\";\n    case TPM_BAD_HANDLE:\n      return \"The handle is incorrect.\";\n    case TPM_BAD_DELEGATE:\n      return \"Delegation is not correct.\";\n    case TPM_BADCONTEXT:\n      return \"The context blob is invalid.\";\n    case TPM_TOOMANYCONTEXTS:\n      return \"Too many contexts held by the TPM.\";\n    case TPM_MA_TICKET_SIGNATURE:\n      return \"Migration authority signature validation failure.\";\n    case TPM_MA_DESTINATION:\n      return \"Migration destination not authenticated.\";\n    case TPM_MA_SOURCE:\n      return \"Migration source incorrect.\";\n    case TPM_MA_AUTHORITY:\n      return \"Incorrect migration authority.\";\n    case TPM_PERMANENTEK:\n      return \"Attempt to revoke the EK and the EK is not revocable.\";\n    case TPM_BAD_SIGNATURE:\n      return \"Bad signature of CMK ticket.\";\n    case TPM_NOCONTEXTSPACE:\n      return \"There is no room in the context list for additional contexts.\";\n    case TPM_RETRY:\n      return \"The TPM is too busy to respond to the command immediately, \"\n\t\"but the command could be resubmitted at a later time.\";\n    default:\n      return \"Unknown TPM error\";\n  }\n}\n"
  },
  {
    "path": "tpm/tpm_eviction.c",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: tpm_eviction.c 364 2010-02-11 10:24:45Z mast $\n */\n\n#include \"tpm_emulator.h\"\n#include \"tpm_commands.h\"\n#include \"tpm_handles.h\"\n#include \"tpm_data.h\"\n#include \"crypto/rsa.h\"\n\n/*\n * Eviction ([TPM_Part3], Section 22)\n * The TPM has numerous resources held inside of the TPM that may need \n * eviction. The need for eviction occurs when the number or resources \n * in use by the TPM exceed the available space. In version 1.1 there were \n * separate commands to evict separate resource types. This new command \n * set uses the resource types defined for context saving and creates a \n * generic command that will evict all resource types.\n */\n\nstatic void dump_sessions(void)\n{\n  int i;\n  for (i = 0; i < TPM_MAX_SESSIONS; i++) {\n    if (tpmData.stany.data.sessions[i].type != TPM_ST_INVALID) {\n      debug(\"session[%d] = %08x\", i, INDEX_TO_AUTH_HANDLE(i));\n    }\n  }\n}\n\nTPM_RESULT TPM_FlushSpecific(TPM_HANDLE handle, \n                             TPM_RESOURCE_TYPE resourceType)\n{\n  TPM_SESSION_DATA *session;\n  TPM_DAA_SESSION_DATA *sessionDAA;\n  TPM_KEY_DATA *key;\n  int i;\n  \n  info(\"TPM_FlushSpecific()\");\n  debug(\"handle = %08x, resourceType = %08x\", handle, resourceType);\n  switch (resourceType) {\n    case TPM_RT_CONTEXT:\n      for (i = 0; i < TPM_MAX_SESSION_LIST; i++)\n        if (tpmData.stany.data.contextList[i] == handle) break;\n      if (i != TPM_MAX_SESSION_LIST)\n        tpmData.stany.data.contextList[i] = 0;\n      return TPM_SUCCESS;\n    \n    case TPM_RT_KEY:\n      key = tpm_get_key(handle);\n      if (key != NULL) {\n        if (key->keyControl & TPM_KEY_CONTROL_OWNER_EVICT)\n          return TPM_KEY_OWNER_CONTROL;\n        if (handle == TPM_KH_SRK) return TPM_FAIL;\n        tpm_rsa_release_private_key(&key->key);\n        memset(key, 0, sizeof(*key));\n        tpm_invalidate_sessions(handle);\n      }\n      return TPM_SUCCESS;\n    \n    case TPM_RT_HASH:\n    case TPM_RT_COUNTER:\n    case TPM_RT_DELEGATE:\n      return TPM_INVALID_RESOURCE;\n    \n    case TPM_RT_AUTH:\n      session = tpm_get_auth(handle);\n      if (session != NULL)\n        memset(session, 0, sizeof(*session));\n      dump_sessions();\n      return TPM_SUCCESS;\n    \n    case TPM_RT_TRANS:\n      session = tpm_get_transport(handle);\n      if (session != NULL)\n        memset(session, 0, sizeof(*session));\n      dump_sessions();\n      return TPM_SUCCESS;\n    \n    case TPM_RT_DAA_TPM:\n      sessionDAA = tpm_get_daa(handle);\n      if (sessionDAA != NULL) {\n        memset(sessionDAA, 0, sizeof(*sessionDAA));\n        if (handle == tpmData.stany.data.currentDAA)\n          tpmData.stany.data.currentDAA = 0;\n        tpm_invalidate_sessions(handle);\n      }\n      return TPM_SUCCESS;\n  }\n  return TPM_INVALID_RESOURCE;\n}\n"
  },
  {
    "path": "tpm/tpm_handles.c",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: tpm_handles.c 364 2010-02-11 10:24:45Z mast $\n */\n\n#include \"tpm_emulator.h\"\n#include \"tpm_handles.h\"\n#include \"tpm_data.h\"\n\nTPM_KEY_DATA *tpm_get_key_slot(TPM_KEY_HANDLE handle)\n{\n  if (handle == TPM_INVALID_HANDLE) return NULL;\n  handle &= 0x00ffffff;\n  if (handle >= TPM_MAX_KEYS) return NULL;\n  return &tpmData.permanent.data.keys[handle];\n}\n\nTPM_SESSION_DATA *tpm_get_session_slot(TPM_HANDLE handle)\n{\n  if (handle == TPM_INVALID_HANDLE) return NULL;\n  handle &= 0x00ffffff;\n  if (handle >= TPM_MAX_SESSIONS) return NULL;\n  return &tpmData.stany.data.sessions[handle];\n}\n\nTPM_DAA_SESSION_DATA *tpm_get_daa_slot(TPM_HANDLE handle)\n{\n  if (handle == TPM_INVALID_HANDLE) return NULL;\n  handle &= 0x00ffffff;\n  if (handle >= TPM_MAX_SESSIONS_DAA) return NULL;\n  return &tpmData.stany.data.sessionsDAA[handle];\n}\n\nTPM_KEY_DATA *tpm_get_key(TPM_KEY_HANDLE handle)\n{\n  /* handle reserved key handles */\n  switch (handle) {\n    case TPM_KH_EK:\n    case TPM_KH_OWNER:\n    case TPM_KH_REVOKE:\n    case TPM_KH_TRANSPORT:\n    case TPM_KH_OPERATOR:\n    case TPM_KH_ADMIN:\n      return NULL;\n    case TPM_KH_SRK:\n      debug(\"SRK valid? %d\", tpmData.permanent.data.srk.payload);\n      return (tpmData.permanent.data.srk.payload) ?\n        &tpmData.permanent.data.srk : NULL;\n  }\n  if (handle == TPM_INVALID_HANDLE \n      || (handle >> 24) != TPM_RT_KEY) return NULL;\n  handle &= 0x00ffffff;\n  if (handle >= TPM_MAX_KEYS\n      || !tpmData.permanent.data.keys[handle].payload) return NULL;\n  return &tpmData.permanent.data.keys[handle];\n}\n\nTPM_SESSION_DATA *tpm_get_auth(TPM_AUTHHANDLE handle)\n{\n  if (handle == TPM_INVALID_HANDLE\n      || (handle >> 24) != TPM_RT_AUTH) return NULL;\n  handle &= 0x00ffffff;\n  if (handle >= TPM_MAX_SESSIONS\n      || (tpmData.stany.data.sessions[handle].type != TPM_ST_OIAP\n          && tpmData.stany.data.sessions[handle].type != TPM_ST_OSAP\n          && tpmData.stany.data.sessions[handle].type != TPM_ST_DSAP)) return NULL;\n  return &tpmData.stany.data.sessions[handle];\n}\n\nTPM_SESSION_DATA *tpm_get_transport(TPM_TRANSHANDLE handle)\n{\n  if (handle == TPM_INVALID_HANDLE\n      || (handle >> 24) != TPM_RT_TRANS) return NULL;\n  handle &= 0x00ffffff;\n  if (handle >= TPM_MAX_SESSIONS\n      || tpmData.stany.data.sessions[handle].type != TPM_ST_TRANSPORT) return NULL;\n  return &tpmData.stany.data.sessions[handle];\n}\n\nTPM_COUNTER_VALUE *tpm_get_counter(TPM_COUNT_ID handle)\n{\n  if ((handle == TPM_INVALID_HANDLE) || ((handle >> 24) != TPM_RT_COUNTER))\n    return NULL;\n  handle &= 0x00ffffff;\n  if ((handle >= TPM_MAX_COUNTERS)\n    || !tpmData.permanent.data.counters[handle].valid) return NULL;\n  return &tpmData.permanent.data.counters[handle];\n}\n\nTPM_DAA_SESSION_DATA *tpm_get_daa(TPM_DAAHANDLE handle)\n{\n  if ((handle == TPM_INVALID_HANDLE) || ((handle >> 24) != TPM_RT_DAA_TPM))\n    return NULL;\n  handle &= 0x00ffffff;\n  if ((handle >= TPM_MAX_SESSIONS_DAA)\n    || (tpmData.stany.data.sessionsDAA[handle].type != TPM_ST_DAA)) return NULL;\n  return &tpmData.stany.data.sessionsDAA[handle];\n}\n"
  },
  {
    "path": "tpm/tpm_handles.h",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: tpm_handles.h 364 2010-02-11 10:24:45Z mast $\n */\n\n#ifndef _TPM_HANDLES_\n#define _TPM_HANDLES_\n\n#include \"tpm_structures.h\"\n\n/*\n * definition of an invalid handle\n */ \n#define TPM_INVALID_HANDLE             0xFFFFFFFF\n\n/*\n * macros to convert array indices to handles\n */\n#define INDEX_TO_KEY_HANDLE(i)         ((i) | (TPM_RT_KEY << 24))\n#define INDEX_TO_AUTH_HANDLE(i)        ((i) | (TPM_RT_AUTH << 24))\n#define INDEX_TO_TRANS_HANDLE(i)       ((i) | (TPM_RT_TRANS << 24))\n#define INDEX_TO_COUNTER_HANDLE(i)     ((i) | (TPM_RT_COUNTER << 24))\n#define INDEX_TO_DAA_HANDLE(i)         ((i) | (TPM_RT_DAA_TPM << 24))\n\n/*\n * marco to convert handles to indices\n */\n#define HANDLE_TO_INDEX(h)             ((h) & 0x00FFFFFF)\n\n/*\n * macro to get the ressource type of a handle\n */\n#define HANDLE_TO_RT(h)                ((h) >> 24)\n\n/*\n * functions to get the dedicated data for a handle\n */\nTPM_KEY_DATA *tpm_get_key_slot(TPM_KEY_HANDLE handle);\nTPM_SESSION_DATA *tpm_get_session_slot(TPM_HANDLE handle);\nTPM_DAA_SESSION_DATA *tpm_get_daa_slot(TPM_HANDLE handle);\n\nTPM_KEY_DATA *tpm_get_key(TPM_KEY_HANDLE handle);\nTPM_SESSION_DATA *tpm_get_auth(TPM_AUTHHANDLE handle);\nTPM_SESSION_DATA *tpm_get_transport(TPM_TRANSHANDLE handle);\nTPM_COUNTER_VALUE *tpm_get_counter(TPM_COUNT_ID handle);\nTPM_DAA_SESSION_DATA *tpm_get_daa(TPM_DAAHANDLE handle);\nTPM_NV_DATA_SENSITIVE *tpm_get_nvs(TPM_NV_INDEX index);\n\n#endif /* _TPM_HANDLES_ */\n\n"
  },
  {
    "path": "tpm/tpm_identity.c",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *               2005-2008 Heiko Stamer <stamer@gaos.org>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: tpm_identity.c 468 2011-09-09 07:58:42Z mast $\n */\n\n#include \"tpm_emulator.h\"\n#include \"tpm_commands.h\"\n#include \"tpm_data.h\"\n#include \"crypto/sha1.h\"\n#include \"crypto/rsa.h\"\n#include \"tpm_handles.h\"\n#include \"tpm_marshalling.h\"\n\n#define LOCALITY tpmData.stany.flags.localityModifier\n\n/*\n * Identity Creation and Activation ([TPM_Part3], Section 15)\n */\n\nTPM_RESULT TPM_MakeIdentity(\n  TPM_ENCAUTH *identityAuth,\n  TPM_CHOSENID_HASH *labelPrivCADigest,\n  TPM_KEY *idKeyParams,\n  TPM_AUTH *auth1,\n  TPM_AUTH *auth2,\n  TPM_KEY *idKey,\n  UINT32 *identityBindingSize,\n  BYTE **identityBinding\n)\n{\n  TPM_RESULT res;\n  TPM_SESSION_DATA *ownerAuth_sessionData;\n  TPM_SECRET A1;\n  tpm_rsa_private_key_t tpm_signature_key;\n  UINT32 key_length;\n  TPM_STORE_ASYMKEY store;\n  TPM_IDENTITY_CONTENTS idContents;\n  UINT32 len;\n  BYTE *buf, *ptr;\n  \n  info(\"TPM_MakeIdentity()\");\n  /* 1. Validate the idKeyParams parameters for the key description */\n    if (idKeyParams->algorithmParms.encScheme != TPM_ES_NONE\n      || idKeyParams->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1)\n        return TPM_BAD_KEY_PROPERTY;\n    /* a. If the algorithm type is RSA the key length MUST be a minimum of 2048.\n     * For interoperability the key length SHOULD be 2048 */\n    /* b. If the algorithm type is other than RSA the strength provided by the \n     * key MUST be comparable to RSA 2048 */\n    /* c. If the TPM is not designed to create a key of the requested type, \n     * return the error code TPM_BAD_KEY_PROPERTY */\n    switch (idKeyParams->algorithmParms.algorithmID) {\n      case TPM_ALG_RSA:\n        if (idKeyParams->algorithmParms.parmSize == 0\n          || idKeyParams->algorithmParms.parms.rsa.keyLength != 2048\n          || idKeyParams->algorithmParms.parms.rsa.numPrimes != 2\n          || idKeyParams->algorithmParms.parms.rsa.exponentSize != 0)\n            return TPM_BAD_KEY_PROPERTY;\n        break;\n      default:\n        return TPM_BAD_KEY_PROPERTY;\n    }\n    /* d. If TPM_PERMANENT_FLAGS->FIPS is TRUE then */\n    if (tpmData.permanent.flags.FIPS == TRUE) {\n      /* i. If authDataUsage specifies TPM_AUTH_NEVER return TPM_NOTFIPS */\n      if (idKeyParams->authDataUsage == TPM_AUTH_NEVER)\n        return TPM_NOTFIPS;\n    }\n  /* 2. Use authHandle to verify that the Owner authorized all TPM_MakeIdentity \n   * input parameters. */\n  if (auth2->authHandle != TPM_INVALID_HANDLE) {\n    res = tpm_verify_auth(auth2, tpmData.permanent.data.ownerAuth, \n      TPM_KH_OWNER);\n    if (res != TPM_SUCCESS) return res;\n    ownerAuth_sessionData = tpm_get_auth(auth2->authHandle);\n  } else {\n    res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, \n      TPM_KH_OWNER);\n    if (res != TPM_SUCCESS) return res;\n    ownerAuth_sessionData = tpm_get_auth(auth1->authHandle);\n  }\n  /* 3. Use srkAuthHandle to verify that the SRK owner authorized all \n   * TPM_MakeIdentity input parameters. */\n  if (auth2->authHandle != TPM_INVALID_HANDLE) {\n    res = tpm_verify_auth(auth1, tpmData.permanent.data.srk.usageAuth, \n      TPM_KH_SRK);\n    if (res != TPM_SUCCESS) return res;\n  }\n  /* 4. Verify that idKeyParams->keyUsage is TPM_KEY_IDENTITY. If it is not, \n   * return TPM_INVALID_KEYUSAGE */\n  if (idKeyParams->keyUsage != TPM_KEY_IDENTITY)\n    return TPM_INVALID_KEYUSAGE;\n  /* 5. Verify that idKeyParams->keyFlags->migratable is FALSE. If it is not,\n   * return TPM_INVALID_KEYUSAGE */\n  if ((idKeyParams->keyFlags & TPM_KEY_FLAG_MIGRATABLE) == \n    TPM_KEY_FLAG_MIGRATABLE)\n      return TPM_INVALID_KEYUSAGE;\n  /* 6. If ownerAuth indicates XOR encryption for the AuthData secrets */\n  if (ownerAuth_sessionData == NULL) return TPM_INVALID_AUTHHANDLE;\n  if ((ownerAuth_sessionData->entityType & 0xFF00) == TPM_ET_XOR) {\n    /* a. Create X1 the SHA-1 of the concatenation of (ownerAuth->sharedSecret \n     * || authLastNonceEven) */\n    /* b. Create A1 by XOR X1 and identityAuth */\n    tpm_decrypt_auth_secret(*identityAuth, ownerAuth_sessionData->sharedSecret, \n      &ownerAuth_sessionData->lastNonceEven, A1);\n  } else {\n  /* 7. Else */\n    /* a. Create A1 by decrypting identityAuth using the algorithm indicated \n     * in the OSAP session */\n    /* b. Key is from ownerAuth->sharedSecret */\n    /* c. IV is SHA-1 of (authLastNonceEven || nonceOdd) */\n    debug(\"TPM_MakeIdentity() does not support entityType=%.8x yet.\", \n      ownerAuth_sessionData->entityType);\n    return TPM_FAIL;\n  }\n  /* 8. Set continueAuthSession and continueSRKSession to FALSE. */\n  auth2->continueAuthSession = FALSE, auth1->continueAuthSession = FALSE;\n  /* 9. Determine the structure version */\n    /* a. If idKeyParms->tag is TPM_TAG_KEY12 */\n    if (idKeyParams->tag == TPM_TAG_KEY12) {\n      /* i. Set V1 to 2 */\n      /* ii. Create idKey a TPM_KEY12 structure using idKeyParams as the \n       * default values for the structure */\n      idKey->tag = TPM_TAG_KEY12;\n      idKey->fill = 0x0000;\n      idKey->keyUsage = TPM_KEY_IDENTITY;\n      idKey->keyFlags = idKeyParams->keyFlags;\n      idKey->authDataUsage = idKeyParams->authDataUsage;\n      idKey->algorithmParms.algorithmID = \n        idKeyParams->algorithmParms.algorithmID;\n      idKey->algorithmParms.encScheme = idKeyParams->algorithmParms.encScheme;\n      idKey->algorithmParms.sigScheme = idKeyParams->algorithmParms.sigScheme;\n      idKey->algorithmParms.parmSize = idKeyParams->algorithmParms.parmSize;\n      switch (idKeyParams->algorithmParms.algorithmID) {\n        case TPM_ALG_RSA:\n          idKey->algorithmParms.parms.rsa.keyLength =\n            idKeyParams->algorithmParms.parms.rsa.keyLength;\n          idKey->algorithmParms.parms.rsa.numPrimes =\n            idKeyParams->algorithmParms.parms.rsa.numPrimes;\n          idKey->algorithmParms.parms.rsa.exponentSize =\n            idKeyParams->algorithmParms.parms.rsa.exponentSize;\n          break;\n        default:\n          return TPM_BAD_KEY_PROPERTY;\n      }\n      idKey->PCRInfoSize = idKeyParams->PCRInfoSize;\n      idKey->PCRInfo.tag = TPM_TAG_PCR_INFO_LONG;\n      idKey->PCRInfo.localityAtCreation = \n        idKeyParams->PCRInfo.localityAtCreation;\n      idKey->PCRInfo.localityAtRelease = \n        idKeyParams->PCRInfo.localityAtRelease;\n      idKey->PCRInfo.creationPCRSelection = \n        idKeyParams->PCRInfo.creationPCRSelection;\n      idKey->PCRInfo.releasePCRSelection = \n        idKeyParams->PCRInfo.releasePCRSelection;\n      idKey->PCRInfo.digestAtCreation = \n        idKeyParams->PCRInfo.digestAtCreation;\n      idKey->PCRInfo.digestAtRelease = \n        idKeyParams->PCRInfo.digestAtRelease;\n    } else if (idKeyParams->tag == 0x0101) {\n    /* b. If idKeyParms->ver is 1.1 */\n      /* i. Set V1 to 1 */\n      /* ii. Create idKey a TPM_KEY structure using idKeyParams as the \n       * default values for the structure */\n      idKey->tag = 0x0101;\n      idKey->fill = 0x0000;\n      idKey->keyUsage = TPM_KEY_IDENTITY;\n      idKey->keyFlags = idKeyParams->keyFlags;\n      idKey->authDataUsage = idKeyParams->authDataUsage;\n      idKey->algorithmParms.algorithmID = \n        idKeyParams->algorithmParms.algorithmID;\n      idKey->algorithmParms.encScheme = idKeyParams->algorithmParms.encScheme;\n      idKey->algorithmParms.sigScheme = idKeyParams->algorithmParms.sigScheme;\n      idKey->algorithmParms.parmSize = idKeyParams->algorithmParms.parmSize;\n      switch (idKeyParams->algorithmParms.algorithmID) {\n        case TPM_ALG_RSA:\n          idKey->algorithmParms.parms.rsa.keyLength =\n            idKeyParams->algorithmParms.parms.rsa.keyLength;\n          idKey->algorithmParms.parms.rsa.numPrimes =\n            idKeyParams->algorithmParms.parms.rsa.numPrimes;\n          idKey->algorithmParms.parms.rsa.exponentSize =\n            idKeyParams->algorithmParms.parms.rsa.exponentSize;\n          break;\n        default:\n          return TPM_BAD_KEY_PROPERTY;\n      }\n      idKey->PCRInfoSize = idKeyParams->PCRInfoSize;\n      idKey->PCRInfo.tag = 0x0000;\n      idKey->PCRInfo.creationPCRSelection = \n        idKeyParams->PCRInfo.creationPCRSelection;\n      idKey->PCRInfo.digestAtRelease = \n        idKeyParams->PCRInfo.digestAtRelease;\n      idKey->PCRInfo.digestAtCreation = \n        idKeyParams->PCRInfo.digestAtCreation;\n    } else {\n      debug(\"TPM_MakeIdentity(): unsupport this TPM_KEY structure.\");\n      return TPM_FAIL;\n    }\n  /* 10. Set the digestAtCreation values for pcrInfo */\n  if (idKey->PCRInfoSize > 0) {\n    res = tpm_compute_pcr_digest(&idKey->PCRInfo.creationPCRSelection,\n      &idKey->PCRInfo.digestAtCreation, NULL);\n    if (res != TPM_SUCCESS) return res;\n      /* a. For PCR_INFO_LONG include the locality of the current command */\n      if (idKey->PCRInfo.tag == TPM_TAG_PCR_INFO_LONG)\n        idKey->PCRInfo.localityAtCreation = (1 << LOCALITY);\n  }\n  /* 11. Create an asymmetric key pair (identityPubKey and tpm_signature_key) \n   * using a TPM-protected capability, in accordance with the algorithm \n   * specified in idKeyParams */\n  key_length = idKeyParams->algorithmParms.parms.rsa.keyLength;\n  if (tpm_rsa_generate_key(&tpm_signature_key, key_length)) {\n    debug(\"TPM_MakeIdentity(): tpm_rsa_generate_key() failed.\");\n    return TPM_FAIL;\n  }\n  /* 12. Ensure that the AuthData information in A1 is properly stored in the \n   * idKey as usageAuth. */\n  memcpy(store.usageAuth, A1, sizeof(TPM_SECRET));\n  /* 13. Attach identityPubKey and tpm_signature_key to idKey */\n  idKey->pubKey.keyLength = key_length >> 3;\n  idKey->pubKey.key = tpm_malloc(idKey->pubKey.keyLength);\n  if (idKey->pubKey.key == NULL) {\n    tpm_rsa_release_private_key(&tpm_signature_key);\n    return TPM_NOSPACE;\n  }\n  store.privKey.keyLength = key_length >> 4;\n  store.privKey.key = tpm_malloc(store.privKey.keyLength);\n  if (store.privKey.key == NULL) {\n    tpm_free(idKey->pubKey.key);\n    tpm_rsa_release_private_key(&tpm_signature_key);\n    return TPM_NOSPACE;\n  }\n  idKey->encDataSize = tpmData.permanent.data.srk.key.size >> 3;\n  idKey->encData = tpm_malloc(idKey->encDataSize);\n  if (idKey->encData == NULL) {\n    tpm_free(store.privKey.key);\n    tpm_free(idKey->pubKey.key);\n    tpm_rsa_release_private_key(&tpm_signature_key);\n    return TPM_NOSPACE;\n  }\n  tpm_rsa_export_modulus(&tpm_signature_key, idKey->pubKey.key, NULL);\n  tpm_rsa_export_prime1(&tpm_signature_key, store.privKey.key, NULL);\n  /* 14. Set idKey->migrationAuth to TPM_PERMANENT_DATA->tpmProof */\n  memcpy(store.migrationAuth, tpmData.permanent.data.tpmProof.nonce, \n    sizeof(TPM_SECRET));\n  /* 15. Ensure that all TPM_PAYLOAD_TYPE structures identify this key as \n   * TPM_PT_ASYM */\n  store.payload = TPM_PT_ASYM;\n  /* compute the digest on all public data of this key */\n  if (tpm_compute_key_digest(idKey, &store.pubDataDigest)) {\n    debug(\"TPM_MakeIdentity(): tpm_compute_key_digest() failed.\");\n    tpm_free(idKey->encData);\n    tpm_free(store.privKey.key);\n    tpm_free(idKey->pubKey.key);\n    tpm_rsa_release_private_key(&tpm_signature_key);\n    return TPM_FAIL;\n  }\n  /* 16. Encrypt the private portion of idKey using the SRK as the parent key */\n  if (tpm_encrypt_private_key(&tpmData.permanent.data.srk, &store, idKey->encData, \n    &idKey->encDataSize)) {\n      tpm_free(idKey->encData);\n      tpm_free(store.privKey.key);\n      tpm_free(idKey->pubKey.key);\n      tpm_rsa_release_private_key(&tpm_signature_key);\n      return TPM_ENCRYPT_ERROR;\n  }\n  tpm_free(store.privKey.key);\n  /* 17. Create a TPM_IDENTITY_CONTENTS structure named idContents using \n   * labelPrivCADigest and the information from idKey */\n  idContents.ver.major = 1, idContents.ver.minor = 1; /* MUST BE 1.1, (Spec) */\n  idContents.ver.revMajor = 0, idContents.ver.revMinor = 0;\n  idContents.ordinal = TPM_ORD_MakeIdentity;\n  memcpy(&idContents.labelPrivCADigest, labelPrivCADigest, \n    sizeof(TPM_CHOSENID_HASH));\n  idContents.identityPubKey.algorithmParms.algorithmID = \n    idKey->algorithmParms.algorithmID;\n  idContents.identityPubKey.algorithmParms.encScheme = \n    idKey->algorithmParms.encScheme;\n  idContents.identityPubKey.algorithmParms.sigScheme = \n    idKey->algorithmParms.sigScheme;\n  idContents.identityPubKey.algorithmParms.parmSize = \n    idKey->algorithmParms.parmSize;\n  switch (idKey->algorithmParms.algorithmID) {\n    case TPM_ALG_RSA:\n      idContents.identityPubKey.algorithmParms.parms.rsa.keyLength =\n        idKey->algorithmParms.parms.rsa.keyLength;\n      idContents.identityPubKey.algorithmParms.parms.rsa.numPrimes =\n        idKey->algorithmParms.parms.rsa.numPrimes;\n      idContents.identityPubKey.algorithmParms.parms.rsa.exponentSize =\n        idKey->algorithmParms.parms.rsa.exponentSize;\n      break;\n    default:\n      tpm_free(idKey->encData);\n      tpm_free(idKey->pubKey.key);\n      tpm_rsa_release_private_key(&tpm_signature_key);\n      return TPM_BAD_KEY_PROPERTY;\n  }\n  idContents.identityPubKey.pubKey.keyLength = key_length >> 3;\n  idContents.identityPubKey.pubKey.key = \n    tpm_malloc(idContents.identityPubKey.pubKey.keyLength);\n  if (idContents.identityPubKey.pubKey.key == NULL) {\n    tpm_free(idKey->encData);\n    tpm_free(idKey->pubKey.key);\n    tpm_rsa_release_private_key(&tpm_signature_key);\n    return TPM_NOSPACE;\n  }\n  tpm_rsa_export_modulus(&tpm_signature_key, idContents.identityPubKey.pubKey.key, NULL);\n  len = sizeof_TPM_IDENTITY_CONTENTS((idContents));\n  buf = ptr = tpm_malloc(len);\n  if (buf == NULL) {\n    tpm_free(idContents.identityPubKey.pubKey.key);\n    tpm_free(idKey->encData);\n    tpm_free(idKey->pubKey.key);\n    tpm_rsa_release_private_key(&tpm_signature_key);\n    return TPM_NOSPACE;\n  }\n  if (tpm_marshal_TPM_IDENTITY_CONTENTS(&ptr, &len, &idContents)) {\n    debug(\"TPM_MakeIdentity(): tpm_marshal_TPM_IDENTITY_CONTENTS() failed.\");\n    tpm_free(buf);\n    tpm_free(idContents.identityPubKey.pubKey.key);\n    tpm_free(idKey->encData);\n    tpm_free(idKey->pubKey.key);\n    tpm_rsa_release_private_key(&tpm_signature_key);\n    return TPM_FAIL;\n  }\n  /* 18. Sign idContents using tpm_signature_key and \n   * TPM_SS_RSASSAPKCS1v15_SHA1. Store the result in identityBinding. */\n  *identityBindingSize = tpm_signature_key.size >> 3;\n  *identityBinding = tpm_malloc(*identityBindingSize);\n  if (*identityBinding == NULL) {\n    tpm_free(buf);\n    tpm_free(idContents.identityPubKey.pubKey.key);\n    tpm_free(idKey->encData);\n    tpm_free(idKey->pubKey.key);\n    tpm_rsa_release_private_key(&tpm_signature_key);\n    return TPM_NOSPACE;\n  }\n  if (tpm_rsa_sign(&tpm_signature_key, RSA_SSA_PKCS1_SHA1, buf, \n    sizeof_TPM_IDENTITY_CONTENTS((idContents)), *identityBinding)) {\n      debug(\"TPM_MakeIdentity(): tpm_rsa_sign() failed.\");\n      tpm_free(*identityBinding);\n      tpm_free(buf);\n      tpm_free(idContents.identityPubKey.pubKey.key);\n      tpm_free(idKey->encData);\n      tpm_free(idKey->pubKey.key);\n      tpm_rsa_release_private_key(&tpm_signature_key);\n      return TPM_FAIL;\n  }\n  tpm_free(buf);\n  tpm_free(idContents.identityPubKey.pubKey.key);\n  tpm_rsa_release_private_key(&tpm_signature_key);\n  \n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_ActivateIdentity(\n  TPM_KEY_HANDLE idKeyHandle,\n  UINT32 blobSize,\n  BYTE *blob,\n  TPM_AUTH *auth1,\n  TPM_AUTH *auth2,\n  TPM_SYMMETRIC_KEY *symmetricKey\n)\n{\n  TPM_RESULT res;\n  TPM_KEY_DATA *idKey = NULL;\n  TPM_PUBKEY pubKey;\n  TPM_DIGEST H1;\n  BYTE *B1 = NULL;\n  size_t sizeB1 = 0;\n  UINT32 len;\n  BYTE *ptr;\n  BYTE B1__what = 0x00;\n  TPM_EK_BLOB B1__ekBlob;\n  TPM_ASYM_CA_CONTENTS B1__asymCaContents;\n  TPM_SYMMETRIC_KEY *K1 = NULL;\n  TPM_EK_BLOB_ACTIVATE A1;\n  TPM_COMPOSITE_HASH C1;\n  \n  info(\"TPM_ActivateIdentity()\");\n  \n  /* 1. Using the authHandle field, validate the owner's AuthData to execute \n   * the command and all of the incoming parameters. */\n  if (auth2->authHandle != TPM_INVALID_HANDLE) {\n    res = tpm_verify_auth(auth2, tpmData.permanent.data.ownerAuth, \n      TPM_KH_OWNER);\n    if (res != TPM_SUCCESS) return res;\n  } else {\n    res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, \n      TPM_KH_OWNER);\n    if (res != TPM_SUCCESS) return res;\n  }\n  \n  /* 2. Using the idKeyAuthHandle, validate the AuthData to execute command \n   * and all of the incoming parameters */\n  idKey = tpm_get_key(idKeyHandle);\n  if (idKey == NULL)\n    return TPM_INVALID_KEYHANDLE;\n  if (auth2->authHandle != TPM_INVALID_HANDLE) { \n    if (idKey->authDataUsage != TPM_AUTH_NEVER) {\n      res = tpm_verify_auth(auth1, idKey->usageAuth, idKeyHandle);\n      if (res != TPM_SUCCESS) return res;\n    }\n  }\n  \n  /* 3. Validate that the idKey is the public key of a valid TPM identity by \n   * checking that idKeyHandle->keyUsage is TPM_KEY_IDENTITY. \n   * Return TPM_BAD_PARAMETER on mismatch */\n  if (idKey->keyUsage != TPM_KEY_IDENTITY)\n    return TPM_BAD_PARAMETER;\n  \n  /* 4. Create H1 the digest of a TPM_PUBKEY derived from idKey */\n  pubKey.pubKey.keyLength = idKey->key.size >> 3;\n  pubKey.pubKey.key = tpm_malloc(pubKey.pubKey.keyLength);\n  if (pubKey.pubKey.key == NULL)\n    return TPM_NOSPACE;\n  tpm_rsa_export_modulus(&idKey->key, pubKey.pubKey.key, NULL);\n  if (tpm_setup_key_parms(idKey, &pubKey.algorithmParms) != 0) {\n    debug(\"TPM_ActivateIdentity(): tpm_setup_key_parms() failed.\");\n    tpm_free(pubKey.pubKey.key);\n    return TPM_FAIL;\n  }\n  tpm_free(pubKey.algorithmParms.parms.rsa.exponent);\n  pubKey.algorithmParms.parms.rsa.exponentSize = 0;\n  pubKey.algorithmParms.parmSize = 12;\n  if (tpm_compute_pubkey_digest(&pubKey, &H1)) {\n    debug(\"TPM_ActivateIdentity(): tpm_compute_pubkey_digest() failed.\");\n    tpm_free(pubKey.pubKey.key);\n    return TPM_FAIL;\n  }\n  \n  /* 5. Decrypt blob creating B1 using PRIVEK as the decryption key */\n  B1 = tpm_malloc(blobSize);\n  if (B1 == NULL) {\n    tpm_free(pubKey.pubKey.key);\n    return TPM_NOSPACE;\n  }\n  if (tpm_rsa_decrypt(&tpmData.permanent.data.endorsementKey, RSA_ES_OAEP_SHA1, \n    blob, blobSize, B1, &sizeB1)) {\n      tpm_free(pubKey.pubKey.key);\n      tpm_free(B1);\n      return TPM_DECRYPT_ERROR;\n  }\n  \n  /* 6. Determine the type and version of B1 */\n  if ((((UINT16)B1[0] << 8) | B1[1]) == TPM_TAG_EK_BLOB) {\n    /* a. If B1->tag is TPM_TAG_EK_BLOB then */\n      /* i. B1 is a TPM_EK_BLOB */\n    ptr = B1;\n    len = sizeB1;\n    if (tpm_unmarshal_TPM_EK_BLOB(&ptr, &len, &B1__ekBlob)) {\n        debug(\"TPM_ActivateIdentity(): tpm_unmarshal_TPM_EK_BLOB() failed.\");\n        tpm_free(pubKey.pubKey.key);\n        tpm_free(B1);\n        return TPM_FAIL;\n    }\n    B1__what = 0x02;\n  } else {\n    /* b. Else */\n      /* i. B1 is a TPM_ASYM_CA_CONTENTS. As there is no tag for this \n       * structure it is possible for the TPM to make a mistake here but \n       * other sections of the structure undergo validation */\n    ptr = B1;\n    len = sizeB1;\n    if (tpm_unmarshal_TPM_ASYM_CA_CONTENTS(&ptr, &len, &B1__asymCaContents)) {\n        debug(\"TPM_ActivateIdentity(): tpm_unmarshal_TPM_ASYM_CA_CONTENTS() failed.\");\n        tpm_free(pubKey.pubKey.key);\n        tpm_free(B1);\n        return TPM_FAIL;\n    }\n    B1__what = 0x01;\n  }\n  \n  /* 7. If B1 is a version 1.1 TPM_ASYM_CA_CONTENTS then */\n  if (B1__what == 0x01) {\n    /* a. Compare H1 to B1->idDigest on mismatch return TPM_BAD_PARAMETER */\n    if (memcmp(H1.digest, B1__asymCaContents.idDigest.digest, \n      sizeof(H1.digest))) {\n        tpm_free(pubKey.pubKey.key);\n        tpm_free(B1);\n        return TPM_BAD_PARAMETER;\n    }\n    /* b. Set K1 to B1->sessionKey */\n    K1 = &B1__asymCaContents.sessionKey;\n  }\n  \n  /* 8. If B1 is a TPM_EK_BLOB then */\n  if (B1__what == 0x02) {\n    /* a. Validate that B1->ekType is TPM_EK_TYPE_ACTIVATE, \n     * return TPM_BAD_TYPE if not. */\n    if (B1__ekBlob.ekType != TPM_EK_TYPE_ACTIVATE) {\n      tpm_free(pubKey.pubKey.key);\n      tpm_free(B1);\n      return TPM_BAD_TYPE;\n    }\n    /* b. Assign A1 as a TPM_EK_BLOB_ACTIVATE structure from B1->blob */\n    ptr = B1__ekBlob.blob;\n    len = B1__ekBlob.blobSize;\n    if (tpm_unmarshal_TPM_EK_BLOB_ACTIVATE(&ptr, &len, &A1)) {\n        debug(\"TPM_ActivateIdentity(): tpm_unmarshal_TPM_EK_BLOB_ACTIVATE() failed.\");\n        tpm_free(pubKey.pubKey.key);\n        tpm_free(B1);\n        return TPM_FAIL;\n    }\n    /* c. Compare H1 to A1->idDigest on mismatch return TPM_BAD_PARAMETER */\n    if (memcmp(H1.digest, A1.idDigest.digest, sizeof(H1.digest))) {\n      tpm_free(pubKey.pubKey.key);\n      tpm_free(B1);\n      return TPM_BAD_PARAMETER;\n    }\n    /* d. If A1->pcrSelection is not NULL */\n    if (A1.pcrInfo.pcrSelection.sizeOfSelect > 0) {\n      /* i. Compute a composite hash C1 using the PCR selection \n       * A1->pcrSelection */\n      if (tpm_compute_pcr_digest(&A1.pcrInfo.pcrSelection, &C1, NULL) !=\n        TPM_SUCCESS) {\n          debug(\"TPM_ActivateIdentity(): tpm_compute_pcr_digest() failed.\");\n          tpm_free(pubKey.pubKey.key);\n          tpm_free(B1);\n          return TPM_FAIL;\n      }\n      /* ii. Compare C1 to A1->pcrInfo->digestAtRelease and return \n       * TPM_WRONGPCRVAL on a mismatch */\n      if (memcmp(&C1, &A1.pcrInfo.digestAtRelease, \n        sizeof(TPM_COMPOSITE_HASH))) {\n          tpm_free(pubKey.pubKey.key);\n          tpm_free(B1);\n          return TPM_WRONGPCRVAL;\n      }\n      /* iii. If A1->pcrInfo specifies a locality ensure that the \n       * appropriate locality has been asserted, return TPM_BAD_LOCALITY \n       * on error */\n      if (!(A1.pcrInfo.localityAtRelease & (1 << LOCALITY))) {\n        tpm_free(pubKey.pubKey.key);\n        tpm_free(B1);\n        return TPM_BAD_LOCALITY;\n      }\n    }\n    /* e. Set K1 to A1->sessionKey */\n    K1 = &A1.sessionKey;\n  }\n  \n  /* 9. Return K1 */\n  if (K1 != NULL) {\n    symmetricKey->algId = K1->algId;\n    symmetricKey->encScheme = K1->encScheme;\n    symmetricKey->size = K1->size;\n    memcpy(symmetricKey->data, K1->data, K1->size);\n  }\n  tpm_free(pubKey.pubKey.key);\n  tpm_free(B1);\n  return TPM_SUCCESS;\n}\n"
  },
  {
    "path": "tpm/tpm_integrity.c",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: tpm_integrity.c 474 2011-12-20 10:27:45Z mast $\n */\n\n#include \"tpm_emulator.h\"\n#include \"tpm_commands.h\"\n#include \"tpm_data.h\"\n#include \"crypto/sha1.h\"\n#include \"crypto/rsa.h\"\n#include \"tpm_handles.h\"\n#include \"tpm_marshalling.h\"\n\n/*\n * Integrity Collection and Reporting ([TPM_Part3], Section 16)\n * This section deals with what commands have direct access to the PCR.\n */\n\n#define PCR_ATTRIB     tpmData.permanent.data.pcrAttrib\n#define PCR_VALUE      tpmData.permanent.data.pcrValue\n#define LOCALITY       tpmData.stany.flags.localityModifier\n\nTPM_RESULT TPM_Extend(TPM_PCRINDEX pcrNum, TPM_DIGEST *inDigest, \n                      TPM_PCRVALUE *outDigest)\n{\n  tpm_sha1_ctx_t ctx;\n\n  info(\"TPM_Extend()\");\n  if (pcrNum >= TPM_NUM_PCR) return TPM_BADINDEX;\n  if (!(PCR_ATTRIB[pcrNum].pcrExtendLocal & (1 << LOCALITY))) return TPM_BAD_LOCALITY;\n  /* compute new PCR value as SHA-1(old PCR value || inDigest) */\n  tpm_sha1_init(&ctx);\n  tpm_sha1_update(&ctx, PCR_VALUE[pcrNum].digest, sizeof(PCR_VALUE[pcrNum].digest));\n  tpm_sha1_update(&ctx, inDigest->digest, sizeof(inDigest->digest));\n  tpm_sha1_final(&ctx, PCR_VALUE[pcrNum].digest);  \n  /* set output digest */\n  if (tpmData.permanent.flags.disable) {\n    memset(outDigest->digest, 0, sizeof(*outDigest->digest));\n  } else {\n    memcpy(outDigest, &PCR_VALUE[pcrNum], sizeof(TPM_PCRVALUE));\n  }\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_PCRRead(TPM_PCRINDEX pcrIndex, TPM_PCRVALUE *outDigest)\n{\n  info(\"TPM_PCRRead()\");\n  if (pcrIndex >= TPM_NUM_PCR) return TPM_BADINDEX;\n  memcpy(outDigest, &PCR_VALUE[pcrIndex], sizeof(TPM_PCRVALUE));\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_Quote(TPM_KEY_HANDLE keyHandle, TPM_NONCE *extrnalData, \n                     TPM_PCR_SELECTION *targetPCR, TPM_AUTH *auth1, \n                     TPM_PCR_COMPOSITE *pcrData, \n                     UINT32 *sigSize, BYTE **sig)\n{\n  TPM_RESULT res;\n  TPM_KEY_DATA *key;\n  TPM_COMPOSITE_HASH hash;\n  BYTE buf[48];\n  info(\"TPM_Quote()\");\n  /* get key */\n  key = tpm_get_key(keyHandle);\n  if (key == NULL) return TPM_INVALID_KEYHANDLE;\n  /* verify authorization */\n  if (auth1->authHandle != TPM_INVALID_HANDLE\n      || key->authDataUsage != TPM_AUTH_NEVER) {\n    res = tpm_verify_auth(auth1, key->usageAuth, keyHandle);\n    if (res != TPM_SUCCESS) return res;\n  }\n  if (key->sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1)\n    return TPM_INAPPROPRIATE_SIG;\n  if (key->keyUsage != TPM_KEY_SIGNING && key->keyUsage != TPM_KEY_LEGACY\n      && key->keyUsage != TPM_KEY_IDENTITY)\n    return TPM_INVALID_KEYUSAGE;\n  /* compute composite hash */\n  res = tpm_compute_pcr_digest(targetPCR, &hash, pcrData);\n  if (res != TPM_SUCCESS) return res;\n  /* setup quote info and sign it */\n  memcpy(&buf[ 0], \"\\x01\\x01\\x00\\x00QUOT\", 8);\n  memcpy(&buf[ 8], hash.digest, 20);\n  memcpy(&buf[28], extrnalData->nonce, 20);\n  *sigSize = key->key.size >> 3;\n  *sig = tpm_malloc(*sigSize);\n  if (*sig == NULL) return TPM_FAIL;\n  if (tpm_rsa_sign(&key->key, RSA_SSA_PKCS1_SHA1, buf, 48, *sig)) {\n    tpm_free(*sig);\n    return TPM_FAIL;\n  }\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_PCR_Reset(TPM_PCR_SELECTION *pcrSelection)\n{\n  int i;\n  info(\"TPM_PCR_Reset()\");\n  if ((pcrSelection->sizeOfSelect * 8) > TPM_NUM_PCR)\n    return TPM_INVALID_PCR_INFO;\n  /* this command must be atomic, thus we first verify that all\n     registers are resetable ... */ \n  for (i = 0; i < pcrSelection->sizeOfSelect * 8; i++) {\n    /* is PCR number i selected ? */\n    if (pcrSelection->pcrSelect[i >> 3] & (1 << (i & 7))) {\n      if (!PCR_ATTRIB[i].pcrReset) return TPM_NOTRESETABLE;\n      if (!(PCR_ATTRIB[i].pcrResetLocal & (1 << LOCALITY))) return TPM_NOTLOCAL;\n    }\n  }\n  /* ... then we reset all registers at once */\n  for (i = 0; i < pcrSelection->sizeOfSelect * 8; i++) {\n    /* is PCR number i selected ? */\n    if (pcrSelection->pcrSelect[i >> 3] & (1 << (i & 7))) {\n      memset(PCR_VALUE[i].digest, 0, sizeof(PCR_VALUE[i].digest));\n    }\n  }\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT tpm_compute_pcr_digest(TPM_PCR_SELECTION *pcrSelection, \n                                  TPM_COMPOSITE_HASH *digest, \n                                  TPM_PCR_COMPOSITE *composite)\n{\n  int i,j;\n  TPM_PCR_COMPOSITE comp;\n  tpm_sha1_ctx_t ctx;\n  UINT32 len;\n  BYTE *buf, *ptr;\n  info(\"tpm_compute_pcr_digest()\");\n  /* create PCR composite */\n  if ((pcrSelection->sizeOfSelect * 8) > TPM_NUM_PCR\n      || pcrSelection->sizeOfSelect == 0) return TPM_INVALID_PCR_INFO;\n  for (i = 0, j = 0; i < pcrSelection->sizeOfSelect * 8; i++) {\n    /* is PCR number i selected ? */\n    if (pcrSelection->pcrSelect[i >> 3] & (1 << (i & 7))) {\n      memcpy(&comp.pcrValue[j++], &PCR_VALUE[i], sizeof(TPM_PCRVALUE));\n    }\n  }\n  memcpy(&comp.select, pcrSelection, sizeof(TPM_PCR_SELECTION));\n  comp.valueSize = j * sizeof(TPM_PCRVALUE);\n  debug(\"comp.valueSize = %d\", comp.valueSize);\n  if (comp.valueSize > 0) {\n    /* marshal composite and compute hash */\n    len = sizeof_TPM_PCR_COMPOSITE(comp);\n    buf = ptr = tpm_malloc(len);\n    if (buf == NULL\n        || tpm_marshal_TPM_PCR_COMPOSITE(&ptr, &len, &comp)) {\n       tpm_free(buf);\n       return TPM_FAIL;\n    }\n    tpm_sha1_init(&ctx);\n    tpm_sha1_update(&ctx, buf, sizeof_TPM_PCR_COMPOSITE(comp));\n    tpm_sha1_final(&ctx, digest->digest);\n    tpm_free(buf);\n  } else {\n    memset(digest, 0, sizeof(TPM_COMPOSITE_HASH));\n  }\n  /* copy composite if requested */\n  if (composite != NULL)\n    memcpy(composite, &comp, sizeof(TPM_PCR_COMPOSITE));\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT tpm_verify_pcr(TPM_KEY_DATA *key, BOOL atrelease, BOOL atcreation)\n{\n  TPM_RESULT res;\n  TPM_COMPOSITE_HASH digest;\n  info(\"tpm_verify_pcr()\");\n  if (atrelease) {\n    res = tpm_compute_pcr_digest(&key->pcrInfo.releasePCRSelection, \n                                 &digest, NULL);\n    if (res != TPM_SUCCESS) return res;\n    if (memcmp(&digest, &key->pcrInfo.digestAtRelease, \n        sizeof(TPM_COMPOSITE_HASH))) return TPM_WRONGPCRVAL;\n    if (key->pcrInfo.tag == TPM_TAG_PCR_INFO_LONG\n        && !(key->pcrInfo.localityAtRelease\n             & (1 << tpmData.stany.flags.localityModifier)))\n      return TPM_BAD_LOCALITY;\n  }\n  if (atcreation) {\n    res = tpm_compute_pcr_digest(&key->pcrInfo.creationPCRSelection, \n                                 &digest, NULL);\n    if (res != TPM_SUCCESS) return res;\n    if (memcmp(&digest, &key->pcrInfo.digestAtCreation, \n        sizeof(TPM_COMPOSITE_HASH))) return TPM_WRONGPCRVAL;\n    if (key->pcrInfo.tag == TPM_TAG_PCR_INFO_LONG\n        && !(key->pcrInfo.localityAtCreation\n             & (1 << tpmData.stany.flags.localityModifier)))\n      return TPM_BAD_LOCALITY;\n  }\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_Quote2(TPM_KEY_HANDLE keyHandle, TPM_NONCE *externalData,\n                      TPM_PCR_SELECTION *targetPCR, BOOL addVersion,\n                      TPM_AUTH *auth1, TPM_PCR_INFO_SHORT *pcrData,\n                      UINT32 *versionInfoSize,\n                      TPM_CAP_VERSION_INFO *versionInfo,\n                      UINT32 *sigSize, BYTE **sig)\n{\n  TPM_RESULT res;\n  TPM_KEY_DATA *key;\n  TPM_COMPOSITE_HASH H1;\n  TPM_QUOTE_INFO2 Q1;\n  tpm_sha1_ctx_t ctx;\n  TPM_DIGEST digest;\n  UINT32 respSize, len, size;\n  BYTE *resp, *ptr, *buf;\n\n  info(\"TPM_Quote2()\");\n  /* get key by keyHandle*/\n  key = tpm_get_key(keyHandle);\n  if (key == NULL) return TPM_INVALID_KEYHANDLE;\n  /* 1. The TPM MUST validate the AuthData to use the key pointed\n   *    to by keyhandle */\n  if (auth1->authHandle != TPM_INVALID_HANDLE\n      || key->authDataUsage != TPM_AUTH_NEVER) {\n    res = tpm_verify_auth(auth1, key->usageAuth, keyHandle);\n    if (res != TPM_SUCCESS) return res;\n  }\n  /* 2. Validate that keyHandle->sigScheme is TPM_SS_RSASSAPKCS1v15_SHA1 or\n        TPM_SS_RSASSAPKCS1v15_INFO, if not return TPM_INAPPROPRIATE_SIG. */\n  if ((key->sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1) &&\n       (key->sigScheme != TPM_SS_RSASSAPKCS1v15_INFO))\n    return TPM_INAPPROPRIATE_SIG;\n  /* 3. Validate that keyHandle->keyUsage is TPM_KEY_SIGNING, TPM_KEY_IDENTITY,\n        or TPM_KEY_LEGACY, if not return TPM_INVALID_KEYUSAGE */\n  if ((key->keyUsage != TPM_KEY_SIGNING) && (key->keyUsage != TPM_KEY_LEGACY)\n      && (key->keyUsage != TPM_KEY_IDENTITY))\n    return TPM_INVALID_KEYUSAGE;\n  /* 4. Validate targetPCR is a valid TPM_PCR_SELECTION structure,\n   *    on errors return TPM_INVALID_PCR_INFO */\n  if (targetPCR->sizeOfSelect > sizeof(targetPCR->pcrSelect))\n    return TPM_INVALID_PCR_INFO;\n  /* 5. Create H1 a SHA-1 hash of a TPM_PCR_COMPOSITE using the\n   *    TPM_STCLEAR_DATA->PCR[] indicated by targetPCR->pcrSelect */\n  res = tpm_compute_pcr_digest(targetPCR, &H1, NULL);\n  if (res != TPM_SUCCESS) return res;\n  /* 6. Create S1 a TPM_PCR_INFO_SHORT */\n    /* a. Set S1->pcrSelection to targetPCR */\n    pcrData->pcrSelection.sizeOfSelect = targetPCR->sizeOfSelect;\n    memcpy(pcrData->pcrSelection.pcrSelect, targetPCR->pcrSelect, targetPCR->sizeOfSelect);\n    /* b. Set S1->localityAtRelease to TPM_STANY_DATA -> localityModifier */\n    pcrData->localityAtRelease = 1 << tpmData.stany.flags.localityModifier;\n    /* c. Set S1->digestAtRelease to H1 */\n    memcpy(&pcrData->digestAtRelease, &H1, sizeof(TPM_COMPOSITE_HASH));\n  /* 7. Create Q1 a TPM_QUOTE_INFO2 structure */\n  Q1.tag = TPM_TAG_QUOTE_INFO2;\n    /* a. Set Q1->fixed to \"QUT2\" */\n    Q1.fixed[0] = 'Q', Q1.fixed[1] = 'U', Q1.fixed[2] = 'T', Q1.fixed[3] = '2';\n    /* b. Set Q1->infoShort to S1 */\n    Q1.infoShort.pcrSelection.sizeOfSelect = pcrData->pcrSelection.sizeOfSelect;\n    memcpy(Q1.infoShort.pcrSelection.pcrSelect,\n      pcrData->pcrSelection.pcrSelect, pcrData->pcrSelection.sizeOfSelect);\n    Q1.infoShort.localityAtRelease = pcrData->localityAtRelease;\n    memcpy(Q1.infoShort.digestAtRelease.digest,\n      pcrData->digestAtRelease.digest, sizeof(TPM_COMPOSITE_HASH));\n    /* c. Set Q1->externalData to externalData */\n    memcpy(&Q1.externalData, externalData, sizeof(TPM_NONCE));\n  size = len = sizeof_TPM_QUOTE_INFO2(Q1);\n  buf = ptr = tpm_malloc(size);\n  if (buf == NULL) return TPM_NOSPACE;\n  if (tpm_marshal_TPM_QUOTE_INFO2(&ptr, &len, &Q1) || (len != 0)) {\n    debug(\"TPM_Quote2(): tpm_marshal_TPM_QUOTE_INFO2() failed.\");\n    tpm_free(buf);\n    return TPM_FAIL;\n  }\n  /* 8. If addVersion is TRUE */\n  if (addVersion == TRUE) {\n    debug(\"TPM_Quote2(): addVersion == TRUE\");\n    /* a. Concatenate to Q1 a TPM_CAP_VERSION_INFO structure */\n    res = TPM_GetCapability(TPM_CAP_VERSION_VAL, 0, NULL, &respSize, &resp);\n    if (res != TPM_SUCCESS) {\n      debug(\"TPM_Quote2(): cap_version_val() failed.\");\n      tpm_free(buf);\n      return TPM_FAIL;\n    }\n    /* b. Set the output parameters for versionInfo */\n    ptr = resp;\n    len = respSize;\n    if (tpm_unmarshal_TPM_CAP_VERSION_INFO(&ptr, &len, versionInfo) ||\n      (len != 0)) {\n        debug(\"TPM_Quote2(): tpm_unmarshal_TPM_CAP_VERSION_INFO() failed.\");\n        tpm_free(buf);\n        return TPM_FAIL;\n    }\n    *versionInfoSize = respSize;\n   } else { /* 9. Else */\n    debug(\"TPM_Quote2(): addVersion == FALSE\");\n    /* a. Set versionInfoSize to 0 */\n    *versionInfoSize = 0;\n    /* b. Return no bytes in versionInfo */\n  }\n  /* 10. Sign a SHA-1 hash of Q1 using keyHandle as the signature key */\n  tpm_sha1_init(&ctx);\n  tpm_sha1_update(&ctx, buf, size);\n  tpm_free(buf);\n  if (addVersion == TRUE) {\n    tpm_sha1_update(&ctx, resp, respSize);\n    tpm_free(resp);\n  }\n  tpm_sha1_final(&ctx, digest.digest);\n  /* 11. Return the signature in sig */\n  return tpm_sign(key, auth1, FALSE, digest.digest, sizeof(TPM_DIGEST), sig, sigSize);\n}\n"
  },
  {
    "path": "tpm/tpm_maintenance.c",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: tpm_maintenance.c 364 2010-02-11 10:24:45Z mast $\n */\n\n#include \"tpm_emulator.h\"\n#include \"tpm_commands.h\"\n#include \"tpm_marshalling.h\"\n#include \"tpm_data.h\"\n#include \"crypto/sha1.h\"\n\n/*\n * Maintenance Functions ([TPM_Part3], Section 12)\n */\n\nstatic int tpm_setup_privkey(TPM_KEY_DATA *key, TPM_KEY *privkey)\n{\n  size_t key_length;\n  \n  privkey->tag = TPM_TAG_KEY12;\n  privkey->fill = 0;\n  privkey->keyUsage = key->keyUsage;\n  privkey->keyFlags = key->keyFlags;\n  privkey->authDataUsage = key->authDataUsage;\n  if (tpm_setup_key_parms(key, &privkey->algorithmParms) != 0) return -1;\n  memcpy(&privkey->PCRInfo, &key->pcrInfo, sizeof(TPM_PCR_INFO)); \n  privkey->PCRInfoSize = sizeof_TPM_PCR_INFO(privkey->PCRInfo);\n  privkey->encDataSize = 0;\n  privkey->encData = NULL;\n  key_length = key->key.size >> 3;\n  privkey->pubKey.key = tpm_malloc(key_length);\n  if (privkey->pubKey.key == NULL) {\n    free_TPM_KEY((*privkey));\n    return -1;\n  }\n  tpm_rsa_export_modulus(&key->key, privkey->pubKey.key, &key_length);\n  privkey->pubKey.keyLength = key_length;\n  return 0;\n}\n\nTPM_RESULT TPM_CreateMaintenanceArchive(BOOL generateRandom, TPM_AUTH *auth1,\n                                        UINT32 *randomSize, BYTE **random,\n                                        UINT32 *archiveSize, BYTE **archive)\n{\n  TPM_RESULT res;\n  TPM_KEY key;\n  TPM_DIGEST key_digest;\n  BYTE *buf, *ptr;\n  UINT32 len;\n  size_t buf_len, p_len;\n  \n  info(\"TPM_CreateMaintenanceArchive()\");\n  if (!tpmData.permanent.flags.allowMaintenance) return TPM_DISABLED_CMD;\n  res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);\n  if (res != TPM_SUCCESS) return res;\n  if (!tpmData.permanent.data.manuMaintPub.valid) return TPM_KEYNOTFOUND;\n  /* set up a TPM_KEY structure for the SRK */\n  if (tpm_setup_privkey(&tpmData.permanent.data.srk, &key) != 0) {\n    debug(\"tpm_setup_privkey(SRK) failed\");\n    return TPM_FAIL;\n  }\n  if (tpm_compute_key_digest(&key, &key_digest) != 0) {\n    debug(\"tpm_compute_key_digest() failed\");\n    free_TPM_KEY(key);\n    return TPM_FAIL;\n  }\n  /* generate an OAEP encoding of the TPM_MIGRATE_ASYMKEY structure for\n     the SRK: 0x00|seed|0x00-pad|0x01|TPM_MIGRATE_ASYMKEY */\n  debug(\"generating OAEP encoding\");\n  buf_len = tpmData.permanent.data.manuMaintPub.key.size >> 3;\n  buf = tpm_malloc(buf_len);\n  if (buf == NULL) {\n    free_TPM_KEY(key);\n    return TPM_NOSPACE;\n  }\n  buf[0] = 0x00;\n  tpm_rsa_export_prime1(&tpmData.permanent.data.srk.key, &buf[5], &p_len);\n  ptr = &buf[1]; len = 4;\n  tpm_marshal_UINT32(&ptr, &len, p_len);\n  memmove(&buf[buf_len - (1 + 45 + p_len - 16)], &buf[5 + 16], p_len - 16);\n  memset(&buf[5 + 16], 0, buf_len - 1 - 20 - 1 - 45 - p_len + 16);\n  len = 1 + 45 + p_len - 16;\n  ptr = &buf[buf_len - len];\n  tpm_marshal_BYTE(&ptr, &len, 0x01);  \n  tpm_marshal_TPM_PAYLOAD_TYPE(&ptr, &len, TPM_PT_MAINT);\n  tpm_marshal_TPM_NONCE(&ptr, &len, &tpmData.permanent.data.tpmProof);\n  tpm_marshal_TPM_DIGEST(&ptr, &len, &key_digest);\n  tpm_marshal_UINT32(&ptr, &len, p_len - 16); \n  tpm_rsa_mask_generation(&buf[1], SHA1_DIGEST_LENGTH, \n    &buf[1 + SHA1_DIGEST_LENGTH], buf_len - SHA1_DIGEST_LENGTH - 1);\n  tpm_rsa_mask_generation(&buf[1 + SHA1_DIGEST_LENGTH], \n    buf_len - SHA1_DIGEST_LENGTH - 1, &buf[1], SHA1_DIGEST_LENGTH);\n  /* XOR encrypt OAEP encoding */\n  debug(\"generateRandom = %d\", generateRandom);\n  if (generateRandom) {\n    *randomSize = buf_len;\n    *random = tpm_malloc(*randomSize);\n    if (*random == NULL) {\n      free_TPM_KEY(key);\n      tpm_free(buf);\n      return TPM_NOSPACE;\n    }\n    tpm_get_random_bytes(*random, *randomSize);\n    for (len = 0; len < buf_len; len++) buf[len] ^= (*random)[len];\n  } else {\n    *randomSize = 0;\n    *random = NULL;\n    tpm_rsa_mask_generation(tpmData.permanent.data.ownerAuth,\n                            SHA1_DIGEST_LENGTH, buf, buf_len);\n  }\n  /* RSA encrypt OAEP encoding */\n  if (tpm_rsa_encrypt(&tpmData.permanent.data.manuMaintPub.key, RSA_ES_PLAIN,\n                      buf, buf_len, buf, &buf_len) != 0) {\n    debug(\"tpm_rsa_encrypt() failed\");\n    free_TPM_KEY(key);\n    tpm_free(buf);\n    return TPM_FAIL;\n  }\n  key.encData = buf;\n  key.encDataSize = buf_len;\n  /* marshal response */\n  len = *archiveSize = sizeof_TPM_KEY(key);\n  ptr = *archive = tpm_malloc(len);\n  debug(\"archiveSize = %d, archive = %p\", *archiveSize, *archive);\n  if (ptr == NULL || tpm_marshal_TPM_KEY(&ptr, &len, &key)) {\n    tpm_free(ptr);\n    tpm_free(*random);\n    free_TPM_KEY(key);\n    return TPM_NOSPACE;\n  }\n  free_TPM_KEY(key);\n  *archiveSize -= len;\n  tpmData.permanent.flags.maintenanceDone = TRUE;\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_LoadMaintenanceArchive(UINT32 archiveSize, BYTE *archive,\n                                      UINT32 sigSize, BYTE *sig,\n                                      UINT32 randomSize, BYTE *random,\n                                      TPM_AUTH *auth1)\n{\n  TPM_RESULT res;\n  TPM_KEY newsrk;\n  TPM_DIGEST digest;\n  tpm_sha1_ctx_t sha1;\n  BYTE *buf, *ptr;\n  UINT32 len;\n  size_t buf_len;\n    \n  info(\"TPM_LoadMaintenanceArchive()\");\n  /* verify authorization */\n  if (!tpmData.permanent.data.manuMaintPub.valid) return TPM_KEYNOTFOUND;\n  if (!tpmData.permanent.flags.allowMaintenance) return TPM_DISABLED_CMD;\n  res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);\n  if (res != TPM_SUCCESS) return res;\n   /* verify signature */\n  tpm_sha1_init(&sha1);\n  tpm_sha1_update(&sha1, archive, archiveSize);\n  tpm_sha1_final(&sha1, digest.digest);\n  if (sigSize != tpmData.permanent.data.manuMaintPub.key.size >> 3\n      || tpm_rsa_verify(&tpmData.permanent.data.manuMaintPub.key,\n                        RSA_SSA_PKCS1_SHA1, digest.digest,\n                        sizeof(digest.digest), sig) != 0)\n    return TPM_BAD_SIGNATURE;\n  /* unmarshal archive */\n  ptr = archive; len = archiveSize;\n  if (tpm_unmarshal_TPM_KEY(&ptr, &len, &newsrk) != 0 || len != 0)\n    return TPM_BAD_PARAMETER;\n  /* decrypt private key */\n  buf_len = newsrk.encDataSize;\n  buf = tpm_malloc(buf_len);\n  if (buf == NULL) return TPM_NOSPACE;\n  if (tpm_rsa_decrypt(&tpmData.permanent.data.srk.key, RSA_ES_PLAIN,\n                      newsrk.encData, newsrk.encDataSize, buf, &buf_len)\n      || buf[0] != 0x00) {\n    debug(\"tpm_rsa_decrypt() failed\");\n    tpm_free(buf);\n    return TPM_DECRYPT_ERROR;\n  }\n  if (randomSize > 0) {\n    for (len = 0; len < buf_len; len++) buf[len] ^= random[len];\n  } else {\n    tpm_rsa_mask_generation(tpmData.permanent.data.ownerAuth,\n                            SHA1_DIGEST_LENGTH, buf, buf_len);\n  }\n  tpm_rsa_mask_generation(&buf[1 + SHA1_DIGEST_LENGTH],\n    buf_len - SHA1_DIGEST_LENGTH - 1, &buf[1], SHA1_DIGEST_LENGTH);\n  tpm_rsa_mask_generation(&buf[1], SHA1_DIGEST_LENGTH,\n    &buf[1 + SHA1_DIGEST_LENGTH], buf_len - SHA1_DIGEST_LENGTH - 1);\n  /* validate new SRK */\n  if (newsrk.keyFlags & TPM_KEY_FLAG_MIGRATABLE\n      || newsrk.keyUsage != TPM_KEY_STORAGE) return TPM_INVALID_KEYUSAGE;\n  if (newsrk.algorithmParms.algorithmID != TPM_ALG_RSA\n      || newsrk.algorithmParms.encScheme != TPM_ES_RSAESOAEP_SHA1_MGF1\n      || newsrk.algorithmParms.sigScheme != TPM_SS_NONE\n      || newsrk.algorithmParms.parmSize == 0\n      || newsrk.algorithmParms.parms.rsa.keyLength != 2048\n      || newsrk.algorithmParms.parms.rsa.numPrimes != 2\n      || newsrk.algorithmParms.parms.rsa.exponentSize != 0\n      || newsrk.PCRInfoSize != 0) return TPM_BAD_KEY_PROPERTY;\n  /* clear owner but keep ownerAuth */\n  memcpy(digest.digest, tpmData.permanent.data.ownerAuth, sizeof(TPM_SECRET));\n  tpm_owner_clear();\n  memcpy(tpmData.permanent.data.ownerAuth, digest.digest, sizeof(TPM_SECRET));\n  /* update tpmProof */\n  for (ptr = &buf[21]; *ptr == 0x00; ptr++);\n  memcpy(&tpmData.permanent.data.tpmProof, &ptr[2], sizeof(TPM_NONCE));\n  ptr += 1 + 25;\n  memmove(&buf[21], ptr, &buf[buf_len] - ptr); \n  /* update SRK */\n  tpmData.permanent.data.srk.keyFlags = newsrk.keyFlags;\n  tpmData.permanent.data.srk.keyFlags |= TPM_KEY_FLAG_PCR_IGNORE;\n  tpmData.permanent.data.srk.keyFlags &= ~TPM_KEY_FLAG_HAS_PCR;\n  tpmData.permanent.data.srk.keyUsage = newsrk.keyUsage;\n  tpmData.permanent.data.srk.keyControl = TPM_KEY_CONTROL_OWNER_EVICT;\n  tpmData.permanent.data.srk.encScheme = newsrk.algorithmParms.encScheme;\n  tpmData.permanent.data.srk.sigScheme = newsrk.algorithmParms.sigScheme;\n  tpmData.permanent.data.srk.authDataUsage = newsrk.authDataUsage;\n  tpmData.permanent.data.srk.parentPCRStatus = FALSE;\n  if (tpm_rsa_import_key(&tpmData.permanent.data.srk.key, RSA_MSB_FIRST,\n    newsrk.pubKey.key, newsrk.pubKey.keyLength,\n    newsrk.algorithmParms.parms.rsa.exponent,\n    newsrk.algorithmParms.parms.rsa.exponentSize, &buf[5], NULL) != 0) {\n    tpm_free(buf);\n    debug(\"tpm_rsa_import_key() failed\");\n    return TPM_FAIL;\n  }\n  /* enable SRK and mark TPM as owned */\n  tpmData.permanent.data.srk.payload = TPM_PT_ASYM;\n  tpmData.permanent.flags.owned = TRUE;\n  tpmData.permanent.flags.maintenanceDone = TRUE;\n  tpm_free(buf);\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_KillMaintenanceFeature(TPM_AUTH *auth1)\n{\n  TPM_RESULT res;\n\n  info(\"TPM_KillMaintenanceFeature()\");\n  res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);\n  if (res != TPM_SUCCESS) return res;\n  tpmData.permanent.flags.allowMaintenance = FALSE;\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_LoadManuMaintPub(TPM_NONCE *antiReplay, TPM_PUBKEY *pubKey,\n                                TPM_DIGEST *checksum)\n{\n  TPM_PUBKEY_DATA *key = &tpmData.permanent.data.manuMaintPub;\n\n  info(\"TPM_LoadManuMaintPub()\");\n  if (key->valid) return TPM_DISABLED_CMD;\n  if (pubKey->algorithmParms.algorithmID != TPM_ALG_RSA\n      || pubKey->algorithmParms.encScheme != TPM_ES_RSAESOAEP_SHA1_MGF1\n      || pubKey->algorithmParms.sigScheme != TPM_SS_NONE\n      || pubKey->algorithmParms.parms.rsa.keyLength < 2048) \n    return TPM_BAD_KEY_PROPERTY;\n  key->encScheme = pubKey->algorithmParms.encScheme;\n  key->sigScheme = pubKey->algorithmParms.sigScheme;\n  if (tpm_rsa_import_public_key(&key->key, RSA_MSB_FIRST, \n        pubKey->pubKey.key, pubKey->pubKey.keyLength,\n        pubKey->algorithmParms.parms.rsa.exponent,\n        pubKey->algorithmParms.parms.rsa.exponentSize) != 0) return TPM_FAIL;\n  if (tpm_compute_pubkey_checksum(antiReplay, pubKey, checksum) != 0)\n    return TPM_FAIL;\n  tpmData.permanent.data.manuMaintPub.valid = 1;\n  return TPM_SUCCESS;\n}\n\nstatic int tpm_setup_pubkey(TPM_PUBKEY_DATA *key, TPM_PUBKEY *pubkey)\n{\n  size_t key_length;\n \n  key_length = key->key.size >> 3;\n  pubkey->pubKey.key = tpm_malloc(key_length);\n  if (pubkey->pubKey.key == NULL) return -1;\n  tpm_rsa_export_public_modulus(&key->key, pubkey->pubKey.key, &key_length);\n  pubkey->pubKey.keyLength = key_length;\n  key_length = key->key.size >> 3;\n  pubkey->algorithmParms.parms.rsa.exponent = tpm_malloc(key_length);\n  if (pubkey->algorithmParms.parms.rsa.exponent == NULL) {\n    tpm_free(pubkey->pubKey.key);\n    return -1;\n  }\n  tpm_rsa_export_public_exponent(&key->key, \n    pubkey->algorithmParms.parms.rsa.exponent, &key_length);\n  pubkey->algorithmParms.parms.rsa.exponentSize = key_length;\n  pubkey->algorithmParms.algorithmID = TPM_ALG_RSA;\n  pubkey->algorithmParms.encScheme = key->encScheme;\n  pubkey->algorithmParms.sigScheme = key->sigScheme;\n  pubkey->algorithmParms.parms.rsa.keyLength = key->key.size;\n  pubkey->algorithmParms.parms.rsa.numPrimes = 2;\n  pubkey->algorithmParms.parmSize = \n    sizeof_TPM_RSA_KEY_PARMS(pubkey->algorithmParms.parms.rsa);\n  return 0;\n}\n\nTPM_RESULT TPM_ReadManuMaintPub(TPM_NONCE *antiReplay, TPM_DIGEST *checksum)\n{\n  TPM_PUBKEY key;\n  int res;\n  \n  info(\"TPM_ReadManuMaintPub()\");\n  if (!tpmData.permanent.data.manuMaintPub.valid) return TPM_KEYNOTFOUND;\n  if (tpm_setup_pubkey(&tpmData.permanent.data.manuMaintPub, &key) != 0)\n    return TPM_FAIL;\n  res = tpm_compute_pubkey_checksum(antiReplay, &key, checksum);\n  free_TPM_PUBKEY(key);\n  return (res == 0) ? TPM_SUCCESS : TPM_FAIL;\n}\n\n"
  },
  {
    "path": "tpm/tpm_management.c",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: tpm_management.c 364 2010-02-11 10:24:45Z mast $\n */\n\n#include \"tpm_emulator.h\"\n#include \"tpm_commands.h\"\n#include \"tpm_data.h\"\n\n/*\n * Administrative Functions ([TPM_Part3], Section 9)\n */\n\nTPM_RESULT TPM_FieldUpgrade()\n{\n  info(\"TPM_FieldUpgrade()\");\n  /* nothing to do so far */\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_SetRedirection(TPM_KEY_HANDLE keyHandle,\n                              TPM_REDIR_COMMAND redirCmd, UINT32 inputDataSize,\n                              BYTE *inputData, TPM_AUTH *auth1)\n{\n  info(\"TPM_SetRedirection()\");\n  /* this command is not supported by the TPM emulator */ \n  return TPM_DISABLED_CMD;\n}\n\nTPM_RESULT TPM_ResetLockValue(TPM_AUTH *auth1)\n{\n  TPM_RESULT res;\n  \n  info(\"TPM_ResetLockValue\");\n  if (tpmData.stclear.data.disableResetLock) return TPM_AUTHFAIL;\n  res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);\n  if (res != TPM_SUCCESS) {\n    tpmData.stclear.data.disableResetLock = TRUE;\n    return res;\n  }\n  /* reset dictionary attack mitigation mechanism */\n  return TPM_SUCCESS;\n}\n"
  },
  {
    "path": "tpm/tpm_marshalling.c",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *               2005-2008 Heiko Stamer <stamer@gaos.org>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: tpm_marshalling.c 372 2010-02-15 12:52:00Z mast $\n */\n\n#include \"tpm_marshalling.h\"\n#include \"tpm_handles.h\"\n#include \"crypto/rsa.h\"\n\nint tpm_marshal_UINT32_ARRAY(BYTE **ptr, UINT32 *length,\n                             UINT32 *v, UINT32 n)\n{\n  UINT32 i;\n  for (i = 0; i < n; i++) {\n    if (tpm_marshal_UINT32(ptr, length, v[i])) return -1;\n  }\n  return 0;\n}\n\nint tpm_unmarshal_UINT32_ARRAY(BYTE **ptr, UINT32 *length,\n                               UINT32 *v, UINT32 n)\n{\n  UINT32 i;\n  for (i = 0; i < n; i++) {\n    if (tpm_unmarshal_UINT32(ptr, length, &v[i])) return -1;\n  }\n  return 0;\n}\n\nint tpm_marshal_TPM_STRUCT_VER(BYTE **ptr, UINT32 *length, TPM_STRUCT_VER *v)\n{\n  if (tpm_marshal_BYTE(ptr, length, v->major)\n      || tpm_marshal_BYTE(ptr, length, v->minor)\n      || tpm_marshal_BYTE(ptr, length, v->revMajor)\n      || tpm_marshal_BYTE(ptr, length, v->revMinor)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_STRUCT_VER(BYTE **ptr, UINT32 *length, TPM_STRUCT_VER *v)\n{\n  if (tpm_unmarshal_BYTE(ptr, length, &v->major)\n      || tpm_unmarshal_BYTE(ptr, length, &v->minor)\n      || tpm_unmarshal_BYTE(ptr, length, &v->revMajor)\n      || tpm_unmarshal_BYTE(ptr, length, &v->revMinor)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_VERSION(BYTE **ptr, UINT32 *length, TPM_VERSION *v)\n{\n  if (tpm_marshal_BYTE(ptr, length, v->major)\n      || tpm_marshal_BYTE(ptr, length, v->minor)\n      || tpm_marshal_BYTE(ptr, length, v->revMajor)\n      || tpm_marshal_BYTE(ptr, length, v->revMinor)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_VERSION(BYTE **ptr, UINT32 *length, TPM_VERSION *v)\n{\n  if (tpm_unmarshal_BYTE(ptr, length, &v->major)\n      || tpm_unmarshal_BYTE(ptr, length, &v->minor)\n      || tpm_unmarshal_BYTE(ptr, length, &v->revMajor)\n      || tpm_unmarshal_BYTE(ptr, length, &v->revMinor)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_DIGEST(BYTE **ptr, UINT32 *length, TPM_DIGEST *v)\n{\n  if (tpm_marshal_BYTE_ARRAY(ptr, length, v->digest, sizeof(v->digest))) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_DIGEST(BYTE **ptr, UINT32 *length, TPM_DIGEST *v)\n{\n  if (tpm_unmarshal_BYTE_ARRAY(ptr, length, v->digest, sizeof(v->digest))) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_PCRVALUE_ARRAY(BYTE **ptr, UINT32 *length,\n                                   TPM_PCRVALUE *v, UINT32 n)\n{\n  UINT32 i;\n  for (i = 0; i < n; i++) {\n    if (tpm_marshal_TPM_PCRVALUE(ptr, length, &v[i])) return -1;\n  }\n  return 0;\n}\n\nint tpm_unmarshal_TPM_PCRVALUE_ARRAY(BYTE **ptr, UINT32 *length,\n                                     TPM_PCRVALUE *v, UINT32 n)\n{\n  UINT32 i;\n  for (i = 0; i < n; i++) {\n    if (tpm_unmarshal_TPM_PCRVALUE(ptr, length, &v[i])) return -1;\n  }\n  return 0;\n}\n\nint tpm_marshal_TPM_NONCE(BYTE **ptr, UINT32 *length, TPM_NONCE *v)\n{\n  if (tpm_marshal_BYTE_ARRAY(ptr, length, v->nonce, sizeof(v->nonce))) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_NONCE(BYTE **ptr, UINT32 *length, TPM_NONCE *v)\n{\n  if (tpm_unmarshal_BYTE_ARRAY(ptr, length, v->nonce, sizeof(v->nonce))) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_AUTHDATA(BYTE **ptr, UINT32 *length, TPM_AUTHDATA *v)\n{\n  if (*length < sizeof(TPM_AUTHDATA)) return -1;\n  memcpy(*ptr, v, sizeof(TPM_AUTHDATA));\n  *ptr += sizeof(TPM_AUTHDATA); *length -= sizeof(TPM_AUTHDATA);\n  return 0;\n}\n\nint tpm_unmarshal_TPM_AUTHDATA(BYTE **ptr, UINT32 *length, TPM_AUTHDATA *v)\n{\n  if (*length < sizeof(TPM_AUTHDATA)) return -1;\n  memcpy(v, *ptr, sizeof(TPM_AUTHDATA));\n  *ptr += sizeof(TPM_AUTHDATA); *length -= sizeof(TPM_AUTHDATA);\n  return 0;\n}\n\nint tpm_marshal_TPM_AUTH(BYTE **ptr, UINT32 *length, TPM_AUTH *v)\n{\n  if (tpm_marshal_TPM_NONCE(ptr, length, &v->nonceEven)\n      || tpm_marshal_BOOL(ptr, length, v->continueAuthSession)\n      || tpm_marshal_TPM_AUTHDATA(ptr, length, &v->auth)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_AUTH(BYTE **ptr, UINT32 *length, TPM_AUTH *v)\n{\n  if (tpm_unmarshal_TPM_AUTHHANDLE(ptr, length, &v->authHandle)\n      || tpm_unmarshal_TPM_NONCE(ptr, length, &v->nonceOdd)\n      || tpm_unmarshal_BOOL(ptr, length, &v->continueAuthSession)\n      || tpm_unmarshal_TPM_AUTHDATA(ptr, length, &v->auth)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_KEY_HANDLE_LIST(BYTE **ptr, UINT32 *length, TPM_KEY_HANDLE_LIST *v)\n{\n  if (tpm_marshal_UINT16(ptr, length, v->loaded)\n      || tpm_marshal_UINT32_ARRAY(ptr, length, v->handle, v->loaded)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_CHANGEAUTH_VALIDATE(BYTE **ptr, UINT32 *length, TPM_CHANGEAUTH_VALIDATE *v)\n{\n  if (tpm_marshal_TPM_SECRET(ptr, length, &v->newAuthSecret)\n      || tpm_marshal_TPM_NONCE(ptr, length, &v->n1)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_CHANGEAUTH_VALIDATE(BYTE **ptr, UINT32 *length, TPM_CHANGEAUTH_VALIDATE *v)\n{\n  if (tpm_unmarshal_TPM_SECRET(ptr, length, &v->newAuthSecret)\n      || tpm_unmarshal_TPM_NONCE(ptr, length, &v->n1)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_COUNTER_VALUE(BYTE **ptr, UINT32 *length, TPM_COUNTER_VALUE *v)\n{\n  if (tpm_marshal_TPM_STRUCTURE_TAG(ptr, length, v->tag)\n      || tpm_marshal_BYTE_ARRAY(ptr, length, v->label, sizeof(v->label))\n      || tpm_marshal_TPM_ACTUAL_COUNT(ptr, length, v->counter)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_COUNTER_VALUE(BYTE **ptr, UINT32 *length, TPM_COUNTER_VALUE *v)\n{\n  if (tpm_unmarshal_TPM_STRUCTURE_TAG(ptr, length, &v->tag)\n      || tpm_unmarshal_BYTE_ARRAY(ptr, length, v->label, sizeof(v->label))\n      || tpm_unmarshal_TPM_ACTUAL_COUNT(ptr, length, &v->counter)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_PCR_SELECTION(BYTE **ptr, UINT32 *length, TPM_PCR_SELECTION *v)\n{\n  if (tpm_marshal_UINT16(ptr, length, v->sizeOfSelect)\n      || v->sizeOfSelect > sizeof(v->pcrSelect) \n      || tpm_marshal_BYTE_ARRAY(ptr, length, v->pcrSelect, v->sizeOfSelect)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_PCR_SELECTION(BYTE **ptr, UINT32 *length, TPM_PCR_SELECTION *v)\n{\n  if (tpm_unmarshal_UINT16(ptr, length, &v->sizeOfSelect)\n      || v->sizeOfSelect > sizeof(v->pcrSelect)\n      || tpm_unmarshal_BYTE_ARRAY(ptr, length, v->pcrSelect, v->sizeOfSelect)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_PCR_COMPOSITE(BYTE **ptr, UINT32 *length, TPM_PCR_COMPOSITE *v)\n{\n  if (tpm_marshal_TPM_PCR_SELECTION(ptr, length, &v->select)\n      || tpm_marshal_UINT32(ptr, length, v->valueSize)\n      || v->valueSize > sizeof(v->pcrValue) \n      || tpm_marshal_TPM_PCRVALUE_ARRAY(ptr, length, v->pcrValue, \n                                        v->valueSize / sizeof(TPM_PCRVALUE))) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_PCR_COMPOSITE(BYTE **ptr, UINT32 *length, TPM_PCR_COMPOSITE *v)\n{\n  if (tpm_unmarshal_TPM_PCR_SELECTION(ptr, length, &v->select)\n      || tpm_unmarshal_UINT32(ptr, length, &v->valueSize)\n      || v->valueSize > sizeof(v->pcrValue)\n      || tpm_unmarshal_TPM_PCRVALUE_ARRAY(ptr, length, v->pcrValue, \n                                          v->valueSize / sizeof(TPM_PCRVALUE))) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_PCR_INFO(BYTE **ptr, UINT32 *length, TPM_PCR_INFO *v)\n{\n  if (v->tag == TPM_TAG_PCR_INFO_LONG) {\n    if (tpm_marshal_TPM_STRUCTURE_TAG(ptr, length, v->tag)\n        || tpm_marshal_TPM_LOCALITY_SELECTION(ptr, length, v->localityAtCreation)\n        || tpm_marshal_TPM_LOCALITY_SELECTION(ptr, length, v->localityAtRelease)\n        || tpm_marshal_TPM_PCR_SELECTION(ptr, length, &v->creationPCRSelection)\n        || tpm_marshal_TPM_PCR_SELECTION(ptr, length, &v->releasePCRSelection)\n        || tpm_marshal_TPM_COMPOSITE_HASH(ptr, length, &v->digestAtCreation)\n        || tpm_marshal_TPM_COMPOSITE_HASH(ptr, length, &v->digestAtRelease)) return -1;\n  } else {\n    if (tpm_marshal_TPM_PCR_SELECTION(ptr, length, &v->creationPCRSelection)\n      || tpm_marshal_TPM_COMPOSITE_HASH(ptr, length, &v->digestAtRelease)\n      || tpm_marshal_TPM_COMPOSITE_HASH(ptr, length, &v->digestAtCreation)) return -1;\n  }\n  return 0;\n}\n\nint tpm_unmarshal_TPM_PCR_INFO(BYTE **ptr, UINT32 *length, TPM_PCR_INFO *v)\n{\n  if ((((UINT16)(*ptr)[0] << 8) | (*ptr)[1]) == TPM_TAG_PCR_INFO_LONG) {\n    if (tpm_unmarshal_TPM_STRUCTURE_TAG(ptr, length, &v->tag)\n        || tpm_unmarshal_TPM_LOCALITY_SELECTION(ptr, length, &v->localityAtCreation)\n        || tpm_unmarshal_TPM_LOCALITY_SELECTION(ptr, length, &v->localityAtRelease)\n        || tpm_unmarshal_TPM_PCR_SELECTION(ptr, length, &v->creationPCRSelection)\n        || tpm_unmarshal_TPM_PCR_SELECTION(ptr, length, &v->releasePCRSelection)\n        || tpm_unmarshal_TPM_COMPOSITE_HASH(ptr, length, &v->digestAtCreation)\n        || tpm_unmarshal_TPM_COMPOSITE_HASH(ptr, length, &v->digestAtRelease)) return -1;\n  } else {\n    if (tpm_unmarshal_TPM_PCR_SELECTION(ptr, length, &v->creationPCRSelection)\n      || tpm_unmarshal_TPM_COMPOSITE_HASH(ptr, length, &v->digestAtRelease)\n      || tpm_unmarshal_TPM_COMPOSITE_HASH(ptr, length, &v->digestAtCreation)) return -1;\n    memcpy(&v->releasePCRSelection, &v->creationPCRSelection, sizeof(TPM_PCR_SELECTION));\n    v->tag = 0x0000;\n    v->localityAtCreation = 0;\n    v->localityAtRelease = 0;\n  }\n  return 0;\n}\n\nint tpm_marshal_TPM_PCR_INFO_SHORT(BYTE **ptr, UINT32 *length, TPM_PCR_INFO_SHORT *v)\n{\n  if (tpm_marshal_TPM_PCR_SELECTION(ptr, length, &v->pcrSelection)\n      || tpm_marshal_TPM_LOCALITY_SELECTION(ptr, length, v->localityAtRelease)\n      || tpm_marshal_TPM_COMPOSITE_HASH(ptr, length, &v->digestAtRelease)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_PCR_INFO_SHORT(BYTE **ptr, UINT32 *length, TPM_PCR_INFO_SHORT *v)\n{\n  if (tpm_unmarshal_TPM_PCR_SELECTION(ptr, length, &v->pcrSelection)\n      || tpm_unmarshal_TPM_LOCALITY_SELECTION(ptr, length, &v->localityAtRelease)\n      || tpm_unmarshal_TPM_COMPOSITE_HASH(ptr, length, &v->digestAtRelease)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_PCR_ATTRIBUTES(BYTE **ptr, UINT32 *length, TPM_PCR_ATTRIBUTES *v)\n{\n  if (tpm_marshal_BOOL(ptr, length, v->pcrReset)\n      || tpm_marshal_TPM_LOCALITY_SELECTION(ptr, length, v->pcrResetLocal)\n      || tpm_marshal_TPM_LOCALITY_SELECTION(ptr, length, v->pcrExtendLocal)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_PCR_ATTRIBUTES(BYTE **ptr, UINT32 *length, TPM_PCR_ATTRIBUTES *v)\n{\n  if (tpm_unmarshal_BOOL(ptr, length, &v->pcrReset)\n      || tpm_unmarshal_TPM_LOCALITY_SELECTION(ptr, length, &v->pcrResetLocal)\n      || tpm_unmarshal_TPM_LOCALITY_SELECTION(ptr, length, &v->pcrExtendLocal)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_STORED_DATA(BYTE **ptr, UINT32 *length, TPM_STORED_DATA *v)\n{\n  if (tpm_marshal_TPM_STRUCTURE_TAG(ptr, length, v->tag)\n      || tpm_marshal_TPM_ENTITY_TYPE(ptr, length, v->et)\n      || tpm_marshal_UINT32(ptr, length, v->sealInfoSize)\n      || (v->sealInfoSize > 0\n          && tpm_marshal_TPM_PCR_INFO(ptr, length, &v->sealInfo))\n      || tpm_marshal_UINT32(ptr, length, v->encDataSize)\n      || tpm_marshal_BLOB(ptr, length, v->encData, v->encDataSize)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_STORED_DATA(BYTE **ptr, UINT32 *length, TPM_STORED_DATA *v)\n{\n  if (tpm_unmarshal_TPM_STRUCTURE_TAG(ptr, length, &v->tag)\n      || tpm_unmarshal_TPM_ENTITY_TYPE(ptr, length, &v->et)\n      || tpm_unmarshal_UINT32(ptr, length, &v->sealInfoSize)\n      || (v->sealInfoSize > 0\n          && tpm_unmarshal_TPM_PCR_INFO(ptr, length, &v->sealInfo))\n      || tpm_unmarshal_UINT32(ptr, length, &v->encDataSize)\n      || tpm_unmarshal_BLOB(ptr, length, &v->encData, v->encDataSize)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_SEALED_DATA(BYTE **ptr, UINT32 *length, TPM_SEALED_DATA *v)\n{\n  if (tpm_marshal_TPM_PAYLOAD_TYPE(ptr, length, v->payload)\n      || tpm_marshal_TPM_SECRET(ptr, length, &v->authData)\n      || tpm_marshal_TPM_NONCE(ptr, length, &v->tpmProof)\n      || tpm_marshal_TPM_DIGEST(ptr, length, &v->storedDigest)\n      || tpm_marshal_UINT32(ptr, length, v->dataSize)\n      || tpm_marshal_BLOB(ptr, length, v->data, v->dataSize)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_SEALED_DATA(BYTE **ptr, UINT32 *length, TPM_SEALED_DATA *v)\n{\n  if (tpm_unmarshal_TPM_PAYLOAD_TYPE(ptr, length, &v->payload)\n      || tpm_unmarshal_TPM_SECRET(ptr, length, &v->authData)\n      || tpm_unmarshal_TPM_NONCE(ptr, length, &v->tpmProof)\n      || tpm_unmarshal_TPM_DIGEST(ptr, length, &v->storedDigest)\n      || tpm_unmarshal_UINT32(ptr, length, &v->dataSize)\n      || tpm_unmarshal_BLOB(ptr, length, &v->data, v->dataSize)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_SYMMETRIC_KEY(BYTE **ptr, UINT32 *length, TPM_SYMMETRIC_KEY *v)\n{\n  if (tpm_marshal_TPM_ALGORITHM_ID(ptr, length, v->algId)\n      || tpm_marshal_TPM_ENC_SCHEME(ptr, length, v->encScheme)\n      || tpm_marshal_UINT16(ptr, length, v->size)\n      || tpm_marshal_BLOB(ptr, length, v->data, v->size)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_SYMMETRIC_KEY(BYTE **ptr, UINT32 *length, TPM_SYMMETRIC_KEY *v)\n{\n  if (tpm_unmarshal_TPM_ALGORITHM_ID(ptr, length, &v->algId)\n      || tpm_unmarshal_TPM_ENC_SCHEME(ptr, length, &v->encScheme)\n      || tpm_unmarshal_UINT16(ptr, length, &v->size)\n      || tpm_unmarshal_BLOB(ptr, length, &v->data, v->size)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_SYMMETRIC_KEY_PARMS(BYTE **ptr, UINT32 *length, TPM_SYMMETRIC_KEY_PARMS *v)\n{\n  if (tpm_marshal_UINT32(ptr, length, v->keyLength)\n      || tpm_marshal_UINT32(ptr, length, v->blockSize)\n      || tpm_marshal_UINT32(ptr, length, v->ivSize)\n      || tpm_marshal_BLOB(ptr, length, v->IV, v->ivSize)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_SYMMETRIC_KEY_PARMS(BYTE **ptr, UINT32 *length, TPM_SYMMETRIC_KEY_PARMS *v)\n{\n  if (tpm_unmarshal_UINT32(ptr, length, &v->keyLength)\n      || tpm_unmarshal_UINT32(ptr, length, &v->blockSize)\n      || tpm_unmarshal_UINT32(ptr, length, &v->ivSize)\n      || tpm_unmarshal_BLOB(ptr, length, &v->IV, v->ivSize)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_RSA_KEY_PARMS(BYTE **ptr, UINT32 *length, TPM_RSA_KEY_PARMS *v)\n{\n  if (tpm_marshal_UINT32(ptr, length, v->keyLength)\n      || tpm_marshal_UINT32(ptr, length, v->numPrimes)\n      || tpm_marshal_UINT32(ptr, length, v->exponentSize)\n      || tpm_marshal_BLOB(ptr, length, v->exponent, v->exponentSize)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_RSA_KEY_PARMS(BYTE **ptr, UINT32 *length, TPM_RSA_KEY_PARMS *v)\n{\n  if (tpm_unmarshal_UINT32(ptr, length, &v->keyLength)\n      || tpm_unmarshal_UINT32(ptr, length, &v->numPrimes)\n      || tpm_unmarshal_UINT32(ptr, length, &v->exponentSize)\n      || tpm_unmarshal_BLOB(ptr, length, &v->exponent, v->exponentSize)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_KEY_PARMS(BYTE **ptr, UINT32 *length, TPM_KEY_PARMS *v)\n{\n  if (tpm_marshal_TPM_ALGORITHM_ID(ptr, length, v->algorithmID)\n      || tpm_marshal_TPM_ENC_SCHEME(ptr, length, v->encScheme)\n      || tpm_marshal_TPM_SIG_SCHEME(ptr, length, v->sigScheme)\n      || tpm_marshal_UINT32(ptr, length, v->parmSize)) return -1;\n  switch (v->algorithmID) {\n    case TPM_ALG_RSA:\n      if (tpm_marshal_TPM_RSA_KEY_PARMS(ptr, length, &v->parms.rsa)) return -1;\n      break;\n    case TPM_ALG_DES: case TPM_ALG_3DES: case TPM_ALG_AES192: case TPM_ALG_AES256:\n      if (tpm_marshal_TPM_SYMMETRIC_KEY_PARMS(ptr, length, &v->parms.skp)) return -1;\n      break;\n    default:\n      if (tpm_marshal_BLOB(ptr, length, v->parms.raw, v->parmSize)) return -1;\n  }\n  return 0;\n}\n\nint tpm_unmarshal_TPM_KEY_PARMS(BYTE **ptr, UINT32 *length, TPM_KEY_PARMS *v)\n{\n  if (tpm_unmarshal_TPM_ALGORITHM_ID(ptr, length, &v->algorithmID)\n      || tpm_unmarshal_TPM_ENC_SCHEME(ptr, length, &v->encScheme)\n      || tpm_unmarshal_TPM_SIG_SCHEME(ptr, length, &v->sigScheme)\n      || tpm_unmarshal_UINT32(ptr, length, &v->parmSize)) return -1;\n  switch (v->algorithmID) {\n    case TPM_ALG_RSA:\n      if (tpm_unmarshal_TPM_RSA_KEY_PARMS(ptr, length, &v->parms.rsa)) return -1;\n      break;\n    case TPM_ALG_DES: case TPM_ALG_3DES: case TPM_ALG_AES192: case TPM_ALG_AES256:\n      if (tpm_unmarshal_TPM_SYMMETRIC_KEY_PARMS(ptr, length, &v->parms.skp)) return -1;\n      break;\n    default:\n      if (tpm_unmarshal_BLOB(ptr, length, &v->parms.raw, v->parmSize)) return -1;\n  }\n  return 0;\n}\n\nint tpm_marshal_TPM_STORE_PUBKEY(BYTE **ptr, UINT32 *length, TPM_STORE_PUBKEY *v)\n{\n  if (tpm_marshal_UINT32(ptr, length, v->keyLength)\n      || tpm_marshal_BLOB(ptr, length, v->key, v->keyLength)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_STORE_PUBKEY(BYTE **ptr, UINT32 *length, TPM_STORE_PUBKEY *v)\n{\n  if (tpm_unmarshal_UINT32(ptr, length, &v->keyLength)\n      || tpm_unmarshal_BLOB(ptr, length, &v->key, v->keyLength)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_KEY(BYTE **ptr, UINT32 *length, TPM_KEY *v)\n{\n  if (tpm_marshal_TPM_STRUCTURE_TAG(ptr, length, v->tag)\n      || tpm_marshal_UINT16(ptr, length, v->fill)\n      || tpm_marshal_TPM_KEY_USAGE(ptr, length, v->keyUsage)\n      || tpm_marshal_TPM_KEY_FLAGS(ptr, length, v->keyFlags)\n      || tpm_marshal_TPM_AUTH_DATA_USAGE(ptr, length, v->authDataUsage)\n      || tpm_marshal_TPM_KEY_PARMS(ptr, length, &v->algorithmParms)\n      || tpm_marshal_UINT32(ptr, length, v->PCRInfoSize)\n      || (v->PCRInfoSize > 0\n          && tpm_marshal_TPM_PCR_INFO(ptr, length, &v->PCRInfo))\n      || tpm_marshal_TPM_STORE_PUBKEY(ptr, length, &v->pubKey)\n      || tpm_marshal_UINT32(ptr, length, v->encDataSize)\n      || tpm_marshal_BLOB(ptr, length, v->encData, v->encDataSize)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_KEY(BYTE **ptr, UINT32 *length, TPM_KEY *v)\n{\n  if (tpm_unmarshal_TPM_STRUCTURE_TAG(ptr, length, &v->tag)\n      || tpm_unmarshal_UINT16(ptr, length, &v->fill)\n      || tpm_unmarshal_TPM_KEY_USAGE(ptr, length, &v->keyUsage)\n      || tpm_unmarshal_TPM_KEY_FLAGS(ptr, length, &v->keyFlags)\n      || tpm_unmarshal_TPM_AUTH_DATA_USAGE(ptr, length, &v->authDataUsage)\n      || tpm_unmarshal_TPM_KEY_PARMS(ptr, length, &v->algorithmParms)\n      || tpm_unmarshal_UINT32(ptr, length, &v->PCRInfoSize)\n      || (v->PCRInfoSize > 0\n          && tpm_unmarshal_TPM_PCR_INFO(ptr, length, &v->PCRInfo))\n      || tpm_unmarshal_TPM_STORE_PUBKEY(ptr, length, &v->pubKey)\n      || tpm_unmarshal_UINT32(ptr, length, &v->encDataSize)\n      || tpm_unmarshal_BLOB(ptr, length, &v->encData, v->encDataSize)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_PUBKEY(BYTE **ptr, UINT32 *length, TPM_PUBKEY *v)\n{\n  if (tpm_marshal_TPM_KEY_PARMS(ptr, length, &v->algorithmParms)\n      || tpm_marshal_TPM_STORE_PUBKEY(ptr, length, &v->pubKey)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_PUBKEY(BYTE **ptr, UINT32 *length, TPM_PUBKEY *v)\n{\n  if (tpm_unmarshal_TPM_KEY_PARMS(ptr, length, &v->algorithmParms)\n      || tpm_unmarshal_TPM_STORE_PUBKEY(ptr, length, &v->pubKey)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_STORE_PRIVKEY(BYTE **ptr, UINT32 *length, TPM_STORE_PRIVKEY *v)\n{\n  if (tpm_marshal_UINT32(ptr, length, v->keyLength)\n      || tpm_marshal_BLOB(ptr, length, v->key, v->keyLength)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_STORE_PRIVKEY(BYTE **ptr, UINT32 *length, TPM_STORE_PRIVKEY *v)\n{\n  if (tpm_unmarshal_UINT32(ptr, length, &v->keyLength)\n      || tpm_unmarshal_BLOB(ptr, length, &v->key, v->keyLength)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_STORE_ASYMKEY(BYTE **ptr, UINT32 *length, TPM_STORE_ASYMKEY *v)\n{\n  if (tpm_marshal_TPM_PAYLOAD_TYPE(ptr, length, v->payload)\n      || tpm_marshal_TPM_SECRET(ptr, length, &v->usageAuth)\n      || tpm_marshal_TPM_SECRET(ptr, length, &v->migrationAuth)\n      || tpm_marshal_TPM_DIGEST(ptr, length, &v->pubDataDigest)\n      || tpm_marshal_TPM_STORE_PRIVKEY(ptr, length, &v->privKey)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_STORE_ASYMKEY(BYTE **ptr, UINT32 *length, TPM_STORE_ASYMKEY *v)\n{\n  if (tpm_unmarshal_TPM_PAYLOAD_TYPE(ptr, length, &v->payload)\n      || tpm_unmarshal_TPM_SECRET(ptr, length, &v->usageAuth)\n      || tpm_unmarshal_TPM_SECRET(ptr, length, &v->migrationAuth)\n      || tpm_unmarshal_TPM_DIGEST(ptr, length, &v->pubDataDigest)\n      || tpm_unmarshal_TPM_STORE_PRIVKEY(ptr, length, &v->privKey)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_MIGRATIONKEYAUTH(BYTE **ptr, UINT32 *length, TPM_MIGRATIONKEYAUTH *v)\n{\n  if (tpm_marshal_TPM_PUBKEY(ptr, length, &v->migrationKey)\n      || tpm_marshal_TPM_MIGRATE_SCHEME(ptr, length, v->migrationScheme)\n      || tpm_marshal_TPM_DIGEST(ptr, length, &v->digest)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_MIGRATIONKEYAUTH(BYTE **ptr, UINT32 *length, TPM_MIGRATIONKEYAUTH *v)\n{\n  if (tpm_unmarshal_TPM_PUBKEY(ptr, length, &v->migrationKey)\n      || tpm_unmarshal_TPM_MIGRATE_SCHEME(ptr, length, &v->migrationScheme)\n      || tpm_unmarshal_TPM_DIGEST(ptr, length, &v->digest)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_CERTIFY_INFO(BYTE **ptr, UINT32 *length, TPM_CERTIFY_INFO *v)\n{\n  if (tpm_marshal_TPM_STRUCTURE_TAG(ptr, length, v->tag)\n      || tpm_marshal_BYTE(ptr, length, v->fill)\n      || tpm_marshal_TPM_PAYLOAD_TYPE(ptr, length, v->payloadType)\n      || tpm_marshal_TPM_KEY_USAGE(ptr, length, v->keyUsage)\n      || tpm_marshal_TPM_KEY_FLAGS(ptr, length, v->keyFlags)\n      || tpm_marshal_TPM_AUTH_DATA_USAGE(ptr, length, v->authDataUsage)\n      || tpm_marshal_TPM_KEY_PARMS(ptr, length, &v->algorithmParms)\n      || tpm_marshal_TPM_DIGEST(ptr, length, &v->pubkeyDigest)\n      || tpm_marshal_TPM_NONCE(ptr, length, &v->data)\n      || tpm_marshal_BOOL(ptr, length, v->parentPCRStatus)\n      || tpm_marshal_UINT32(ptr, length, v->PCRInfoSize)\n      || (v->PCRInfoSize > 0\n          && tpm_marshal_TPM_PCR_INFO(ptr, length, &v->PCRInfo))\n      || (v->tag == TPM_TAG_CERTIFY_INFO2\n          && tpm_marshal_UINT32(ptr, length, v->migrationAuthoritySize))\n      || (v->tag == TPM_TAG_CERTIFY_INFO2 && v->migrationAuthoritySize > 0\n          && tpm_marshal_BLOB(ptr, length, v->migrationAuthority,\n                              v->migrationAuthoritySize))) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_CERTIFY_INFO(BYTE **ptr, UINT32 *length, TPM_CERTIFY_INFO *v)\n{\n  if (tpm_unmarshal_TPM_STRUCTURE_TAG(ptr, length, &v->tag)\n      || tpm_unmarshal_BYTE(ptr, length, &v->fill)\n      || tpm_unmarshal_TPM_PAYLOAD_TYPE(ptr, length, &v->payloadType)\n      || tpm_unmarshal_TPM_KEY_USAGE(ptr, length, &v->keyUsage)\n      || tpm_unmarshal_TPM_KEY_FLAGS(ptr, length, &v->keyFlags)\n      || tpm_unmarshal_TPM_AUTH_DATA_USAGE(ptr, length, &v->authDataUsage)\n      || tpm_unmarshal_TPM_KEY_PARMS(ptr, length, &v->algorithmParms)\n      || tpm_unmarshal_TPM_DIGEST(ptr, length, &v->pubkeyDigest)\n      || tpm_unmarshal_TPM_NONCE(ptr, length, &v->data)\n      || tpm_unmarshal_BOOL(ptr, length, &v->parentPCRStatus)\n      || tpm_unmarshal_UINT32(ptr, length, &v->PCRInfoSize)\n      || (v->PCRInfoSize > 0\n          && tpm_unmarshal_TPM_PCR_INFO(ptr, length, &v->PCRInfo))\n      || (v->tag == TPM_TAG_CERTIFY_INFO2\n          && tpm_unmarshal_UINT32(ptr, length, &v->migrationAuthoritySize))\n      || (v->tag == TPM_TAG_CERTIFY_INFO2 && v->migrationAuthoritySize > 0\n          && tpm_unmarshal_BLOB(ptr, length, &v->migrationAuthority,\n                                v->migrationAuthoritySize))) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_IDENTITY_CONTENTS(BYTE **ptr, UINT32 *length, TPM_IDENTITY_CONTENTS *v)\n{\n  if (tpm_marshal_TPM_STRUCT_VER(ptr, length, &v->ver)\n      || tpm_marshal_UINT32(ptr, length, v->ordinal)\n      || tpm_marshal_TPM_CHOSENID_HASH(ptr, length, &v->labelPrivCADigest)\n      || tpm_marshal_TPM_PUBKEY(ptr, length, &v->identityPubKey)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_IDENTITY_CONTENTS(BYTE **ptr, UINT32 *length, TPM_IDENTITY_CONTENTS *v)\n{\n  if (tpm_unmarshal_TPM_STRUCT_VER(ptr, length, &v->ver)\n      || tpm_unmarshal_UINT32(ptr, length, &v->ordinal)\n      || tpm_unmarshal_TPM_CHOSENID_HASH(ptr, length, &v->labelPrivCADigest)\n      || tpm_unmarshal_TPM_PUBKEY(ptr, length, &v->identityPubKey)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_CURRENT_TICKS(BYTE **ptr, UINT32 *length, TPM_CURRENT_TICKS *v)\n{\n  if (tpm_marshal_TPM_STRUCTURE_TAG(ptr, length, v->tag)\n      || tpm_marshal_UINT64(ptr, length, v->currentTicks)\n      || tpm_marshal_UINT16(ptr, length, v->tickRate)\n      || tpm_marshal_TPM_NONCE(ptr, length, &v->tickNonce)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_CURRENT_TICKS(BYTE **ptr, UINT32 *length, TPM_CURRENT_TICKS *v)\n{\n  if (tpm_unmarshal_TPM_STRUCTURE_TAG(ptr, length, &v->tag)\n      || tpm_unmarshal_UINT64(ptr, length, &v->currentTicks)\n      || tpm_unmarshal_UINT16(ptr, length, &v->tickRate)\n      || tpm_unmarshal_TPM_NONCE(ptr, length, &v->tickNonce)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_TRANSPORT_PUBLIC(BYTE **ptr, UINT32 *length, TPM_TRANSPORT_PUBLIC *v)\n{\n  if (tpm_marshal_TPM_STRUCTURE_TAG(ptr, length, v->tag)\n      || tpm_marshal_TPM_TRANSPORT_ATTRIBUTES(ptr, length, v->transAttributes)\n      || tpm_marshal_TPM_ALGORITHM_ID(ptr, length, v->algID)\n      || tpm_marshal_TPM_ENC_SCHEME(ptr, length, v->encScheme)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_TRANSPORT_PUBLIC(BYTE **ptr, UINT32 *length, TPM_TRANSPORT_PUBLIC *v)\n{\n  if (tpm_unmarshal_TPM_STRUCTURE_TAG(ptr, length, &v->tag)\n      || tpm_unmarshal_TPM_TRANSPORT_ATTRIBUTES(ptr, length, &v->transAttributes)\n      || tpm_unmarshal_TPM_ALGORITHM_ID(ptr, length, &v->algID)\n      || tpm_unmarshal_TPM_ENC_SCHEME(ptr, length, &v->encScheme)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_TRANSPORT_INTERNAL(BYTE **ptr, UINT32 *length, TPM_TRANSPORT_INTERNAL *v)\n{\n  if (tpm_marshal_TPM_STRUCTURE_TAG(ptr, length, v->tag)\n      || tpm_marshal_TPM_AUTHDATA(ptr, length, &v->authData)\n      || tpm_marshal_TPM_TRANSPORT_PUBLIC(ptr, length, &v->transPublic)\n      || tpm_marshal_TPM_TRANSHANDLE(ptr, length, v->transHandle)\n      || tpm_marshal_TPM_NONCE(ptr, length, &v->transNonceEven)\n      || tpm_marshal_TPM_DIGEST(ptr, length, &v->transDigest)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_TRANSPORT_INTERNAL(BYTE **ptr, UINT32 *length, TPM_TRANSPORT_INTERNAL *v)\n{\n  if (tpm_unmarshal_TPM_STRUCTURE_TAG(ptr, length, &v->tag)\n      || tpm_unmarshal_TPM_AUTHDATA(ptr, length, &v->authData)\n      || tpm_unmarshal_TPM_TRANSPORT_PUBLIC(ptr, length, &v->transPublic)\n      || tpm_unmarshal_TPM_TRANSHANDLE(ptr, length, &v->transHandle)\n      || tpm_unmarshal_TPM_NONCE(ptr, length, &v->transNonceEven)\n      || tpm_unmarshal_TPM_DIGEST(ptr, length, &v->transDigest)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_CONTEXT_BLOB(BYTE **ptr, UINT32 *length, TPM_CONTEXT_BLOB *v)\n{\n  if (tpm_marshal_TPM_STRUCTURE_TAG(ptr, length, v->tag)\n      || tpm_marshal_TPM_RESOURCE_TYPE(ptr, length, v->resourceType)\n      || tpm_marshal_TPM_HANDLE(ptr, length, v->handle)\n      || tpm_marshal_BYTE_ARRAY(ptr, length, v->label, sizeof(v->label))\n      || tpm_marshal_UINT32(ptr, length, v->contextCount)\n      || tpm_marshal_TPM_DIGEST(ptr, length, &v->integrityDigest)\n      || tpm_marshal_UINT32(ptr, length, v->additionalSize)\n      || tpm_marshal_BLOB(ptr, length, v->additionalData, v->additionalSize)\n      || tpm_marshal_UINT32(ptr, length, v->sensitiveSize)\n      || tpm_marshal_BLOB(ptr, length, v->sensitiveData, v->sensitiveSize)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_CONTEXT_BLOB(BYTE **ptr, UINT32 *length, TPM_CONTEXT_BLOB *v)\n{\n  if (tpm_unmarshal_TPM_STRUCTURE_TAG(ptr, length, &v->tag)\n      || tpm_unmarshal_TPM_RESOURCE_TYPE(ptr, length, &v->resourceType)\n      || tpm_unmarshal_TPM_HANDLE(ptr, length, &v->handle)\n      || tpm_unmarshal_BYTE_ARRAY(ptr, length, v->label, sizeof(v->label))\n      || tpm_unmarshal_UINT32(ptr, length, &v->contextCount)\n      || tpm_unmarshal_TPM_DIGEST(ptr, length, &v->integrityDigest)\n      || tpm_unmarshal_UINT32(ptr, length, &v->additionalSize)\n      || tpm_unmarshal_BLOB(ptr, length, &v->additionalData, v->additionalSize)\n      || tpm_unmarshal_UINT32(ptr, length, &v->sensitiveSize)\n      || tpm_unmarshal_BLOB(ptr, length, &v->sensitiveData, v->sensitiveSize)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_CONTEXT_SENSITIVE(BYTE **ptr, UINT32 *length, TPM_CONTEXT_SENSITIVE *v)\n{\n  if (tpm_marshal_TPM_STRUCTURE_TAG(ptr, length, v->tag)\n      || tpm_marshal_TPM_NONCE(ptr, length, &v->contextNonce)\n      || tpm_marshal_UINT32(ptr, length, v->internalSize)\n      || tpm_marshal_TPM_RESOURCE_TYPE(ptr, length, v->resourceType))\n        return -1;\n  switch (v->resourceType) {\n    case TPM_RT_KEY:\n      if (tpm_marshal_TPM_KEY_DATA(ptr, length, &v->internalData.key))\n        return -1;\n      break;\n    case TPM_RT_AUTH:\n    case TPM_RT_TRANS:\n      if (tpm_marshal_TPM_SESSION_DATA(ptr, length, &v->internalData.session))\n        return -1;\n      break;\n    case TPM_RT_DAA_TPM:\n      if (tpm_marshal_TPM_DAA_SESSION_DATA(ptr, length, &v->internalData.sessionDAA))\n        return -1;\n      break;\n    default:\n      return -1;\n  }\n  return 0;\n}\n\nint tpm_unmarshal_TPM_CONTEXT_SENSITIVE(BYTE **ptr, UINT32 *length, TPM_CONTEXT_SENSITIVE *v)\n{\n  if (tpm_unmarshal_TPM_STRUCTURE_TAG(ptr, length, &v->tag)\n      || tpm_unmarshal_TPM_NONCE(ptr, length, &v->contextNonce)\n      || tpm_unmarshal_UINT32(ptr, length, &v->internalSize)\n      || tpm_unmarshal_TPM_RESOURCE_TYPE(ptr, length, &v->resourceType))\n        return -1;\n  switch (v->resourceType) {\n    case TPM_RT_KEY:\n      if (tpm_unmarshal_TPM_KEY_DATA(ptr, length, &v->internalData.key))\n        return -1;\n      break;\n    case TPM_RT_AUTH:\n    case TPM_RT_TRANS:\n      if (tpm_unmarshal_TPM_SESSION_DATA(ptr, length, &v->internalData.session))\n        return -1;\n      break;\n    case TPM_RT_DAA_TPM:\n      if (tpm_unmarshal_TPM_DAA_SESSION_DATA(ptr, length, &v->internalData.sessionDAA))\n        return -1;\n      break;\n    default:\n      return -1;\n  }\n  return 0;\n}\n\nint tpm_marshal_TPM_DAA_BLOB(BYTE **ptr, UINT32 *length, TPM_DAA_BLOB *v)\n{\n  if (tpm_marshal_TPM_STRUCTURE_TAG(ptr, length, v->tag)\n      || tpm_marshal_TPM_RESOURCE_TYPE(ptr, length, v->resourceType)\n      || tpm_marshal_BYTE_ARRAY(ptr, length, v->label, sizeof(v->label))\n      || tpm_marshal_TPM_DIGEST(ptr, length, &v->blobIntegrity)\n      || tpm_marshal_UINT32(ptr, length, v->additionalSize)\n      || tpm_marshal_BLOB(ptr, length, v->additionalData, v->additionalSize)\n      || tpm_marshal_UINT32(ptr, length, v->sensitiveSize)\n      || tpm_marshal_BLOB(ptr, length, v->sensitiveData, v->sensitiveSize))\n        return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_DAA_BLOB(BYTE **ptr, UINT32 *length, TPM_DAA_BLOB *v)\n{\n  if (tpm_unmarshal_TPM_STRUCTURE_TAG(ptr, length, &v->tag)\n      || tpm_unmarshal_TPM_RESOURCE_TYPE(ptr, length, &v->resourceType)\n      || tpm_unmarshal_BYTE_ARRAY(ptr, length, v->label, sizeof(v->label))\n      || tpm_unmarshal_TPM_DIGEST(ptr, length, &v->blobIntegrity)\n      || tpm_unmarshal_UINT32(ptr, length, &v->additionalSize)\n      || tpm_unmarshal_BLOB(ptr, length, &v->additionalData, v->additionalSize)\n      || tpm_unmarshal_UINT32(ptr, length, &v->sensitiveSize)\n      || tpm_unmarshal_BLOB(ptr, length, &v->sensitiveData, v->sensitiveSize))\n        return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_DAA_SENSITIVE(BYTE **ptr, UINT32 *length, TPM_DAA_SENSITIVE *v)\n{\n  if (tpm_marshal_TPM_STRUCTURE_TAG(ptr, length, v->tag)\n      || tpm_marshal_UINT32(ptr, length, v->internalSize)\n      || tpm_marshal_BYTE_ARRAY(ptr, length, v->internalData, v->internalSize))\n        return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_DAA_SENSITIVE(BYTE **ptr, UINT32 *length, TPM_DAA_SENSITIVE *v)\n{\n  if (tpm_unmarshal_TPM_STRUCTURE_TAG(ptr, length, &v->tag)\n      || tpm_unmarshal_UINT32(ptr, length, &v->internalSize)\n      || tpm_unmarshal_BYTE_ARRAY(ptr, length, v->internalData, v->internalSize))\n        return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_DAA_ISSUER(BYTE **ptr, UINT32 *length, TPM_DAA_ISSUER *v)\n{\n  if (tpm_marshal_TPM_STRUCTURE_TAG(ptr, length, v->tag)\n      || tpm_marshal_TPM_DIGEST(ptr, length, &v->DAA_digest_R0)\n      || tpm_marshal_TPM_DIGEST(ptr, length, &v->DAA_digest_R1)\n      || tpm_marshal_TPM_DIGEST(ptr, length, &v->DAA_digest_S0)\n      || tpm_marshal_TPM_DIGEST(ptr, length, &v->DAA_digest_S1)\n      || tpm_marshal_TPM_DIGEST(ptr, length, &v->DAA_digest_n)\n      || tpm_marshal_TPM_DIGEST(ptr, length, &v->DAA_digest_gamma)\n      || tpm_marshal_BYTE_ARRAY(ptr, length, v->DAA_generic_q, sizeof(v->DAA_generic_q)))\n        return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_DAA_ISSUER(BYTE **ptr, UINT32 *length, TPM_DAA_ISSUER *v)\n{\n  if (tpm_unmarshal_TPM_STRUCTURE_TAG(ptr, length, &v->tag)\n      || tpm_unmarshal_TPM_DIGEST(ptr, length, &v->DAA_digest_R0)\n      || tpm_unmarshal_TPM_DIGEST(ptr, length, &v->DAA_digest_R1)\n      || tpm_unmarshal_TPM_DIGEST(ptr, length, &v->DAA_digest_S0)\n      || tpm_unmarshal_TPM_DIGEST(ptr, length, &v->DAA_digest_S1)\n      || tpm_unmarshal_TPM_DIGEST(ptr, length, &v->DAA_digest_n)\n      || tpm_unmarshal_TPM_DIGEST(ptr, length, &v->DAA_digest_gamma)\n      || tpm_unmarshal_BYTE_ARRAY(ptr, length, v->DAA_generic_q, sizeof(v->DAA_generic_q)))\n        return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_DAA_TPM(BYTE **ptr, UINT32 *length, TPM_DAA_TPM *v)\n{\n  if (tpm_marshal_TPM_STRUCTURE_TAG(ptr, length, v->tag)\n      || tpm_marshal_TPM_DIGEST(ptr, length, &v->DAA_digestIssuer)\n      || tpm_marshal_TPM_DIGEST(ptr, length, &v->DAA_digest_v0)\n      || tpm_marshal_TPM_DIGEST(ptr, length, &v->DAA_digest_v1)\n      || tpm_marshal_TPM_DIGEST(ptr, length, &v->DAA_rekey)\n      || tpm_marshal_UINT32(ptr, length, v->DAA_count))\n        return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_DAA_TPM(BYTE **ptr, UINT32 *length, TPM_DAA_TPM *v)\n{\n  if (tpm_unmarshal_TPM_STRUCTURE_TAG(ptr, length, &v->tag)\n      || tpm_unmarshal_TPM_DIGEST(ptr, length, &v->DAA_digestIssuer)\n      || tpm_unmarshal_TPM_DIGEST(ptr, length, &v->DAA_digest_v0)\n      || tpm_unmarshal_TPM_DIGEST(ptr, length, &v->DAA_digest_v1)\n      || tpm_unmarshal_TPM_DIGEST(ptr, length, &v->DAA_rekey)\n      || tpm_unmarshal_UINT32(ptr, length, &v->DAA_count))\n        return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_DAA_CONTEXT(BYTE **ptr, UINT32 *length, TPM_DAA_CONTEXT *v)\n{\n  if (tpm_marshal_TPM_STRUCTURE_TAG(ptr, length, v->tag)\n      || tpm_marshal_TPM_DIGEST(ptr, length, &v->DAA_digestContext)\n      || tpm_marshal_TPM_DIGEST(ptr, length, &v->DAA_digest)\n      || tpm_marshal_TPM_NONCE(ptr, length, &v->DAA_contextSeed)\n      || tpm_marshal_BYTE_ARRAY(ptr, length, v->DAA_scratch, sizeof(v->DAA_scratch))\n      || tpm_marshal_BYTE(ptr, length, v->DAA_stage))\n        return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_DAA_CONTEXT(BYTE **ptr, UINT32 *length, TPM_DAA_CONTEXT *v)\n{\n  if (tpm_unmarshal_TPM_STRUCTURE_TAG(ptr, length, &v->tag)\n      || tpm_unmarshal_TPM_DIGEST(ptr, length, &v->DAA_digestContext)\n      || tpm_unmarshal_TPM_DIGEST(ptr, length, &v->DAA_digest)\n      || tpm_unmarshal_TPM_NONCE(ptr, length, &v->DAA_contextSeed)\n      || tpm_unmarshal_BYTE_ARRAY(ptr, length, v->DAA_scratch, sizeof(v->DAA_scratch))\n      || tpm_unmarshal_BYTE(ptr, length, &v->DAA_stage))\n        return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_DAA_JOINDATA(BYTE **ptr, UINT32 *length, TPM_DAA_JOINDATA *v)\n{\n  if (tpm_marshal_BYTE_ARRAY(ptr, length, v->DAA_join_u0, sizeof(v->DAA_join_u0))\n      || tpm_marshal_BYTE_ARRAY(ptr, length, v->DAA_join_u1, sizeof(v->DAA_join_u1))\n      || tpm_marshal_TPM_DIGEST(ptr, length, &v->DAA_digest_n0))\n        return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_DAA_JOINDATA(BYTE **ptr, UINT32 *length, TPM_DAA_JOINDATA *v)\n{\n  if (tpm_unmarshal_BYTE_ARRAY(ptr, length, v->DAA_join_u0, sizeof(v->DAA_join_u0))\n      || tpm_unmarshal_BYTE_ARRAY(ptr, length, v->DAA_join_u1, sizeof(v->DAA_join_u1))\n      || tpm_unmarshal_TPM_DIGEST(ptr, length, &v->DAA_digest_n0))\n        return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_DAA_SESSION_DATA(BYTE **ptr, UINT32 *length, TPM_DAA_SESSION_DATA *v)\n{\n  if (tpm_marshal_BYTE(ptr, length, v->type)\n      || tpm_marshal_TPM_DAA_ISSUER(ptr, length, &v->DAA_issuerSettings)\n      || tpm_marshal_TPM_DAA_TPM(ptr, length, &v->DAA_tpmSpecific)\n      || tpm_marshal_TPM_DAA_CONTEXT(ptr, length, &v->DAA_session)\n      || tpm_marshal_TPM_DAA_JOINDATA(ptr, length, &v->DAA_joinSession)\n      || tpm_marshal_TPM_HANDLE(ptr, length, v->handle)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_DAA_SESSION_DATA(BYTE **ptr, UINT32 *length, TPM_DAA_SESSION_DATA *v)\n{\n  if (tpm_unmarshal_BYTE(ptr, length, &v->type)\n      || tpm_unmarshal_TPM_DAA_ISSUER(ptr, length, &v->DAA_issuerSettings)\n      || tpm_unmarshal_TPM_DAA_TPM(ptr, length, &v->DAA_tpmSpecific)\n      || tpm_unmarshal_TPM_DAA_CONTEXT(ptr, length, &v->DAA_session)\n      || tpm_unmarshal_TPM_DAA_JOINDATA(ptr, length, &v->DAA_joinSession)\n      || tpm_unmarshal_TPM_HANDLE(ptr, length, &v->handle)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_MSA_COMPOSITE(BYTE **ptr, UINT32 *length, TPM_MSA_COMPOSITE *v)\n{\n  UINT32 i;\n  if (tpm_marshal_UINT32(ptr, length, v->MSAlist))\n    return -1;\n  for (i = 0; i < v->MSAlist; i++) {\n    if (tpm_marshal_TPM_DIGEST(ptr, length, &v->migAuthDigest[i])) return -1;\n  }\n  return 0;\n}\n\nint tpm_unmarshal_TPM_MSA_COMPOSITE(BYTE **ptr, UINT32 *length, TPM_MSA_COMPOSITE *v)\n{\n  UINT32 i;\n  if (tpm_unmarshal_UINT32(ptr, length, &v->MSAlist))\n    return -1;\n  if (v->MSAlist > MAX_MSA_COMPOSITE_ENTRIES) return -1;\n  for (i = 0; i < v->MSAlist; i++) {\n    if (tpm_unmarshal_TPM_DIGEST(ptr, length, &v->migAuthDigest[i])) return -1;\n  }\n  return 0;\n}\n\nint tpm_marshal_TPM_CMK_AUTH(BYTE **ptr, UINT32 *length, TPM_CMK_AUTH *v)\n{\n  if (tpm_marshal_TPM_DIGEST(ptr, length, &v->migrationAuthorityDigest)\n      || tpm_marshal_TPM_DIGEST(ptr, length, &v->destinationKeyDigest)\n      || tpm_marshal_TPM_DIGEST(ptr, length, &v->sourceKeyDigest))\n        return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_CMK_AUTH(BYTE **ptr, UINT32 *length, TPM_CMK_AUTH *v)\n{\n  if (tpm_unmarshal_TPM_DIGEST(ptr, length, &v->migrationAuthorityDigest)\n      || tpm_unmarshal_TPM_DIGEST(ptr, length, &v->destinationKeyDigest)\n      || tpm_unmarshal_TPM_DIGEST(ptr, length, &v->sourceKeyDigest))\n        return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_SELECT_SIZE(BYTE **ptr, UINT32 *length, TPM_SELECT_SIZE *v)\n{\n  if (tpm_marshal_BYTE(ptr, length, v->major)\n      || tpm_marshal_BYTE(ptr, length, v->minor)\n      || tpm_marshal_UINT16(ptr, length, v->reqSize)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_SELECT_SIZE(BYTE **ptr, UINT32 *length, TPM_SELECT_SIZE *v)\n{\n  if (tpm_unmarshal_BYTE(ptr, length, &v->major)\n      || tpm_unmarshal_BYTE(ptr, length, &v->minor)\n      || tpm_unmarshal_UINT16(ptr, length, &v->reqSize)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_CAP_VERSION_INFO(BYTE **ptr, UINT32 *length, TPM_CAP_VERSION_INFO *v)\n{\n  if (tpm_marshal_TPM_STRUCTURE_TAG(ptr, length, v->tag)\n      || tpm_marshal_TPM_VERSION(ptr, length, &v->version)\n      || tpm_marshal_UINT16(ptr, length, v->specLevel)\n      || tpm_marshal_BYTE(ptr, length, v->errataRev)\n      || tpm_marshal_BYTE(ptr, length, v->tpmVendorID[0])\n      || tpm_marshal_BYTE(ptr, length, v->tpmVendorID[1])\n      || tpm_marshal_BYTE(ptr, length, v->tpmVendorID[2])\n      || tpm_marshal_BYTE(ptr, length, v->tpmVendorID[3])\n      || tpm_marshal_UINT16(ptr, length, v->vendorSpecificSize)\n      || tpm_marshal_BLOB(ptr, length, v->vendorSpecific, v->vendorSpecificSize))\n        return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_CAP_VERSION_INFO(BYTE **ptr, UINT32 *length, TPM_CAP_VERSION_INFO *v)\n{\n  if (tpm_unmarshal_TPM_STRUCTURE_TAG(ptr, length, &v->tag)\n      || tpm_unmarshal_TPM_VERSION(ptr, length, &v->version)\n      || tpm_unmarshal_UINT16(ptr, length, &v->specLevel)\n      || tpm_unmarshal_BYTE(ptr, length, &v->errataRev)\n      || tpm_unmarshal_BYTE(ptr, length, &v->tpmVendorID[0])\n      || tpm_unmarshal_BYTE(ptr, length, &v->tpmVendorID[1])\n      || tpm_unmarshal_BYTE(ptr, length, &v->tpmVendorID[2])\n      || tpm_unmarshal_BYTE(ptr, length, &v->tpmVendorID[3])\n      || tpm_unmarshal_UINT16(ptr, length, &v->vendorSpecificSize)\n      || tpm_unmarshal_BLOB(ptr, length, &v->vendorSpecific, v->vendorSpecificSize))\n        return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_ASYM_CA_CONTENTS(BYTE **ptr, UINT32 *length, TPM_ASYM_CA_CONTENTS *v)\n{\n  if (tpm_marshal_TPM_SYMMETRIC_KEY(ptr, length, &v->sessionKey)\n      || tpm_marshal_TPM_DIGEST(ptr, length, &v->idDigest))\n        return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_ASYM_CA_CONTENTS(BYTE **ptr, UINT32 *length, TPM_ASYM_CA_CONTENTS *v)\n{\n  if (tpm_unmarshal_TPM_SYMMETRIC_KEY(ptr, length, &v->sessionKey)\n      || tpm_unmarshal_TPM_DIGEST(ptr, length, &v->idDigest))\n        return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_QUOTE_INFO2(BYTE **ptr, UINT32 *length, TPM_QUOTE_INFO2 *v)\n{\n  if (tpm_marshal_TPM_STRUCTURE_TAG(ptr, length, v->tag)\n      || tpm_marshal_BYTE(ptr, length, v->fixed[0])\n      || tpm_marshal_BYTE(ptr, length, v->fixed[1])\n      || tpm_marshal_BYTE(ptr, length, v->fixed[2])\n      || tpm_marshal_BYTE(ptr, length, v->fixed[3])\n      || tpm_marshal_TPM_NONCE(ptr, length, &v->externalData)\n      || tpm_marshal_TPM_PCR_INFO_SHORT(ptr, length, &v->infoShort))\n        return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_QUOTE_INFO2(BYTE **ptr, UINT32 *length, TPM_QUOTE_INFO2 *v)\n{\n  if (tpm_unmarshal_TPM_STRUCTURE_TAG(ptr, length, &v->tag)\n      || tpm_unmarshal_BYTE(ptr, length, &v->fixed[0])\n      || tpm_unmarshal_BYTE(ptr, length, &v->fixed[1])\n      || tpm_unmarshal_BYTE(ptr, length, &v->fixed[2])\n      || tpm_unmarshal_BYTE(ptr, length, &v->fixed[3])\n      || tpm_unmarshal_TPM_NONCE(ptr, length, &v->externalData)\n      || tpm_unmarshal_TPM_PCR_INFO_SHORT(ptr, length, &v->infoShort))\n        return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_EK_BLOB(BYTE **ptr, UINT32 *length, TPM_EK_BLOB *v)\n{\n  if (tpm_marshal_TPM_STRUCTURE_TAG(ptr, length, v->tag)\n      || tpm_marshal_TPM_EK_TYPE(ptr, length, v->ekType)\n      || tpm_marshal_UINT32(ptr, length, v->blobSize)\n      || tpm_marshal_BLOB(ptr, length, v->blob, v->blobSize))\n        return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_EK_BLOB(BYTE **ptr, UINT32 *length, TPM_EK_BLOB *v)\n{\n  if (tpm_unmarshal_TPM_STRUCTURE_TAG(ptr, length, &v->tag)\n      || tpm_unmarshal_TPM_EK_TYPE(ptr, length, &v->ekType)\n      || tpm_unmarshal_UINT32(ptr, length, &v->blobSize)\n      || tpm_unmarshal_BLOB(ptr, length, &v->blob, v->blobSize))\n        return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_EK_BLOB_ACTIVATE(BYTE **ptr, UINT32 *length, TPM_EK_BLOB_ACTIVATE *v)\n{\n  if (tpm_marshal_TPM_STRUCTURE_TAG(ptr, length, v->tag)\n      || tpm_marshal_TPM_SYMMETRIC_KEY(ptr, length, &v->sessionKey)\n      || tpm_marshal_TPM_DIGEST(ptr, length, &v->idDigest)\n      || tpm_marshal_TPM_PCR_INFO_SHORT(ptr, length, &v->pcrInfo))\n        return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_EK_BLOB_ACTIVATE(BYTE **ptr, UINT32 *length, TPM_EK_BLOB_ACTIVATE *v)\n{\n  if (tpm_unmarshal_TPM_STRUCTURE_TAG(ptr, length, &v->tag)\n      || tpm_unmarshal_TPM_SYMMETRIC_KEY(ptr, length, &v->sessionKey)\n      || tpm_unmarshal_TPM_DIGEST(ptr, length, &v->idDigest)\n      || tpm_unmarshal_TPM_PCR_INFO_SHORT(ptr, length, &v->pcrInfo))\n        return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_NV_ATTRIBUTES(BYTE **ptr, UINT32 *length, TPM_NV_ATTRIBUTES *v)\n{\n  if (tpm_marshal_TPM_STRUCTURE_TAG(ptr, length, v->tag)\n      || tpm_marshal_UINT32(ptr, length, v->attributes)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_NV_ATTRIBUTES(BYTE **ptr, UINT32 *length, TPM_NV_ATTRIBUTES *v)\n{\n  if (tpm_unmarshal_TPM_STRUCTURE_TAG(ptr, length, &v->tag)\n      || tpm_unmarshal_UINT32(ptr, length, &v->attributes)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_NV_DATA_PUBLIC(BYTE **ptr, UINT32 *length, TPM_NV_DATA_PUBLIC *v)\n{\n  if (tpm_marshal_TPM_STRUCTURE_TAG(ptr, length, v->tag)\n      || tpm_marshal_TPM_NV_INDEX(ptr, length, v->nvIndex)\n      || tpm_marshal_TPM_PCR_INFO_SHORT(ptr, length, &v->pcrInfoRead)\n      || tpm_marshal_TPM_PCR_INFO_SHORT(ptr, length, &v->pcrInfoWrite)\n      || tpm_marshal_TPM_NV_ATTRIBUTES(ptr, length, &v->permission)\n      || tpm_marshal_BOOL(ptr, length, v->bReadSTClear)\n      || tpm_marshal_BOOL(ptr, length, v->bWriteSTClear)\n      || tpm_marshal_BOOL(ptr, length, v->bWriteDefine)\n      || tpm_marshal_UINT32(ptr, length, v->dataSize)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_NV_DATA_PUBLIC(BYTE **ptr, UINT32 *length, TPM_NV_DATA_PUBLIC *v)\n{\n  if (tpm_unmarshal_TPM_STRUCTURE_TAG(ptr, length, &v->tag)\n      || tpm_unmarshal_TPM_NV_INDEX(ptr, length, &v->nvIndex)\n      || tpm_unmarshal_TPM_PCR_INFO_SHORT(ptr, length, &v->pcrInfoRead)\n      || tpm_unmarshal_TPM_PCR_INFO_SHORT(ptr, length, &v->pcrInfoWrite)\n      || tpm_unmarshal_TPM_NV_ATTRIBUTES(ptr, length, &v->permission)\n      || tpm_unmarshal_BOOL(ptr, length, &v->bReadSTClear)\n      || tpm_unmarshal_BOOL(ptr, length, &v->bWriteSTClear)\n      || tpm_unmarshal_BOOL(ptr, length, &v->bWriteDefine)\n      || tpm_unmarshal_UINT32(ptr, length, &v->dataSize)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_NV_DATA_SENSITIVE(BYTE **ptr, UINT32 *length, TPM_NV_DATA_SENSITIVE *v)\n{\n  if (tpm_marshal_TPM_STRUCTURE_TAG(ptr, length, v->tag)\n      || tpm_marshal_TPM_NV_DATA_PUBLIC(ptr, length, &v->pubInfo)\n      || tpm_marshal_TPM_AUTHDATA(ptr, length, &v->authValue)\n      || tpm_marshal_UINT32(ptr, length, v->dataIndex)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_NV_DATA_SENSITIVE(BYTE **ptr, UINT32 *length, TPM_NV_DATA_SENSITIVE *v)\n{\n  if (tpm_unmarshal_TPM_STRUCTURE_TAG(ptr, length, &v->tag)\n      || tpm_unmarshal_TPM_NV_DATA_PUBLIC(ptr, length, &v->pubInfo)\n      || tpm_unmarshal_TPM_AUTHDATA(ptr, length, &v->authValue)\n      || tpm_unmarshal_UINT32(ptr, length, &v->dataIndex)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_DELEGATIONS(BYTE **ptr, UINT32 *length, TPM_DELEGATIONS *v)\n{\n  if (tpm_marshal_TPM_STRUCTURE_TAG(ptr, length, v->tag)\n      || tpm_marshal_UINT32(ptr, length, v->delegateType)\n      || tpm_marshal_UINT32(ptr, length, v->per1)\n      || tpm_marshal_UINT32(ptr, length, v->per2)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_DELEGATIONS(BYTE **ptr, UINT32 *length, TPM_DELEGATIONS *v)\n{\n  if (tpm_unmarshal_TPM_STRUCTURE_TAG(ptr, length, &v->tag)\n      || tpm_unmarshal_UINT32(ptr, length, &v->delegateType)\n      || tpm_unmarshal_UINT32(ptr, length, &v->per1)\n      || tpm_unmarshal_UINT32(ptr, length, &v->per2)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_FAMILY_LABEL(BYTE **ptr, UINT32 *length, TPM_FAMILY_LABEL *v)\n{\n  if (tpm_marshal_BYTE(ptr, length, v->label)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_FAMILY_LABEL(BYTE **ptr, UINT32 *length, TPM_FAMILY_LABEL *v)\n{\n  if (tpm_unmarshal_BYTE(ptr, length, &v->label)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_FAMILY_TABLE_ENTRY(BYTE **ptr, UINT32 *length, TPM_FAMILY_TABLE_ENTRY *v)\n{\n  if (tpm_marshal_TPM_STRUCTURE_TAG(ptr, length, v->tag)\n      || tpm_marshal_TPM_FAMILY_LABEL(ptr, length, &v->familyLabel)\n      || tpm_marshal_TPM_FAMILY_ID(ptr, length, v->familyID)\n      || tpm_marshal_TPM_FAMILY_VERIFICATION(ptr, length, v->verificationCount)\n      || tpm_marshal_TPM_FAMILY_FLAGS(ptr, length, v->flags)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_FAMILY_TABLE_ENTRY(BYTE **ptr, UINT32 *length, TPM_FAMILY_TABLE_ENTRY *v)\n{\n  if (tpm_unmarshal_TPM_STRUCTURE_TAG(ptr, length, &v->tag)\n      || tpm_unmarshal_TPM_FAMILY_LABEL(ptr, length, &v->familyLabel)\n      || tpm_unmarshal_TPM_FAMILY_ID(ptr, length, &v->familyID)\n      || tpm_unmarshal_TPM_FAMILY_VERIFICATION(ptr, length, &v->verificationCount)\n      || tpm_unmarshal_TPM_FAMILY_FLAGS(ptr, length, &v->flags)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_DELEGATE_LABEL(BYTE **ptr, UINT32 *length, TPM_DELEGATE_LABEL *v)\n{\n  if (tpm_marshal_BYTE(ptr, length, v->label)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_DELEGATE_LABEL(BYTE **ptr, UINT32 *length, TPM_DELEGATE_LABEL *v)\n{\n  if (tpm_unmarshal_BYTE(ptr, length, &v->label)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_DELEGATE_PUBLIC(BYTE **ptr, UINT32 *length, TPM_DELEGATE_PUBLIC *v)\n{\n  if (tpm_marshal_TPM_STRUCTURE_TAG(ptr, length, v->tag)\n      || tpm_marshal_TPM_DELEGATE_LABEL(ptr, length, &v->rowLabel)\n      || tpm_marshal_TPM_PCR_INFO_SHORT(ptr, length, &v->pcrInfo)\n      || tpm_marshal_TPM_DELEGATIONS(ptr, length, &v->permissions)\n      || tpm_marshal_TPM_FAMILY_ID(ptr, length, v->familyID)\n      || tpm_marshal_TPM_FAMILY_VERIFICATION(ptr, length, v->verificationCount)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_DELEGATE_PUBLIC(BYTE **ptr, UINT32 *length, TPM_DELEGATE_PUBLIC *v)\n{\n  if (tpm_unmarshal_TPM_STRUCTURE_TAG(ptr, length, &v->tag)\n      || tpm_unmarshal_TPM_DELEGATE_LABEL(ptr, length, &v->rowLabel)\n      || tpm_unmarshal_TPM_PCR_INFO_SHORT(ptr, length, &v->pcrInfo)\n      || tpm_unmarshal_TPM_DELEGATIONS(ptr, length, &v->permissions)\n      || tpm_unmarshal_TPM_FAMILY_ID(ptr, length, &v->familyID)\n      || tpm_unmarshal_TPM_FAMILY_VERIFICATION(ptr, length, &v->verificationCount)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_DELEGATE_PUBLIC_ARRAY(BYTE **ptr, UINT32 *length,\n                                          TPM_DELEGATE_PUBLIC *v, UINT32 n)\n{\n  UINT32 i;\n  for (i = 0; i < n; i++) {\n    if (tpm_marshal_TPM_DELEGATE_PUBLIC(ptr, length, &v[i])) return -1;\n  }\n  return 0;\n}\n\nint tpm_unmarshal_TPM_DELEGATE_PUBLIC_ARRAY(BYTE **ptr, UINT32 *length,\n                                            TPM_DELEGATE_PUBLIC *v, UINT32 n)\n{\n  UINT32 i;\n  for (i = 0; i < n; i++) {\n    if (tpm_unmarshal_TPM_DELEGATE_PUBLIC(ptr, length, &v[i])) return -1;\n  }\n  return 0;\n}\n\nint tpm_marshal_TPM_DELEGATE_TABLE_ROW(BYTE **ptr, UINT32 *length, TPM_DELEGATE_TABLE_ROW *v)\n{\n  if (tpm_marshal_TPM_STRUCTURE_TAG(ptr, length, v->tag)\n      || tpm_marshal_TPM_DELEGATE_PUBLIC(ptr, length, &v->pub)\n      || tpm_marshal_TPM_SECRET(ptr, length, &v->authValue)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_DELEGATE_TABLE_ROW(BYTE **ptr, UINT32 *length, TPM_DELEGATE_TABLE_ROW *v)\n{\n  if (tpm_unmarshal_TPM_STRUCTURE_TAG(ptr, length, &v->tag)\n      || tpm_unmarshal_TPM_DELEGATE_PUBLIC(ptr, length, &v->pub)\n      || tpm_unmarshal_TPM_SECRET(ptr, length, &v->authValue)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_DELEGATE_SENSITIVE(BYTE **ptr, UINT32 *length, TPM_DELEGATE_SENSITIVE *v)\n{\n  if (tpm_marshal_TPM_STRUCTURE_TAG(ptr, length, v->tag)\n      || tpm_marshal_TPM_SECRET(ptr, length, &v->authValue)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_DELEGATE_SENSITIVE(BYTE **ptr, UINT32 *length, TPM_DELEGATE_SENSITIVE *v)\n{\n  if (tpm_unmarshal_TPM_STRUCTURE_TAG(ptr, length, &v->tag)\n    || tpm_unmarshal_TPM_SECRET(ptr, length, &v->authValue)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_DELEGATE_OWNER_BLOB(BYTE **ptr, UINT32 *length, TPM_DELEGATE_OWNER_BLOB *v)\n{\n  if (tpm_marshal_TPM_STRUCTURE_TAG(ptr, length, v->tag)\n      || tpm_marshal_TPM_DELEGATE_PUBLIC(ptr, length, &v->pub)\n      || tpm_marshal_TPM_DIGEST(ptr, length, &v->integrityDigest)\n      || tpm_marshal_UINT32(ptr, length, v->additionalSize)\n      || tpm_marshal_BLOB(ptr, length, v->additionalArea, v->additionalSize)\n      || tpm_marshal_UINT32(ptr, length, v->sensitiveSize)\n      || tpm_marshal_BLOB(ptr, length, v->sensitiveArea, v->sensitiveSize)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_DELEGATE_OWNER_BLOB(BYTE **ptr, UINT32 *length, TPM_DELEGATE_OWNER_BLOB *v)\n{\n  if (tpm_unmarshal_TPM_STRUCTURE_TAG(ptr, length, &v->tag)\n      || tpm_unmarshal_TPM_DELEGATE_PUBLIC(ptr, length, &v->pub)\n      || tpm_unmarshal_TPM_DIGEST(ptr, length, &v->integrityDigest)\n      || tpm_unmarshal_UINT32(ptr, length, &v->additionalSize)\n      || tpm_unmarshal_BLOB(ptr, length, &v->additionalArea, v->additionalSize)\n      || tpm_unmarshal_UINT32(ptr, length, &v->sensitiveSize)\n      || tpm_unmarshal_BLOB(ptr, length, &v->sensitiveArea, v->sensitiveSize)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_DELEGATE_KEY_BLOB(BYTE **ptr, UINT32 *length, TPM_DELEGATE_KEY_BLOB *v)\n{\n  if (tpm_marshal_TPM_STRUCTURE_TAG(ptr, length, v->tag)\n      || tpm_marshal_TPM_DELEGATE_PUBLIC(ptr, length, &v->pub)\n      || tpm_marshal_TPM_DIGEST(ptr, length, &v->integrityDigest)\n      || tpm_marshal_TPM_DIGEST(ptr, length, &v->pubKeyDigest)\n      || tpm_marshal_UINT32(ptr, length, v->additionalSize)\n      || tpm_marshal_BLOB(ptr, length, v->additionalArea, v->additionalSize)\n      || tpm_marshal_UINT32(ptr, length, v->sensitiveSize)\n      || tpm_marshal_BLOB(ptr, length, v->sensitiveArea, v->sensitiveSize)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_DELEGATE_KEY_BLOB(BYTE **ptr, UINT32 *length, TPM_DELEGATE_KEY_BLOB *v)\n{\n  if (tpm_unmarshal_TPM_STRUCTURE_TAG(ptr, length, &v->tag)\n      || tpm_unmarshal_TPM_DELEGATE_PUBLIC(ptr, length, &v->pub)\n      || tpm_unmarshal_TPM_DIGEST(ptr, length, &v->integrityDigest)\n      || tpm_unmarshal_TPM_DIGEST(ptr, length, &v->pubKeyDigest)\n      || tpm_unmarshal_UINT32(ptr, length, &v->additionalSize)\n      || tpm_unmarshal_BLOB(ptr, length, &v->additionalArea, v->additionalSize)\n      || tpm_unmarshal_UINT32(ptr, length, &v->sensitiveSize)\n      || tpm_unmarshal_BLOB(ptr, length, &v->sensitiveArea, v->sensitiveSize)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_PERMANENT_FLAGS(BYTE **ptr, UINT32 *length, TPM_PERMANENT_FLAGS *v)\n{\n  if (tpm_marshal_TPM_STRUCTURE_TAG(ptr, length, v->tag)\n      || tpm_marshal_BOOL(ptr, length, v->disable)\n      || tpm_marshal_BOOL(ptr, length, v->ownership)\n      || tpm_marshal_BOOL(ptr, length, v->deactivated)\n      || tpm_marshal_BOOL(ptr, length, v->readPubek)\n      || tpm_marshal_BOOL(ptr, length, v->disableOwnerClear)\n      || tpm_marshal_BOOL(ptr, length, v->allowMaintenance)\n      || tpm_marshal_BOOL(ptr, length, v->physicalPresenceLifetimeLock)\n      || tpm_marshal_BOOL(ptr, length, v->physicalPresenceHWEnable)\n      || tpm_marshal_BOOL(ptr, length, v->physicalPresenceCMDEnable)\n      || tpm_marshal_BOOL(ptr, length, v->CEKPUsed)\n      || tpm_marshal_BOOL(ptr, length, v->TPMpost)\n      || tpm_marshal_BOOL(ptr, length, v->TPMpostLock)\n      || tpm_marshal_BOOL(ptr, length, v->FIPS)\n      || tpm_marshal_BOOL(ptr, length, v->operator)\n      || tpm_marshal_BOOL(ptr, length, v->enableRevokeEK)\n      || tpm_marshal_BOOL(ptr, length, v->nvLocked)\n      || tpm_marshal_BOOL(ptr, length, v->readSRKPub)\n      || tpm_marshal_BOOL(ptr, length, v->tpmEstablished)\n      || tpm_marshal_BOOL(ptr, length, v->maintenanceDone)\n      || tpm_marshal_BOOL(ptr, length, v->disableFullDALogicInfo)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_PERMANENT_FLAGS(BYTE **ptr, UINT32 *length, TPM_PERMANENT_FLAGS *v)\n{\n  if (tpm_unmarshal_TPM_STRUCTURE_TAG(ptr, length, &v->tag)\n      || tpm_unmarshal_BOOL(ptr, length, &v->disable)\n      || tpm_unmarshal_BOOL(ptr, length, &v->ownership)\n      || tpm_unmarshal_BOOL(ptr, length, &v->deactivated)\n      || tpm_unmarshal_BOOL(ptr, length, &v->readPubek)\n      || tpm_unmarshal_BOOL(ptr, length, &v->disableOwnerClear)\n      || tpm_unmarshal_BOOL(ptr, length, &v->allowMaintenance)\n      || tpm_unmarshal_BOOL(ptr, length, &v->physicalPresenceLifetimeLock)\n      || tpm_unmarshal_BOOL(ptr, length, &v->physicalPresenceHWEnable)\n      || tpm_unmarshal_BOOL(ptr, length, &v->physicalPresenceCMDEnable)\n      || tpm_unmarshal_BOOL(ptr, length, &v->CEKPUsed)\n      || tpm_unmarshal_BOOL(ptr, length, &v->TPMpost)\n      || tpm_unmarshal_BOOL(ptr, length, &v->TPMpostLock)\n      || tpm_unmarshal_BOOL(ptr, length, &v->FIPS)\n      || tpm_unmarshal_BOOL(ptr, length, &v->operator)\n      || tpm_unmarshal_BOOL(ptr, length, &v->enableRevokeEK)\n      || tpm_unmarshal_BOOL(ptr, length, &v->nvLocked)\n      || tpm_unmarshal_BOOL(ptr, length, &v->readSRKPub)\n      || tpm_unmarshal_BOOL(ptr, length, &v->tpmEstablished)\n      || tpm_unmarshal_BOOL(ptr, length, &v->maintenanceDone)\n      || tpm_unmarshal_BOOL(ptr, length, &v->disableFullDALogicInfo)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_STCLEAR_FLAGS(BYTE **ptr, UINT32 *length, TPM_STCLEAR_FLAGS *v)\n{\n  if (tpm_marshal_TPM_STRUCTURE_TAG(ptr, length, v->tag)\n      || tpm_marshal_BOOL(ptr, length, v->deactivated)\n      || tpm_marshal_BOOL(ptr, length, v->disableForceClear)\n      || tpm_marshal_BOOL(ptr, length, v->physicalPresence)\n      || tpm_marshal_BOOL(ptr, length, v->physicalPresenceLock)\n      || tpm_marshal_BOOL(ptr, length, v->bGlobalLock)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_STCLEAR_FLAGS(BYTE **ptr, UINT32 *length, TPM_STCLEAR_FLAGS *v)\n{\n  if (tpm_unmarshal_TPM_STRUCTURE_TAG(ptr, length, &v->tag)\n      || tpm_unmarshal_BOOL(ptr, length, &v->deactivated)\n      || tpm_unmarshal_BOOL(ptr, length, &v->disableForceClear)\n      || tpm_unmarshal_BOOL(ptr, length, &v->physicalPresence)\n      || tpm_unmarshal_BOOL(ptr, length, &v->physicalPresenceLock)\n      || tpm_unmarshal_BOOL(ptr, length, &v->bGlobalLock)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_STANY_FLAGS(BYTE **ptr, UINT32 *length, TPM_STANY_FLAGS *v)\n{\n  if (tpm_marshal_TPM_STRUCTURE_TAG(ptr, length, v->tag)\n      || tpm_marshal_BOOL(ptr, length, v->postInitialise)\n      || tpm_marshal_UINT32(ptr, length, v->localityModifier)\n      || tpm_marshal_BOOL(ptr, length, v->transportExclusive)\n      || tpm_marshal_BOOL(ptr, length, v->TOSPresent)) return -1;\n  return 0;\n} \n\nint tpm_unmarshal_TPM_STANY_FLAGS(BYTE **ptr, UINT32 *length, TPM_STANY_FLAGS *v)\n{\n  if (tpm_unmarshal_TPM_STRUCTURE_TAG(ptr, length, &v->tag)\n      || tpm_unmarshal_BOOL(ptr, length, &v->postInitialise)\n      || tpm_unmarshal_UINT32(ptr, length, &v->localityModifier)\n      || tpm_unmarshal_BOOL(ptr, length, &v->transportExclusive)\n      || tpm_unmarshal_BOOL(ptr, length, &v->TOSPresent)) return -1;\n  return 0;\n}\n\nint tpm_marshal_RSA(BYTE **ptr, UINT32 *length, tpm_rsa_private_key_t *v)\n{\n  size_t m_len, e_len, q_len;\n  if (*length < (UINT32)sizeof_RSA((*v))) return -1;\n  if (v->size > 0) {\n    tpm_rsa_export_modulus(v, &(*ptr)[6], &m_len);\n    tpm_rsa_export_exponent(v, &(*ptr)[6+m_len], &e_len);\n    tpm_rsa_export_prime1(v, &(*ptr)[6+m_len+e_len], &q_len);\n    tpm_marshal_UINT16(ptr, length, m_len);\n    tpm_marshal_UINT16(ptr, length, e_len);\n    tpm_marshal_UINT16(ptr, length, q_len);\n    *ptr += m_len + e_len + q_len;\n    *length -= m_len + e_len + q_len;\n  } else {\n    tpm_marshal_UINT16(ptr, length, 0);\n    tpm_marshal_UINT16(ptr, length, 0);\n    tpm_marshal_UINT16(ptr, length, 0);\n  }\n  return 0;\n}\n\nint tpm_unmarshal_RSA(BYTE **ptr, UINT32 *length, tpm_rsa_private_key_t *v)\n{\n  UINT16 m_len, e_len, q_len;\n  if (tpm_unmarshal_UINT16(ptr, length, &m_len)\n      || tpm_unmarshal_UINT16(ptr, length, &e_len)\n      || tpm_unmarshal_UINT16(ptr, length, &q_len)) return -1;\n  if (m_len == 0) {\n    v->size = 0;\n    return 0;\n  }\n  if (*length < (UINT32)m_len + (UINT32)e_len + (UINT32)q_len\n      || q_len != m_len/2\n      || tpm_rsa_import_key(v, RSA_MSB_FIRST,\n                        &(*ptr)[0], m_len,\n                        &(*ptr)[m_len], e_len,\n                        &(*ptr)[m_len+e_len], NULL)) return -1;\n  *ptr += m_len + e_len + q_len;\n  *length -= m_len + e_len + q_len;\n  return 0;\n}\n\nint tpm_marshal_RSAPub(BYTE **ptr, UINT32 *length, tpm_rsa_public_key_t *v)\n{\n  size_t m_len, e_len;\n  if (*length < (UINT32)sizeof_RSAPub((*v))) return -1;\n  if (v->size > 0) {\n    tpm_rsa_export_public_modulus(v, &(*ptr)[4], &m_len);\n    tpm_rsa_export_public_exponent(v, &(*ptr)[4+m_len], &e_len);\n    tpm_marshal_UINT16(ptr, length, m_len);\n    tpm_marshal_UINT16(ptr, length, e_len);\n    *ptr += m_len + e_len;\n    *length -= m_len + e_len;\n  } else {\n    tpm_marshal_UINT16(ptr, length, 0);\n    tpm_marshal_UINT16(ptr, length, 0);\n  }\n  return 0;\n}\n\nint tpm_unmarshal_RSAPub(BYTE **ptr, UINT32 *length, tpm_rsa_public_key_t *v)\n{\n  UINT16 m_len, e_len;\n  if (tpm_unmarshal_UINT16(ptr, length, &m_len)\n      || tpm_unmarshal_UINT16(ptr, length, &e_len)) return -1;\n  if (m_len == 0) {\n    v->size = 0;\n    return 0;\n  }\n  if (*length < (UINT32)m_len + (UINT32)e_len\n      || tpm_rsa_import_public_key(v, RSA_MSB_FIRST, &(*ptr)[0], m_len, \n                                   &(*ptr)[m_len], e_len)) return -1;\n  *ptr += m_len + e_len;\n  *length -= m_len + e_len;\n  return 0;\n}\n\nint tpm_marshal_TPM_KEY_DATA(BYTE **ptr, UINT32 *length, TPM_KEY_DATA *v)\n{\n  if (tpm_marshal_TPM_PAYLOAD_TYPE(ptr, length, v->payload)) return -1;\n  if (v->payload) {\n    if (tpm_marshal_TPM_KEY_USAGE(ptr, length, v->keyUsage)\n        || tpm_marshal_TPM_KEY_FLAGS(ptr, length, v->keyFlags)\n        || tpm_marshal_TPM_KEY_CONTROL(ptr, length, v->keyControl)\n        || tpm_marshal_TPM_AUTH_DATA_USAGE(ptr, length, v->authDataUsage)\n        || tpm_marshal_TPM_ENC_SCHEME(ptr, length, v->encScheme)\n        || tpm_marshal_TPM_SIG_SCHEME(ptr, length, v->sigScheme)\n        || tpm_marshal_TPM_SECRET(ptr, length, &v->usageAuth)\n        || tpm_marshal_TPM_SECRET(ptr, length, &v->migrationAuth)\n        || (v->keyFlags & TPM_KEY_FLAG_HAS_PCR\n            && tpm_marshal_TPM_PCR_INFO(ptr, length, &v->pcrInfo))\n        || tpm_marshal_BOOL(ptr, length, v->parentPCRStatus)\n        || tpm_marshal_RSA(ptr, length, &v->key)) return -1;\n  }\n  return 0;\n}\n\nint tpm_unmarshal_TPM_KEY_DATA(BYTE **ptr, UINT32 *length, TPM_KEY_DATA *v)\n{\n  if (tpm_unmarshal_TPM_PAYLOAD_TYPE(ptr, length, &v->payload)) return -1;\n  if (v->payload) {\n    if (tpm_unmarshal_TPM_KEY_USAGE(ptr, length, &v->keyUsage)\n        || tpm_unmarshal_TPM_KEY_FLAGS(ptr, length, &v->keyFlags)\n        || tpm_unmarshal_TPM_KEY_CONTROL(ptr, length, &v->keyControl)\n        || tpm_unmarshal_TPM_AUTH_DATA_USAGE(ptr, length, &v->authDataUsage)\n        || tpm_unmarshal_TPM_ENC_SCHEME(ptr, length, &v->encScheme)\n        || tpm_unmarshal_TPM_SIG_SCHEME(ptr, length, &v->sigScheme)\n        || tpm_unmarshal_TPM_SECRET(ptr, length, &v->usageAuth)\n        || tpm_unmarshal_TPM_SECRET(ptr, length, &v->migrationAuth)\n        || (v->keyFlags & TPM_KEY_FLAG_HAS_PCR\n            && tpm_unmarshal_TPM_PCR_INFO(ptr, length, &v->pcrInfo))\n        || tpm_unmarshal_BOOL(ptr, length, &v->parentPCRStatus)\n        || tpm_unmarshal_RSA(ptr, length, &v->key)) return -1;\n    }\n  return 0;\n}\n\nint tpm_marshal_TPM_PUBKEY_DATA(BYTE **ptr, UINT32 *length, TPM_PUBKEY_DATA *v)\n{\n  if (tpm_marshal_BOOL(ptr, length, v->valid)) return -1;\n  if (v->valid) {\n    if (tpm_marshal_TPM_ENC_SCHEME(ptr, length, v->encScheme)\n        || tpm_marshal_TPM_SIG_SCHEME(ptr, length, v->sigScheme)\n        || tpm_marshal_RSAPub(ptr, length, &v->key)) return -1;\n    }\n  return 0;\n}\n\nint tpm_unmarshal_TPM_PUBKEY_DATA(BYTE **ptr, UINT32 *length, TPM_PUBKEY_DATA *v)\n{\n  if (tpm_unmarshal_BOOL(ptr, length, &v->valid)) return -1;\n  if (v->valid) {\n    if (tpm_unmarshal_TPM_ENC_SCHEME(ptr, length, &v->encScheme)\n        || tpm_unmarshal_TPM_SIG_SCHEME(ptr, length, &v->sigScheme)\n        || tpm_unmarshal_RSAPub(ptr, length, &v->key)) return -1;\n    }\n  return 0;\n}\n\nint tpm_marshal_TPM_PERMANENT_DATA(BYTE **ptr, UINT32 *length, TPM_PERMANENT_DATA *v)\n{\n  UINT32 i;\n  if (tpm_marshal_TPM_STRUCTURE_TAG(ptr, length, v->tag)\n      || tpm_marshal_TPM_VERSION(ptr, length, &v->version)\n      || tpm_marshal_TPM_NONCE(ptr, length, &v->tpmProof)\n      || tpm_marshal_TPM_NONCE(ptr, length, &v->ekReset)\n      || tpm_marshal_TPM_SECRET(ptr, length, &v->ownerAuth)\n      || tpm_marshal_TPM_SECRET(ptr, length, &v->operatorAuth)\n      || tpm_marshal_TPM_NONCE(ptr, length, &v->tpmDAASeed)\n      || tpm_marshal_TPM_NONCE(ptr, length, &v->daaProof)\n      || tpm_marshal_TPM_PUBKEY_DATA(ptr, length, &v->manuMaintPub)\n      || tpm_marshal_RSA(ptr, length, &v->endorsementKey)\n      || tpm_marshal_TPM_KEY_DATA(ptr, length, &v->srk)\n      || tpm_marshal_BYTE_ARRAY(ptr, length, v->contextKey, sizeof(v->contextKey))\n      || tpm_marshal_BYTE_ARRAY(ptr, length, v->delegateKey, sizeof(v->contextKey))\n      || tpm_marshal_BYTE_ARRAY(ptr, length, v->daaKey, sizeof(v->contextKey))\n      || tpm_marshal_TPM_ACTUAL_COUNT(ptr, length, v->auditMonotonicCounter)) return -1;\n  for (i = 0; i < TPM_MAX_COUNTERS; i++) {\n    if (tpm_marshal_TPM_COUNTER_VALUE(ptr, length, &v->counters[i])\n        || tpm_marshal_TPM_SECRET(ptr, length, &v->counters[i].usageAuth)\n        || tpm_marshal_BOOL(ptr, length, v->counters[i].valid)) return -1;\n  }\n  for (i = 0; i < TPM_NUM_PCR; i++) {\n    if (tpm_marshal_TPM_PCR_ATTRIBUTES(ptr, length, &v->pcrAttrib[i])) return -1;\n  }\n  for (i = 0; i < TPM_NUM_PCR; i++) {\n    if (tpm_marshal_TPM_PCRVALUE(ptr, length, &v->pcrValue[i])) return -1;\n  }\n  if (tpm_marshal_BYTE_ARRAY(ptr, length, v->ordinalAuditStatus, sizeof(v->ordinalAuditStatus))\n      || tpm_marshal_BYTE_ARRAY(ptr, length, v->rngState, sizeof(v->rngState))) return -1;\n  for (i = 0; i < TPM_NUM_FAMILY_TABLE_ENTRY; i++) {\n    if (tpm_marshal_BOOL(ptr, length, v->familyTable.famRow[i].valid)) return -1;\n    if (v->familyTable.famRow[i].valid) {\n      if (tpm_marshal_TPM_FAMILY_TABLE_ENTRY(ptr, length, &v->familyTable.famRow[i])) return -1;\n    }\n  }\n  for (i = 0; i < TPM_NUM_DELEGATE_TABLE_ENTRY; i++) {\n    if (tpm_marshal_BOOL(ptr, length, v->delegateTable.delRow[i].valid)) return -1;\n    if (v->delegateTable.delRow[i].valid) {\n      if (tpm_marshal_TPM_DELEGATE_TABLE_ROW(ptr, length, &v->delegateTable.delRow[i])) return -1;\n    }\n  }\n  if (tpm_marshal_UINT32(ptr, length, v->lastFamilyID)\n      || tpm_marshal_TPM_CMK_DELEGATE(ptr, length, v->restrictDelegate)\n      || tpm_marshal_UINT32(ptr, length, v->maxNVBufSize)\n      || tpm_marshal_UINT32(ptr, length, v->noOwnerNVWrite)\n      || tpm_marshal_UINT32(ptr, length, v->nvDataSize)\n      || tpm_marshal_BYTE_ARRAY(ptr, length, v->nvData, sizeof(v->nvData))) return -1;\n  for (i = 0; i < TPM_MAX_NVS; i++) {\n    if (tpm_marshal_BOOL(ptr, length, v->nvStorage[i].valid)) return -1;\n    if (v->nvStorage[i].valid) {\n      if (tpm_marshal_TPM_NV_DATA_SENSITIVE(ptr, length, &v->nvStorage[i])) return -1;\n    }\n  }\n  for (i = 0; i < TPM_MAX_KEYS; i++) {\n    if (tpm_marshal_TPM_KEY_DATA(ptr, length, &v->keys[i])) return -1;\n  }\n  if (tpm_marshal_UINT32_ARRAY(ptr, length, v->tis_timeouts, TPM_NUM_TIS_TIMEOUTS)\n      || tpm_marshal_UINT32_ARRAY(ptr, length, v->cmd_durations, TPM_NUM_CMD_DURATIONS)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_PERMANENT_DATA(BYTE **ptr, UINT32 *length, TPM_PERMANENT_DATA *v)\n{\n  UINT32 i;\n  if (tpm_unmarshal_TPM_STRUCTURE_TAG(ptr, length, &v->tag)\n      || tpm_unmarshal_TPM_VERSION(ptr, length, &v->version)\n      || tpm_unmarshal_TPM_NONCE(ptr, length, &v->tpmProof)\n      || tpm_unmarshal_TPM_NONCE(ptr, length, &v->ekReset)\n      || tpm_unmarshal_TPM_SECRET(ptr, length, &v->ownerAuth)\n      || tpm_unmarshal_TPM_SECRET(ptr, length, &v->operatorAuth)\n      || tpm_unmarshal_TPM_NONCE(ptr, length, &v->tpmDAASeed)\n      || tpm_unmarshal_TPM_NONCE(ptr, length, &v->daaProof)\n      || tpm_unmarshal_TPM_PUBKEY_DATA(ptr, length, &v->manuMaintPub)\n      || tpm_unmarshal_RSA(ptr, length, &v->endorsementKey)\n      || tpm_unmarshal_TPM_KEY_DATA(ptr, length, &v->srk)\n      || tpm_unmarshal_BYTE_ARRAY(ptr, length, v->contextKey, sizeof(v->contextKey))\n      || tpm_unmarshal_BYTE_ARRAY(ptr, length, v->delegateKey, sizeof(v->contextKey))\n      || tpm_unmarshal_BYTE_ARRAY(ptr, length, v->daaKey, sizeof(v->contextKey))\n      || tpm_unmarshal_TPM_ACTUAL_COUNT(ptr, length, &v->auditMonotonicCounter)) return -1;\n  for (i = 0; i < TPM_MAX_COUNTERS; i++) {\n    if (tpm_unmarshal_TPM_COUNTER_VALUE(ptr, length, &v->counters[i])\n        || tpm_unmarshal_TPM_SECRET(ptr, length, &v->counters[i].usageAuth)\n        || tpm_unmarshal_BOOL(ptr, length, &v->counters[i].valid)) return -1;\n  }\n  for (i = 0; i < TPM_NUM_PCR; i++) {\n    if (tpm_unmarshal_TPM_PCR_ATTRIBUTES(ptr, length, &v->pcrAttrib[i])) return -1;\n  }\n  for (i = 0; i < TPM_NUM_PCR; i++) {\n    if (tpm_unmarshal_TPM_PCRVALUE(ptr, length, &v->pcrValue[i])) return -1;\n  }\n  if (tpm_unmarshal_BYTE_ARRAY(ptr, length, v->ordinalAuditStatus, sizeof(v->ordinalAuditStatus))\n      || tpm_unmarshal_BYTE_ARRAY(ptr, length, v->rngState, sizeof(v->rngState))) return -1;\n  for (i = 0; i < TPM_NUM_FAMILY_TABLE_ENTRY; i++) {\n    if (tpm_unmarshal_BOOL(ptr, length, &v->familyTable.famRow[i].valid)) return -1;\n    if (v->familyTable.famRow[i].valid) {\n      if (tpm_unmarshal_TPM_FAMILY_TABLE_ENTRY(ptr, length, &v->familyTable.famRow[i])) return -1;\n    }\n  }\n  for (i = 0; i < TPM_NUM_DELEGATE_TABLE_ENTRY; i++) {\n    if (tpm_unmarshal_BOOL(ptr, length, &v->delegateTable.delRow[i].valid)) return -1;\n    if (v->delegateTable.delRow[i].valid) {\n      if (tpm_unmarshal_TPM_DELEGATE_TABLE_ROW(ptr, length, &v->delegateTable.delRow[i])) return -1;\n    }\n  }\n  if (tpm_unmarshal_UINT32(ptr, length, &v->lastFamilyID)\n      || tpm_unmarshal_TPM_CMK_DELEGATE(ptr, length, &v->restrictDelegate)\n      || tpm_unmarshal_UINT32(ptr, length, &v->maxNVBufSize)\n      || tpm_unmarshal_UINT32(ptr, length, &v->noOwnerNVWrite)\n      || tpm_unmarshal_UINT32(ptr, length, &v->nvDataSize)\n      || tpm_unmarshal_BYTE_ARRAY(ptr, length, v->nvData, sizeof(v->nvData))) return -1;\n  for (i = 0; i < TPM_MAX_NVS; i++) {\n    if (tpm_unmarshal_BOOL(ptr, length, &v->nvStorage[i].valid)) return -1;\n    if (v->nvStorage[i].valid) {\n      if (tpm_unmarshal_TPM_NV_DATA_SENSITIVE(ptr, length, &v->nvStorage[i])) return -1;\n    }\n  }\n  for (i = 0; i < TPM_MAX_KEYS; i++) {\n    if (tpm_unmarshal_TPM_KEY_DATA(ptr, length, &v->keys[i])) return -1;\n  }\n  if (tpm_unmarshal_UINT32_ARRAY(ptr, length, v->tis_timeouts, TPM_NUM_TIS_TIMEOUTS)\n      || tpm_unmarshal_UINT32_ARRAY(ptr, length, v->cmd_durations, TPM_NUM_CMD_DURATIONS)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_STCLEAR_DATA(BYTE **ptr, UINT32 *length, TPM_STCLEAR_DATA *v)\n{\n  if (tpm_marshal_TPM_STRUCTURE_TAG(ptr, length, v->tag)\n      || tpm_marshal_TPM_NONCE(ptr, length, &v->contextNonceKey)\n      || tpm_marshal_TPM_COUNT_ID(ptr, length, v->countID)\n      || tpm_marshal_UINT32(ptr, length, v->ownerReference)\n      || tpm_marshal_BOOL(ptr, length, v->disableResetLock)\n      || tpm_marshal_UINT32(ptr, length, v->deferredPhysicalPresence)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_STCLEAR_DATA(BYTE **ptr, UINT32 *length, TPM_STCLEAR_DATA *v)\n{\n  if (tpm_unmarshal_TPM_STRUCTURE_TAG(ptr, length, &v->tag)\n      || tpm_unmarshal_TPM_NONCE(ptr, length, &v->contextNonceKey)\n      || tpm_unmarshal_TPM_COUNT_ID(ptr, length, &v->countID)\n      || tpm_unmarshal_UINT32(ptr, length, &v->ownerReference)\n      || tpm_unmarshal_BOOL(ptr, length, &v->disableResetLock)\n      || tpm_unmarshal_UINT32(ptr, length, &v->deferredPhysicalPresence)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_SESSION_DATA(BYTE **ptr, UINT32 *length, TPM_SESSION_DATA *v)\n{\n  if (tpm_marshal_BYTE(ptr, length, v->type)\n      || tpm_marshal_TPM_NONCE(ptr, length, &v->nonceEven)\n      || tpm_marshal_TPM_NONCE(ptr, length, &v->lastNonceEven)\n      || tpm_marshal_TPM_SECRET(ptr, length, &v->sharedSecret)\n      || tpm_marshal_TPM_HANDLE(ptr, length, v->handle)\n      || tpm_marshal_TPM_ENTITY_TYPE(ptr, length, v->entityType)\n      || (v->type == TPM_ST_DSAP\n          && (tpm_marshal_TPM_DELEGATIONS(ptr, length, &v->permissions)\n              || tpm_marshal_TPM_FAMILY_ID(ptr, length, v->familyID)))\n      || (v->type == TPM_ST_TRANSPORT \n          && tpm_marshal_TPM_TRANSPORT_INTERNAL(ptr, length, &v->transInternal))) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_SESSION_DATA(BYTE **ptr, UINT32 *length, TPM_SESSION_DATA *v)\n{\n  if (tpm_unmarshal_BYTE(ptr, length, &v->type)\n      || tpm_unmarshal_TPM_NONCE(ptr, length, &v->nonceEven)\n      || tpm_unmarshal_TPM_NONCE(ptr, length, &v->lastNonceEven)\n      || tpm_unmarshal_TPM_SECRET(ptr, length, &v->sharedSecret)\n      || tpm_unmarshal_TPM_HANDLE(ptr, length, &v->handle)\n      || tpm_unmarshal_TPM_ENTITY_TYPE(ptr, length, &v->entityType)\n      || (v->type == TPM_ST_DSAP\n          && (tpm_unmarshal_TPM_DELEGATIONS(ptr, length, &v->permissions)\n              || tpm_unmarshal_TPM_FAMILY_ID(ptr, length, &v->familyID)))\n      || (v->type == TPM_ST_TRANSPORT \n          && tpm_unmarshal_TPM_TRANSPORT_INTERNAL(ptr, length, &v->transInternal))) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_STANY_DATA(BYTE **ptr, UINT32 *length, TPM_STANY_DATA *v)\n{\n  UINT32 i;\n  if (tpm_marshal_TPM_STRUCTURE_TAG(ptr, length, v->tag)\n      || tpm_marshal_TPM_NONCE(ptr, length, &v->contextNonceSession)\n      || tpm_marshal_TPM_DIGEST(ptr, length, &v->auditDigest)\n      || tpm_marshal_BOOL(ptr, length, v->auditSession)\n      || tpm_marshal_TPM_CURRENT_TICKS(ptr, length, &v->currentTicks)\n      || tpm_marshal_UINT32(ptr, length, v->contextCount)\n      || tpm_marshal_UINT32_ARRAY(ptr, length, v->contextList, TPM_MAX_SESSION_LIST)) return -1;\n  for (i = 0; i < TPM_MAX_SESSIONS; i++) {\n    if (tpm_marshal_TPM_SESSION_DATA(ptr, length, &v->sessions[i])) return -1;\n  }\n  for (i = 0; i < TPM_MAX_SESSIONS_DAA; i++) {\n    if (tpm_marshal_TPM_DAA_SESSION_DATA(ptr, length, &v->sessionsDAA[i])) return -1;\n  }\n  if (tpm_marshal_DAAHANDLE(ptr, length, v->currentDAA)\n      || tpm_marshal_TPM_TRANSHANDLE(ptr, length, v->transExclusive)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_STANY_DATA(BYTE **ptr, UINT32 *length, TPM_STANY_DATA *v)\n{\n  UINT32 i;\n  if (tpm_unmarshal_TPM_STRUCTURE_TAG(ptr, length, &v->tag)\n      || tpm_unmarshal_TPM_NONCE(ptr, length, &v->contextNonceSession)\n      || tpm_unmarshal_TPM_DIGEST(ptr, length, &v->auditDigest)\n      || tpm_unmarshal_BOOL(ptr, length, &v->auditSession)\n      || tpm_unmarshal_TPM_CURRENT_TICKS(ptr, length, &v->currentTicks)\n      || tpm_unmarshal_UINT32(ptr, length, &v->contextCount)\n      || tpm_unmarshal_UINT32_ARRAY(ptr, length, v->contextList, TPM_MAX_SESSION_LIST)) return -1;\n  for (i = 0; i < TPM_MAX_SESSIONS; i++) {\n    if (tpm_unmarshal_TPM_SESSION_DATA(ptr, length, &v->sessions[i])) return -1;\n  }\n  for (i = 0; i < TPM_MAX_SESSIONS_DAA; i++) {\n    if (tpm_unmarshal_TPM_DAA_SESSION_DATA(ptr, length, &v->sessionsDAA[i])) return -1;\n  }\n  if (tpm_unmarshal_DAAHANDLE(ptr, length, &v->currentDAA)\n      || tpm_unmarshal_TPM_TRANSHANDLE(ptr, length, &v->transExclusive)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_DATA(BYTE **ptr, UINT32 *length, TPM_DATA *v)\n{\n  if (tpm_marshal_TPM_PERMANENT_FLAGS(ptr, length, &v->permanent.flags)\n      || tpm_marshal_BOOL(ptr, length, v->permanent.flags.selfTestSucceeded)\n      || tpm_marshal_BOOL(ptr, length, v->permanent.flags.owned)\n      || tpm_marshal_TPM_PERMANENT_DATA(ptr, length, &v->permanent.data)\n      || tpm_marshal_TPM_STCLEAR_FLAGS(ptr, length, &v->stclear.flags)\n      || tpm_marshal_TPM_STCLEAR_DATA(ptr, length, &v->stclear.data)\n      || tpm_marshal_TPM_STANY_DATA(ptr, length, &v->stany.data)) return -1;\n  return 0;\n}\n\nint tpm_unmarshal_TPM_DATA(BYTE **ptr, UINT32 *length, TPM_DATA *v)\n{\n  if (tpm_unmarshal_TPM_PERMANENT_FLAGS(ptr, length, &v->permanent.flags)\n      || tpm_unmarshal_BOOL(ptr, length, &v->permanent.flags.selfTestSucceeded)\n      || tpm_unmarshal_BOOL(ptr, length, &v->permanent.flags.owned)\n      || tpm_unmarshal_TPM_PERMANENT_DATA(ptr, length, &v->permanent.data)\n      || tpm_unmarshal_TPM_STCLEAR_FLAGS(ptr, length, &v->stclear.flags)\n      || tpm_unmarshal_TPM_STCLEAR_DATA(ptr, length, &v->stclear.data)\n      || tpm_unmarshal_TPM_STANY_DATA(ptr, length, &v->stany.data)) return -1;\n  return 0;\n}\n\nint tpm_marshal_TPM_RESPONSE(BYTE **ptr, UINT32 *length, TPM_RESPONSE *v)\n{\n  if (tpm_marshal_TPM_TAG(ptr, length, v->tag)\n      || tpm_marshal_UINT32(ptr, length, v->size)\n      || tpm_marshal_TPM_RESULT(ptr, length, v->result)\n      || tpm_marshal_BLOB(ptr, length, v->param, v->paramSize)) return -1;\n  if (v->tag == TPM_TAG_RSP_AUTH2_COMMAND) {\n    if (tpm_marshal_TPM_AUTH(ptr, length, v->auth1)\n        || tpm_marshal_TPM_AUTH(ptr, length, v->auth2)) return -1;\n  } else if (v->tag == TPM_TAG_RSP_AUTH1_COMMAND) {\n    if (tpm_marshal_TPM_AUTH(ptr, length, v->auth1)) return -1;\n  }\n  return 0;\n}\n\nint tpm_unmarshal_TPM_REQUEST(BYTE **ptr, UINT32 *length, TPM_REQUEST *v)\n{\n  if (tpm_unmarshal_TPM_TAG(ptr, length, &v->tag)\n      || tpm_unmarshal_UINT32(ptr, length, &v->size)\n      || tpm_unmarshal_TPM_COMMAND_CODE(ptr, length, &v->ordinal)) return -1;\n  v->param = *ptr;\n  v->paramSize = *length;\n  if (v->tag == TPM_TAG_RQU_AUTH2_COMMAND) {\n    if (*length < 2 * 45) return -1;\n    v->paramSize = *length - 2 * 45;\n    if (tpm_unmarshal_BLOB(ptr, length, &v->param, v->paramSize)\n        || tpm_unmarshal_TPM_AUTH(ptr, length, &v->auth1)\n        || tpm_unmarshal_TPM_AUTH(ptr, length, &v->auth2)) return -1;\n    v->auth1.ordinal = v->ordinal;\n    v->auth2.ordinal = v->ordinal;\n  } else if (v->tag == TPM_TAG_RQU_AUTH1_COMMAND) {\n    if (*length < 45) return -1;\n    v->paramSize = *length - 45;\n    if (tpm_unmarshal_BLOB(ptr, length, &v->param, v->paramSize)\n        || tpm_unmarshal_TPM_AUTH(ptr, length, &v->auth1)) return -1;\n    v->auth1.ordinal = v->ordinal;\n    v->auth2.authHandle = TPM_INVALID_HANDLE;\n  } else {\n    v->auth1.authHandle = TPM_INVALID_HANDLE;\n    v->auth2.authHandle = TPM_INVALID_HANDLE;\n  }\n  return 0;\n}\n"
  },
  {
    "path": "tpm/tpm_marshalling.h",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: tpm_marshalling.h 384 2010-02-17 14:17:43Z mast $\n */\n\n#ifndef _TPM_MARSHALLING_H_\n#define _TPM_MARSHALLING_H_\n\n#include \"tpm_emulator.h\"\n#include \"tpm_structures.h\"\n\n/*\n * The following functions perform the data marshalling of all\n * TPM structures (as defined in [TPM_Part2]) which are used\n * either as an input or an output parameter by one of the\n * TPM commands (as defined in [TPM_Part3]).\n */\n\n/**\n * tpm_marshal_TYPE - marshals a value of type TYPE\n * @ptr: target buffer to store the marshalled value into\n * @length: length of the target buffer\n * @v: value to marshal\n * Returns: 0 on success, -1 otherwise\n *\n * Description: Performs the data marshalling for values of type TYPE.\n * On success 0 is returned and the values of ptr as well as length are\n * updated (i.e., ptr := ptr + sizeof(marshalled value) and length :=\n * length - sizeof(marshalled value)). In case of an error, -1 is\n * returned and the values of ptr and length are undefined.\n */\n\n/**\n * tpm_unmarshal_TYPE - unmarshals a value of type TYPE\n * @ptr: source buffer containing the marshalled value\n * @length: length of the source buffer\n * @v: variable to store the unmarshalled value into\n * Returns: 0 on success, -1 otherwise\n *\n * Description: Performs the data unmarshalling for values of type TYPE.\n * On success 0 is returned and the values of ptr as well as length are\n * updated (i.e., ptr := ptr + sizeof(marshalled value) and length :=\n * length - sizeof(marshalled value)). In case of an error, -1 is\n * returned and the values of ptr and length are undefined.\n */\n\nstatic inline int tpm_marshal_BYTE(BYTE **ptr, UINT32 *length, BYTE v)\n{\n  if (*length < 1) return -1;\n  **ptr = v;\n  *ptr += 1; *length -= 1;\n  return 0;\n}\n\nstatic inline int tpm_unmarshal_BYTE(BYTE **ptr, UINT32 *length, BYTE *v)\n{\n  if (*length < 1) return -1;\n  *v = **ptr;\n  *ptr += 1; *length -= 1;\n  return 0;\n}\n\nstatic inline int tpm_marshal_UINT16(BYTE **ptr, UINT32 *length, UINT16 v)\n{\n  if (*length < 2) return -1;\n  (*ptr)[0] = (BYTE)((v >> 8) & 0xff); \n  (*ptr)[1] = (BYTE)(v & 0xff);\n  *ptr += 2; *length -= 2;\n  return 0;\n}\n\nstatic inline int tpm_unmarshal_UINT16(BYTE **ptr, UINT32 *length, UINT16 *v)\n{\n  if (*length < 2) return -1;\n  *v = (((UINT16)(*ptr)[0] << 8) | (*ptr)[1]);\n  *ptr += 2; *length -= 2;\n  return 0;\n}\n\nstatic inline int tpm_marshal_UINT32(BYTE **ptr, UINT32 *length, UINT32 v)\n{\n  if (*length < 4) return -1;\n  (*ptr)[0] = (BYTE)((v >> 24) & 0xff); (*ptr)[1] = (BYTE)((v >> 16) & 0xff);\n  (*ptr)[2] = (BYTE)((v >>  8) & 0xff); (*ptr)[3] = (BYTE)(v & 0xff);\n  *ptr += 4; *length -= 4;\n  return 0;\n}\n\nstatic inline int tpm_unmarshal_UINT32(BYTE **ptr, UINT32 *length, UINT32 *v)\n{\n  if (*length < 4) return -1;\n  *v = (((UINT32)(*ptr)[0] << 24) | ((UINT32)(*ptr)[1] << 16) | \n        ((UINT32)(*ptr)[2] <<  8) | (*ptr)[3]);\n  *ptr += 4; *length -= 4;\n  return 0;\n}\n\nstatic inline int tpm_marshal_UINT64(BYTE **ptr, UINT32 *length, UINT64 v)\n{\n  if (*length < 8) return -1;\n  (*ptr)[0] = (BYTE)((v >> 56) & 0xff); (*ptr)[1] = (BYTE)((v >> 48) & 0xff);\n  (*ptr)[2] = (BYTE)((v >> 40) & 0xff); (*ptr)[3] = (BYTE)((v >> 32) & 0xff);\n  (*ptr)[4] = (BYTE)((v >> 24) & 0xff); (*ptr)[5] = (BYTE)((v >> 16) & 0xff);\n  (*ptr)[6] = (BYTE)((v >>  8) & 0xff); (*ptr)[7] = (BYTE)(v & 0xff);\n  *ptr += 8; *length -= 8;\n  return 0;\n}\n\nstatic inline int tpm_unmarshal_UINT64(BYTE **ptr, UINT32 *length, UINT64 *v)\n{\n  if (*length < 8) return -1;\n  *v = (((UINT64)(*ptr)[0] << 56) | ((UINT64)(*ptr)[1] << 48) |\n        ((UINT64)(*ptr)[2] << 40) | ((UINT64)(*ptr)[3] << 32) |\n        ((UINT64)(*ptr)[4] << 24) | ((UINT64)(*ptr)[5] << 16) |\n        ((UINT64)(*ptr)[6] <<  8) | (*ptr)[7]);\n  *ptr += 8; *length -= 8;\n  return 0;\n}\n\nstatic inline int tpm_marshal_BLOB(BYTE **ptr, UINT32 *ptr_length,\n                                   BYTE *b, UINT32 b_length)\n{\n  if (*ptr_length < b_length) return -1;\n  if (b_length) memcpy(*ptr, b, b_length);\n  *ptr += b_length; *ptr_length -= b_length;\n  return 0;\n}\n\nstatic inline int tpm_unmarshal_BLOB(BYTE **ptr, UINT32 *ptr_length,\n                                     BYTE **b, UINT32 b_length)\n{\n  if (*ptr_length < b_length) return -1;\n  *b = (b_length) ? *ptr : NULL;\n  *ptr += b_length; *ptr_length -= b_length;\n  return 0;\n}\n\nstatic inline int tpm_marshal_BYTE_ARRAY(BYTE **ptr, UINT32 *ptr_length,\n                                         BYTE *b, UINT32 b_length)\n{\n  if (*ptr_length < b_length) return -1;\n  memcpy(*ptr, b, b_length);\n  *ptr += b_length; *ptr_length -= b_length;\n  return 0;\n}\n\nstatic inline int tpm_unmarshal_BYTE_ARRAY(BYTE **ptr, UINT32 *ptr_length,\n                                           BYTE *b, UINT32 b_length)\n{\n  if (*ptr_length < b_length) return -1;\n  if (b_length) memcpy(b, *ptr, b_length);\n  *ptr += b_length; *ptr_length -= b_length;\n  return 0;\n}\n\nstatic inline int tpm_marshal_BOOL(BYTE **ptr, UINT32 *length, BOOL v)\n{\n  if (*length < 1) return -1;\n  **ptr = v & 0x01;\n  *ptr += 1; *length -= 1;\n  return 0;\n}\n\nstatic inline int tpm_unmarshal_BOOL(BYTE **ptr, UINT32 *length, BOOL *v)\n{\n  if (*length < 1 || (**ptr & 0xfe)) return -1;\n  *v = **ptr;\n  *ptr += 1; *length -= 1;\n  return 0;\n}\n\n#define tpm_marshal_BOOL_ARRAY                 tpm_marshal_BYTE_ARRAY\n#define tpm_unmarshal_BOOL_ARRAY               tpm_unmarshal_BYTE_ARRAY\n#define tpm_marshal_TPM_AUTH_DATA_USAGE        tpm_marshal_BYTE\n#define tpm_unmarshal_TPM_AUTH_DATA_USAGE      tpm_unmarshal_BYTE\n#define tpm_marshal_TPM_PAYLOAD_TYPE           tpm_marshal_BYTE\n#define tpm_unmarshal_TPM_PAYLOAD_TYPE         tpm_unmarshal_BYTE\n#define tpm_marshal_TPM_LOCALITY_SELECTION     tpm_marshal_BYTE\n#define tpm_unmarshal_TPM_LOCALITY_SELECTION   tpm_unmarshal_BYTE\n#define tpm_marshal_TPM_TAG                    tpm_marshal_UINT16\n#define tpm_unmarshal_TPM_TAG                  tpm_unmarshal_UINT16\n#define tpm_marshal_TPM_PROTOCOL_ID            tpm_marshal_UINT16\n#define tpm_unmarshal_TPM_PROTOCOL_ID          tpm_unmarshal_UINT16\n#define tpm_marshal_TPM_STARTUP_TYPE           tpm_marshal_UINT16\n#define tpm_unmarshal_TPM_STARTUP_TYPE         tpm_unmarshal_UINT16\n#define tpm_marshal_TPM_ENC_SCHEME             tpm_marshal_UINT16\n#define tpm_unmarshal_TPM_ENC_SCHEME           tpm_unmarshal_UINT16\n#define tpm_marshal_TPM_SIG_SCHEME             tpm_marshal_UINT16\n#define tpm_unmarshal_TPM_SIG_SCHEME           tpm_unmarshal_UINT16\n#define tpm_marshal_TPM_MIGRATE_SCHEME         tpm_marshal_UINT16\n#define tpm_unmarshal_TPM_MIGRATE_SCHEME       tpm_unmarshal_UINT16\n#define tpm_marshal_TPM_PHYSICAL_PRESENCE      tpm_marshal_UINT16\n#define tpm_unmarshal_TPM_PHYSICAL_PRESENCE    tpm_unmarshal_UINT16\n#define tpm_marshal_TPM_ENTITY_TYPE            tpm_marshal_UINT16\n#define tpm_unmarshal_TPM_ENTITY_TYPE          tpm_unmarshal_UINT16\n#define tpm_marshal_TPM_KEY_USAGE              tpm_marshal_UINT16\n#define tpm_unmarshal_TPM_KEY_USAGE            tpm_unmarshal_UINT16\n#define tpm_marshal_TPM_STRUCTURE_TAG          tpm_marshal_UINT16\n#define tpm_unmarshal_TPM_STRUCTURE_TAG        tpm_unmarshal_UINT16\n#define tpm_marshal_TPM_PLATFORM_SPECIFIC      tpm_marshal_UINT16\n#define tpm_unmarshal_TPM_PLATFORM_SPECIFIC    tpm_unmarshal_UINT16\n#define tpm_marshal_TPM_EK_TYPE                tpm_marshal_UINT16\n#define tpm_unmarshal_TPM_EK_TYPE              tpm_unmarshal_UINT16\n#define tpm_marshal_TPM_COMMAND_CODE           tpm_marshal_UINT32\n#define tpm_unmarshal_TPM_COMMAND_CODE         tpm_unmarshal_UINT32\n#define tpm_marshal_TPM_CAPABILITY_AREA        tpm_marshal_UINT32\n#define tpm_unmarshal_TPM_CAPABILITY_AREA      tpm_unmarshal_UINT32\n#define tpm_marshal_TPM_KEY_FLAGS              tpm_marshal_UINT32\n#define tpm_unmarshal_TPM_KEY_FLAGS            tpm_unmarshal_UINT32\n#define tpm_marshal_TPM_ALGORITHM_ID           tpm_marshal_UINT32\n#define tpm_unmarshal_TPM_ALGORITHM_ID         tpm_unmarshal_UINT32\n#define tpm_marshal_TPM_MODIFIER_INDICATOR     tpm_marshal_UINT32\n#define tpm_unmarshal_TPM_MODIFIER_INDICATOR   tpm_unmarshal_UINT32\n#define tpm_marshal_TPM_ACTUAL_COUNT           tpm_marshal_UINT32\n#define tpm_unmarshal_TPM_ACTUAL_COUNT         tpm_unmarshal_UINT32\n#define tpm_marshal_TPM_TRANSPORT_ATTRIBUTES   tpm_marshal_UINT32\n#define tpm_unmarshal_TPM_TRANSPORT_ATTRIBUTES tpm_unmarshal_UINT32\n#define tpm_marshal_TPM_AUTHHANDLE             tpm_marshal_UINT32\n#define tpm_unmarshal_TPM_AUTHHANDLE           tpm_unmarshal_UINT32\n#define tpm_marshal_TPM_RESULT                 tpm_marshal_UINT32\n#define tpm_unmarshal_TPM_RESULT               tpm_unmarshal_UINT32\n#define tpm_marshal_TPM_DIRINDEX               tpm_marshal_UINT32\n#define tpm_unmarshal_TPM_DIRINDEX             tpm_unmarshal_UINT32\n#define tpm_marshal_TPM_KEY_HANDLE             tpm_marshal_UINT32\n#define tpm_unmarshal_TPM_KEY_HANDLE           tpm_unmarshal_UINT32\n#define tpm_marshal_TPM_PCRINDEX               tpm_marshal_UINT32\n#define tpm_unmarshal_TPM_PCRINDEX             tpm_unmarshal_UINT32\n#define tpm_marshal_TPM_RESOURCE_TYPE          tpm_marshal_UINT32\n#define tpm_unmarshal_TPM_RESOURCE_TYPE        tpm_unmarshal_UINT32\n#define tpm_marshal_TPM_KEY_CONTROL            tpm_marshal_UINT32\n#define tpm_unmarshal_TPM_KEY_CONTROL          tpm_unmarshal_UINT32  \n#define tpm_marshal_TPM_NV_INDEX               tpm_marshal_UINT32\n#define tpm_unmarshal_TPM_NV_INDEX             tpm_unmarshal_UINT32\n#define tpm_marshal_TPM_FAMILY_ID              tpm_marshal_UINT32\n#define tpm_unmarshal_TPM_FAMILY_ID            tpm_unmarshal_UINT32\n#define tpm_marshal_TPM_FAMILY_VERIFICATION    tpm_marshal_UINT32\n#define tpm_unmarshal_TPM_FAMILY_VERIFICATION  tpm_unmarshal_UINT32\n#define tpm_marshal_TPM_STARTUP_EFFECTS        tpm_marshal_UINT32\n#define tpm_unmarshal_TPM_STARTUP_EFFECTS      tpm_unmarshal_UINT32\n#define tpm_marshal_TPM_SYM_MODE               tpm_marshal_UINT32\n#define tpm_unmarshal_TPM_SYM_MODE             tpm_unmarshal_UINT32\n#define tpm_marshal_TPM_FAMILY_FLAGS           tpm_marshal_UINT32\n#define tpm_unmarshal_TPM_FAMILY_FLAGS         tpm_unmarshal_UINT32\n#define tpm_marshal_TPM_DELEGATE_INDEX         tpm_marshal_UINT32\n#define tpm_unmarshal_TPM_DELEGATE_INDEX       tpm_unmarshal_UINT32\n#define tpm_marshal_TPM_COUNT_ID               tpm_marshal_UINT32\n#define tpm_unmarshal_TPM_COUNT_ID             tpm_unmarshal_UINT32\n#define tpm_marshal_TPM_TRANSHANDLE            tpm_marshal_UINT32\n#define tpm_unmarshal_TPM_TRANSHANDLE          tpm_unmarshal_UINT32\n#define tpm_marshal_TPM_HANDLE                 tpm_marshal_UINT32\n#define tpm_unmarshal_TPM_HANDLE               tpm_unmarshal_UINT32\n#define tpm_marshal_TPM_FAMILY_OPERATION       tpm_marshal_UINT32\n#define tpm_unmarshal_TPM_FAMILY_OPERATION     tpm_unmarshal_UINT32\n#define tpm_marshal_TPM_CMK_DELEGATE           tpm_marshal_UINT32\n#define tpm_unmarshal_TPM_CMK_DELEGATE         tpm_unmarshal_UINT32\n#define tpm_marshal_TPM_REDIR_COMMAND          tpm_marshal_UINT32\n#define tpm_unmarshal_TPM_REDIR_COMMAND        tpm_unmarshal_UINT32\n#define tpm_marshal_DAAHANDLE                  tpm_marshal_UINT32\n#define tpm_unmarshal_DAAHANDLE                tpm_unmarshal_UINT32\n\nint tpm_marshal_UINT32_ARRAY(BYTE **ptr, UINT32 *length, UINT32 *v, UINT32 n);\nint tpm_unmarshal_UINT32_ARRAY(BYTE **ptr, UINT32 *length, UINT32 *v, UINT32 n);\n\nint tpm_marshal_TPM_STRUCT_VER(BYTE **ptr, UINT32 *length, TPM_STRUCT_VER *v);\nint tpm_unmarshal_TPM_STRUCT_VER(BYTE **ptr, UINT32 *length, TPM_STRUCT_VER *v);\n\nint tpm_marshal_TPM_VERSION(BYTE **ptr, UINT32 *length, TPM_VERSION *v);\nint tpm_unmarshal_TPM_VERSION(BYTE **ptr, UINT32 *length, TPM_VERSION *v);\n\nint tpm_marshal_TPM_DIGEST(BYTE **ptr, UINT32 *length, TPM_DIGEST *v);\nint tpm_unmarshal_TPM_DIGEST(BYTE **ptr, UINT32 *length, TPM_DIGEST *v);\n\n#define tpm_marshal_TPM_CHOSENID_HASH          tpm_marshal_TPM_DIGEST\n#define tpm_unmarshal_TPM_CHOSENID_HASH        tpm_unmarshal_TPM_DIGEST\n#define tpm_marshal_TPM_COMPOSITE_HASH         tpm_marshal_TPM_DIGEST\n#define tpm_unmarshal_TPM_COMPOSITE_HASH       tpm_unmarshal_TPM_DIGEST\n#define tpm_marshal_TPM_DIRVALUE               tpm_marshal_TPM_DIGEST\n#define tpm_unmarshal_TPM_DIRVALUE             tpm_unmarshal_TPM_DIGEST\n#define tpm_marshal_TPM_HMAC                   tpm_marshal_TPM_DIGEST\n#define tpm_unmarshal_TPM_HMAC                 tpm_unmarshal_TPM_DIGEST\n#define tpm_marshal_TPM_PCRVALUE               tpm_marshal_TPM_DIGEST\n#define tpm_unmarshal_TPM_PCRVALUE             tpm_unmarshal_TPM_DIGEST\n\nint tpm_marshal_TPM_PCRVALUE_ARRAY(BYTE **ptr, UINT32 *length, TPM_PCRVALUE *v, UINT32 n);\nint tpm_unmarshal_TPM_PCRVALUE_ARRAY(BYTE **ptr, UINT32 *length, TPM_PCRVALUE *v, UINT32 n);\n\nint tpm_marshal_TPM_NONCE(BYTE **ptr, UINT32 *length, TPM_NONCE *v);\nint tpm_unmarshal_TPM_NONCE(BYTE **ptr, UINT32 *length, TPM_NONCE *v);\n\nint tpm_marshal_TPM_AUTHDATA(BYTE **ptr, UINT32 *length, TPM_AUTHDATA *v);\nint tpm_unmarshal_TPM_AUTHDATA(BYTE **ptr, UINT32 *length, TPM_AUTHDATA *v);\n\n#define tpm_marshal_TPM_SECRET                 tpm_marshal_TPM_AUTHDATA\n#define tpm_unmarshal_TPM_SECRET               tpm_unmarshal_TPM_AUTHDATA\n#define tpm_marshal_TPM_ENCAUTH                tpm_marshal_TPM_AUTHDATA\n#define tpm_unmarshal_TPM_ENCAUTH              tpm_unmarshal_TPM_AUTHDATA\n\nint tpm_marshal_TPM_AUTH(BYTE **ptr, UINT32 *length, TPM_AUTH *v);\nint tpm_unmarshal_TPM_AUTH(BYTE **ptr, UINT32 *length, TPM_AUTH *v);\n\nint tpm_marshal_TPM_KEY_HANDLE_LIST(BYTE **ptr, UINT32 *length, TPM_KEY_HANDLE_LIST *v);\n\nint tpm_marshal_TPM_CHANGEAUTH_VALIDATE(BYTE **ptr, UINT32 *length, TPM_CHANGEAUTH_VALIDATE *v);\nint tpm_unmarshal_TPM_CHANGEAUTH_VALIDATE(BYTE **ptr, UINT32 *length, TPM_CHANGEAUTH_VALIDATE *v);\n\nint tpm_marshal_TPM_COUNTER_VALUE(BYTE **ptr, UINT32 *length, TPM_COUNTER_VALUE *v);\nint tpm_unmarshal_TPM_COUNTER_VALUE(BYTE **ptr, UINT32 *length, TPM_COUNTER_VALUE *v);\n\nint tpm_marshal_TPM_PCR_SELECTION(BYTE **ptr, UINT32 *length, TPM_PCR_SELECTION *v);\nint tpm_unmarshal_TPM_PCR_SELECTION(BYTE **ptr, UINT32 *length, TPM_PCR_SELECTION *v);\n\nint tpm_marshal_TPM_PCR_COMPOSITE(BYTE **ptr, UINT32 *length, TPM_PCR_COMPOSITE *v);\nint tpm_unmarshal_TPM_PCR_COMPOSITE(BYTE **ptr, UINT32 *length, TPM_PCR_COMPOSITE *v);\n\nint tpm_marshal_TPM_PCR_INFO(BYTE **ptr, UINT32 *length, TPM_PCR_INFO *v);\nint tpm_unmarshal_TPM_PCR_INFO(BYTE **ptr, UINT32 *length, TPM_PCR_INFO *v);\n\nint tpm_marshal_TPM_PCR_INFO_SHORT(BYTE **ptr, UINT32 *length, TPM_PCR_INFO_SHORT *v);\nint tpm_unmarshal_TPM_PCR_INFO_SHORT(BYTE **ptr, UINT32 *length, TPM_PCR_INFO_SHORT *v);\n\nint tpm_marshal_TPM_PCR_ATTRIBUTES(BYTE **ptr, UINT32 *length, TPM_PCR_ATTRIBUTES *v);\nint tpm_unmarshal_TPM_PCR_ATTRIBUTES(BYTE **ptr, UINT32 *length, TPM_PCR_ATTRIBUTES *v);\n\nint tpm_marshal_TPM_STORED_DATA(BYTE **ptr, UINT32 *length, TPM_STORED_DATA *v);\nint tpm_unmarshal_TPM_STORED_DATA(BYTE **ptr, UINT32 *length, TPM_STORED_DATA *v);\n\nint tpm_marshal_TPM_SEALED_DATA(BYTE **ptr, UINT32 *length, TPM_SEALED_DATA *v);\nint tpm_unmarshal_TPM_SEALED_DATA(BYTE **ptr, UINT32 *length, TPM_SEALED_DATA *v);\n\nint tpm_marshal_TPM_SYMMETRIC_KEY(BYTE **ptr, UINT32 *length, TPM_SYMMETRIC_KEY *v);\nint tpm_unmarshal_TPM_SYMMETRIC_KEY(BYTE **ptr, UINT32 *length, TPM_SYMMETRIC_KEY *v);\n\nint tpm_marshal_TPM_SYMMETRIC_KEY_PARMS(BYTE **ptr, UINT32 *length, TPM_SYMMETRIC_KEY_PARMS *v);\nint tpm_unmarshal_TPM_SYMMETRIC_KEY_PARMS(BYTE **ptr, UINT32 *length, TPM_SYMMETRIC_KEY_PARMS *v);\n\nint tpm_marshal_TPM_RSA_KEY_PARMS(BYTE **ptr, UINT32 *length, TPM_RSA_KEY_PARMS *v);\nint tpm_unmarshal_TPM_RSA_KEY_PARMS(BYTE **ptr, UINT32 *length, TPM_RSA_KEY_PARMS *v);\n\nint tpm_marshal_TPM_KEY_PARMS(BYTE **ptr, UINT32 *length, TPM_KEY_PARMS *v);\nint tpm_unmarshal_TPM_KEY_PARMS(BYTE **ptr, UINT32 *length, TPM_KEY_PARMS *v);\n\nint tpm_marshal_TPM_STORE_PUBKEY(BYTE **ptr, UINT32 *length, TPM_STORE_PUBKEY *v);\nint tpm_unmarshal_TPM_STORE_PUBKEY(BYTE **ptr, UINT32 *length, TPM_STORE_PUBKEY *v);\n\nint tpm_marshal_TPM_KEY(BYTE **ptr, UINT32 *length, TPM_KEY *v);\nint tpm_unmarshal_TPM_KEY(BYTE **ptr, UINT32 *length, TPM_KEY *v);\n\nint tpm_marshal_TPM_PUBKEY(BYTE **ptr, UINT32 *length, TPM_PUBKEY *v);\nint tpm_unmarshal_TPM_PUBKEY(BYTE **ptr, UINT32 *length, TPM_PUBKEY *v);\n\nint tpm_marshal_TPM_STORE_PRIVKEY(BYTE **ptr, UINT32 *length, TPM_STORE_PRIVKEY *v);\nint tpm_unmarshal_TPM_STORE_PRIVKEY(BYTE **ptr, UINT32 *length, TPM_STORE_PRIVKEY *v);\n\nint tpm_marshal_TPM_STORE_ASYMKEY(BYTE **ptr, UINT32 *length, TPM_STORE_ASYMKEY *v);\nint tpm_unmarshal_TPM_STORE_ASYMKEY(BYTE **ptr, UINT32 *length, TPM_STORE_ASYMKEY *v);\n\nint tpm_marshal_TPM_MIGRATIONKEYAUTH(BYTE **ptr, UINT32 *length, TPM_MIGRATIONKEYAUTH *v);\nint tpm_unmarshal_TPM_MIGRATIONKEYAUTH(BYTE **ptr, UINT32 *length, TPM_MIGRATIONKEYAUTH *v);\n\nint tpm_marshal_TPM_CERTIFY_INFO(BYTE **ptr, UINT32 *length, TPM_CERTIFY_INFO *v);\nint tpm_unmarshal_TPM_CERTIFY_INFO(BYTE **ptr, UINT32 *length, TPM_CERTIFY_INFO *v);\n\nint tpm_marshal_TPM_IDENTITY_CONTENTS(BYTE **ptr, UINT32 *length, TPM_IDENTITY_CONTENTS *v);\nint tpm_unmarshal_TPM_IDENTITY_CONTENTS(BYTE **ptr, UINT32 *length, TPM_IDENTITY_CONTENTS *v);\n\nint tpm_marshal_TPM_CURRENT_TICKS(BYTE **ptr, UINT32 *length, TPM_CURRENT_TICKS *v);\nint tpm_unmarshal_TPM_CURRENT_TICKS(BYTE **ptr, UINT32 *length, TPM_CURRENT_TICKS *v);\n\nint tpm_marshal_TPM_TRANSPORT_PUBLIC(BYTE **ptr, UINT32 *length, TPM_TRANSPORT_PUBLIC *v);\nint tpm_unmarshal_TPM_TRANSPORT_PUBLIC(BYTE **ptr, UINT32 *length, TPM_TRANSPORT_PUBLIC *v);\n\nint tpm_marshal_TPM_TRANSPORT_INTERNAL(BYTE **ptr, UINT32 *length, TPM_TRANSPORT_INTERNAL *v);\nint tpm_unmarshal_TPM_TRANSPORT_INTERNAL(BYTE **ptr, UINT32 *length, TPM_TRANSPORT_INTERNAL *v);\n\nint tpm_marshal_TPM_CONTEXT_BLOB(BYTE **ptr, UINT32 *length, TPM_CONTEXT_BLOB *v);\nint tpm_unmarshal_TPM_CONTEXT_BLOB(BYTE **ptr, UINT32 *length, TPM_CONTEXT_BLOB *v);\n\nint tpm_marshal_TPM_CONTEXT_SENSITIVE(BYTE **ptr, UINT32 *length, TPM_CONTEXT_SENSITIVE *v);\nint tpm_unmarshal_TPM_CONTEXT_SENSITIVE(BYTE **ptr, UINT32 *length, TPM_CONTEXT_SENSITIVE *v);\n\nint tpm_marshal_TPM_DAA_BLOB(BYTE **ptr, UINT32 *length, TPM_DAA_BLOB *v);\nint tpm_unmarshal_TPM_DAA_BLOB(BYTE **ptr, UINT32 *length, TPM_DAA_BLOB *v);\n\nint tpm_marshal_TPM_DAA_SENSITIVE(BYTE **ptr, UINT32 *length, TPM_DAA_SENSITIVE *v);\nint tpm_unmarshal_TPM_DAA_SENSITIVE(BYTE **ptr, UINT32 *length, TPM_DAA_SENSITIVE *v);\n\nint tpm_marshal_TPM_DAA_ISSUER(BYTE **ptr, UINT32 *length, TPM_DAA_ISSUER *v);\nint tpm_unmarshal_TPM_DAA_ISSUER(BYTE **ptr, UINT32 *length, TPM_DAA_ISSUER *v);\n\nint tpm_marshal_TPM_DAA_TPM(BYTE **ptr, UINT32 *length, TPM_DAA_TPM *v);\nint tpm_unmarshal_TPM_DAA_TPM(BYTE **ptr, UINT32 *length, TPM_DAA_TPM *v);\n\nint tpm_marshal_TPM_DAA_CONTEXT(BYTE **ptr, UINT32 *length, TPM_DAA_CONTEXT *v);\nint tpm_unmarshal_TPM_DAA_CONTEXT(BYTE **ptr, UINT32 *length, TPM_DAA_CONTEXT *v);\n\nint tpm_marshal_TPM_DAA_JOINDATA(BYTE **ptr, UINT32 *length, TPM_DAA_JOINDATA *v);\nint tpm_unmarshal_TPM_DAA_JOINDATA(BYTE **ptr, UINT32 *length, TPM_DAA_JOINDATA *v);\n\nint tpm_marshal_TPM_DAA_SESSION_DATA(BYTE **ptr, UINT32 *length, TPM_DAA_SESSION_DATA *v);\nint tpm_unmarshal_TPM_DAA_SESSION_DATA(BYTE **ptr, UINT32 *length, TPM_DAA_SESSION_DATA *v);\n\nint tpm_marshal_TPM_MSA_COMPOSITE(BYTE **ptr, UINT32 *length, TPM_MSA_COMPOSITE *v);\nint tpm_unmarshal_TPM_MSA_COMPOSITE(BYTE **ptr, UINT32 *length, TPM_MSA_COMPOSITE *v);\n\nint tpm_marshal_TPM_CMK_AUTH(BYTE **ptr, UINT32 *length, TPM_CMK_AUTH *v);\nint tpm_unmarshal_TPM_CMK_AUTH(BYTE **ptr, UINT32 *length, TPM_CMK_AUTH *v);\n\nint tpm_marshal_TPM_SELECT_SIZE(BYTE **ptr, UINT32 *length, TPM_SELECT_SIZE *v);\nint tpm_unmarshal_TPM_SELECT_SIZE(BYTE **ptr, UINT32 *length, TPM_SELECT_SIZE *v);\n\nint tpm_marshal_TPM_CAP_VERSION_INFO(BYTE **ptr, UINT32 *length, TPM_CAP_VERSION_INFO *v);\nint tpm_unmarshal_TPM_CAP_VERSION_INFO(BYTE **ptr, UINT32 *length, TPM_CAP_VERSION_INFO *v);\n\nint tpm_marshal_TPM_ASYM_CA_CONTENTS(BYTE **ptr, UINT32 *length, TPM_ASYM_CA_CONTENTS *v);\nint tpm_unmarshal_TPM_ASYM_CA_CONTENTS(BYTE **ptr, UINT32 *length, TPM_ASYM_CA_CONTENTS *v);\n\nint tpm_marshal_TPM_QUOTE_INFO2(BYTE **ptr, UINT32 *length, TPM_QUOTE_INFO2 *v);\nint tpm_unmarshal_TPM_QUOTE_INFO2(BYTE **ptr, UINT32 *length, TPM_QUOTE_INFO2 *v);\n\nint tpm_marshal_TPM_EK_BLOB(BYTE **ptr, UINT32 *length, TPM_EK_BLOB *v);\nint tpm_unmarshal_TPM_EK_BLOB(BYTE **ptr, UINT32 *length, TPM_EK_BLOB *v);\n\nint tpm_marshal_TPM_EK_BLOB_ACTIVATE(BYTE **ptr, UINT32 *length, TPM_EK_BLOB_ACTIVATE *v);\nint tpm_unmarshal_TPM_EK_BLOB_ACTIVATE(BYTE **ptr, UINT32 *length, TPM_EK_BLOB_ACTIVATE *v);\n\nint tpm_marshal_TPM_NV_ATTRIBUTES(BYTE **ptr, UINT32 *length, TPM_NV_ATTRIBUTES *v);\nint tpm_unmarshal_TPM_NV_ATTRIBUTES(BYTE **ptr, UINT32 *length, TPM_NV_ATTRIBUTES *v);\n\nint tpm_marshal_TPM_NV_DATA_PUBLIC(BYTE **ptr, UINT32 *length, TPM_NV_DATA_PUBLIC *v);\nint tpm_unmarshal_TPM_NV_DATA_PUBLIC(BYTE **ptr, UINT32 *length, TPM_NV_DATA_PUBLIC *v);\n\nint tpm_marshal_TPM_DELEGATIONS(BYTE **ptr, UINT32 *length, TPM_DELEGATIONS *v);\nint tpm_unmarshal_TPM_DELEGATIONS(BYTE **ptr, UINT32 *length, TPM_DELEGATIONS *v);\n\nint tpm_marshal_TPM_FAMILY_LABEL(BYTE **ptr, UINT32 *length, TPM_FAMILY_LABEL *v);\nint tpm_unmarshal_TPM_FAMILY_LABEL(BYTE **ptr, UINT32 *length, TPM_FAMILY_LABEL *v);\n\nint tpm_marshal_TPM_FAMILY_TABLE_ENTRY(BYTE **ptr, UINT32 *length, TPM_FAMILY_TABLE_ENTRY *v);\nint tpm_unmarshal_TPM_FAMILY_TABLE_ENTRY(BYTE **ptr, UINT32 *length, TPM_FAMILY_TABLE_ENTRY *v);\n\nint tpm_marshal_TPM_DELEGATE_LABEL(BYTE **ptr, UINT32 *length, TPM_DELEGATE_LABEL *v);\nint tpm_unmarshal_TPM_DELEGATE_LABEL(BYTE **ptr, UINT32 *length, TPM_DELEGATE_LABEL *v);\n\nint tpm_marshal_TPM_DELEGATE_PUBLIC(BYTE **ptr, UINT32 *length, TPM_DELEGATE_PUBLIC *v);\nint tpm_unmarshal_TPM_DELEGATE_PUBLIC(BYTE **ptr, UINT32 *length, TPM_DELEGATE_PUBLIC *v);\n\nint tpm_marshal_TPM_DELEGATE_PUBLIC_ARRAY(BYTE **ptr, UINT32 *length, TPM_DELEGATE_PUBLIC *v, UINT32 n);\nint tpm_unmarshal_TPM_DELEGATE_PUBLIC_ARRAY(BYTE **ptr, UINT32 *length, TPM_DELEGATE_PUBLIC *v, UINT32 n);\n\nint tpm_marshal_TPM_DELEGATE_TABLE_ROW(BYTE **ptr, UINT32 *length, TPM_DELEGATE_TABLE_ROW *v);\nint tpm_unmarshal_TPM_DELEGATE_TABLE_ROW(BYTE **ptr, UINT32 *length, TPM_DELEGATE_TABLE_ROW *v);\n\nint tpm_marshal_TPM_DELEGATE_SENSITIVE(BYTE **ptr, UINT32 *length, TPM_DELEGATE_SENSITIVE *v);\nint tpm_unmarshal_TPM_DELEGATE_SENSITIVE(BYTE **ptr, UINT32 *length, TPM_DELEGATE_SENSITIVE *v);\n\nint tpm_marshal_TPM_DELEGATE_OWNER_BLOB(BYTE **ptr, UINT32 *length, TPM_DELEGATE_OWNER_BLOB *v);\nint tpm_unmarshal_TPM_DELEGATE_OWNER_BLOB(BYTE **ptr, UINT32 *length, TPM_DELEGATE_OWNER_BLOB *v);\n\nint tpm_marshal_TPM_DELEGATE_KEY_BLOB(BYTE **ptr, UINT32 *length, TPM_DELEGATE_KEY_BLOB *v);\nint tpm_unmarshal_TPM_DELEGATE_KEY_BLOB(BYTE **ptr, UINT32 *length, TPM_DELEGATE_KEY_BLOB *v);\n\nint tpm_marshal_TPM_PERMANENT_FLAGS(BYTE **ptr, UINT32 *length, TPM_PERMANENT_FLAGS *v);\nint tpm_unmarshal_TPM_PERMANENT_FLAGS(BYTE **ptr, UINT32 *length, TPM_PERMANENT_FLAGS *v);\n\nint tpm_marshal_TPM_STCLEAR_FLAGS(BYTE **ptr, UINT32 *length, TPM_STCLEAR_FLAGS *v);\nint tpm_unmarshal_TPM_STCLEAR_FLAGS(BYTE **ptr, UINT32 *length, TPM_STCLEAR_FLAGS *v);\n\nint tpm_marshal_TPM_STANY_FLAGS(BYTE **ptr, UINT32 *length, TPM_STANY_FLAGS *v);\nint tpm_unmarshal_TPM_STANY_FLAGS(BYTE **ptr, UINT32 *length, TPM_STANY_FLAGS *v);\n\nint tpm_marshal_RSA(BYTE **ptr, UINT32 *length, tpm_rsa_private_key_t *v);\nint tpm_unmarshal_RSA(BYTE **ptr, UINT32 *length, tpm_rsa_private_key_t *v);\n\nint tpm_marshal_RSAPub(BYTE **ptr, UINT32 *length, tpm_rsa_public_key_t *v);\nint tpm_unmarshal_RSAPub(BYTE **ptr, UINT32 *length, tpm_rsa_public_key_t *v);\n\nint tpm_marshal_TPM_KEY_DATA(BYTE **ptr, UINT32 *length, TPM_KEY_DATA *v);\nint tpm_unmarshal_TPM_KEY_DATA(BYTE **ptr, UINT32 *length, TPM_KEY_DATA *v);\n\nint tpm_marshal_TPM_PERMANENT_DATA(BYTE **ptr, UINT32 *length, TPM_PERMANENT_DATA *);\nint tpm_unmarshal_TPM_PERMANENT_DATA(BYTE **ptr, UINT32 *length, TPM_PERMANENT_DATA *);\n\nint tpm_marshal_TPM_STCLEAR_DATA(BYTE **ptr, UINT32 *length, TPM_STCLEAR_DATA *v);\nint tpm_unmarshal_TPM_STCLEAR_DATA(BYTE **ptr, UINT32 *length, TPM_STCLEAR_DATA *v);\n\nint tpm_marshal_TPM_SESSION_DATA(BYTE **ptr, UINT32 *length, TPM_SESSION_DATA *v);\nint tpm_unmarshal_TPM_SESSION_DATA(BYTE **ptr, UINT32 *length, TPM_SESSION_DATA *v);\n\nint tpm_marshal_TPM_STANY_DATA(BYTE **ptr, UINT32 *length, TPM_STANY_DATA *v);\nint tpm_unmarshal_TPM_STANY_DATA(BYTE **ptr, UINT32 *length, TPM_STANY_DATA *v);\n\nint tpm_unmarshal_TPM_DATA(BYTE **ptr, UINT32 *length, TPM_DATA *v);\nint tpm_marshal_TPM_DATA(BYTE **ptr, UINT32 *length, TPM_DATA *v);\n\nint tpm_marshal_TPM_RESPONSE(BYTE **ptr, UINT32 *length, TPM_RESPONSE *v);\nint tpm_unmarshal_TPM_REQUEST(BYTE **ptr, UINT32 *length, TPM_REQUEST *v);\n\n#endif /* _TPM_MARSHALLING_H_ */\n"
  },
  {
    "path": "tpm/tpm_migration.c",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: tpm_migration.c 462 2011-06-04 14:14:33Z mast $\n */\n\n#include \"tpm_emulator.h\"\n#include \"tpm_commands.h\"\n#include \"tpm_handles.h\"\n#include \"tpm_data.h\"\n#include \"tpm_marshalling.h\"\n#include \"crypto/sha1.h\"\n#include \"crypto/hmac.h\"\n\n/*\n * Migration ([TPM_Part3], Section 11)\n */\n\nstatic int tpm_compute_migration_digest(TPM_PUBKEY *migrationKey,\n                                        TPM_MIGRATE_SCHEME migrationScheme,\n                                        TPM_NONCE *tpmProof, TPM_DIGEST *digest)\n{\n  tpm_sha1_ctx_t sha1;\n  UINT32 len = sizeof_TPM_PUBKEY((*migrationKey));\n  BYTE *buf, *ptr, buf2[2];\n  buf = ptr = tpm_malloc(len);\n  if (buf == NULL\n      || tpm_marshal_TPM_PUBKEY(&ptr, &len, migrationKey)) {\n    tpm_free(buf);\n    return -1;\n  }\n  /* compute SHA1 hash */\n  tpm_sha1_init(&sha1);\n  tpm_sha1_update(&sha1, buf, sizeof_TPM_PUBKEY((*migrationKey)));\n  ptr = buf2; len = 2;\n  tpm_marshal_UINT16(&ptr, &len, migrationScheme);\n  tpm_sha1_update(&sha1, buf2, 2);\n  tpm_sha1_update(&sha1, tpmProof->nonce, sizeof(TPM_NONCE));\n  tpm_sha1_final(&sha1, digest->digest);\n  tpm_free(buf);\n  return 0;\n}\n\nstatic int tpm_verify_migration_digest(TPM_MIGRATIONKEYAUTH *migrationKeyAuth,\n                                       TPM_NONCE *tpmProof)\n{\n  TPM_DIGEST digest;\n  if (tpm_compute_migration_digest(&migrationKeyAuth->migrationKey,\n      migrationKeyAuth->migrationScheme, tpmProof, &digest)) return -1;\n  return memcmp(digest.digest, migrationKeyAuth->digest.digest, sizeof(TPM_DIGEST));\n}\n\nTPM_RESULT TPM_CreateMigrationBlob(TPM_KEY_HANDLE parentHandle,\n                                   TPM_MIGRATE_SCHEME migrationType,\n                                   TPM_MIGRATIONKEYAUTH *migrationKeyAuth,\n                                   UINT32 encDataSize, BYTE *encData,\n                                   TPM_AUTH *auth1, TPM_AUTH *auth2,\n                                   UINT32 *randomSize, BYTE **random,\n                                   UINT32 *outDataSize, BYTE **outData)\n{\n  TPM_RESULT res;\n  TPM_KEY_DATA *parent;\n  TPM_SESSION_DATA *session;\n  BYTE *key_buf;\n  UINT32 key_buf_size;\n  TPM_STORE_ASYMKEY store;\n  TPM_PUBKEY_DATA key;\n\n  info(\"TPM_CreateMigrationBlob()\");\n  /* get parent key */\n  parent = tpm_get_key(parentHandle);\n  if (parent == NULL) return TPM_INVALID_KEYHANDLE;\n  /* verify parent authorization */\n  res = tpm_verify_auth(auth1, parent->usageAuth, parentHandle);\n  if (res != TPM_SUCCESS) return res;\n  session = tpm_get_auth(auth2->authHandle);\n  if (session == NULL || session->type != TPM_ST_OIAP) return TPM_AUTHFAIL;\n  /* verify key properties */\n  if (parent->keyUsage != TPM_KEY_STORAGE) return TPM_INVALID_KEYUSAGE;\n  /* decrypt private key */\n  if (tpm_decrypt_private_key(parent, encData, encDataSize,\n                              &store, &key_buf, &key_buf_size) != 0) {\n    return TPM_DECRYPT_ERROR;\n  }\n  if (store.payload != TPM_PT_ASYM) {\n    tpm_free(key_buf);\n    return TPM_DECRYPT_ERROR;\n  }\n  debug(\"key size: %d / %d\", store.privKey.keyLength, key_buf_size);\n  /* verify migration authorization */\n  res = tpm_verify_auth(auth2, store.migrationAuth, TPM_INVALID_HANDLE);\n  if (res != TPM_SUCCESS) {\n    tpm_free(key_buf);\n    return TPM_MIGRATEFAIL;\n  }\n  if (tpm_verify_migration_digest(migrationKeyAuth,\n      &tpmData.permanent.data.tpmProof)) {\n    debug(\"tpm_verify_migration_digest() failed\");\n    tpm_free(key_buf);\n    return TPM_MIGRATEFAIL;\n  }\n  debug(\"migration authorization is valid.\");\n  /* set public key */\n  if (tpm_setup_pubkey_data(&migrationKeyAuth->migrationKey, &key) != 0) {\n      debug(\"tpm_setup_pubkey() failed\");\n      tpm_free(key_buf);\n      return TPM_FAIL;\n  }\n  /* perform migration */\n  if (migrationType == TPM_MS_REWRAP) {\n    /* re-encrypt raw key data */\n    debug(\"migrationType = TPM_MS_REWRAP\");\n    *random = NULL;\n    *randomSize = 0;\n    *outDataSize = key.key.size >> 3;\n    *outData = tpm_malloc(*outDataSize);\n    if (*outData == NULL) {\n      free_TPM_PUBKEY_DATA(key);\n      tpm_free(*outData);\n      tpm_free(key_buf);\n      return TPM_FAIL;\n    }\n    if (tpm_encrypt_public(&key, key_buf, key_buf_size,\n                           *outData, outDataSize) != 0) {\n        free_TPM_PUBKEY_DATA(key);\n        tpm_free(*outData);\n        tpm_free(key_buf);\n        return TPM_ENCRYPT_ERROR;\n    }\n  } else if (migrationType == TPM_MS_MIGRATE) {\n    BYTE *ptr, *buf;\n    UINT32 len;\n    size_t buf_len;\n    /* generate an OAEP encoding of the TPM_MIGRATE_ASYMKEY structure:\n       K1|seed|0x00-pad|0x01|TPM_MIGRATE_ASYMKEY */\n    debug(\"migrationType = TPM_MS_MIGRATE\");\n    len = buf_len = 198;\n    ptr = buf = tpm_malloc(buf_len);\n    *randomSize = buf_len;\n    *random = tpm_malloc(*randomSize);\n    *outDataSize = key.key.size >> 3;\n    *outData = tpm_malloc(*outDataSize);\n    if (buf == NULL || *random == NULL || *outData == NULL) {\n      free_TPM_PUBKEY_DATA(key);\n      tpm_free(buf);\n      tpm_free(*random);\n      tpm_free(*outData);\n      tpm_free(key_buf);\n      return TPM_NOSPACE;\n    }\n    memset(buf, 0, buf_len);\n    tpm_marshal_UINT32(&ptr, &len, store.privKey.keyLength);\n    memcpy(ptr, store.privKey.key, 16);\n    ptr += 16;\n    memcpy(ptr, store.migrationAuth, sizeof(TPM_SECRET));\n    len = 46 + store.privKey.keyLength - 16;\n    ptr = &buf[buf_len - len];\n    tpm_marshal_BYTE(&ptr, &len, 0x01);\n    tpm_marshal_TPM_PAYLOAD_TYPE(&ptr, &len, TPM_PT_MIGRATE);\n    tpm_marshal_TPM_SECRET(&ptr, &len, &store.usageAuth);\n    tpm_marshal_TPM_DIGEST(&ptr, &len, &store.pubDataDigest);\n    tpm_marshal_UINT32(&ptr, &len, store.privKey.keyLength - 16);\n    memcpy(ptr, &store.privKey.key[16], store.privKey.keyLength - 16);\n    tpm_rsa_mask_generation(buf, SHA1_DIGEST_LENGTH,\n      &buf[SHA1_DIGEST_LENGTH], buf_len - SHA1_DIGEST_LENGTH);\n    tpm_rsa_mask_generation(&buf[SHA1_DIGEST_LENGTH],\n      buf_len - SHA1_DIGEST_LENGTH, buf, SHA1_DIGEST_LENGTH);\n    /* XOR encrypt OAEP encoding */\n    tpm_get_random_bytes(*random, *randomSize);\n    for (len = 0; len < buf_len; len++) buf[len] ^= (*random)[len];\n    /* RSA encrypt OAEP encoding */\n    if (tpm_rsa_encrypt(&key.key, RSA_ES_OAEP_SHA1, buf, buf_len,\n                        *outData, &buf_len)) {\n      debug(\"tpm_rsa_encrypt() failed\");\n      free_TPM_PUBKEY_DATA(key);\n      tpm_free(buf);\n      tpm_free(*random);\n      tpm_free(*outData);\n      tpm_free(key_buf);\n      return TPM_ENCRYPT_ERROR;\n    }\n    *outDataSize = buf_len;\n    tpm_free(buf);\n  } else {\n    debug(\"invalid migration type: %d\", migrationType);\n    free_TPM_PUBKEY_DATA(key);\n    tpm_free(key_buf);\n    return TPM_BAD_PARAMETER;\n  }\n  free_TPM_PUBKEY_DATA(key);\n  tpm_free(key_buf);\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_ConvertMigrationBlob(TPM_KEY_HANDLE parentHandle,\n                                    UINT32 inDataSize, BYTE *inData,\n                                    UINT32 randomSize, BYTE *random,\n                                    TPM_AUTH *auth1,\n                                    UINT32 *outDataSize,BYTE **outData)\n{\n  TPM_RESULT res;\n  TPM_KEY_DATA *parent;\n  BYTE *ptr, *buf;\n  UINT32 len;\n  size_t buf_len;\n  TPM_STORE_ASYMKEY store;\n\n  info(\"TPM_ConvertMigrationBlob()\");\n  /* get parent key */\n  parent = tpm_get_key(parentHandle);\n  if (parent == NULL) return TPM_INVALID_KEYHANDLE;\n  /* verify parent authorization */\n  if (auth1->authHandle != TPM_INVALID_HANDLE\n      || parent->authDataUsage != TPM_AUTH_NEVER) {\n    res = tpm_verify_auth(auth1, parent->usageAuth, parentHandle);\n    if (res != TPM_SUCCESS) return res;\n  }\n  /* verify key properties */\n  if (parent->keyUsage != TPM_KEY_STORAGE) return TPM_INVALID_KEYUSAGE;\n  /* decrypt private key */\n  buf_len = parent->key.size >> 3;\n  buf = tpm_malloc(buf_len);\n  if (buf == NULL) return TPM_NOSPACE;\n  /* RSA decrypt OAEP encoding */\n  if (tpm_rsa_decrypt(&parent->key, RSA_ES_OAEP_SHA1,\n                      inData, inDataSize, buf, &buf_len)\n      || buf_len != randomSize || buf_len != 198) {\n    debug(\"tpm_rsa_decrypt() failed\");\n    tpm_free(buf);\n    return TPM_DECRYPT_ERROR;\n  }\n  /* XOR decrypt OAEP encoding */\n  for (len = 0; len < buf_len; len++) buf[len] ^= random[len];\n  /* unmask OAEP encoding */\n  tpm_rsa_mask_generation(&buf[SHA1_DIGEST_LENGTH],\n    buf_len - SHA1_DIGEST_LENGTH, buf, SHA1_DIGEST_LENGTH);\n  tpm_rsa_mask_generation(buf, SHA1_DIGEST_LENGTH,\n    &buf[SHA1_DIGEST_LENGTH], buf_len - SHA1_DIGEST_LENGTH);\n  /* create a TPM_STORE_ASYMKEY structure */\n  memcpy(store.migrationAuth, &buf[20], sizeof(TPM_SECRET));\n  for (ptr = &buf[20 + sizeof(TPM_SECRET)]; *ptr == 0x00; ptr++);\n  if (ptr[0] != 0x01 || ptr[1] != TPM_PT_MIGRATE) {\n      debug(\"OAEP encoding is invalid\");\n      tpm_free(buf);\n      return TPM_DECRYPT_ERROR;\n  }\n  ptr += 2;\n  len = buf_len - (ptr - buf);\n  store.payload = TPM_PT_ASYM;\n  tpm_unmarshal_TPM_SECRET(&ptr, &len, &store.usageAuth);\n  tpm_unmarshal_TPM_DIGEST(&ptr, &len, &store.pubDataDigest);\n  tpm_unmarshal_UINT32(&ptr, &len, &store.privKey.keyLength);\n  store.privKey.keyLength += 16;\n  if (store.privKey.keyLength != len + 16) {\n    error(\"invalid key length %d; expected %d\",\n          store.privKey.keyLength, len + 16);\n    tpm_free(buf);\n    return TPM_DECRYPT_ERROR;\n  }\n  memmove(&buf[20], ptr, len);\n  store.privKey.key = &buf[4];\n  /* encrypt private key */\n  *outDataSize = parent->key.size >> 3;\n  *outData = tpm_malloc(*outDataSize);\n  if (*outData == NULL) {\n    tpm_free(buf);\n    return TPM_NOSPACE;\n  }\n  if (tpm_encrypt_private_key(parent, &store, *outData, outDataSize)) {\n    debug(\"tpm_encrypt_private_key() failed\");\n    tpm_free(*outData);\n    tpm_free(buf);\n    return TPM_ENCRYPT_ERROR;\n  }\n  tpm_free(buf);\n  return TPM_SUCCESS;\n}\n\nstatic int tpm_copy_pubkey(TPM_PUBKEY *in, TPM_PUBKEY *out)\n{\n  memcpy(out, in, sizeof(TPM_PUBKEY));\n  out->pubKey.key = tpm_malloc(out->pubKey.keyLength);\n  if (out->pubKey.key == NULL) return -1;\n  memcpy(out->pubKey.key, in->pubKey.key, out->pubKey.keyLength);\n  out->algorithmParms.parms.rsa.exponent =\n    tpm_malloc(out->algorithmParms.parms.rsa.exponentSize);\n  if (out->algorithmParms.parms.rsa.exponent == NULL) {\n    tpm_free(out->pubKey.key);\n    return -1;\n  }\n  memcpy(out->algorithmParms.parms.rsa.exponent,\n    in->algorithmParms.parms.rsa.exponent,\n    out->algorithmParms.parms.rsa.exponentSize);\n  return 0;\n}\n\nTPM_RESULT TPM_AuthorizeMigrationKey(TPM_MIGRATE_SCHEME migrateScheme,\n                                     TPM_PUBKEY *migrationKey, TPM_AUTH *auth1,\n                                     TPM_MIGRATIONKEYAUTH *outData)\n{\n  TPM_RESULT res;\n\n  info(\"TPM_AuthorizeMigrationKey()\");\n  /* verify authorization */\n  res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);\n  if (res != TPM_SUCCESS) return res;\n  /* verify the key size and encryption scheme */\n  if (migrationKey->algorithmParms.encScheme != TPM_ES_RSAESOAEP_SHA1_MGF1\n      || migrationKey->algorithmParms.algorithmID != TPM_ALG_RSA)\n    return TPM_INAPPROPRIATE_ENC;\n  if (migrationKey->algorithmParms.parms.rsa.keyLength  < 2048)\n    return TPM_BAD_KEY_PROPERTY;\n  /* create migration key authorization */\n  if (tpm_compute_migration_digest(migrationKey, migrateScheme,\n      &tpmData.permanent.data.tpmProof, &outData->digest) != 0) {\n      debug(\"tpm_compute_migration_digest() failed\");\n      return TPM_FAIL;\n  }\n  outData->migrationScheme = migrateScheme;\n  if (tpm_copy_pubkey(migrationKey, &outData->migrationKey) != 0) {\n      debug(\"tpm_copy_pubkey() failed\");\n      return TPM_FAIL;\n  }\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_MigrateKey(TPM_KEY_HANDLE maKeyHandle, TPM_PUBKEY *pubKey,\n                          UINT32 inDataSize, BYTE *inData, TPM_AUTH *auth1,\n                          UINT32 *outDataSize, BYTE **outData)\n{\n  TPM_RESULT res;\n  TPM_KEY_DATA *key;\n  TPM_PUBKEY_DATA key2;\n  UINT32 size;\n  BYTE *buf;\n  UINT32 buf_len;\n\n  info(\"TPM_MigrateKey()\");\n  key = tpm_get_key(maKeyHandle);\n  if (key == NULL) return TPM_INVALID_KEYHANDLE;\n  /* verify key authorization */\n  res = tpm_verify_auth(auth1, key->usageAuth, maKeyHandle);\n  if (res != TPM_SUCCESS) return res;\n  /* verify key usage */\n  if (key->keyUsage != TPM_KEY_MIGRATE) return TPM_BAD_KEY_PROPERTY;\n  if (key->encScheme != TPM_ES_RSAESOAEP_SHA1_MGF1) return TPM_INAPPROPRIATE_ENC;\n  /* verify public key  */\n  if (pubKey->algorithmParms.algorithmID != TPM_ALG_RSA\n      || pubKey->algorithmParms.parms.rsa.keyLength < (inDataSize << 3))\n    return TPM_BAD_KEY_PROPERTY;\n  if (tpm_setup_pubkey_data(pubKey, &key2) != 0) return TPM_FAIL;\n  /* decrypt inData and re-encrypt it with the public key */\n  *outDataSize = size = pubKey->algorithmParms.parms.rsa.keyLength >> 3;\n  *outData = tpm_malloc(*outDataSize);\n  buf_len = inDataSize;\n  buf = tpm_malloc(buf_len);\n  if (*outData == NULL || buf == NULL) {\n    free_TPM_PUBKEY_DATA(key2);\n    tpm_free(*outData);\n    tpm_free(buf);\n    return TPM_NOSPACE;\n  }\n  if (tpm_decrypt(key, inData, inDataSize, buf, &buf_len) != 0) {\n    free_TPM_PUBKEY_DATA(key2);\n    tpm_free(*outData);\n    tpm_free(buf);\n    return TPM_DECRYPT_ERROR;\n  }\n  if (tpm_encrypt_public(&key2, buf, buf_len, *outData, outDataSize) != 0) {\n    free_TPM_PUBKEY_DATA(key2);\n    tpm_free(*outData);\n    tpm_free(buf);\n    return TPM_ENCRYPT_ERROR;\n  }\n  free_TPM_PUBKEY_DATA(key2);\n  tpm_free(buf);\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_CMK_SetRestrictions(TPM_CMK_DELEGATE restriction,\n                                   TPM_AUTH *auth1)\n{\n  TPM_RESULT res;\n\n  info(\"TPM_CMK_SetRestrictions()\");\n  /* verify authorization */\n  res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);\n  if (res != TPM_SUCCESS) return res;\n  /* update delegation restriction */\n  tpmData.permanent.data.restrictDelegate = restriction;\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_CMK_ApproveMA(TPM_DIGEST *migrationAuthorityDigest,\n                             TPM_AUTH *auth1, TPM_HMAC *outData)\n{\n  TPM_RESULT res;\n  BYTE buf[2];\n  tpm_hmac_ctx_t ctx;\n\n  info(\"TPM_CMK_ApproveMA()\");\n  /* verify authorization */\n  res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);\n  if (res != TPM_SUCCESS) return res;\n  /* create hmac of a TPM_CMK_MA_APPROVAL structure */\n  buf[0] = (TPM_TAG_CMK_MA_APPROVAL >> 8) & 0xff;\n  buf[1] = TPM_TAG_CMK_MA_APPROVAL & 0xff;\n  tpm_hmac_init(&ctx, tpmData.permanent.data.tpmProof.nonce, sizeof(TPM_NONCE));\n  tpm_hmac_update(&ctx, buf, 2);\n  tpm_hmac_update(&ctx, migrationAuthorityDigest->digest, sizeof(TPM_DIGEST));\n  tpm_hmac_final(&ctx, outData->digest);\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_CMK_CreateKey(TPM_KEY_HANDLE parentHandle,\n                             TPM_ENCAUTH *dataUsageAuth,\n                             TPM_KEY *keyInfo,\n                             TPM_HMAC *migrationAuthorityApproval,\n                             TPM_DIGEST *migrationAuthorityDigest,\n                             TPM_AUTH *auth1, TPM_AUTH *auth2,\n                             TPM_KEY *wrappedKey)\n{\n  TPM_RESULT res;\n  TPM_KEY_DATA *parent;\n  TPM_SESSION_DATA *session;\n  tpm_hmac_ctx_t ctx;\n  BYTE buf[SHA1_DIGEST_LENGTH];\n  TPM_STORE_ASYMKEY store;\n  tpm_rsa_private_key_t rsa;\n  UINT32 key_length;\n  TPM_PUBKEY pubKey;\n  TPM_DIGEST keyDigest;\n\n  info(\"TPM_CMK_CreateKey()\");\n  /* get parent key */\n  parent = tpm_get_key(parentHandle);\n  if (parent == NULL) return TPM_INVALID_KEYHANDLE;\n  /* verify authorization */\n  res = tpm_verify_auth(auth1, parent->usageAuth, parentHandle);\n  if (res != TPM_SUCCESS) return res;\n  auth1->continueAuthSession = FALSE;\n  session = tpm_get_auth(auth1->authHandle);\n  if (session->type != TPM_ST_OSAP) return TPM_AUTHFAIL;\n  /* must be TPM_KEY12 */\n  if (keyInfo->tag != TPM_TAG_KEY12) return TPM_INVALID_STRUCTURE;\n  /* verify key parameters */\n  if (parent->keyUsage != TPM_KEY_STORAGE\n      || parent->encScheme == TPM_ES_NONE\n      || parent->keyFlags & TPM_KEY_FLAG_MIGRATABLE\n      || !(keyInfo->keyFlags & TPM_KEY_FLAG_MIGRATABLE)\n      || !(keyInfo->keyFlags & TPM_KEY_FLAG_AUTHORITY)\n      || keyInfo->keyUsage == TPM_KEY_IDENTITY\n      || keyInfo->keyUsage == TPM_KEY_AUTHCHANGE) return TPM_INVALID_KEYUSAGE;\n  if (keyInfo->algorithmParms.algorithmID != TPM_ALG_RSA\n      || keyInfo->algorithmParms.parmSize == 0\n      || keyInfo->algorithmParms.parms.rsa.keyLength < 512\n      || keyInfo->algorithmParms.parms.rsa.numPrimes != 2\n      || keyInfo->algorithmParms.parms.rsa.exponentSize != 0)\n    return TPM_BAD_KEY_PROPERTY;\n  if (tpmData.permanent.flags.FIPS\n      && (keyInfo->algorithmParms.parms.rsa.keyLength < 1024\n          || keyInfo->authDataUsage == TPM_AUTH_NEVER\n          || keyInfo->keyUsage == TPM_KEY_LEGACY)) return TPM_NOTFIPS;\n  if ((keyInfo->keyUsage == TPM_KEY_STORAGE\n       || keyInfo->keyUsage == TPM_KEY_MIGRATE)\n      && (keyInfo->algorithmParms.algorithmID != TPM_ALG_RSA\n          || keyInfo->algorithmParms.parms.rsa.keyLength != 2048\n          || keyInfo->algorithmParms.sigScheme != TPM_SS_NONE\n          || keyInfo->algorithmParms.encScheme != TPM_ES_RSAESOAEP_SHA1_MGF1))\n    return TPM_BAD_KEY_PROPERTY;\n  /* verify migration authority */\n  buf[0] = (TPM_TAG_CMK_MA_APPROVAL >> 8) & 0xff;\n  buf[1] = TPM_TAG_CMK_MA_APPROVAL & 0xff;\n  tpm_hmac_init(&ctx, tpmData.permanent.data.tpmProof.nonce, sizeof(TPM_NONCE));\n  tpm_hmac_update(&ctx, buf, 2);\n  tpm_hmac_update(&ctx, migrationAuthorityDigest->digest, sizeof(TPM_DIGEST));\n  tpm_hmac_final(&ctx, buf);\n  if (memcmp(migrationAuthorityApproval->digest, buf, sizeof(TPM_HMAC)) != 0)\n    return TPM_MA_AUTHORITY;\n  /* setup the wrapped key */\n  memcpy(wrappedKey, keyInfo, sizeof(TPM_KEY));\n  /* setup key store */\n  store.payload = TPM_PT_MIGRATE_RESTRICTED;\n  tpm_decrypt_auth_secret(*dataUsageAuth, session->sharedSecret,\n    &session->lastNonceEven, store.usageAuth);\n  /* compute PCR digest */\n  if (keyInfo->PCRInfoSize > 0) {\n    tpm_compute_pcr_digest(&keyInfo->PCRInfo.creationPCRSelection,\n      &keyInfo->PCRInfo.digestAtCreation, NULL);\n    keyInfo->PCRInfo.localityAtCreation =\n      tpmData.stany.flags.localityModifier;\n  }\n  /* generate key and store it */\n  key_length = keyInfo->algorithmParms.parms.rsa.keyLength;\n  if (tpm_rsa_generate_key(&rsa, key_length)) {\n    debug(\"TPM_CreateWrapKey(): tpm_rsa_generate_key() failed.\");\n    return TPM_FAIL;\n  }\n  wrappedKey->pubKey.keyLength = key_length >> 3;\n  wrappedKey->pubKey.key = tpm_malloc(wrappedKey->pubKey.keyLength);\n  store.privKey.keyLength = key_length >> 4;\n  store.privKey.key = tpm_malloc(store.privKey.keyLength);\n  wrappedKey->encDataSize = parent->key.size >> 3;\n  wrappedKey->encData = tpm_malloc(wrappedKey->encDataSize);\n  if (wrappedKey->pubKey.key == NULL || store.privKey.key == NULL\n      || wrappedKey->encData == NULL) {\n    tpm_rsa_release_private_key(&rsa);\n    tpm_free(wrappedKey->pubKey.key);\n    tpm_free(store.privKey.key);\n    tpm_free(wrappedKey->encData);\n    return TPM_NOSPACE;\n  }\n  tpm_rsa_export_modulus(&rsa, wrappedKey->pubKey.key, NULL);\n  tpm_rsa_export_prime1(&rsa, store.privKey.key, NULL);\n  tpm_rsa_release_private_key(&rsa);\n  /* create hmac of TPM_CMK_MIGAUTH  */\n  buf[0] = (TPM_TAG_CMK_MIGAUTH >> 8) & 0xff;\n  buf[1] = TPM_TAG_CMK_MIGAUTH & 0xff;\n  memcpy(&pubKey.algorithmParms, &wrappedKey->algorithmParms,\n         sizeof(TPM_KEY_PARMS));\n  memcpy(&pubKey.pubKey, &wrappedKey->pubKey, sizeof(TPM_STORE_PUBKEY));\n  if (tpm_compute_pubkey_digest(&pubKey, &keyDigest) !=0 ) {\n    debug(\"tpm_compute_pubkey_digest() failed\");\n    return TPM_FAIL;\n  }\n  tpm_hmac_init(&ctx, tpmData.permanent.data.tpmProof.nonce, sizeof(TPM_NONCE));\n  tpm_hmac_update(&ctx, buf, 2);\n  tpm_hmac_update(&ctx, migrationAuthorityDigest->digest, sizeof(TPM_DIGEST));\n  tpm_hmac_update(&ctx, keyDigest.digest, sizeof(TPM_DIGEST));\n  tpm_hmac_final(&ctx, store.migrationAuth);\n  /* compute the digest of the wrapped key (without encData) */\n  if (tpm_compute_key_digest(wrappedKey, &store.pubDataDigest)) {\n    debug(\"TPM_CreateWrapKey(): tpm_compute_key_digest() failed.\");\n    return TPM_FAIL;\n  }\n  /* encrypt private key data */\n  if (tpm_encrypt_private_key(parent, &store, wrappedKey->encData,\n      &wrappedKey->encDataSize)) {\n    tpm_free(wrappedKey->pubKey.key);\n    tpm_free(store.privKey.key);\n    tpm_free(wrappedKey->encData);\n    return TPM_ENCRYPT_ERROR;\n  }\n  tpm_free(store.privKey.key);\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_CMK_CreateTicket(TPM_PUBKEY *verificationKey,\n                                TPM_DIGEST *signedData,\n                                UINT32 signatureValueSize,\n                                BYTE *signatureValue, TPM_AUTH *auth1,\n                                TPM_DIGEST *sigTicket)\n{\n  TPM_RESULT res;\n  TPM_PUBKEY_DATA key;\n  BYTE buf[2];\n  TPM_DIGEST keyDigest;\n  tpm_hmac_ctx_t ctx;\n\n  info(\"TPM_CMK_CreateTicket()\");\n  /* verify authorization */\n  res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);\n  /* verify key type and algorithm */\n  if (verificationKey->algorithmParms.algorithmID != TPM_ALG_RSA\n      || verificationKey->algorithmParms.encScheme != TPM_ES_NONE)\n    return TPM_BAD_KEY_PROPERTY;\n  if (verificationKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1\n      && verificationKey->algorithmParms.sigScheme != TPM_SS_RSASSAPKCS1v15_INFO)\n    return TPM_BAD_KEY_PROPERTY;\n  /* verify signature */\n  if (tpm_setup_pubkey_data(verificationKey, &key) != 0) return TPM_FAIL;\n  res = tpm_verify(&key, auth1, FALSE, signedData->digest, sizeof(TPM_DIGEST),\n                   signatureValue, signatureValueSize);\n  free_TPM_PUBKEY_DATA(key);\n  if (res != TPM_SUCCESS) return res;\n  /* create hmac on TPM_CMK_SIGTICKET */\n  buf[0] = (TPM_TAG_CMK_SIGTICKET >> 8) & 0xff;\n  buf[1] = TPM_TAG_CMK_SIGTICKET & 0xff;\n  if (tpm_compute_pubkey_digest(verificationKey, &keyDigest) !=0 ) {\n    debug(\"tpm_compute_pubkey_digest() failed\");\n    return TPM_FAIL;\n  }\n  tpm_hmac_init(&ctx, tpmData.permanent.data.tpmProof.nonce, sizeof(TPM_NONCE));\n  tpm_hmac_update(&ctx, buf, 2);\n  tpm_hmac_update(&ctx, keyDigest.digest, sizeof(TPM_DIGEST));\n  tpm_hmac_update(&ctx, signedData->digest, sizeof(TPM_DIGEST));\n  tpm_hmac_final(&ctx, sigTicket->digest);\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_CMK_CreateBlob(TPM_KEY_HANDLE parentHandle,\n                              TPM_MIGRATE_SCHEME migrationType,\n                              TPM_MIGRATIONKEYAUTH *migrationKeyAuth,\n                              TPM_DIGEST *pubSourceKeyDigest,\n                              TPM_MSA_COMPOSITE *msaList,\n                              TPM_CMK_AUTH *restrictTicket,\n                              TPM_HMAC *sigTicket,\n                              UINT32 encDataSize, BYTE *encData,\n                              TPM_AUTH *auth1,\n                              UINT32 *randomSize, BYTE **random,\n                              UINT32 *outDataSize, BYTE **outData)\n{\n  TPM_RESULT res;\n  TPM_KEY_DATA *parent;\n  TPM_STORE_ASYMKEY store;\n  BYTE *key_buf;\n  UINT32 key_buf_size;\n  tpm_hmac_ctx_t hmac_ctx;\n  tpm_sha1_ctx_t sha1_ctx;\n  BYTE tag[2], hmac[SHA1_DIGEST_LENGTH];\n  BYTE *ptr, *buf;\n  UINT32 i, len;\n  size_t buf_len;\n  TPM_DIGEST migKeyDigest;\n  TPM_DIGEST msaListDigest;\n  TPM_DIGEST ticketDigest;\n  TPM_PUBKEY_DATA key;\n\n  info(\"TPM_CMK_CreateBlob()\");\n  /* get parent key */\n  parent = tpm_get_key(parentHandle);\n  if (parent == NULL) return TPM_INVALID_KEYHANDLE;\n  /* verify authorization */\n  res = tpm_verify_auth(auth1, parent->usageAuth, parentHandle);\n  if (res != TPM_SUCCESS) return res;\n  /* migrationType must match */\n  if (migrationType != migrationKeyAuth->migrationScheme) return TPM_BAD_MODE;\n  if (parent->keyFlags & TPM_KEY_FLAG_MIGRATABLE) return TPM_BAD_KEY_PROPERTY;\n  /* decrypt private key */\n  if (tpm_decrypt_private_key(parent, encData, encDataSize,\n                              &store, &key_buf, &key_buf_size) != 0) {\n    return TPM_DECRYPT_ERROR;\n  }\n  if (store.payload != TPM_PT_MIGRATE_RESTRICTED\n      && store.payload != TPM_PT_MIGRATE_EXTERNAL) {\n    tpm_free(key_buf);\n    return TPM_DECRYPT_ERROR;\n  }\n  if (tpm_verify_migration_digest(migrationKeyAuth,\n      &tpmData.permanent.data.tpmProof)) {\n    debug(\"tpm_verify_migration_digest() failed\");\n    tpm_free(key_buf);\n    return TPM_MIGRATEFAIL;\n  }\n  /* verify the migration authority list */\n  len = sizeof_TPM_MSA_COMPOSITE((*msaList));\n  ptr = buf = tpm_malloc(len);\n  if (buf == NULL || tpm_marshal_TPM_MSA_COMPOSITE(&ptr, &len, msaList)) {\n    debug(\"tpm_marshal_TPM_MSA_COMPOSITE() failed\");\n    tpm_free(buf);\n    tpm_free(key_buf);\n    return TPM_FAIL;\n  }\n  tpm_sha1_init(&sha1_ctx);\n  tpm_sha1_update(&sha1_ctx, buf, sizeof_TPM_MSA_COMPOSITE((*msaList)));\n  tpm_sha1_final(&sha1_ctx, msaListDigest.digest);\n  tpm_free(buf);\n  tag[0] = (TPM_TAG_CMK_MIGAUTH >> 8) & 0xff;\n  tag[1] = TPM_TAG_CMK_MIGAUTH & 0xff;\n  tpm_hmac_init(&hmac_ctx, tpmData.permanent.data.tpmProof.nonce, sizeof(TPM_NONCE));\n  tpm_hmac_update(&hmac_ctx, tag, 2);\n  tpm_hmac_update(&hmac_ctx, msaListDigest.digest, sizeof(TPM_DIGEST));\n  tpm_hmac_update(&hmac_ctx, pubSourceKeyDigest->digest, sizeof(TPM_DIGEST));\n  tpm_hmac_final(&hmac_ctx, hmac);\n  if (memcmp(hmac, store.migrationAuth, sizeof(TPM_SECRET)) != 0) {\n    tpm_free(key_buf);\n    return TPM_MA_AUTHORITY;\n  }\n  if (tpm_compute_pubkey_digest(&migrationKeyAuth->migrationKey, &migKeyDigest) !=0 ) {\n    debug(\"tpm_compute_pubkey_digest() failed\");\n    tpm_free(key_buf);\n    return TPM_FAIL;\n  }\n  len = sizeof_TPM_CMK_AUTH((*restrictTicket));\n  ptr = buf = tpm_malloc(len);\n  if (buf == NULL || tpm_marshal_TPM_CMK_AUTH(&ptr, &len, restrictTicket)) {\n    debug(\"tpm_marshal_TPM_CMK_AUTH() failed\");\n    tpm_free(buf);\n    tpm_free(key_buf);\n    return TPM_FAIL;\n  }\n  tpm_sha1_init(&sha1_ctx);\n  tpm_sha1_update(&sha1_ctx, buf, sizeof_TPM_CMK_AUTH((*restrictTicket)));\n  tpm_sha1_final(&sha1_ctx, ticketDigest.digest);\n  tpm_free(buf);\n  /* verify the migration destination */\n  if (migrationKeyAuth->migrationScheme == TPM_MS_RESTRICT_MIGRATE) {\n    for (i = 0; i < msaList->MSAlist; i++) {\n        if (memcmp(msaList->migAuthDigest[i].digest, migKeyDigest.digest,\n                   sizeof(TPM_DIGEST)) == 0) break;\n    }\n    if (i >= msaList->MSAlist) {\n      tpm_free(key_buf);\n      return TPM_MA_AUTHORITY;\n    }\n    /* verify the key type and algorithm */\n    if (migrationKeyAuth->migrationKey.algorithmParms.algorithmID != TPM_ALG_RSA\n        || migrationKeyAuth->migrationKey.algorithmParms.encScheme != TPM_ES_RSAESOAEP_SHA1_MGF1\n        || migrationKeyAuth->migrationKey.algorithmParms.sigScheme != TPM_SS_NONE) {\n      tpm_free(key_buf);\n      return TPM_BAD_KEY_PROPERTY;\n    }\n  } else if (migrationKeyAuth->migrationScheme == TPM_MS_RESTRICT_APPROVE) {\n    if (restrictTicket == NULL || sigTicket == NULL) {\n      tpm_free(key_buf);\n      return TPM_BAD_PARAMETER;\n    }\n    for (i = 0; i < msaList->MSAlist; i++) {\n      /* create hmac of TPM_CMK_SIGTICKET */\n      tag[0] = (TPM_TAG_CMK_SIGTICKET >> 8) & 0xff;\n      tag[1] = TPM_TAG_CMK_SIGTICKET & 0xff;\n      tpm_hmac_init(&hmac_ctx, tpmData.permanent.data.tpmProof.nonce,\n                    sizeof(TPM_NONCE));\n      tpm_hmac_update(&hmac_ctx, tag, 2);\n      tpm_hmac_update(&hmac_ctx, msaList->migAuthDigest[i].digest,\n                      sizeof(TPM_DIGEST));\n      tpm_hmac_update(&hmac_ctx, ticketDigest.digest, sizeof(TPM_DIGEST));\n      tpm_hmac_final(&hmac_ctx, hmac);\n      if (memcmp(hmac, sigTicket->digest, sizeof(TPM_DIGEST)) == 0) break;\n    }\n    if (i >= msaList->MSAlist) {\n      tpm_free(key_buf);\n      return TPM_MA_AUTHORITY;\n    }\n    if (memcmp(&restrictTicket->destinationKeyDigest, &migKeyDigest,\n               sizeof(TPM_DIGEST)) != 0) {\n      tpm_free(key_buf);\n      return TPM_MA_DESTINATION;\n    }\n    if (memcmp(&restrictTicket->sourceKeyDigest, pubSourceKeyDigest,\n               sizeof(TPM_DIGEST)) != 0) {\n      tpm_free(key_buf);\n      return TPM_MA_SOURCE;\n    }\n  } else {\n    tpm_free(key_buf);\n    return TPM_BAD_PARAMETER;\n  }\n  /* set public key */\n  if (tpm_setup_pubkey_data(&migrationKeyAuth->migrationKey, &key) != 0) {\n    debug(\"tpm_setup_pubkey() failed\");\n    tpm_free(key_buf);\n    return TPM_FAIL;\n  }\n  /* generate an OAEP encoding of the TPM_MIGRATE_ASYMKEY structure:\n     0x00|seed|K1|0x00-pad|0x01|TPM_MIGRATE_ASYMKEY */\n  len = buf_len = 198;\n  ptr = buf = tpm_malloc(buf_len);\n  *randomSize = buf_len;\n  *random = tpm_malloc(*randomSize);\n  *outDataSize = key.key.size >> 3;\n  *outData = tpm_malloc(*outDataSize);\n  if (buf == NULL || *random == NULL || *outData == NULL) {\n    free_TPM_PUBKEY_DATA(key);\n    tpm_free(buf);\n    tpm_free(*random);\n    tpm_free(*outData);\n    tpm_free(key_buf);\n    return TPM_NOSPACE;\n  }\n  memset(buf, 0, buf_len);\n  tpm_marshal_UINT32(&ptr, &len, store.privKey.keyLength);\n  memcpy(ptr, store.privKey.key, 16);\n  ptr += 16;\n  tpm_sha1_init(&sha1_ctx);\n  tpm_sha1_update(&sha1_ctx, msaListDigest.digest, sizeof(TPM_DIGEST));\n  tpm_sha1_update(&sha1_ctx, pubSourceKeyDigest->digest, sizeof(TPM_DIGEST));\n  tpm_sha1_final(&sha1_ctx, ptr);\n  len = 46 + store.privKey.keyLength - 16;\n  ptr = &buf[buf_len - len];\n  tpm_marshal_BYTE(&ptr, &len, 0x01);\n  tpm_marshal_TPM_PAYLOAD_TYPE(&ptr, &len, TPM_PT_CMK_MIGRATE);\n  tpm_marshal_TPM_SECRET(&ptr, &len, &store.usageAuth);\n  tpm_marshal_TPM_DIGEST(&ptr, &len, &store.pubDataDigest);\n  tpm_marshal_UINT32(&ptr, &len, store.privKey.keyLength - 16);\n  memcpy(ptr, &store.privKey.key[16], store.privKey.keyLength - 16);\n  tpm_rsa_mask_generation(buf, SHA1_DIGEST_LENGTH,\n    &buf[SHA1_DIGEST_LENGTH], buf_len - SHA1_DIGEST_LENGTH);\n  tpm_rsa_mask_generation(&buf[SHA1_DIGEST_LENGTH],\n    buf_len - SHA1_DIGEST_LENGTH, buf, SHA1_DIGEST_LENGTH);\n  /* XOR encrypt OAEP encoding */\n  tpm_get_random_bytes(*random, *randomSize);\n  for (len = 0; len < buf_len; len++) buf[len] ^= (*random)[len];\n  /* RSA encrypt OAEP encoding */\n  if (tpm_rsa_encrypt(&key.key, RSA_ES_OAEP_SHA1, buf, buf_len,\n                      *outData, &buf_len)) {\n    debug(\"tpm_rsa_encrypt() failed\");\n    free_TPM_PUBKEY_DATA(key);\n    tpm_free(buf);\n    tpm_free(*random);\n    tpm_free(*outData);\n    tpm_free(key_buf);\n    return TPM_ENCRYPT_ERROR;\n  }\n  *outDataSize = buf_len;\n  free_TPM_PUBKEY_DATA(key);\n  tpm_free(key_buf);\n  tpm_free(buf);\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_CMK_ConvertMigration(TPM_KEY_HANDLE parentHandle,\n                                    TPM_CMK_AUTH *restrictTicket,\n                                    TPM_HMAC *sigTicket, TPM_KEY *migratedKey,\n                                    TPM_MSA_COMPOSITE *msaList,\n                                    UINT32 randomSize, BYTE *random,\n                                    TPM_AUTH *auth1,\n                                    UINT32 *outDataSize, BYTE **outData)\n{\n  TPM_RESULT res;\n  TPM_KEY_DATA *parent;\n  BYTE *ptr, *buf, *buf2;\n  UINT32 i, len;\n  size_t buf_len;\n  BYTE tag[2], hmac[SHA1_DIGEST_LENGTH];\n  TPM_STORE_ASYMKEY store;\n  tpm_sha1_ctx_t sha1_ctx;\n  tpm_hmac_ctx_t hmac_ctx;\n  TPM_PUBKEY migratedPubKey;\n  TPM_PUBKEY parentPubKey;\n  TPM_DIGEST migKeyDigest;\n  TPM_DIGEST msaListDigest;\n  TPM_DIGEST ticketDigest;\n  TPM_DIGEST parentDigest;\n\n  info(\"TPM_CMK_ConvertMigration()\");\n  /* get parent key */\n  parent = tpm_get_key(parentHandle);\n  if (parent == NULL) return TPM_INVALID_KEYHANDLE;\n  /* verify authorization */\n  if (auth1->authHandle != TPM_INVALID_HANDLE\n      || parent->authDataUsage != TPM_AUTH_NEVER) {\n    res = tpm_verify_auth(auth1, parent->usageAuth, parentHandle);\n    if (res != TPM_SUCCESS) return res;\n  }\n  /* verify key properties */\n  if (parent->keyUsage != TPM_KEY_STORAGE\n      || parent->keyFlags & TPM_KEY_FLAG_MIGRATABLE) return TPM_INVALID_KEYUSAGE;\n  if (!(migratedKey->keyFlags & TPM_KEY_FLAG_MIGRATABLE)\n      && (!(migratedKey->keyFlags & TPM_KEY_FLAG_AUTHORITY))) return TPM_INVALID_KEYUSAGE;\n  /* decrypt private key */\n  buf_len = parent->key.size >> 3;\n  buf = tpm_malloc(buf_len);\n  if (buf == NULL) return TPM_NOSPACE;\n  /* RSA decrypt OAEP encoding */\n  if (tpm_rsa_decrypt(&parent->key, RSA_ES_OAEP_SHA1, migratedKey->encData,\n                      migratedKey->encDataSize, buf, &buf_len)\n      || buf_len != randomSize || buf_len != 198) {\n    debug(\"tpm_rsa_decrypt() failed\");\n    tpm_free(buf);\n    return TPM_DECRYPT_ERROR;\n  }\n  /* XOR decrypt OAEP encoding */\n  for (len = 0; len < buf_len; len++) buf[len] ^= random[len];\n  /* unmask OAEP encoding */\n  tpm_rsa_mask_generation(&buf[SHA1_DIGEST_LENGTH],\n    buf_len - SHA1_DIGEST_LENGTH , buf, SHA1_DIGEST_LENGTH);\n  tpm_rsa_mask_generation(buf, SHA1_DIGEST_LENGTH,\n    &buf[SHA1_DIGEST_LENGTH], buf_len - SHA1_DIGEST_LENGTH);\n  /* compute digest of migrated public key */\n  memcpy(&migratedPubKey.algorithmParms, &migratedKey->algorithmParms,\n         sizeof(TPM_KEY_PARMS));\n  memcpy(&migratedPubKey.pubKey, &migratedKey->pubKey, sizeof(TPM_STORE_PUBKEY));\n  if (tpm_compute_pubkey_digest(&migratedPubKey, &migKeyDigest) != 0) {\n    debug(\"tpm_compute_pubkey_digest() failed\");\n    tpm_free(buf);\n    return TPM_FAIL;\n  }\n  /* compute digest of parent key */\n  parentPubKey.pubKey.keyLength = parent->key.size >> 3;\n  parentPubKey.pubKey.key = tpm_malloc(parentPubKey.pubKey.keyLength);\n  if (parentPubKey.pubKey.key == NULL) {\n    tpm_free(buf);\n    return TPM_NOSPACE;\n  }\n  tpm_rsa_export_modulus(&parent->key, parentPubKey.pubKey.key, NULL);\n  if (tpm_setup_key_parms(parent, &parentPubKey.algorithmParms) != 0) {\n    debug(\"tpm_setup_key_parms() failed.\");\n    tpm_free(parentPubKey.pubKey.key);\n    tpm_free(buf);\n    return TPM_FAIL;\n  }\n  if (tpm_compute_pubkey_digest(&parentPubKey, &parentDigest) != 0) {\n    debug(\"tpm_compute_pubkey_digest() failed.\");\n    free_TPM_PUBKEY(parentPubKey);\n    tpm_free(buf);\n    return TPM_FAIL;\n  }\n  free_TPM_PUBKEY(parentPubKey);\n  /* compute digest of msaList */\n  len = sizeof_TPM_MSA_COMPOSITE((*msaList));\n  ptr = buf2 = tpm_malloc(len);\n  if (buf2 == NULL || tpm_marshal_TPM_MSA_COMPOSITE(&ptr, &len, msaList)) {\n    debug(\"tpm_marshal_TPM_MSA_COMPOSITE() failed\");\n    tpm_free(buf2);\n    tpm_free(buf);\n    return TPM_FAIL;\n  }\n  tpm_sha1_init(&sha1_ctx);\n  tpm_sha1_update(&sha1_ctx, buf2, sizeof_TPM_MSA_COMPOSITE((*msaList)));\n  tpm_sha1_final(&sha1_ctx, msaListDigest.digest);\n  tpm_free(buf2);\n  /* compute digest of restrictedTicket */\n  len = sizeof_TPM_CMK_AUTH((*restrictTicket));\n  ptr = buf2 = tpm_malloc(len);\n  if (buf2 == NULL || tpm_marshal_TPM_CMK_AUTH(&ptr, &len, restrictTicket)) {\n    debug(\"tpm_marshal_TPM_CMK_AUTH() failed\");\n    tpm_free(buf2);\n    tpm_free(buf);\n    return TPM_FAIL;\n  }\n  tpm_sha1_init(&sha1_ctx);\n  tpm_sha1_update(&sha1_ctx, buf2, sizeof_TPM_CMK_AUTH((*restrictTicket)));\n  tpm_sha1_final(&sha1_ctx, ticketDigest.digest);\n  tpm_free(buf2);\n  /* verify decoded data */\n  tpm_sha1_init(&sha1_ctx);\n  tpm_sha1_update(&sha1_ctx, msaListDigest.digest, sizeof(TPM_DIGEST));\n  tpm_sha1_update(&sha1_ctx, migKeyDigest.digest, sizeof(TPM_DIGEST));\n  tpm_sha1_final(&sha1_ctx, hmac);\n  if (memcmp(&buf[20], hmac, sizeof(TPM_DIGEST)) != 0) {\n    tpm_free(buf);\n    return TPM_INVALID_STRUCTURE;\n  }\n  /* create a TPM_STORE_ASYMKEY structure */\n  for (ptr = &buf[40]; *ptr == 0x00; ptr++);\n  if (ptr[0] != 0x01 || ptr[1] != TPM_PT_CMK_MIGRATE) {\n    debug(\"OAEP encoding is invalid\");\n    tpm_free(buf);\n    return TPM_DECRYPT_ERROR;\n  }\n  ptr += 2;\n  len = buf_len - (ptr - buf);\n  store.payload = TPM_PT_MIGRATE_EXTERNAL;\n  tpm_unmarshal_TPM_SECRET(&ptr, &len, &store.usageAuth);\n  tpm_unmarshal_TPM_DIGEST(&ptr, &len, &store.pubDataDigest);\n  tpm_unmarshal_UINT32(&ptr, &len, &store.privKey.keyLength);\n  store.privKey.keyLength += 16;\n  if (store.privKey.keyLength != len + 16) {\n    error(\"invalid key length %d; expected %d\",\n          store.privKey.keyLength, len + 16);\n    tpm_free(buf);\n    return TPM_DECRYPT_ERROR;\n  }\n  memmove(&buf[20], ptr, len);\n  store.privKey.key = &buf[4];  \n  tag[0] = (TPM_TAG_CMK_MIGAUTH >> 8) & 0xff;\n  tag[1] = TPM_TAG_CMK_MIGAUTH & 0xff;\n  tpm_hmac_init(&hmac_ctx, tpmData.permanent.data.tpmProof.nonce, sizeof(TPM_NONCE));\n  tpm_hmac_update(&hmac_ctx, tag, 2);\n  tpm_hmac_update(&hmac_ctx, msaListDigest.digest, sizeof(TPM_DIGEST));\n  tpm_hmac_update(&hmac_ctx, migKeyDigest.digest, sizeof(TPM_DIGEST));\n  tpm_hmac_final(&hmac_ctx, store.migrationAuth);\n  /* verify the migration destination */\n  for (i = 0; i < msaList->MSAlist; i++) {\n    /* create hmac of TPM_CMK_SIGTICKET */\n    tag[0] = (TPM_TAG_CMK_SIGTICKET >> 8) & 0xff;\n    tag[1] = TPM_TAG_CMK_SIGTICKET & 0xff;\n    tpm_hmac_init(&hmac_ctx, tpmData.permanent.data.tpmProof.nonce,\n                  sizeof(TPM_NONCE));\n    tpm_hmac_update(&hmac_ctx, tag, 2);\n    tpm_hmac_update(&hmac_ctx, msaList->migAuthDigest[i].digest,\n                    sizeof(TPM_DIGEST));\n    tpm_hmac_update(&hmac_ctx, ticketDigest.digest, sizeof(TPM_DIGEST));\n    tpm_hmac_final(&hmac_ctx, hmac);\n    if (memcmp(hmac, sigTicket->digest, sizeof(TPM_DIGEST)) == 0) break;\n  }\n  if (i >= msaList->MSAlist) {\n    tpm_free(buf);\n    return TPM_MA_AUTHORITY;\n  }\n  if (memcmp(&restrictTicket->destinationKeyDigest, &parentDigest,\n             sizeof(TPM_DIGEST)) != 0) {\n    tpm_free(buf);\n    return TPM_MA_DESTINATION;\n  }\n  if (memcmp(&restrictTicket->sourceKeyDigest, &migKeyDigest,\n             sizeof(TPM_DIGEST)) != 0) {\n    tpm_free(buf);\n    return TPM_MA_SOURCE;\n  }\n  /* encrypt private key */\n  *outDataSize = parent->key.size >> 3;\n  *outData = tpm_malloc(*outDataSize);\n  if (*outData == NULL) {\n    tpm_free(buf);\n    return TPM_NOSPACE;\n  }\n  if (tpm_encrypt_private_key(parent, &store, *outData, outDataSize)) {\n    debug(\"tpm_encrypt_private_key() failed\");\n    tpm_free(*outData);\n    tpm_free(buf);\n    return TPM_ENCRYPT_ERROR;\n  }\n  tpm_free(buf);\n  return TPM_SUCCESS;\n}\n"
  },
  {
    "path": "tpm/tpm_nv_storage.c",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: tpm_nv_storage.c 465 2011-07-19 17:20:32Z mast $\n */\n\n#include \"tpm_emulator.h\"\n#include \"tpm_commands.h\"\n#include \"tpm_data.h\"\n#include \"tpm_handles.h\"\n\n/*\n * Non-volatile Storage ([TPM_Part3], Section 20)\n * This section handles the allocation and use of the TPM non-volatile storage.\n */\n\nTPM_NV_DATA_SENSITIVE *tpm_get_nvs(TPM_NV_INDEX index)\n{\n  int i;\n  for (i = 0; i < TPM_MAX_NVS; i++) {\n    if (tpmData.permanent.data.nvStorage[i].valid\n        && tpmData.permanent.data.nvStorage[i].pubInfo.nvIndex == index) {\n      return &tpmData.permanent.data.nvStorage[i];\n    }\n  }\n  return NULL;\n}\n\nstatic TPM_NV_DATA_SENSITIVE *tpm_get_free_nvs(void)\n{\n  int i;\n  for (i = 0; i < TPM_MAX_NVS; i++) {\n    if (!tpmData.permanent.data.nvStorage[i].valid) {\n      return &tpmData.permanent.data.nvStorage[i];\n    }\n  }\n  return NULL;\n}\n\nvoid tpm_nv_remove_data(TPM_NV_DATA_SENSITIVE *nv)\n{\n  UINT32 i;\n  /* remove data */\n  memcpy(tpmData.permanent.data.nvData + nv->dataIndex,\n    tpmData.permanent.data.nvData + nv->dataIndex + nv->pubInfo.dataSize,\n    nv->pubInfo.dataSize);\n  /* adapt indices */\n  for (i = 0; i < TPM_MAX_NVS; i++) {\n    if (tpmData.permanent.data.nvStorage[i].valid\n        && tpmData.permanent.data.nvStorage[i].dataIndex > nv->dataIndex)\n      tpmData.permanent.data.nvStorage[i].dataIndex -= nv->pubInfo.dataSize;\n  }\n  tpmData.permanent.data.nvDataSize -= nv->pubInfo.dataSize;\n  /* invalidate meta data */\n  memset(tpmData.permanent.data.nvData + tpmData.permanent.data.nvDataSize,\n    0xff, nv->pubInfo.dataSize);\n  memset(nv, 0x00, sizeof(TPM_NV_DATA_SENSITIVE));\n}\n\nTPM_RESULT TPM_NV_DefineSpace(TPM_NV_DATA_PUBLIC *pubInfo,\n                              TPM_ENCAUTH *encAuth, TPM_AUTH *auth1)\n{\n  TPM_RESULT res;\n  TPM_SECRET plainAuth;\n  TPM_NV_DATA_SENSITIVE *nv;\n  TPM_SESSION_DATA *session = NULL;\n  UINT32 i;\n\n  info(\"TPM_NV_DefineSpace()\");\n  /* lock NV storage */\n  if (auth1->authHandle == TPM_INVALID_HANDLE\n      && pubInfo->nvIndex == TPM_NV_INDEX_LOCK) {\n    debug(\"nvIndex = TPM_NV_INDEX_LOCK\");\n    tpmData.permanent.flags.nvLocked = TRUE;\n    return TPM_SUCCESS;\n  }\n  debug(\"nvIndex = %08x\", pubInfo->nvIndex);\n  /* verify maximal number of writes without an owner */\n  if (!tpmData.permanent.flags.owned\n      && ++tpmData.permanent.data.noOwnerNVWrite > TPM_MAX_NV_WRITE_NOOWNER)\n    return TPM_MAXNVWRITES;\n  /* if NV storage is not locked omit authorization verifications */\n  if (tpmData.permanent.flags.nvLocked) {\n    if (auth1->authHandle == TPM_INVALID_HANDLE) {\n      /* no authorization available */\n      if (!tpm_get_physical_presence()) return TPM_BAD_PRESENCE;\n      if (tpmData.permanent.flags.owned) return TPM_OWNER_SET;\n      if (pubInfo->dataSize == 0) return TPM_BAD_DATASIZE;\n      memcpy(plainAuth, *encAuth, sizeof(TPM_SECRET));\n    } else {\n      /* verify authorization */\n      res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);\n      if (res != TPM_SUCCESS) return res;\n      session = tpm_get_auth(auth1->authHandle);\n      if (session->type != TPM_ST_OSAP) return TPM_AUTHFAIL;\n      auth1->continueAuthSession = FALSE;\n      /* decrypt auth */\n      tpm_decrypt_auth_secret(*encAuth, session->sharedSecret,\n                              &session->lastNonceEven, plainAuth);\n    }\n    if (pubInfo->nvIndex & TPM_NV_INDEX_D) return TPM_BADINDEX;\n  }\n  /* check whether nvIndex is reserved */\n  if (pubInfo->nvIndex == TPM_NV_INDEX0\n      || pubInfo->nvIndex == TPM_NV_INDEX_DIR) return TPM_BADINDEX;\n  /* check whether nvIndex points to a valid NV storage area */\n  nv = tpm_get_nvs(pubInfo->nvIndex);\n  if (nv != NULL) {\n    if (tpmData.permanent.flags.nvLocked) {\n      if ((nv->pubInfo.permission.attributes & TPM_NV_PER_GLOBALLOCK)\n          && tpmData.stclear.flags.bGlobalLock) return TPM_AREA_LOCKED;\n      if ((nv->pubInfo.permission.attributes & TPM_NV_PER_WRITE_STCLEAR)\n          && nv->pubInfo.bWriteSTClear) return TPM_AREA_LOCKED;\n    }\n    debug(\"deleting NV storage area for index %08x\", pubInfo->nvIndex);\n    /* invalidate all associated sessions but the current one */\n    for (i = 0; i < TPM_MAX_SESSIONS; i++) {\n      if (tpmData.stany.data.sessions[i].handle == pubInfo->nvIndex\n          && &tpmData.stany.data.sessions[i] != session) {\n          memset(&tpmData.stany.data.sessions[i], 0, sizeof(TPM_SESSION_DATA));\n      }\n    }\n    /* delete the NV storage area */\n    tpm_nv_remove_data(nv);\n    if (pubInfo->dataSize == 0) return TPM_SUCCESS;\n  }\n  /* verify pcrInfoRead and pcrInfoWrite */\n  if (pubInfo->pcrInfoRead.pcrSelection.sizeOfSelect > TPM_NUM_PCR/8\n      || (pubInfo->pcrInfoRead.localityAtRelease & 0x1f) == 0\n      || (pubInfo->pcrInfoRead.localityAtRelease & 0xe0) != 0\n      || pubInfo->pcrInfoWrite.pcrSelection.sizeOfSelect > TPM_NUM_PCR/8\n      || (pubInfo->pcrInfoWrite.localityAtRelease & 0x1f) == 0\n      || (pubInfo->pcrInfoWrite.localityAtRelease & 0xe0) != 0)\n    return TPM_INVALID_STRUCTURE;\n  /* verify that attributes are consistent */\n  if ((pubInfo->permission.attributes & TPM_NV_PER_OWNERWRITE)\n      && (pubInfo->permission.attributes & TPM_NV_PER_AUTHWRITE))\n    return TPM_AUTH_CONFLICT;\n  if ((pubInfo->permission.attributes & TPM_NV_PER_OWNERREAD)\n      && (pubInfo->permission.attributes & TPM_NV_PER_AUTHREAD))\n    return TPM_AUTH_CONFLICT;\n  if (!(pubInfo->permission.attributes & (TPM_NV_PER_OWNERWRITE \n        | TPM_NV_PER_AUTHWRITE | TPM_NV_PER_WRITEDEFINE | TPM_NV_PER_PPWRITE))\n      && pubInfo->pcrInfoWrite.localityAtRelease == 0x1f) return TPM_PER_NOWRITE;\n  if (pubInfo->dataSize == 0) return TPM_BAD_PARAM_SIZE;\n  /* check whether there is enough space for the new NV storage area */\n  nv = tpm_get_free_nvs();\n  if (pubInfo->dataSize > (TPM_MAX_NV_SIZE - tpmData.permanent.data.nvDataSize)\n      || nv == NULL) return TPM_NOSPACE;\n  /* return success if this was just a test */\n  if (pubInfo->nvIndex == TPM_NV_INDEX_TRIAL) return TPM_SUCCESS;\n  /* allocate and initialize a new NV storage area */\n  nv->tag = TPM_TAG_NV_DATA_SENSITIVE;\n  memcpy(&nv->pubInfo, pubInfo, sizeof(TPM_NV_DATA_PUBLIC));\n  nv->pubInfo.bReadSTClear = FALSE;\n  nv->pubInfo.bWriteSTClear = FALSE;\n  nv->pubInfo.bWriteDefine = FALSE;\n  memcpy(nv->authValue, plainAuth, sizeof(TPM_SECRET));\n  nv->dataIndex = tpmData.permanent.data.nvDataSize;\n  tpmData.permanent.data.nvDataSize += pubInfo->dataSize;\n  nv->valid = TRUE;\n  memset(tpmData.permanent.data.nvData + nv->dataIndex, \n         0xff, pubInfo->dataSize);\n  return TPM_SUCCESS;\n}\n\nstatic TPM_RESULT nv_write(TPM_NV_DATA_SENSITIVE *nv, UINT32 offset,\n                           UINT32 dataSize, BYTE *data, BOOL verify)\n{\n  TPM_RESULT res;\n  TPM_DIGEST digest;\n\n  if (verify) {\n    /* test for physical presence if required */\n    if ((nv->pubInfo.permission.attributes & TPM_NV_PER_PPWRITE)\n        && !tpm_get_physical_presence()) return TPM_BAD_PRESENCE;\n    /* verify that area is not locked */\n    if ((nv->pubInfo.permission.attributes & TPM_NV_PER_WRITEDEFINE)\n        && nv->pubInfo.bWriteDefine) return TPM_AREA_LOCKED;\n    if ((nv->pubInfo.permission.attributes & TPM_NV_PER_GLOBALLOCK)\n        && tpmData.stclear.flags.bGlobalLock) return TPM_AREA_LOCKED;\n    if ((nv->pubInfo.permission.attributes & TPM_NV_PER_WRITE_STCLEAR)\n        && nv->pubInfo.bWriteSTClear) return TPM_AREA_LOCKED;\n    /* verify locality and PCRs */\n    if (!(nv->pubInfo.pcrInfoWrite.localityAtRelease\n          & (1 << tpmData.stany.flags.localityModifier)))\n      return TPM_BAD_LOCALITY;\n    res = tpm_compute_pcr_digest(&nv->pubInfo.pcrInfoWrite.pcrSelection,\n                                 &digest, NULL);\n    if (res != TPM_SUCCESS) return res;\n    if (memcmp(&digest, &nv->pubInfo.pcrInfoWrite.digestAtRelease,\n               sizeof(TPM_DIGEST))) return TPM_WRONGPCRVAL;\n  }\n  /* write data */\n  if (dataSize == 0) {\n    nv->pubInfo.bWriteSTClear = TRUE;\n    nv->pubInfo.bWriteDefine = TRUE;\n  } else {\n    if (offset + dataSize > nv->pubInfo.dataSize) return TPM_NOSPACE;\n    if ((nv->pubInfo.permission.attributes & TPM_NV_PER_WRITEALL)\n        && dataSize != nv->pubInfo.dataSize) return TPM_NOT_FULLWRITE;\n    memcpy(tpmData.permanent.data.nvData + nv->dataIndex + offset,\n           data, dataSize);\n  }\n  nv->pubInfo.bReadSTClear = FALSE;\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_NV_WriteValue(TPM_NV_INDEX nvIndex, UINT32 offset,\n                             UINT32 dataSize, BYTE *data, TPM_AUTH *auth1)\n{\n  TPM_RESULT res;\n  TPM_NV_DATA_SENSITIVE *nv;\n\n  info(\"TPM_NV_WriteValue()\");\n  /* set global lock */\n  if (nvIndex == TPM_NV_INDEX0) {\n    debug(\"nvIndex = TPM_NV_INDEX0\");\n    tpmData.stclear.flags.bGlobalLock = TRUE;\n    return TPM_SUCCESS;\n  }\n  debug(\"nvIndex = %08x, offset = %d, dataSize = %d\",\n        nvIndex, offset, dataSize);\n  /* get NV storage area that nvIndex points to */\n  nv = tpm_get_nvs(nvIndex);\n  if (nv == NULL) return TPM_BADINDEX;\n  if (nv->pubInfo.permission.attributes & TPM_NV_PER_AUTHWRITE)\n    return TPM_AUTH_CONFLICT;\n  /* if NV storage is not locked omit authorization verifications */\n  if (tpmData.permanent.flags.nvLocked) {\n    if (auth1->authHandle == TPM_INVALID_HANDLE) {\n      /* no authorization available */\n      if (nv->pubInfo.permission.attributes & TPM_NV_PER_OWNERWRITE)\n        return TPM_AUTH_CONFLICT;\n      if (++tpmData.permanent.data.noOwnerNVWrite > TPM_MAX_NV_WRITE_NOOWNER)\n        return TPM_MAXNVWRITES;\n    } else {\n      /* verify authorization */\n      if (!(nv->pubInfo.permission.attributes & TPM_NV_PER_OWNERWRITE))\n        return TPM_AUTH_CONFLICT;\n      res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);\n      if (res != TPM_SUCCESS) return res;\n    }\n  }\n  /* write data */\n  return nv_write(nv, offset, dataSize, data,\n                  tpmData.permanent.flags.nvLocked);\n}\n\nTPM_RESULT TPM_NV_WriteValueAuth(TPM_NV_INDEX nvIndex, UINT32 offset,\n                                 UINT32 dataSize, BYTE *data, TPM_AUTH *auth1)\n{\n  TPM_RESULT res;\n  TPM_NV_DATA_SENSITIVE *nv;\n\n  info(\"TPM_NV_WriteValueAuth()\");\n  debug(\"nvIndex = %08x, offset = %d, dataSize = %d\",\n        nvIndex, offset, dataSize);\n  /* get NV storage area that nvIndex points to */\n  nv = tpm_get_nvs(nvIndex);\n  if (nv == NULL) return TPM_BADINDEX;\n  if (!(nv->pubInfo.permission.attributes & TPM_NV_PER_AUTHWRITE))\n    return TPM_AUTH_CONFLICT;\n  /* verify authorization */\n  res = tpm_verify_auth(auth1, nv->authValue, nvIndex);\n  if (res != TPM_SUCCESS) return res;\n  /* write data */\n  return nv_write(nv, offset, dataSize, data, TRUE);\n}\n\nTPM_RESULT nv_read(TPM_NV_DATA_SENSITIVE *nv,  UINT32 offset,\n                   UINT32 inDataSize, UINT32 *outDataSize, \n                   BYTE **data, BOOL verify)\n{\n  TPM_RESULT res;\n  TPM_DIGEST digest;\n\n  if (verify) {\n    /* test for physical presence if required */\n    if ((nv->pubInfo.permission.attributes & TPM_NV_PER_PPREAD)\n        && !tpm_get_physical_presence()) return TPM_BAD_PRESENCE;\n    /* verify that area is not locked */\n    if ((nv->pubInfo.permission.attributes & TPM_NV_PER_READ_STCLEAR)\n        && nv->pubInfo.bReadSTClear) return TPM_DISABLED_CMD;\n    /* verify locality and PCRs */\n    if (!(nv->pubInfo.pcrInfoRead.localityAtRelease\n          & (1 << tpmData.stany.flags.localityModifier)))\n      return TPM_BAD_LOCALITY;\n    res = tpm_compute_pcr_digest(&nv->pubInfo.pcrInfoRead.pcrSelection,\n                                 &digest, NULL);\n    if (res != TPM_SUCCESS) return res;\n    if (memcmp(&digest, &nv->pubInfo.pcrInfoRead.digestAtRelease,\n               sizeof(TPM_DIGEST))) return TPM_WRONGPCRVAL;\n  }\n  /* read data */\n  if (inDataSize == 0) {\n    nv->pubInfo.bReadSTClear = TRUE;\n    *outDataSize = 0;\n    *data = NULL; \n  } else {\n    if (offset + inDataSize > nv->pubInfo.dataSize) return TPM_NOSPACE;\n    *outDataSize = inDataSize;\n    *data = tpm_malloc(*outDataSize);\n    if (*data == NULL) return TPM_FAIL;\n    memcpy(*data, tpmData.permanent.data.nvData + nv->dataIndex + offset,\n           inDataSize);\n  }\n  return TPM_SUCCESS;\n\n}\n\nTPM_RESULT TPM_NV_ReadValue(TPM_NV_INDEX nvIndex,  UINT32 offset,\n                            UINT32 inDataSize, TPM_AUTH *auth1,  \n                            UINT32 *outDataSize, BYTE **data)\n{\n  TPM_RESULT res;\n  TPM_NV_DATA_SENSITIVE *nv;\n\n  info(\"TPM_NV_ReadValue()\");\n  debug(\"nvIndex = %08x, offset = %d, inDataSize = %d\",\n        nvIndex, offset, inDataSize);\n  /* get NV storage area that nvIndex points to */\n  nv = tpm_get_nvs(nvIndex);\n  if (nv == NULL) return TPM_BADINDEX;\n  if (nv->pubInfo.permission.attributes & TPM_NV_PER_AUTHREAD)\n    return TPM_AUTH_CONFLICT;\n  /* if NV storage is not locked omit authorization verifications */\n  if (tpmData.permanent.flags.nvLocked) {\n    if (auth1->authHandle == TPM_INVALID_HANDLE) {\n      /* no authorization available */\n      if (nv->pubInfo.permission.attributes & TPM_NV_PER_OWNERREAD)\n        return TPM_AUTH_CONFLICT;\n    } else {\n      /* verify authorization */\n      if (!(nv->pubInfo.permission.attributes & TPM_NV_PER_OWNERREAD))\n        return TPM_AUTH_CONFLICT;\n      res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);\n      if (res != TPM_SUCCESS) return res;\n    }\n  }\n  /* read data */\n  return nv_read(nv, offset, inDataSize, outDataSize, data, TRUE);\n}\n\nTPM_RESULT TPM_NV_ReadValueAuth(TPM_NV_INDEX nvIndex,  UINT32 offset,\n                                UINT32 inDataSize, TPM_AUTH *auth1,  \n                                UINT32 *outDataSize, BYTE **data)\n{\n  TPM_RESULT res;\n  TPM_NV_DATA_SENSITIVE *nv;\n\n  info(\"TPM_NV_ReadValueAuth()\");\n  debug(\"nvIndex = %08x, offset = %d, inDataSize = %d\",\n        nvIndex, offset, inDataSize);\n  /* get NV storage area that nvIndex points to */\n  nv = tpm_get_nvs(nvIndex);\n  if (nv == NULL) return TPM_BADINDEX;\n  if (!(nv->pubInfo.permission.attributes & TPM_NV_PER_AUTHREAD))\n    return TPM_AUTH_CONFLICT;\n  /* verify authorization */\n  res = tpm_verify_auth(auth1, nv->authValue, nvIndex);\n  if (res != TPM_SUCCESS) return res;\n  /* read data */\n  return nv_read(nv, offset, inDataSize, outDataSize, data, TRUE);\n}\n\n"
  },
  {
    "path": "tpm/tpm_owner.c",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: tpm_owner.c 470 2011-10-25 12:02:49Z mast $\n */\n\n#include \"tpm_emulator.h\"\n#include \"tpm_commands.h\"\n#include \"tpm_data.h\"\n#include \"tpm_handles.h\"\n#include \"crypto/rsa.h\"\n\n/*\n * Admin Opt-in ([TPM_Part3], Section 5)\n * [tpm_owner.c]\n */\n\nTPM_RESULT TPM_SetOwnerInstall(BOOL state)\n{\n  info(\"TPM_SetOwnerInstall()\");\n  if (tpmData.permanent.flags.owned) return TPM_SUCCESS;\n  if (!tpm_get_physical_presence()) return TPM_BAD_PRESENCE;\n  tpmData.permanent.flags.ownership = state;\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_OwnerSetDisable(BOOL disableState, TPM_AUTH *auth1)\n{\n  TPM_RESULT res;\n  info(\"TPM_OwnerSetDisable()\");\n  res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);\n  if (res != TPM_SUCCESS) return res;\n  tpmData.permanent.flags.disable = disableState;\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_PhysicalEnable()\n{\n  info(\"TPM_PhysicalEnable()\");\n  if (!tpm_get_physical_presence()) return TPM_BAD_PRESENCE;\n  tpmData.permanent.flags.disable = FALSE;\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_PhysicalDisable()\n{\n  info(\"TPM_PhysicalDisable()\");\n  if (!tpm_get_physical_presence()) return TPM_BAD_PRESENCE;\n  tpmData.permanent.flags.disable = TRUE;\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_PhysicalSetDeactivated(BOOL state)\n{\n  info(\"TPM_PhysicalSetDeactivated()\");\n  if (!tpm_get_physical_presence()) return TPM_BAD_PRESENCE;\n  tpmData.permanent.flags.deactivated = state;\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_SetTempDeactivated(TPM_AUTH *auth1)\n{\n  TPM_RESULT res;\n  info(\"TPM_SetTempDeactivated()\");\n  if (auth1->authHandle == TPM_INVALID_HANDLE) {\n    if (!tpm_get_physical_presence()) return TPM_BAD_PRESENCE;\n  } else {\n    if (!tpmData.permanent.flags.operator) return TPM_NOOPERATOR;\n    res = tpm_verify_auth(auth1, tpmData.permanent.data.operatorAuth, TPM_KH_OPERATOR);\n    if (res != TPM_SUCCESS) return res;\n  }\n  tpmData.stclear.flags.deactivated = TRUE;\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_SetOperatorAuth(TPM_SECRET *operatorAuth)\n{\n  info(\"TPM_SetOperatorAuth()\");\n  if (!tpm_get_physical_presence()) return TPM_BAD_PRESENCE;\n  memcpy(&tpmData.permanent.data.operatorAuth,\n    operatorAuth, sizeof(TPM_SECRET));\n  tpmData.permanent.flags.operator = TRUE;\n  return TPM_SUCCESS;\n}\n\n/*\n * Admin Ownership ([TPM_Part3], Section 6)\n */\n\nTPM_RESULT TPM_TakeOwnership(TPM_PROTOCOL_ID protocolID,\n                             UINT32 encOwnerAuthSize, BYTE *encOwnerAuth,\n                             UINT32 encSrkAuthSize, BYTE *encSrkAuth,\n                             TPM_KEY *srkParams, TPM_AUTH *auth1,\n                             TPM_KEY *srkPub)\n{\n  TPM_RESULT res;\n  tpm_rsa_private_key_t *ek = &tpmData.permanent.data.endorsementKey;\n  TPM_KEY_DATA *srk = &tpmData.permanent.data.srk;\n  size_t buf_size = ek->size >> 3;\n  BYTE buf[buf_size];\n\n  info(\"TPM_TakeOwnership()\");\n  if (!ek->size) return TPM_NO_ENDORSEMENT;\n  if (protocolID != TPM_PID_OWNER) return TPM_BAD_PARAMETER;\n  if (tpmData.permanent.flags.owned) return TPM_OWNER_SET;\n  if (!tpmData.permanent.flags.ownership) return TPM_INSTALL_DISABLED;\n  /* decrypt ownerAuth */\n  if (tpm_rsa_decrypt(ek, RSA_ES_OAEP_SHA1, encOwnerAuth, encOwnerAuthSize,\n      buf, &buf_size) != 0) return TPM_DECRYPT_ERROR;\n  if (buf_size != sizeof(TPM_SECRET)) return TPM_BAD_KEY_PROPERTY;\n  memcpy(tpmData.permanent.data.ownerAuth, buf, buf_size);\n  /* verify authorization */\n  res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);\n  if (res != TPM_SUCCESS) return res;\n  if (tpm_get_auth(auth1->authHandle)->type != TPM_ST_OIAP)\n    return TPM_AUTHFAIL;\n  /* reset srk and decrypt srkAuth */\n  memset(srk, 0, sizeof(*srk));\n  if (tpm_rsa_decrypt(ek, RSA_ES_OAEP_SHA1, encSrkAuth, encSrkAuthSize,\n      buf, &buf_size) != 0) return TPM_DECRYPT_ERROR;\n  if (buf_size != sizeof(TPM_SECRET)) return TPM_BAD_KEY_PROPERTY;\n  memcpy(srk->usageAuth, buf, buf_size);\n  /* validate SRK parameters */\n  if (srkParams->keyFlags & TPM_KEY_FLAG_MIGRATABLE\n      || srkParams->keyUsage != TPM_KEY_STORAGE) return TPM_INVALID_KEYUSAGE;\n  if (srkParams->algorithmParms.algorithmID != TPM_ALG_RSA\n      || srkParams->algorithmParms.encScheme != TPM_ES_RSAESOAEP_SHA1_MGF1\n      || srkParams->algorithmParms.sigScheme != TPM_SS_NONE\n      || srkParams->algorithmParms.parmSize == 0\n      || srkParams->algorithmParms.parms.rsa.keyLength != 2048\n      || srkParams->algorithmParms.parms.rsa.numPrimes != 2\n      || srkParams->algorithmParms.parms.rsa.exponentSize != 0\n      || srkParams->PCRInfoSize != 0) return TPM_BAD_KEY_PROPERTY;\n  /* setup and generate SRK */\n  srk->keyFlags = srkParams->keyFlags;\n  srk->keyFlags |= TPM_KEY_FLAG_PCR_IGNORE;\n  srk->keyFlags &= ~TPM_KEY_FLAG_HAS_PCR;\n  srk->keyUsage = srkParams->keyUsage;\n  srk->encScheme = srkParams->algorithmParms.encScheme;\n  srk->sigScheme = srkParams->algorithmParms.sigScheme;\n  srk->authDataUsage = srkParams->authDataUsage;\n  debug(\"srk->authDataUsage = %02x\", srk->authDataUsage);\n  srk->parentPCRStatus = FALSE;\n  srkParams->algorithmParms.parms.rsa.keyLength = 2048;\n  if (tpm_rsa_generate_key(&srk->key,\n      srkParams->algorithmParms.parms.rsa.keyLength)) return TPM_FAIL;\n  srk->payload = TPM_PT_ASYM;\n  /* generate context, delegate, and DAA key */\n  tpm_get_random_bytes(tpmData.permanent.data.contextKey,\n    sizeof(tpmData.permanent.data.contextKey));\n  tpm_get_random_bytes(tpmData.permanent.data.delegateKey,\n      sizeof(tpmData.permanent.data.delegateKey));\n  tpm_get_random_bytes(tpmData.permanent.data.daaKey,\n      sizeof(tpmData.permanent.data.daaKey));\n  /* export SRK */\n  memcpy(srkPub, srkParams, sizeof(TPM_KEY));\n  srkPub->pubKey.keyLength = srk->key.size >> 3;\n  srkPub->pubKey.key = tpm_malloc(srkPub->pubKey.keyLength);\n  if (srkPub->pubKey.key == NULL) {\n    tpm_rsa_release_private_key(&srk->key);\n    srk->payload = TPM_PT_NONE;\n    return TPM_FAIL;\n  }\n  tpm_rsa_export_modulus(&srk->key, srkPub->pubKey.key, NULL);\n  /* setup tpmProof/daaProof and set state to owned */\n  tpm_get_random_bytes(tpmData.permanent.data.tpmProof.nonce,\n    sizeof(tpmData.permanent.data.tpmProof.nonce));\n  tpm_get_random_bytes(tpmData.permanent.data.daaProof.nonce,\n    sizeof(tpmData.permanent.data.daaProof.nonce));\n  tpmData.permanent.flags.readPubek = FALSE;\n  tpmData.permanent.flags.owned = TRUE;\n  return TPM_SUCCESS;\n}\n\nvoid tpm_owner_clear()\n{\n  int i;\n  /* unload all keys */\n  for (i = 0; i < TPM_MAX_KEYS; i++) {\n    if (tpmData.permanent.data.keys[i].payload)\n      TPM_FlushSpecific(INDEX_TO_KEY_HANDLE(i), TPM_RT_KEY);\n  }\n  /* invalidate stany and stclear data */\n  memset(&tpmData.stany.data, 0 , sizeof(tpmData.stany.data));\n  memset(&tpmData.stclear.data, 0 , sizeof(tpmData.stclear.data));\n  /* release SRK */\n  tpm_rsa_release_private_key(&tpmData.permanent.data.srk.key);\n  /* invalidate permanent data */\n  memset(&tpmData.permanent.data.ownerAuth, 0,\n    sizeof(tpmData.permanent.data.ownerAuth));\n  memset(&tpmData.permanent.data.srk, 0,\n    sizeof(tpmData.permanent.data.srk));\n  memset(&tpmData.permanent.data.tpmProof, 0,\n    sizeof(tpmData.permanent.data.tpmProof));\n  memset(&tpmData.permanent.data.operatorAuth, 0,\n    sizeof(tpmData.permanent.data.operatorAuth));\n  /* invalidate delegate, context, and DAA key */\n  memset(&tpmData.permanent.data.contextKey, 0,\n    sizeof(tpmData.permanent.data.contextKey));\n  memset(&tpmData.permanent.data.delegateKey, 0,\n    sizeof(tpmData.permanent.data.delegateKey));\n  /* set permanent data */\n  tpmData.permanent.data.noOwnerNVWrite = 0;\n  tpmData.permanent.data.restrictDelegate = 0;\n  memset (tpmData.permanent.data.ordinalAuditStatus, 0,\n          sizeof(tpmData.permanent.data.ordinalAuditStatus));\n  /* set permanent flags */\n  tpmData.permanent.flags.owned = FALSE;\n  tpmData.permanent.flags.operator = FALSE;\n  tpmData.permanent.flags.disableOwnerClear = FALSE;\n  tpmData.permanent.flags.ownership = TRUE;\n  tpmData.permanent.flags.disable = FALSE;\n  tpmData.permanent.flags.deactivated = FALSE;\n  tpmData.permanent.flags.maintenanceDone = FALSE;\n  tpmData.permanent.flags.allowMaintenance = TRUE;\n  tpmData.permanent.flags.disableFullDALogicInfo = FALSE;\n  tpmData.permanent.flags.readPubek = TRUE;\n  /* release all counters */\n  for (i = 0; i < TPM_MAX_COUNTERS; i++)\n    memset(&tpmData.permanent.data.counters[i], 0, sizeof(TPM_COUNTER_VALUE));\n  /* invalidate family and delegates table */\n  for (i = 0; i < TPM_NUM_FAMILY_TABLE_ENTRY; i++) {\n    memset(&tpmData.permanent.data.familyTable.famRow[i], 0,\n           sizeof(TPM_FAMILY_TABLE_ENTRY));\n  }\n  for (i = 0; i < TPM_NUM_DELEGATE_TABLE_ENTRY; i++) {\n    memset(&tpmData.permanent.data.delegateTable.delRow[i], 0,\n           sizeof(TPM_DELEGATE_TABLE_ROW));\n  }\n  /* release NV storage */\n  for (i = 0; i < TPM_MAX_NVS; i++) {\n    if (tpmData.permanent.data.nvStorage[i].valid\n        && (tpmData.permanent.data.nvStorage[i].pubInfo.permission.attributes\n            & (TPM_NV_PER_OWNERWRITE | TPM_NV_PER_OWNERREAD))) {\n      tpm_nv_remove_data(&tpmData.permanent.data.nvStorage[i]);\n    }\n  }\n}\n\nTPM_RESULT TPM_OwnerClear(TPM_AUTH *auth1)\n{\n  TPM_RESULT res;\n  info(\"TPM_OwnerClear()\");\n  res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);\n  if (res != TPM_SUCCESS) return res;\n  if (tpmData.permanent.flags.disableOwnerClear) return TPM_CLEAR_DISABLED;\n  tpm_owner_clear();\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_ForceClear()\n{\n  info(\"TPM_ForceClear()\");\n  if (!tpm_get_physical_presence()) return TPM_BAD_PRESENCE;\n  if (tpmData.stclear.flags.disableForceClear) return TPM_CLEAR_DISABLED;\n  tpm_owner_clear();\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_DisableOwnerClear(TPM_AUTH *auth1)\n{\n  TPM_RESULT res;\n  info(\"TPM_DisableOwnerClear()\");\n  res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);\n  if (res != TPM_SUCCESS) return res;\n  tpmData.permanent.flags.disableOwnerClear = TRUE;\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_DisableForceClear()\n{\n  info(\"TPM_DisableForceClear()\");\n  tpmData.stclear.flags.disableForceClear = TRUE;\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TSC_PhysicalPresence(TPM_PHYSICAL_PRESENCE physicalPresence)\n{\n  info(\"TSC_PhysicalPresence()\");\n  if (!tpmData.permanent.flags.physicalPresenceLifetimeLock) {\n    /* enable physicalPresenceHW or physicalPresenceCMD */\n    if (physicalPresence & TPM_PHYSICAL_PRESENCE_HW_ENABLE)\n      tpmData.permanent.flags.physicalPresenceHWEnable = TRUE;\n    if (physicalPresence & TPM_PHYSICAL_PRESENCE_CMD_ENABLE)\n      tpmData.permanent.flags.physicalPresenceCMDEnable = TRUE;\n  } else if (physicalPresence & TPM_PHYSICAL_PRESENCE_LIFETIME_LOCK) {\n    /* set physicalPresenceLifetimeLock */\n    tpmData.permanent.flags.physicalPresenceLifetimeLock = TRUE;\n  } else if (tpmData.permanent.flags.physicalPresenceCMDEnable &&\n             !tpmData.stclear.flags.physicalPresenceLock) {\n    /* set physicalPresence or physicalPresenceLock */\n    if (physicalPresence & TPM_PHYSICAL_PRESENCE_PRESENT)\n      tpmData.stclear.flags.physicalPresence = TRUE;\n    if (physicalPresence & TPM_PHYSICAL_PRESENCE_NOTPRESENT)\n      tpmData.stclear.flags.physicalPresence = FALSE;\n    if (physicalPresence & TPM_PHYSICAL_PRESENCE_LOCK)\n      tpmData.stclear.flags.physicalPresenceLock = TRUE;\n  } else {\n    return TPM_BAD_PARAMETER;\n  }\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TSC_ResetEstablishmentBit()\n{\n  info(\"TSC_ResetEstablishmentBit()\");\n  /* locality must be three or four */\n  if (tpmData.stany.flags.localityModifier != 3\n      && tpmData.stany.flags.localityModifier != 4) return TPM_BAD_LOCALITY;\n  /* as we do not have such a bit we do nothing and just return true */\n  return TPM_SUCCESS;\n}\n"
  },
  {
    "path": "tpm/tpm_startup.c",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: tpm_startup.c 367 2010-02-13 15:52:18Z mast $\n */\n\n#include \"tpm_emulator.h\"\n#include \"tpm_commands.h\"\n#include \"tpm_data.h\"\n#include \"tpm_handles.h\"\n\n/*\n * Admin Startup and State ([TPM_Part3], Section 3)\n * This section describes the commands that start a TPM.\n */\n\nvoid TPM_Init(TPM_STARTUP_TYPE startupType)\n{\n  info(\"TPM_Init()\");\n  /* startup the TPM */\n  tpmData.stany.flags.postInitialise = TRUE;\n  TPM_SelfTestFull();\n  TPM_Startup(startupType);\n}\n\n#define SET_TO_ZERO(a) memset(a, 0x00, sizeof(*a))\n#define SET_TO_0xFF(a) memset(a, 0xff, sizeof(*a)) \n#define SET_TO_RAND(a) tpm_get_random_bytes(a, sizeof(*a))\n\nTPM_RESULT TPM_Startup(TPM_STARTUP_TYPE startupType)\n{\n  int i;\n  info(\"TPM_Startup(%d)\", startupType);\n  if (tpmData.stany.flags.postInitialise == FALSE) return TPM_INVALID_POSTINIT;\n  /* reset STANY_FLAGS */\n  SET_TO_ZERO(&tpmData.stany.flags);\n  tpmData.stany.flags.tag = TPM_TAG_STANY_FLAGS;\n  /* set data and flags according to the given startup type */\n  if (startupType == TPM_ST_CLEAR) {\n    /* reset STANY_DATA (invalidates ALL sessions) */\n    SET_TO_ZERO(&tpmData.stany.data);\n    tpmData.stany.data.tag = TPM_TAG_STANY_DATA;\n    /* init session-context nonce */\n    SET_TO_RAND(&tpmData.stany.data.contextNonceSession);\n    /* reset PCR values */\n    for (i = 0; i < TPM_NUM_PCR; i++) {\n      if (tpmData.permanent.data.pcrAttrib[i].pcrReset)\n        SET_TO_0xFF(&tpmData.permanent.data.pcrValue[i].digest);\n      else\n        SET_TO_ZERO(&tpmData.permanent.data.pcrValue[i].digest);\n    }\n    /* reset STCLEAR_FLAGS */\n    SET_TO_ZERO(&tpmData.stclear.flags);\n    tpmData.stclear.flags.tag = TPM_TAG_STCLEAR_FLAGS;\n    tpmData.stclear.flags.deactivated = tpmData.permanent.flags.deactivated;\n    /* reset STCLEAR_DATA */\n    SET_TO_ZERO(&tpmData.stclear.data);\n    tpmData.stclear.data.tag = TPM_TAG_STCLEAR_DATA;\n    /* flush volatiles and PCR dependent keys */\n    for (i = 0; i < TPM_MAX_KEYS; i++) {\n      if (tpmData.permanent.data.keys[i].payload\n          && ((tpmData.permanent.data.keys[i].keyFlags & TPM_KEY_FLAG_VOLATILE)\n              || tpmData.permanent.data.keys[i].parentPCRStatus))\n        TPM_FlushSpecific(INDEX_TO_KEY_HANDLE(i), TPM_RT_KEY);\n    }\n    /* init key-context nonce */\n    SET_TO_RAND(&tpmData.stclear.data.contextNonceKey);\n    /* invalidate counter handle */\n    tpmData.stclear.data.countID = TPM_INVALID_HANDLE;\n    /* reset NV read and write flags */\n    for (i = 0; i < TPM_MAX_NVS; i++) {\n        tpmData.permanent.data.nvStorage[i].pubInfo.bReadSTClear = FALSE;\n        tpmData.permanent.data.nvStorage[i].pubInfo.bWriteSTClear = FALSE;\n    }\n  } else if (startupType == TPM_ST_STATE) {\n    if (!tpmData.permanent.flags.dataRestored) {\n      error(\"restoring permanent data failed\");\n      tpmData.permanent.data.testResult = \"tpm_restore_permanent_data() failed\";\n      tpmData.permanent.flags.selfTestSucceeded = FALSE;\n      return TPM_FAIL;\n    }\n  } else if (startupType == TPM_ST_DEACTIVATED) {\n    tpmData.stclear.flags.deactivated = TRUE;\n    /* invalidate any saved state */\n    tpm_erase_permanent_data();\n  } else {\n    return TPM_BAD_PARAMETER;\n  }\n  tpmData.stany.flags.postInitialise = FALSE;\n  tpmData.stany.flags.TOSPresent = FALSE;\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_SaveState()\n{\n  info(\"TPM_SaveState()\");\n  if (tpmData.permanent.flags.selfTestSucceeded && !tpmData.stclear.flags.deactivated) { \n    return (tpm_store_permanent_data()) ? TPM_FAIL : TPM_SUCCESS;\n  } else {\n    debug(\"TPM is deactivated or in fail-stop mode, thus the permanent data is not stored\");\n    return TPM_SUCCESS;\n  }\n}\n"
  },
  {
    "path": "tpm/tpm_storage.c",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: tpm_storage.c 364 2010-02-11 10:24:45Z mast $\n */\n\n#include \"tpm_emulator.h\"\n#include \"tpm_commands.h\"\n#include \"tpm_data.h\"\n#include \"tpm_handles.h\"\n#include \"crypto/sha1.h\"\n#include \"crypto/rsa.h\"\n#include \"tpm_marshalling.h\"\n\n/*\n * Storage functions ([TPM_Part3], Section 10)\n */\n\nTPM_KEY_HANDLE tpm_get_free_key(void)\n{\n  int i;\n  for (i = 0; i < TPM_MAX_KEYS; i++) {\n    if (!tpmData.permanent.data.keys[i].payload) {\n      tpmData.permanent.data.keys[i].payload = TPM_PT_ASYM;\n      return INDEX_TO_KEY_HANDLE(i);\n    }\n  }\n  return TPM_INVALID_HANDLE;\n}\n\nint tpm_encrypt_public(TPM_PUBKEY_DATA *key, BYTE *in, UINT32 in_size,\n                       BYTE *enc, UINT32 *enc_size)\n{\n  size_t size = *enc_size;\n  int scheme;\n  switch (key->encScheme) {\n    case TPM_ES_RSAESOAEP_SHA1_MGF1: scheme = RSA_ES_OAEP_SHA1; break;\n    case TPM_ES_RSAESPKCSv15: scheme = RSA_ES_PKCSV15; break;\n    default:\n      debug(\"unsupported encryption scheme: %d\", key->encScheme);\n      return -1;\n  }\n  if (tpm_rsa_encrypt(&key->key, scheme, in, in_size, enc, &size) != 0) {\n    debug(\"tpm_rsa_encrypt() failed\");\n    return -1;\n  }\n  *enc_size = size;\n  return 0;\n}\n\nint tpm_encrypt_private(TPM_KEY_DATA *key, BYTE *in, UINT32 in_size,\n                        BYTE *enc, UINT32 *enc_size)\n{\n  int res;\n  TPM_PUBKEY_DATA pubKey;\n  pubKey.encScheme = key->encScheme;\n  TPM_RSA_EXTRACT_PUBLIC_KEY(key->key, pubKey.key);\n  res = tpm_encrypt_public(&pubKey, in, in_size, enc, enc_size);\n  free_TPM_PUBKEY_DATA(pubKey);\n  return res;\n}\n\nint tpm_decrypt(TPM_KEY_DATA *key, BYTE *enc, UINT32 enc_size,\n                BYTE *out, UINT32 *out_size)\n{\n  size_t size = *out_size;\n  int scheme;\n  switch (key->encScheme) {\n    case TPM_ES_RSAESOAEP_SHA1_MGF1: scheme = RSA_ES_OAEP_SHA1; break;\n    case TPM_ES_RSAESPKCSv15: scheme = RSA_ES_PKCSV15; break;\n    default:\n      debug(\"unsupported encryption scheme: %d\", key->encScheme);\n      return -1;\n  }\n  if (tpm_rsa_decrypt(&key->key, scheme, enc, enc_size, out, &size) != 0) {\n    debug(\"tpm_rsa_decrypt() failed\");\n    return -1;\n  }\n  *out_size = size;\n  return 0;\n}\n\nint tpm_encrypt_sealed_data(TPM_KEY_DATA *key, TPM_SEALED_DATA *seal,\n                            BYTE *enc, UINT32 *enc_size)\n{\n  UINT32 len = sizeof_TPM_SEALED_DATA((*seal));\n  BYTE *buf, *ptr;\n  buf = ptr = tpm_malloc(len);\n  if (buf == NULL\n      || tpm_marshal_TPM_SEALED_DATA(&ptr, &len, seal)\n      || tpm_encrypt_private(key, buf, sizeof_TPM_SEALED_DATA((*seal)),\n                             enc, enc_size)) {\n    tpm_free(buf);\n    return -1;\n  }\n  tpm_free(buf);\n  return 0;\n}\n\nint tpm_decrypt_sealed_data(TPM_KEY_DATA *key, BYTE *enc, UINT32 enc_size,\n                            TPM_SEALED_DATA *seal, BYTE **buf)\n{\n  BYTE *ptr;\n  *buf = ptr = tpm_malloc(enc_size);\n  if (*buf == NULL\n      || tpm_decrypt(key, enc, enc_size, *buf, &enc_size)\n      || tpm_unmarshal_TPM_SEALED_DATA(&ptr, &enc_size, seal)) {\n    tpm_free(*buf);\n    return -1;\n  }\n  return 0;\n}\n\nint tpm_encrypt_private_key(TPM_KEY_DATA *key, TPM_STORE_ASYMKEY *store,\n                            BYTE *enc, UINT32 *enc_size)\n{\n  UINT32 len = sizeof_TPM_STORE_ASYMKEY((*store));\n  BYTE *buf, *ptr;\n  buf = ptr = tpm_malloc(len);\n  if (buf == NULL\n      || tpm_marshal_TPM_STORE_ASYMKEY(&ptr, &len, store)\n      || tpm_encrypt_private(key, buf, sizeof_TPM_STORE_ASYMKEY((*store)),\n                             enc, enc_size)) {\n    tpm_free(buf);\n    return -1;\n  }\n  tpm_free(buf);\n  return 0;\n}\n\nint tpm_decrypt_private_key(TPM_KEY_DATA *key, BYTE *enc, UINT32 enc_size,\n                            TPM_STORE_ASYMKEY *store,\n                            BYTE **buf, UINT32 *buf_size)\n{\n  BYTE *ptr;\n  *buf = ptr = tpm_malloc(enc_size);\n  if (*buf == NULL || tpm_decrypt(key, enc, enc_size, *buf, &enc_size)) {\n    tpm_free(*buf);\n    return -1;\n  }\n  if (buf_size != NULL) *buf_size = enc_size;\n  if (tpm_unmarshal_TPM_STORE_ASYMKEY(&ptr, &enc_size, store) != 0) {\n    tpm_free(*buf);\n    return -1;\n  }\n  if (buf_size != NULL) *buf_size -= enc_size;\n  return 0;\n}\n\nstatic void tpm_xor_encrypt(TPM_SESSION_DATA *session, TPM_NONCE *nonceOdd,\n                            BYTE *data, UINT32 data_size)\n{\n  BYTE seed[2 * sizeof(TPM_NONCE) + 3 + sizeof(TPM_SECRET)];\n  BYTE *ptr = seed;\n\n  /* set up seed */\n  memcpy(ptr, session->lastNonceEven.nonce, sizeof(TPM_NONCE));\n  ptr += sizeof(TPM_NONCE);\n  memcpy(ptr, nonceOdd->nonce, sizeof(TPM_NONCE));\n  ptr += sizeof(TPM_NONCE);\n  memcpy(ptr, (const BYTE*)\"XOR\", 3);\n  ptr += 3;\n  memcpy(ptr, session->sharedSecret, sizeof(TPM_SECRET));\n  /* decrypt data */\n  tpm_rsa_mask_generation(seed, sizeof(seed), data, data_size);\n}\n\nint tpm_compute_key_digest(TPM_KEY *key, TPM_DIGEST *digest)\n{\n  tpm_sha1_ctx_t sha1;\n  UINT32 len = sizeof_TPM_KEY((*key));\n  BYTE *buf, *ptr;\n  buf = ptr = tpm_malloc(len);\n  if (buf == NULL\n      || tpm_marshal_TPM_KEY(&ptr, &len, key)) {\n    tpm_free(buf);\n    return -1;\n  }\n  /* compute SHA1 hash */\n  tpm_sha1_init(&sha1);\n  tpm_sha1_update(&sha1, buf, sizeof_TPM_KEY((*key)) - key->encDataSize - 4);\n  tpm_sha1_final(&sha1, digest->digest);\n  tpm_free(buf);\n  return 0;\n}\n\nint tpm_compute_key_data_digest(TPM_KEY_DATA *key, TPM_DIGEST *digest)\n{\n  tpm_sha1_ctx_t sha1;\n  UINT32 key_len = key->key.size >> 3;\n  BYTE *buf = tpm_malloc(4 + key_len);\n  if (buf == NULL) {\n    debug(\"tpm_malloc() failed.\");\n    return -1;\n  }\n  /* extract modulus  */\n  buf[0] = (key_len >> 24) & 0xff;\n  buf[1] = (key_len >> 16) & 0xff;\n  buf[2] = (key_len >>  8) & 0xff;\n  buf[3] = (key_len >>  0) & 0xff;\n  tpm_rsa_export_modulus(&key->key, &buf[4], NULL);\n  /* compute SHA1 hash */\n  tpm_sha1_init(&sha1);\n  tpm_sha1_update(&sha1, buf, 4 + key_len);\n  tpm_sha1_final(&sha1, digest->digest);\n  tpm_free(buf);\n  return 0;\n}\n\nstatic int tpm_verify_key_digest(TPM_KEY *key, TPM_DIGEST *digest)\n{\n  TPM_DIGEST key_digest;\n  if (tpm_compute_key_digest(key, &key_digest)) return -1;\n  return memcmp(key_digest.digest, digest->digest, sizeof(key_digest.digest));\n}\n\nint tpm_compute_pubkey_checksum(TPM_NONCE *antiReplay, TPM_PUBKEY *pubKey,\n                                TPM_DIGEST *checksum)\n{\n  tpm_sha1_ctx_t sha1;\n  UINT32 len = sizeof_TPM_PUBKEY((*pubKey));\n  BYTE buf[len], *ptr = buf;\n\n  if (tpm_marshal_TPM_PUBKEY(&ptr, &len, pubKey)) return -1;\n  /* compute SHA1 hash */\n  tpm_sha1_init(&sha1);\n  tpm_sha1_update(&sha1, buf, sizeof_TPM_PUBKEY((*pubKey)));\n  tpm_sha1_update(&sha1, antiReplay->nonce, sizeof(antiReplay->nonce));\n  tpm_sha1_final(&sha1, checksum->digest);\n  return 0;\n}\n\nint tpm_compute_pubkey_digest(TPM_PUBKEY *key, TPM_DIGEST *digest)\n{\n  tpm_sha1_ctx_t sha1;\n  UINT32 len = sizeof_TPM_PUBKEY((*key));\n  BYTE *buf, *ptr;\n  buf = ptr = tpm_malloc(len);\n  if (buf == NULL\n      || tpm_marshal_TPM_PUBKEY(&ptr, &len, key)) {\n    tpm_free(buf);\n    return -1;\n  }\n  /* compute SHA1 hash */\n  tpm_sha1_init(&sha1);\n  tpm_sha1_update(&sha1, buf, sizeof_TPM_PUBKEY((*key)));\n  tpm_sha1_final(&sha1, digest->digest);\n  tpm_free(buf);\n  return 0;\n}\n\nint tpm_setup_key_parms(TPM_KEY_DATA *key, TPM_KEY_PARMS *parms)\n{\n  size_t exp_len;\n  parms->algorithmID = TPM_ALG_RSA;\n  parms->encScheme = key->encScheme;\n  parms->sigScheme = key->sigScheme;\n  parms->parms.rsa.keyLength = key->key.size;\n  parms->parms.rsa.numPrimes = 2;\n  if (tpm_bn_cmp_ui(key->key.e, 65537) == 0) {\n    parms->parms.rsa.exponentSize = 0;\n    parms->parms.rsa.exponent = NULL;\n  } else {\n    parms->parms.rsa.exponentSize = tpm_rsa_exponent_length(&key->key);\n    parms->parms.rsa.exponent = tpm_malloc(parms->parms.rsa.exponentSize);\n    if (parms->parms.rsa.exponent == NULL) return -1;\n    tpm_rsa_export_exponent(&key->key, parms->parms.rsa.exponent, &exp_len);\n    parms->parms.rsa.exponentSize = exp_len;\n  }\n  parms->parmSize = 12 + parms->parms.rsa.exponentSize;\n  return 0;\n}\n\nint tpm_setup_pubkey_data(TPM_PUBKEY *in, TPM_PUBKEY_DATA *out)\n{\n  out->valid = TRUE;\n  out->encScheme = in->algorithmParms.encScheme;\n  out->sigScheme = in->algorithmParms.sigScheme;\n  out->key.size = in->algorithmParms.parms.rsa.keyLength;\n  if (tpm_rsa_import_public_key(&out->key, RSA_MSB_FIRST,\n      in->pubKey.key, in->pubKey.keyLength,\n      in->algorithmParms.parms.rsa.exponent,\n      in->algorithmParms.parms.rsa.exponentSize) != 0) return -1;\n  return 0;\n}\n\nint tpm_extract_pubkey(TPM_KEY_DATA *key, TPM_PUBKEY *pubKey)\n{\n  pubKey->pubKey.keyLength = key->key.size >> 3;\n  pubKey->pubKey.key = tpm_malloc(pubKey->pubKey.keyLength);\n  if (pubKey->pubKey.key == NULL) {\n    debug(\"tpm_malloc() failed.\");\n    return -1;\n  }\n  tpm_rsa_export_modulus(&key->key, pubKey->pubKey.key, NULL);\n  if (tpm_setup_key_parms(key, &pubKey->algorithmParms) != 0) {\n    debug(\"tpm_setup_key_parms() failed.\");\n    tpm_free(pubKey->pubKey.key);\n    return -1;\n  }\n  return 0;\n}\n\nint tpm_extract_store_pubkey(TPM_KEY_DATA *key, TPM_STORE_PUBKEY *pubKey)\n{\n  pubKey->keyLength = key->key.size >> 3;\n  pubKey->key = tpm_malloc(pubKey->keyLength);\n  if (pubKey->key == NULL) {\n    debug(\"tpm_malloc() failed.\");\n    return -1;\n  }\n  tpm_rsa_export_modulus(&key->key, pubKey->key, NULL);\n  return 0;\n}\n\nstatic int compute_store_digest(TPM_STORED_DATA *store, TPM_DIGEST *digest)\n{\n  tpm_sha1_ctx_t sha1;\n  UINT32 len = sizeof_TPM_STORED_DATA((*store));\n  BYTE *buf, *ptr;\n  buf = ptr = tpm_malloc(len);\n  if (buf == NULL\n      || tpm_marshal_TPM_STORED_DATA(&ptr, &len, store)) {\n    tpm_free(buf);\n    return -1;\n  }\n  /* compute SHA1 hash */\n  tpm_sha1_init(&sha1);\n  tpm_sha1_update(&sha1, buf, sizeof_TPM_STORED_DATA((*store)));\n  tpm_sha1_final(&sha1, digest->digest);\n  tpm_free(buf);\n  return 0;\n}\n\nstatic int verify_store_digest(TPM_STORED_DATA *store, TPM_DIGEST *digest)\n{\n  TPM_DIGEST store_digest;\n  if (compute_store_digest(store, &store_digest)) return -1;\n  return memcmp(store_digest.digest, digest->digest,\n    sizeof(store_digest.digest));\n}\n\nTPM_RESULT TPM_Seal(TPM_KEY_HANDLE keyHandle, TPM_ENCAUTH *encAuth,\n                    UINT32 pcrInfoSize, TPM_PCR_INFO *pcrInfo,\n                    UINT32 inDataSize, BYTE *inData,\n                    TPM_AUTH *auth1, TPM_STORED_DATA *sealedData)\n{\n  TPM_RESULT res;\n  TPM_KEY_DATA *key;\n  TPM_SESSION_DATA *session;\n  TPM_SEALED_DATA seal;\n  info(\"TPM_Seal()\");\n  if (inDataSize == 0) return TPM_BAD_PARAMETER;\n  /* get key */\n  key = tpm_get_key(keyHandle);\n  if (key == NULL) return TPM_INVALID_KEYHANDLE;\n  /* verify authorization */\n  res = tpm_verify_auth(auth1, key->usageAuth, keyHandle);\n  if (res != TPM_SUCCESS) return res;\n  auth1->continueAuthSession = FALSE;\n  session = tpm_get_auth(auth1->authHandle);\n  if (session->type != TPM_ST_OSAP) return TPM_AUTHFAIL;\n  /* verify key properties */\n  if (key->keyUsage != TPM_KEY_STORAGE\n      || key->keyFlags & TPM_KEY_FLAG_MIGRATABLE)\n    return TPM_INVALID_KEYUSAGE;\n  /* setup store */\n  if (pcrInfo->tag == TPM_TAG_PCR_INFO_LONG) {\n    sealedData->tag = TPM_TAG_STORED_DATA12;\n    sealedData->et = 0x0000;\n  } else {\n    sealedData->tag = 0x0101;\n    sealedData->et = 0x0000;\n  }   \n  sealedData->encDataSize = 0;\n  sealedData->encData = NULL;\n  sealedData->sealInfoSize = pcrInfoSize;\n  if (pcrInfoSize > 0) {\n    sealedData->sealInfoSize = pcrInfoSize;\n    memcpy(&sealedData->sealInfo, pcrInfo, sizeof(TPM_PCR_INFO));\n    res = tpm_compute_pcr_digest(&pcrInfo->creationPCRSelection, \n      &sealedData->sealInfo.digestAtCreation, NULL);\n    if (res != TPM_SUCCESS) return res;\n    sealedData->sealInfo.localityAtCreation = \n      tpmData.stany.flags.localityModifier;\n  }\n  /* setup seal */\n  seal.payload = TPM_PT_SEAL;\n  memcpy(&seal.tpmProof, &tpmData.permanent.data.tpmProof, \n    sizeof(TPM_NONCE));\n  if (compute_store_digest(sealedData, &seal.storedDigest)) {\n    debug(\"TPM_Seal(): compute_store_digest() failed.\");\n    return TPM_FAIL;\n  }\n  if ((session->entityType & 0xff00) !=  TPM_ET_XOR)\n    return TPM_INAPPROPRIATE_ENC;\n  tpm_decrypt_auth_secret(*encAuth, session->sharedSecret,\n    &session->lastNonceEven, seal.authData);\n  seal.dataSize = inDataSize; \n  seal.data = inData;\n  /* encrypt sealed data */\n  sealedData->encDataSize = key->key.size >> 3;\n  sealedData->encData = tpm_malloc(sealedData->encDataSize);\n  if (sealedData->encData == NULL) return TPM_NOSPACE;\n  if (tpm_encrypt_sealed_data(key, &seal, sealedData->encData, \n                              &sealedData->encDataSize)) {\n    tpm_free(sealedData->encData);\n    return TPM_ENCRYPT_ERROR;\n  }\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_Sealx(TPM_KEY_HANDLE keyHandle, TPM_ENCAUTH *encAuth,\n                    UINT32 pcrInfoSize, TPM_PCR_INFO *pcrInfo,\n                    UINT32 inDataSize, BYTE *inData,\n                    TPM_AUTH *auth1, TPM_STORED_DATA *sealedData)\n{\n  TPM_RESULT res;\n  TPM_KEY_DATA *key;\n  TPM_SESSION_DATA *session;\n  TPM_SEALED_DATA seal;\n\n  info(\"TPM_Sealx()\");\n  if (inDataSize == 0) return TPM_BAD_PARAMETER;\n  /* get key */\n  key = tpm_get_key(keyHandle);\n  if (key == NULL) return TPM_INVALID_KEYHANDLE;\n  /* verify authorization */\n  res = tpm_verify_auth(auth1, key->usageAuth, keyHandle);\n  if (res != TPM_SUCCESS) return res;\n  auth1->continueAuthSession = FALSE;\n  session = tpm_get_auth(auth1->authHandle);\n  if (session->type != TPM_ST_OSAP) return TPM_AUTHFAIL;\n  /* verify key properties */\n  if (key->keyUsage != TPM_KEY_STORAGE\n      || key->keyFlags & TPM_KEY_FLAG_MIGRATABLE)\n    return TPM_INVALID_KEYUSAGE;\n  /* setup store */\n  if (pcrInfo->tag != TPM_TAG_PCR_INFO_LONG)\n    return TPM_BAD_PARAMETER;\n  if ((session->entityType & 0xff00) !=  TPM_ET_XOR)\n    return TPM_INAPPROPRIATE_ENC;\n  sealedData->tag = TPM_TAG_STORED_DATA12;\n  sealedData->et = TPM_ET_XOR | TPM_ET_KEY;\n  sealedData->encDataSize = 0;\n  sealedData->encData = NULL;\n  sealedData->sealInfoSize = pcrInfoSize;\n  if (pcrInfoSize > 0) {\n    sealedData->sealInfoSize = pcrInfoSize;\n    memcpy(&sealedData->sealInfo, pcrInfo, sizeof(TPM_PCR_INFO));\n    res = tpm_compute_pcr_digest(&pcrInfo->creationPCRSelection,\n      &sealedData->sealInfo.digestAtCreation, NULL);\n    if (res != TPM_SUCCESS) return res;\n    sealedData->sealInfo.localityAtCreation =\n      tpmData.stany.flags.localityModifier;\n  }  \n  /* setup seal */\n  seal.payload = TPM_PT_SEAL;\n  memcpy(&seal.tpmProof, &tpmData.permanent.data.tpmProof,\n    sizeof(TPM_NONCE));\n  if (compute_store_digest(sealedData, &seal.storedDigest)) {\n    debug(\"TPM_Sealx(): compute_store_digest() failed.\");\n    return TPM_FAIL;\n  }\n  tpm_decrypt_auth_secret(*encAuth, session->sharedSecret,\n    &session->lastNonceEven, seal.authData);\n  tpm_xor_encrypt(session, &auth1->nonceOdd, inData, inDataSize);\n  seal.dataSize = inDataSize;\n  seal.data = inData;\n  /* encrypt sealed data */\n  sealedData->encDataSize = key->key.size >> 3;\n  sealedData->encData = tpm_malloc(sealedData->encDataSize);\n  if (sealedData->encData == NULL) return TPM_NOSPACE;\n  if (tpm_encrypt_sealed_data(key, &seal, sealedData->encData,\n                              &sealedData->encDataSize)) {\n    tpm_free(sealedData->encData);\n    return TPM_ENCRYPT_ERROR;\n  }\n  return TPM_SUCCESS;\n\n}\n\nTPM_RESULT TPM_Unseal(TPM_KEY_HANDLE parentHandle, TPM_STORED_DATA *inData,\n                      TPM_AUTH *auth1, TPM_AUTH *auth2,  UINT32 *sealedDataSize, \n                      BYTE **secret)\n{\n  TPM_RESULT res;\n  TPM_KEY_DATA *key;\n  TPM_SESSION_DATA *session;\n  TPM_SEALED_DATA seal;\n  BYTE *seal_buf;\n  TPM_DIGEST digest;\n  info(\"TPM_Unseal()\");\n  /* get key */\n  key = tpm_get_key(parentHandle);\n  if (key == NULL) return TPM_INVALID_KEYHANDLE;\n  /* verify authorization, if only auth1 is present we use it for the data */\n  if (auth2->authHandle != TPM_INVALID_HANDLE \n      || key->authDataUsage != TPM_AUTH_NEVER) {\n    res = tpm_verify_auth(auth1, key->usageAuth, parentHandle);\n    if (res != TPM_SUCCESS) return res;\n    auth1->continueAuthSession = FALSE;\n    session = tpm_get_auth(auth1->authHandle);\n  } else {\n    session = NULL;\n  }\n  /* verify key properties */\n  if (key->keyUsage != TPM_KEY_STORAGE\n      || key->keyFlags & TPM_KEY_FLAG_MIGRATABLE) return TPM_INVALID_KEYUSAGE;\n  /* verify PCR info */\n  if (inData->sealInfoSize > 0) {\n    res = tpm_compute_pcr_digest(&inData->sealInfo.releasePCRSelection,\n      &digest, NULL);\n    if (res != TPM_SUCCESS) return res;\n    if (memcmp(&digest, &inData->sealInfo.digestAtRelease, sizeof(TPM_DIGEST)))\n      return TPM_WRONGPCRVAL;\n    if (inData->sealInfo.tag == TPM_TAG_PCR_INFO_LONG\n        && !(inData->sealInfo.localityAtRelease \n             & (1 << tpmData.stany.flags.localityModifier)))\n       return TPM_BAD_LOCALITY;\n  }\n  /* decrypt sealed data */\n  if (tpm_decrypt_sealed_data(key, inData->encData, inData->encDataSize,\n                              &seal, &seal_buf)) return TPM_DECRYPT_ERROR;\n  inData->encDataSize = 0;\n  if (seal.payload != TPM_PT_SEAL\n      || memcmp(&tpmData.permanent.data.tpmProof, &seal.tpmProof, \n             sizeof(TPM_NONCE))\n      || verify_store_digest(inData, &seal.storedDigest)) {\n    tpm_free(seal_buf);\n    return TPM_NOTSEALED_BLOB;\n  }\n  /* verify data auth */\n  if (auth2->authHandle != TPM_INVALID_HANDLE) {\n    res = tpm_verify_auth(auth2, seal.authData, TPM_INVALID_HANDLE);\n    if (res != TPM_SUCCESS) return (res == TPM_AUTHFAIL) ? TPM_AUTH2FAIL : res;\n  } else {\n    res = tpm_verify_auth(auth1, seal.authData, TPM_INVALID_HANDLE);\n    if (res != TPM_SUCCESS) return res;\n  }\n  /* encrypt data if required */\n  debug(\"entity type = %04x\", inData->et & 0xff00);\n  if (inData->et != 0) {\n     if (auth2->authHandle == TPM_INVALID_HANDLE) return TPM_AUTHFAIL;\n     if (session->type != TPM_ST_OSAP) return TPM_BAD_MODE;\n     if ((inData->et & 0xff00) == TPM_ET_XOR) {\n        tpm_xor_encrypt(session, &auth1->nonceOdd, seal.data, seal.dataSize);\n     } else return TPM_INAPPROPRIATE_ENC;\n  }\n  /* return secret */\n  *sealedDataSize = seal.dataSize;\n  *secret = tpm_malloc(*sealedDataSize);\n  if (*secret == NULL) {\n    tpm_free(seal_buf);\n    return TPM_NOSPACE;\n  }\n  memcpy(*secret, seal.data, seal.dataSize);\n  tpm_free(seal_buf);\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_UnBind(TPM_KEY_HANDLE keyHandle, UINT32 inDataSize,\n                      BYTE *inData, TPM_AUTH *auth1, \n                      UINT32 *outDataSize, BYTE **outData)\n{\n  TPM_RESULT res;\n  TPM_KEY_DATA *key;\n  size_t out_len;\n  int scheme;\n  \n  info(\"TPM_UnBind()\");\n  /* get key */\n  key = tpm_get_key(keyHandle);\n  if (key == NULL) return TPM_INVALID_KEYHANDLE;\n  /* verify auth */\n  if (auth1->authHandle != TPM_INVALID_HANDLE \n      || key->authDataUsage != TPM_AUTH_NEVER) {\n    res = tpm_verify_auth(auth1, key->usageAuth, keyHandle);\n    if (res != TPM_SUCCESS) return res;\n  }\n  /* verify key properties */\n  if (key->keyUsage != TPM_KEY_BIND \n      && key->keyUsage != TPM_KEY_LEGACY) return TPM_INVALID_KEYUSAGE;\n  /* the size of the input data muss be greater than zero */\n  if (inDataSize == 0) return TPM_BAD_PARAMETER;\n  /* decrypt data */\n  *outDataSize = inDataSize;\n  *outData = tpm_malloc(*outDataSize);\n  if (*outData == NULL) return TPM_NOSPACE;\n  switch (key->encScheme) {\n    case TPM_ES_RSAESOAEP_SHA1_MGF1: scheme = RSA_ES_OAEP_SHA1; break;\n    case TPM_ES_RSAESPKCSv15: scheme = RSA_ES_PKCSV15; break;\n    default: tpm_free(*outData); return TPM_DECRYPT_ERROR;\n  }\n  if (tpm_rsa_decrypt(&key->key, scheme, inData, inDataSize, *outData, &out_len)) {\n    tpm_free(*outData);\n    return TPM_DECRYPT_ERROR;\n  }\n  *outDataSize = out_len;\n  /* verify data if it is of type TPM_BOUND_DATA */\n  if (key->encScheme == TPM_ES_RSAESOAEP_SHA1_MGF1 \n      || key->keyUsage != TPM_KEY_LEGACY) {\n    if (*outDataSize < 5 || memcmp(*outData, \"\\x01\\x01\\00\\x00\\x02\", 5) != 0) {\n      tpm_free(*outData);\n      return TPM_DECRYPT_ERROR;\n    }\n    *outDataSize -= 5;\n    memmove(*outData, &(*outData)[5], *outDataSize);\n  }\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_CreateWrapKey(TPM_KEY_HANDLE parentHandle, \n                             TPM_ENCAUTH *dataUsageAuth,\n                             TPM_ENCAUTH *dataMigrationAuth,\n                             TPM_KEY *keyInfo, TPM_AUTH *auth1,  \n                             TPM_KEY *wrappedKey)\n{\n  TPM_RESULT res;\n  TPM_KEY_DATA *parent;\n  TPM_SESSION_DATA *session;\n  TPM_STORE_ASYMKEY store;\n  tpm_rsa_private_key_t rsa;\n  UINT32 key_length;\n\n  info(\"TPM_CreateWrapKey()\");\n  /* get parent key */\n  parent = tpm_get_key(parentHandle);\n  if (parent == NULL) return TPM_INVALID_KEYHANDLE;\n  /* verify authorization */\n  res = tpm_verify_auth(auth1, parent->usageAuth, parentHandle);\n  if (res != TPM_SUCCESS) return res;\n  auth1->continueAuthSession = FALSE;\n  session = tpm_get_auth(auth1->authHandle);\n  if (session->type != TPM_ST_OSAP && session->type != TPM_ST_DSAP)\n    return TPM_AUTHFAIL;\n  /* verify key parameters */\n  if (parent->keyUsage != TPM_KEY_STORAGE\n      || parent->encScheme == TPM_ES_NONE\n      || ((parent->keyFlags & TPM_KEY_FLAG_MIGRATABLE)\n          && !(keyInfo->keyFlags & TPM_KEY_FLAG_MIGRATABLE))\n      || keyInfo->keyUsage == TPM_KEY_IDENTITY\n      || keyInfo->keyUsage == TPM_KEY_AUTHCHANGE) return TPM_INVALID_KEYUSAGE;\n  if (keyInfo->algorithmParms.algorithmID != TPM_ALG_RSA\n      || keyInfo->algorithmParms.parmSize == 0\n      || keyInfo->algorithmParms.parms.rsa.keyLength < 512\n      || keyInfo->algorithmParms.parms.rsa.numPrimes != 2\n      || keyInfo->algorithmParms.parms.rsa.exponentSize != 0)\n    return TPM_BAD_KEY_PROPERTY;\n  if (tpmData.permanent.flags.FIPS\n      && (keyInfo->algorithmParms.parms.rsa.keyLength < 1024\n          || keyInfo->authDataUsage == TPM_AUTH_NEVER\n          || keyInfo->keyUsage == TPM_KEY_LEGACY)) return TPM_NOTFIPS;\n  if ((keyInfo->keyUsage == TPM_KEY_STORAGE\n       || keyInfo->keyUsage == TPM_KEY_MIGRATE)\n      && (keyInfo->algorithmParms.algorithmID != TPM_ALG_RSA\n          || keyInfo->algorithmParms.parms.rsa.keyLength != 2048\n          || keyInfo->algorithmParms.sigScheme != TPM_SS_NONE\n          || keyInfo->algorithmParms.encScheme != TPM_ES_RSAESOAEP_SHA1_MGF1))\n    return TPM_BAD_KEY_PROPERTY;\n  /* setup the wrapped key */\n  memcpy(wrappedKey, keyInfo, sizeof(TPM_KEY));\n  /* setup key store */\n  store.payload = TPM_PT_ASYM;\n  tpm_decrypt_auth_secret(*dataUsageAuth, session->sharedSecret, \n    &session->lastNonceEven, store.usageAuth);\n  if (keyInfo->keyFlags & TPM_KEY_FLAG_MIGRATABLE) {\n    tpm_decrypt_auth_secret(*dataMigrationAuth, session->sharedSecret, \n      &auth1->nonceOdd, store.migrationAuth);\n    /* clear PCR digest */\n    if (keyInfo->PCRInfoSize > 0) {\n      memset(keyInfo->PCRInfo.digestAtCreation.digest, 0,\n          sizeof(keyInfo->PCRInfo.digestAtCreation.digest));\n      keyInfo->PCRInfo.localityAtCreation = 0;\n    }\n  } else {\n    memcpy(store.migrationAuth, tpmData.permanent.data.tpmProof.nonce, \n      sizeof(TPM_SECRET));\n    /* compute PCR digest */\n    if (keyInfo->PCRInfoSize > 0) {\n      tpm_compute_pcr_digest(&keyInfo->PCRInfo.creationPCRSelection, \n        &keyInfo->PCRInfo.digestAtCreation, NULL);\n      keyInfo->PCRInfo.localityAtCreation = \n        tpmData.stany.flags.localityModifier;\n    }\n  }\n  /* generate key and store it */\n  key_length = keyInfo->algorithmParms.parms.rsa.keyLength;\n  if (tpm_rsa_generate_key(&rsa, key_length)) {\n    debug(\"TPM_CreateWrapKey(): tpm_rsa_generate_key() failed.\");\n    return TPM_FAIL;\n  }\n  wrappedKey->pubKey.keyLength = key_length >> 3;\n  wrappedKey->pubKey.key = tpm_malloc(wrappedKey->pubKey.keyLength);\n  store.privKey.keyLength = key_length >> 4;\n  store.privKey.key = tpm_malloc(store.privKey.keyLength);\n  wrappedKey->encDataSize = parent->key.size >> 3;\n  wrappedKey->encData = tpm_malloc(wrappedKey->encDataSize);\n  if (wrappedKey->pubKey.key == NULL || store.privKey.key == NULL\n      || wrappedKey->encData == NULL) {\n    tpm_rsa_release_private_key(&rsa);\n    tpm_free(wrappedKey->pubKey.key);\n    tpm_free(store.privKey.key);\n    tpm_free(wrappedKey->encData);\n    return TPM_NOSPACE;\n  }\n  tpm_rsa_export_modulus(&rsa, wrappedKey->pubKey.key, NULL);\n  tpm_rsa_export_prime1(&rsa, store.privKey.key, NULL);\n  tpm_rsa_release_private_key(&rsa);\n  /* compute the digest of the wrapped key (without encData) */\n  if (tpm_compute_key_digest(wrappedKey, &store.pubDataDigest)) {\n    debug(\"TPM_CreateWrapKey(): tpm_compute_key_digest() failed.\");\n    return TPM_FAIL;\n  }\n  /* encrypt private key data */\n  if (tpm_encrypt_private_key(parent, &store, wrappedKey->encData, \n      &wrappedKey->encDataSize)) {\n    tpm_free(wrappedKey->pubKey.key);\n    tpm_free(store.privKey.key);\n    tpm_free(wrappedKey->encData);\n    return TPM_ENCRYPT_ERROR;\n  }\n  tpm_free(store.privKey.key);\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_LoadKey(TPM_KEY_HANDLE parentHandle, TPM_KEY *inKey,\n                       TPM_AUTH *auth1, TPM_KEY_HANDLE *inkeyHandle)\n{\n  TPM_RESULT res;\n  TPM_KEY_DATA *parent, *key;\n  BYTE *key_buf;\n  TPM_STORE_ASYMKEY store;\n  info(\"TPM_LoadKey()\");\n  /* get parent key */\n  debug(\"parentHandle = %08x\", parentHandle);\n  parent = tpm_get_key(parentHandle);\n  if (parent == NULL) return TPM_INVALID_KEYHANDLE;\n  /* verify authorization */\n  if (auth1->authHandle != TPM_INVALID_HANDLE) {\n    debug(\"authDataUsage = %02x\", parent->authDataUsage);\n    res = tpm_verify_auth(auth1, parent->usageAuth, parentHandle);\n    if (res != TPM_SUCCESS) return res;\n  } else if (parent->authDataUsage != TPM_AUTH_NEVER) {\n    debug(\"TPM_LoadKey(): parent key requires authorization.\");\n    return TPM_AUTHFAIL;\n  }\n  if (parent->keyUsage != TPM_KEY_STORAGE) return TPM_INVALID_KEYUSAGE;\n  /* verify key properties */\n  if (inKey->algorithmParms.algorithmID != TPM_ALG_RSA\n      || inKey->algorithmParms.parmSize == 0\n      || inKey->algorithmParms.parms.rsa.keyLength > 2048\n      || inKey->algorithmParms.parms.rsa.numPrimes != 2)\n    return TPM_BAD_KEY_PROPERTY;\n  if (inKey->keyUsage == TPM_KEY_AUTHCHANGE) return TPM_INVALID_KEYUSAGE;\n  if (inKey->keyUsage == TPM_KEY_STORAGE\n       && (inKey->algorithmParms.algorithmID != TPM_ALG_RSA\n           || inKey->algorithmParms.parms.rsa.keyLength != 2048\n           || inKey->algorithmParms.sigScheme != TPM_SS_NONE)) \n    return TPM_INVALID_KEYUSAGE;\n  if (inKey->keyUsage == TPM_KEY_IDENTITY\n      && (inKey->keyFlags & TPM_KEY_FLAG_MIGRATABLE\n          || inKey->algorithmParms.algorithmID != TPM_ALG_RSA\n          || inKey->algorithmParms.parms.rsa.keyLength != 2048\n          || inKey->algorithmParms.encScheme != TPM_ES_NONE)) \n    return TPM_INVALID_KEYUSAGE;\n  /* decrypt private key */\n  if (tpm_decrypt_private_key(parent, inKey->encData, inKey->encDataSize,\n                              &store, &key_buf, NULL)) return TPM_DECRYPT_ERROR;\n  /* get a free key-slot, if any free slot is left */\n  *inkeyHandle = tpm_get_free_key();\n  key = tpm_get_key(*inkeyHandle);\n  if (key == NULL) {\n    tpm_free(key_buf);\n    return TPM_NOSPACE;\n  }\n  /* import key */\n  if (tpm_verify_key_digest(inKey, &store.pubDataDigest) != 0) {\n    debug(\"tpm_verify_key_digest() failed.\");\n    memset(key, 0, sizeof(TPM_KEY_DATA));\n    tpm_free(key_buf);\n    return TPM_FAIL;\n  }\n  if (inKey->pubKey.keyLength != (store.privKey.keyLength * 2)) {\n    debug(\"size of the public modulus does not match the secret prime\");\n    memset(key, 0, sizeof(TPM_KEY_DATA));\n    tpm_free(key_buf);\n    return TPM_FAIL;\n  }\n  if (tpm_rsa_import_key(&key->key, RSA_MSB_FIRST,\n                         inKey->pubKey.key, inKey->pubKey.keyLength,\n                         inKey->algorithmParms.parms.rsa.exponent,\n                         inKey->algorithmParms.parms.rsa.exponentSize,\n                         store.privKey.key, NULL)) {\n    debug(\"tpm_rsa_import_key() failed.\");\n    memset(key, 0, sizeof(TPM_KEY_DATA));\n    tpm_free(key_buf);\n    return TPM_FAIL;\n  }\n  /* verify tpmProof */\n  if (!(inKey->keyFlags & TPM_KEY_FLAG_MIGRATABLE)) {\n    if (memcmp(tpmData.permanent.data.tpmProof.nonce,\n               store.migrationAuth, sizeof(TPM_NONCE))) {\n      debug(\"TPM_LoadKey(): tpmProof verification failed.\");\n      memset(key, 0, sizeof(TPM_KEY_DATA));\n      tpm_free(key_buf);\n      return TPM_FAIL;\n    }\n  }\n  if (store.payload) key->payload = store.payload;\n  key->keyUsage = inKey->keyUsage;\n  key->keyFlags = inKey->keyFlags;\n  key->authDataUsage = inKey->authDataUsage;\n  key->encScheme = inKey->algorithmParms.encScheme;\n  key->sigScheme = inKey->algorithmParms.sigScheme;\n  memcpy(key->usageAuth, store.usageAuth, sizeof(TPM_SECRET));\n  memcpy(key->migrationAuth, store.migrationAuth, sizeof(TPM_SECRET));\n  /* setup PCR info */\n  if (inKey->PCRInfoSize > 0) {\n    memcpy(&key->pcrInfo, &inKey->PCRInfo, sizeof(TPM_PCR_INFO));\n    key->keyFlags |= TPM_KEY_FLAG_HAS_PCR;\n  } else {\n    key->keyFlags |= TPM_KEY_FLAG_PCR_IGNORE;\n    key->keyFlags &= ~TPM_KEY_FLAG_HAS_PCR;\n  }\n  key->parentPCRStatus = parent->parentPCRStatus;\n  tpm_free(key_buf);\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_LoadKey2(TPM_KEY_HANDLE parentHandle, TPM_KEY *inKey,\n                        TPM_AUTH *auth1, TPM_KEY_HANDLE *inkeyHandle)\n{\n  info(\"TPM_LoadKey2()\");\n  return TPM_LoadKey(parentHandle, inKey, auth1, inkeyHandle);\n}\n\nTPM_RESULT internal_TPM_LoadKey(TPM_KEY *inKey, TPM_KEY_HANDLE *inkeyHandle)\n{\n  TPM_KEY_DATA *parent, *key;\n  BYTE *key_buf;\n  TPM_STORE_ASYMKEY store;\n  info(\"internal_TPM_LoadKey()\");\n  /* get SRK */\n  parent = tpm_get_key(TPM_KH_SRK);\n  if (parent == NULL) return TPM_FAIL;\n  /* verify key properties */\n  if (inKey->algorithmParms.algorithmID != TPM_ALG_RSA\n      || inKey->algorithmParms.parmSize == 0\n      || inKey->algorithmParms.parms.rsa.keyLength > 2048\n      || inKey->algorithmParms.parms.rsa.numPrimes != 2)\n    return TPM_BAD_KEY_PROPERTY;\n  /* decrypt private key */\n  if (tpm_decrypt_private_key(parent, inKey->encData, inKey->encDataSize,\n                              &store, &key_buf, NULL)) return TPM_DECRYPT_ERROR;\n  /* get a free key-slot, if any free slot is left */\n  *inkeyHandle = tpm_get_free_key();\n  key = tpm_get_key(*inkeyHandle);\n  if (key == NULL) {\n    tpm_free(key_buf);\n    return TPM_NOSPACE;\n  }\n  /* import key */\n  if (tpm_verify_key_digest(inKey, &store.pubDataDigest)\n      || inKey->pubKey.keyLength != (store.privKey.keyLength * 2)\n      || tpm_rsa_import_key(&key->key, RSA_MSB_FIRST,\n                        inKey->pubKey.key, inKey->pubKey.keyLength,\n                        inKey->algorithmParms.parms.rsa.exponent,\n                        inKey->algorithmParms.parms.rsa.exponentSize,\n                        store.privKey.key, NULL)) {\n    debug(\"internal_LoadKey(): tpm_verify_key_digest() or tpm_rsa_import_key() failed.\");\n    memset(key, 0, sizeof(TPM_KEY_DATA));\n    tpm_free(key_buf);\n    return TPM_FAIL;\n  }\n  key->keyUsage = inKey->keyUsage;\n  key->keyFlags = inKey->keyFlags;\n  key->authDataUsage = inKey->authDataUsage;\n  key->encScheme = inKey->algorithmParms.encScheme;\n  key->sigScheme = inKey->algorithmParms.sigScheme;\n  memcpy(key->usageAuth, store.usageAuth, sizeof(TPM_SECRET));\n  /* setup PCR info */\n  if (inKey->PCRInfoSize > 0) {\n    memcpy(&key->pcrInfo, &inKey->PCRInfo, sizeof(TPM_PCR_INFO));\n    key->keyFlags |= TPM_KEY_FLAG_HAS_PCR;\n  } else {\n    key->keyFlags |= TPM_KEY_FLAG_PCR_IGNORE;\n    key->keyFlags &= ~TPM_KEY_FLAG_HAS_PCR;\n  }\n  key->parentPCRStatus = parent->parentPCRStatus;\n  tpm_free(key_buf);\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_GetPubKey(TPM_KEY_HANDLE keyHandle, TPM_AUTH *auth1,\n                         TPM_PUBKEY *pubKey)\n{\n  TPM_RESULT res;\n  TPM_KEY_DATA *key;\n  TPM_DIGEST digest;\n  info(\"TPM_GetPubKey()\");\n  /* get key */\n  if (keyHandle == TPM_KH_SRK\n      && !tpmData.permanent.flags.readSRKPub) return TPM_INVALID_KEYHANDLE;\n  key = tpm_get_key(keyHandle);\n  if (key == NULL) return TPM_INVALID_KEYHANDLE;\n  /* verify authorization */\n  if (auth1->authHandle != TPM_INVALID_HANDLE\n      || (key->authDataUsage != TPM_AUTH_NEVER\n          && key->authDataUsage != TPM_AUTH_PRIV_USE_ONLY)) {\n              res = tpm_verify_auth(auth1, key->usageAuth, keyHandle);\n              if (res != TPM_SUCCESS) return res;\n  }\n  if (!(key->keyFlags & TPM_KEY_FLAG_PCR_IGNORE)) {\n    res = tpm_compute_pcr_digest(&key->pcrInfo.releasePCRSelection,\n      &digest, NULL);\n    if (res != TPM_SUCCESS) return res;\n    if (memcmp(&digest, &key->pcrInfo.digestAtRelease, sizeof(TPM_DIGEST)))\n      return TPM_WRONGPCRVAL;\n    if (key->pcrInfo.tag == TPM_TAG_PCR_INFO_LONG\n        && !(key->pcrInfo.localityAtRelease\n             & (1 << tpmData.stany.flags.localityModifier)))\n       return TPM_BAD_LOCALITY;\n  }\n  /* extract pubKey */\n  if (tpm_extract_pubkey(key, pubKey) != 0) return TPM_FAIL;\n  return TPM_SUCCESS;\n}\n"
  },
  {
    "path": "tpm/tpm_structures.h",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *               2005-2008 Heiko Stamer <stamer@gaos.org>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: tpm_structures.h 467 2011-07-19 17:36:12Z mast $\n */\n\n#ifndef _TPM_STRUCTURES_H_\n#define _TPM_STRUCTURES_H_\n\n#include \"tpm_emulator.h\"\n#include \"crypto/rsa.h\"\n\n/*\n * The following types and structures are specified in\n * TPM Main Part 2 TPM Structures [TPM_Part2].\n */\n\n/*\n * Basic Data Types ([TPM_Part2], Section 2.2.1 and 2.2.2)\n */\ntypedef uint8_t  BYTE;\ntypedef uint16_t UINT16;\ntypedef uint32_t UINT32;\ntypedef uint64_t UINT64;\ntypedef BYTE     BOOL;\n#define TRUE     0x01\n#define FALSE    0x00\n\n/*\n * TPM Helper Data Types ([TPM_Part2], Section 2.2.3)\n */\ntypedef BYTE   TPM_AUTH_DATA_USAGE;\ntypedef BYTE   TPM_PAYLOAD_TYPE;\ntypedef BYTE   TPM_VERSION_BYTE;\ntypedef BYTE   TPM_DA_STATE;\ntypedef UINT16 TPM_TAG;\ntypedef UINT16 TPM_PROTOCOL_ID;\ntypedef UINT16 TPM_STARTUP_TYPE;\ntypedef UINT16 TPM_ENC_SCHEME;\ntypedef UINT16 TPM_SIG_SCHEME;\ntypedef UINT16 TPM_MIGRATE_SCHEME;\ntypedef UINT16 TPM_PHYSICAL_PRESENCE;\ntypedef UINT16 TPM_ENTITY_TYPE;\ntypedef UINT16 TPM_KEY_USAGE;\ntypedef UINT16 TPM_EK_TYPE;\ntypedef UINT16 TPM_STRUCTURE_TAG;\ntypedef UINT16 TPM_PLATFORM_SPECIFIC;\ntypedef UINT32 TPM_COMMAND_CODE;\ntypedef UINT32 TPM_CAPABILITY_AREA;\ntypedef UINT32 TPM_KEY_FLAGS;\ntypedef UINT32 TPM_ALGORITHM_ID;\ntypedef UINT32 TPM_MODIFIER_INDICATOR;\ntypedef UINT32 TPM_ACTUAL_COUNT;\ntypedef UINT32 TPM_TRANSPORT_ATTRIBUTES;\ntypedef UINT32 TPM_AUTHHANDLE;\ntypedef UINT32 TPM_DIRINDEX;\ntypedef UINT32 TPM_KEY_HANDLE;\ntypedef UINT32 TPM_PCRINDEX;\ntypedef UINT32 TPM_RESULT;\ntypedef UINT32 TPM_RESOURCE_TYPE;\ntypedef UINT32 TPM_KEY_CONTROL;\ntypedef UINT32 TPM_NV_INDEX;\ntypedef UINT32 TPM_FAMILY_ID;\ntypedef UINT32 TPM_FAMILY_VERIFICATION;\ntypedef UINT32 TPM_STARTUP_EFFECTS;\ntypedef UINT32 TPM_SYM_MODE;\ntypedef UINT32 TPM_FAMILY_FLAGS;\ntypedef UINT32 TPM_DELEGATE_INDEX;\ntypedef UINT32 TPM_CMK_DELEGATE;\ntypedef UINT32 TPM_COUNT_ID;\ntypedef UINT32 TPM_REDIT_COMMAND;\ntypedef UINT32 TPM_TRANSHANDLE;\ntypedef UINT32 TPM_HANDLE;\ntypedef UINT32 TPM_FAMILY_OPERATION;\n\n/*\n * Vendor Specific ([TPM_Part2], Section 2.2.4)\n */\n#define TPM_Vendor_Specific32   0x00000400\n#define TPM_Vendor_Specific8    0x80\n\n/*\n * Structure Tags ([TPM_Part2], Section 3.1)\n * are defined together with the dedicated structures.\n */\n\n/*\n * TPM_RESOURCE_TYPE ([TPM_Part2], Section 4.1)\n * Specifies the resource type.\n */\n#define TPM_RT_KEY              0x00000001\n#define TPM_RT_AUTH             0x00000002\n#define TPM_RT_HASH             0x00000003\n#define TPM_RT_TRANS            0x00000004\n#define TPM_RT_CONTEXT          0x00000005\n#define TPM_RT_COUNTER          0x00000006\n#define TPM_RT_DELEGATE         0x00000007\n#define TPM_RT_DAA_TPM          0x00000008\n#define TPM_RT_DAA_V0           0x00000009\n#define TPM_RT_DAA_V1           0x0000000A\n\n/*\n * TPM_PAYLOAD_TYPE ([TPM_Part2], Section 4.2)\n * This specifies the type of payload in various messages.\n */\n#define TPM_PT_ASYM                     0x01\n#define TPM_PT_BIND                     0x02\n#define TPM_PT_MIGRATE                  0x03\n#define TPM_PT_MAINT                    0x04\n#define TPM_PT_SEAL                     0x05\n#define TPM_PT_MIGRATE_RESTRICTED       0x06\n#define TPM_PT_MIGRATE_EXTERNAL         0x07\n#define TPM_PT_CMK_MIGRATE              0x08\n/* 0x09 - 0x7F Reserved for future use by TPM */\n/* 0x80 - 0xFF Vendor specific payloads */\n#define TPM_PT_NONE                     0x00\n\n/*\n * TPM_ENTITY_TYPE ([TPM_Part2], Section 4.3)\n * This specifies the types of entity and ADIP encryption schemes\n * that are supported by the TPM.\n *\n * The LSB is used to indicate the entity type. The MSB is used to\n * indicate the ADIP encryption scheme when applicable.\n * \n * For compatibility with TPM 1.1, some values are maintained.\n */\n/* LSB Values */\n#define TPM_ET_KEYHANDLE        0x01\n#define TPM_ET_OWNER            0x02\n#define TPM_ET_DATA             0x03\n#define TPM_ET_SRK              0x04\n#define TPM_ET_KEY              0x05\n#define TPM_ET_REVOKE           0x06\n#define TPM_ET_DEL_OWNER_BLOB   0x07\n#define TPM_ET_DEL_ROW          0x08\n#define TPM_ET_DEL_KEY_BLOB     0x09\n#define TPM_ET_COUNTER          0x0A\n#define TPM_ET_NV               0x0B\n#define TPM_ET_OPERATOR         0x0C\n#define TPM_ET_VERIFICATION_AUTH 0x0D\n#define TPM_ET_RESERVED_HANDLE  0x40\n/* MSB Values */\n#define TPM_ET_XOR              0x00\n#define TPM_ET_AES128_CTR       0x06\n\n/*\n * Reserved Key Handles ([TPM_Part2], Section 4.4.1)\n * These values specify specific keys or specific actions for the TPM.\n */\n#define TPM_KH_SRK              0x40000000\n#define TPM_KH_OWNER            0x40000001\n#define TPM_KH_REVOKE           0x40000002\n#define TPM_KH_TRANSPORT        0x40000003\n#define TPM_KH_OPERATOR         0x40000004\n#define TPM_KH_ADMIN            0x40000005\n#define TPM_KH_EK               0x40000006\n\n/*\n * TPM_STARTUP_TYPE ([TPM_Part2], Section 4.5)\n * To specify what type of startup is occurring.\n */\n#define TPM_ST_CLEAR            0x0001\n#define TPM_ST_STATE            0x0002\n#define TPM_ST_DEACTIVATED      0x0003\n\n/*\n * TPM_STARTUP_EFFECTS ([TPM_Part2], Section 4.6)\n * This structure lists for the various resources and sessions on a TPM\n * the affect that TPM_Startup has on the values.\n */\n/* 31-8 reserved and must be 0 */\n#define TPM_STARTUP_RT_DAA_TPM_ST_STATE        (1 << 8)\n#define TPM_STARTUP_AUDIT_DIGEST_IGNORE        (1 << 7)\n#define TPM_STARTUP_AUDIT_DIGEST_ST_CLEAR      (1 << 6)\n#define TPM_STARTUP_AUDIT_DIGEST_ST_ANY        (1 << 5)\n#define TPM_STARTUP_RT_KEY_ST_ANY              (1 << 4)\n#define TPM_STARTUP_RT_AUTH_ST_STATE           (1 << 3)\n#define TPM_STARTUP_RT_HASH_ST_STATE           (1 << 2)\n#define TPM_STARTUP_RT_TRANS_ST_STATE          (1 << 1)\n#define TPM_STARTUP_RT_CONTEXT_ST_STATE        (1 << 0)\n\n/*\n * TPM_PROTOCOL_ID ([TPM_Part2], Section 4.7)\n * This value identifies the protocol in use.\n */\n#define TPM_PID_OIAP            0x0001\n#define TPM_PID_OSAP            0x0002\n#define TPM_PID_ADIP            0x0003\n#define TPM_PID_ADCP            0x0004\n#define TPM_PID_OWNER           0x0005\n#define TPM_PID_DSAP            0x0006\n#define TPM_PID_TRANSPORT       0x0007\n\n/*\n * TPM_ALGORITHM_ID ([TPM_Part2], Section 4.8)\n * This table defines the types of algorithms which may be supported by the TPM.\n */\n#define TPM_ALG_RSA             0x00000001\n#define TPM_ALG_DES             0x00000002\n#define TPM_ALG_3DES            0x00000003\n#define TPM_ALG_SHA             0x00000004\n#define TPM_ALG_HMAC            0x00000005\n#define TPM_ALG_AES128          0x00000006\n#define TPM_ALG_MGF1            0x00000007\n#define TPM_ALG_AES192          0x00000008\n#define TPM_ALG_AES256          0x00000009\n#define TPM_ALG_XOR             0x0000000A\n\n/*\n * TPM_PHYSICAL_PRESENCE ([TPM_Part2], Section 4.9)\n * Values to setup the Physical Presence\n */\n#define TPM_PHYSICAL_PRESENCE_HW_DISABLE        0x0200\n#define TPM_PHYSICAL_PRESENCE_CMD_DISABLE       0x0100\n#define TPM_PHYSICAL_PRESENCE_LIFETIME_LOCK     0x0080\n#define TPM_PHYSICAL_PRESENCE_HW_ENABLE         0x0040\n#define TPM_PHYSICAL_PRESENCE_CMD_ENABLE        0x0020\n#define TPM_PHYSICAL_PRESENCE_NOTPRESENT        0x0010\n#define TPM_PHYSICAL_PRESENCE_PRESENT           0x0008\n#define TPM_PHYSICAL_PRESENCE_LOCK              0x0004\n\n/*\n * TPM_MIGRATE_SCHEME ([TPM_Part2], Section 4.10)\n * Indicates how the StartMigrate command should handle the\n * migration of the encrypted blob.\n */\n#define TPM_MS_MIGRATE                    0x0001\n#define TPM_MS_REWRAP                     0x0002\n#define TPM_MS_MAINT                      0x0003\n#define TPM_MS_RESTRICT_MIGRATE           0x0004\n#define TPM_MS_RESTRICT_APPROVE           0x0005\n\n/*\n * TPM_EK_TYPE ([TPM_Part2], Section 4.11)\n * Indicates what type of information that the EK is dealing with.\n */\n#define TPM_EK_TYPE_ACTIVATE    0x0001\n#define TPM_EK_TYPE_AUTH        0x0002\n\n/*\n * TPM_PLATFORM_SPECIFIC ([TPM_Part2], Section 4.12)\n * Indicates the platform specific spec that the information relates to.\n */\n#define TPM_PS_PC_11            0x0001\n#define TPM_PS_PC_12            0x0002\n#define TPM_PS_PDA_12           0x0003\n#define TPM_PS_Server_12        0x0004\n#define TPM_PS_Mobile_12        0x0005\n\n/*\n * TPM Basic Structures\n */\n\n/*\n * TPM_STRUCT_VER ([TPM_Part2], Section 5.1)\n * This indicates the version of the structure.\n */\ntypedef struct tdTPM_STRUCT_VER {\n  BYTE major;\n  BYTE minor;\n  BYTE revMajor;\n  BYTE revMinor;\n} TPM_STRUCT_VER;\n\n/*\n * TPM_VERSION ([TPM_Part2], Section 5.3)\n * This structure provides information relative the version of the TPM.\n * This structure should only be in use by TPM_GetCapability to provide\n * the information relative to the TPM.\n */\ntypedef struct tdTPM_VERSION {\n  TPM_VERSION_BYTE major;\n  TPM_VERSION_BYTE minor;\n  BYTE revMajor;\n  BYTE revMinor;\n} TPM_VERSION;\n#define sizeof_TPM_VERSION(s) (4)\n\n/*\n * TPM_DIGEST ([TPM_Part2], Section 5.4)\n * The digest value reports the result of a hash operation.\n * In version 1 the hash algorithm is SHA-1 (20 bytes resp. 160 bits).\n */\ntypedef struct tdTPM_DIGEST {\n  BYTE digest[20];\n} TPM_DIGEST;\n\n/* Redefinitions */\ntypedef TPM_DIGEST TPM_CHOSENID_HASH;\ntypedef TPM_DIGEST TPM_COMPOSITE_HASH;\ntypedef TPM_DIGEST TPM_DIRVALUE;\ntypedef TPM_DIGEST TPM_HMAC;\ntypedef TPM_DIGEST TPM_PCRVALUE;\ntypedef TPM_DIGEST TPM_AUDITDIGEST;\n\n/*\n * TPM_NONCE ([TPM_Part2], Section 5.5)\n * A random value that provides protection from replay and other attacks.\n */\ntypedef struct tdTPM_NONCE{\n  BYTE nonce[20];\n} TPM_NONCE;\n\n/* Redefinitions */\ntypedef TPM_NONCE TPM_DAA_TPM_SEED;\ntypedef TPM_NONCE TPM_DAA_CONTEXT_SEED;\n\n/*\n * TPM_AUTHDATA ([TPM_Part2], Section 5.6)\n * Information that is saved or passed to provide proof of ownership of an\n * entity. For version 1 this area is always 20 bytes.\n */\ntypedef BYTE TPM_AUTHDATA[20];\n\n/* Redefinitions */\ntypedef TPM_AUTHDATA TPM_SECRET;\ntypedef TPM_AUTHDATA TPM_ENCAUTH;\n\n/*\n * TPM_KEY_HANDLE_LIST ([TPM_Part2], Section 5.7)\n * Structure used to describe the handles of all keys currently\n * loaded into a TPM.\n */\ntypedef struct tdTPM_KEY_HANDLE_LIST {\n  UINT16 loaded;\n  TPM_KEY_HANDLE *handle;\n} TPM_KEY_HANDLE_LIST;\n\n/*\n * TPM_KEY_USAGE ([TPM_Part2], Section 5.8)\n * Defines the types of keys that are possible.\n */\n#define TPM_KEY_SIGNING         0x0010\n#define TPM_KEY_STORAGE         0x0011\n#define TPM_KEY_IDENTITY        0x0012\n#define TPM_KEY_AUTHCHANGE      0x0013\n#define TPM_KEY_BIND            0x0014\n#define TPM_KEY_LEGACY          0x0015\n#define TPM_KEY_MIGRATE         0x0016\n\n/* \n * Encryption Schemes ([TPM_Part2], Section 5.8.1)\n */\n#define TPM_ES_NONE                    0x0001\n#define TPM_ES_RSAESPKCSv15            0x0002\n#define TPM_ES_RSAESOAEP_SHA1_MGF1     0x0003\n#define TPM_ES_SYM_CTR                 0x0004\n#define TPM_ES_SYM_OFB                 0x0005\n\n/*\n * Signature Schemes ([TPM_Part2], Section 5.8.1)\n */\n#define TPM_SS_NONE                    0x0001\n#define TPM_SS_RSASSAPKCS1v15_SHA1     0x0002\n#define TPM_SS_RSASSAPKCS1v15_DER      0x0003\n#define TPM_SS_RSASSAPKCS1v15_INFO     0x0004\n\n/*\n * TPM_AUTH_DATA_USAGE ([TPM_Part2], Section 5.9)\n * Indication when authorization sessions for an entity are required.\n */\n#define TPM_AUTH_NEVER          0x00\n#define TPM_AUTH_ALWAYS         0x01\n#define TPM_AUTH_PRIV_USE_ONLY  0x03\n\n/*\n * TPM_KEY_FLAGS ([TPM_Part2], Section 5.10)\n * This table defines the meanings of the bits in a TPM_KEY_FLAGS structure.\n */\n#define TPM_KEY_FLAG_REDIRECT   0x00000001\n#define TPM_KEY_FLAG_MIGRATABLE 0x00000002\n#define TPM_KEY_FLAG_VOLATILE   0x00000004\n#define TPM_KEY_FLAG_PCR_IGNORE 0x00000008\n#define TPM_KEY_FLAG_AUTHORITY  0x00000010\n/* to use with TPM_KEY_DATA only! */\n#define TPM_KEY_FLAG_HAS_PCR    0x10000000\n#define TPM_KEY_FLAG_MASK       0x0fffffff\n\n/*\n * TPM_CHANGEAUTH_VALIDATE ([TPM_Part2], Section 5.11)\n * To store the new authorization data and the challenger's nonce.\n */\ntypedef struct tdTPM_CHANGEAUTH_VALIDATE {\n  TPM_SECRET newAuthSecret;\n  TPM_NONCE n1;\n} TPM_CHANGEAUTH_VALIDATE;\n#define sizeof_TPM_CHANGEAUTH_VALIDATE(s) (20 + 20)\n\n/*\n * TPM_COUNTER_VALUE ([TPM_Part2], Section 5.13)\n * This structure returns the counter value.\n * For interoperability, the value size should be 4 bytes.\n */\n#define TPM_TAG_COUNTER_VALUE 0x000E\ntypedef struct tdTPM_COUNTER_VALUE {\n  TPM_STRUCTURE_TAG tag;\n  BYTE label[4];\n  TPM_ACTUAL_COUNT counter;\n  /* additional, not marshalled data */\n  TPM_SECRET usageAuth;\n  BOOL valid;\n} TPM_COUNTER_VALUE;\n#define sizeof_TPM_COUNTER_VALUE(s) (2 + 4 + 4)\n#define sizeof_TPM_COUNTER_VALUE2(s) (2 + 4 + 4 + 20 + 1)\n\n/*\n * TPM_SIGN_INFO Structure ([TPM_Part2], Section 5.14)\n * To provide the mechanism to quote the current values of a list of PCRs.\n */\n#define TPM_TAG_SIGNINFO 0x0005\ntypedef struct tdTPM_SIGN_INFO {\n  TPM_STRUCTURE_TAG tag;\n  BYTE fixed[4];\n  TPM_NONCE replay;\n  UINT32 dataLen;\n  BYTE* data;\n} TPM_SIGN_INFO;\n\n#define MAX_MSA_COMPOSITE_ENTRIES 16\n\n/*\n * TPM_MSA_COMPOSITE ([TPM_Part2], Section 5.15)\n * Contains an arbitrary number of digests of public keys belonging to\n * Migration Authorities.\n */\ntypedef struct tdTPM_MSA_COMPOSITE {\n  UINT32 MSAlist;\n  TPM_DIGEST migAuthDigest[MAX_MSA_COMPOSITE_ENTRIES];\n} TPM_MSA_COMPOSITE;\n#define sizeof_TPM_MSA_COMPOSITE(s) (4 + s.MSAlist * 20)\n\n/*\n * TPM_CMK_AUTH ([TPM_Part2], Section 5.16)\n */\ntypedef struct tdTPM_CMK_AUTH {\n  TPM_DIGEST migrationAuthorityDigest;\n  TPM_DIGEST destinationKeyDigest;\n  TPM_DIGEST sourceKeyDigest;\n} TPM_CMK_AUTH;\n#define sizeof_TPM_CMK_AUTH(s) (3 * 20)\n\n/*\n * TPM_CMK_DELEGATE ([TPM_Part2], Section 5.17)\n * Determine how to respond to delegated requests to manipulate a\n * restricted-migration key.\n */\n#define TPM_CMK_DELEGATE_SIGNING            (1 << 31)\n#define TPM_CMK_DELEGATE_STORAGE            (1 << 30)\n#define TPM_CMK_DELEGATE_BIND               (1 << 29)\n#define TPM_CMK_DELEGATE_LEGACY             (1 << 28)\n#define TPM_CMK_DELEGATE_MIGRATE            (1 << 27)\n/* bits 26-0 are reserved and must be 0 */\n\n/*\n * TPM_SELECT_SIZE ([TPM_Part2], Section 5.18)\n * Indication for the version and size of TPM_SELECTION in TPM_GetCapability.\n */\ntypedef struct tdTPM_SELECT_SIZE {\n  BYTE major;\n  BYTE minor;\n  UINT16 reqSize;\n} TPM_SELECT_SIZE;\n\n/*\n * TPM_CMK_MIGAUTH ([TPM_Part2], Section 5.19)\n * Structure to keep track of the CMK migration authorization.\n */\n#define TPM_TAG_CMK_MIGAUTH 0x0033\ntypedef struct tdTPM_CMK_MIGAUTH {\n  TPM_STRUCTURE_TAG tag;\n  TPM_DIGEST msaDigest;\n  TPM_DIGEST pubKeyDigest;\n} TPM_CMK_MIGAUTH;\n\n/*\n * TPM_CMK_SIGTICKET ([TPM_Part2], Section 5.20)\n * Structure to keep track of the CMK migration authorization.\n */\n#define TPM_TAG_CMK_SIGTICKET 0x0034\ntypedef struct tdTPM_CMK_SIGTICKET {\n  TPM_STRUCTURE_TAG tag;\n  TPM_DIGEST verKeyDigest;\n  TPM_DIGEST signedData;\n} TPM_CMK_SIGTICKET;\n\n/*\n * TPM_CMK_MA_APPROVAL ([TPM_Part2], Section 5.21)\n * Structure to keep track of the CMK migration authorization.\n */\n#define TPM_TAG_CMK_MA_APPROVAL 0x0035\ntypedef struct tdTPM_CMK_MA_APPROVAL {\n  TPM_STRUCTURE_TAG tag;\n  TPM_DIGEST migrationAuthorityDigest;\n} TPM_CMK_MA_APPROVAL;\n\n/*\n * Command Tags ([TPM_Part2], Section 6)\n * Indicate the construction of the command either as input or as output.\n */\n#define TPM_TAG_RQU_COMMAND             0x00C1\n#define TPM_TAG_RQU_AUTH1_COMMAND       0x00C2\n#define TPM_TAG_RQU_AUTH2_COMMAND       0x00C3\n#define TPM_TAG_RSP_COMMAND             0x00C4\n#define TPM_TAG_RSP_AUTH1_COMMAND       0x00C5\n#define TPM_TAG_RSP_AUTH2_COMMAND       0x00C6\n\n/*\n * Ordinals ([TPM_Part2], Section 17)\n * The command ordinals provide the index value for each command.\n */\n#define TPM_PROTECTED_COMMAND           0x00000000\n#define TPM_UNPROTECTED_COMMAND         0x80000000\n#define TPM_CONNECTION_COMMAND          0x40000000\n#define TPM_VENDOR_COMMAND              0x20000000\n\n#define TPM_MAIN                        0x00\n#define TPM_PC                          0x01\n#define TPM_PDA                         0x02\n#define TPM_CELL_PHONE                  0x03\n#define TPM_SERVER                      0x04\n\n#define TPM_PROTECTED_ORDINAL           (TPM_PROTECTED_COMMAND | TPM_MAIN)\n#define TPM_UNPROTECTED_ORDINAL         (TPM_UNPROTECTED_COMMAND | TPM_MAIN)\n#define TPM_CONNECTION_ORDINAL          (TPM_CONNECTION_COMMAND | TPM_MAIN)\n\n#define TPM_ORD_INDEX_MASK              0x0000FFFF\n\n#define TPM_ORD_OIAP                            10\n#define TPM_ORD_OSAP                            11\n#define TPM_ORD_ChangeAuth                      12\n#define TPM_ORD_TakeOwnership                   13\n#define TPM_ORD_ChangeAuthAsymStart             14\n#define TPM_ORD_ChangeAuthAsymFinish            15\n#define TPM_ORD_ChangeAuthOwner                 16\n#define TPM_ORD_DSAP                            17\n#define TPM_ORD_CMK_CreateTicket                18\n#define TPM_ORD_CMK_CreateKey                   19\n#define TPM_ORD_Extend                          20\n#define TPM_ORD_PCRRead                         21\n#define TPM_ORD_Quote                           22\n#define TPM_ORD_Seal                            23\n#define TPM_ORD_Unseal                          24\n#define TPM_ORD_DirWriteAuth                    25\n#define TPM_ORD_DirRead                         26\n#define TPM_ORD_CMK_CreateBlob                  27\n#define TPM_ORD_CMK_SetRestrictions             28\n#define TPM_ORD_CMK_ApproveMA                   29\n#define TPM_ORD_UnBind                          30\n#define TPM_ORD_CreateWrapKey                   31\n#define TPM_ORD_LoadKey                         32\n#define TPM_ORD_GetPubKey                       33\n#define TPM_ORD_EvictKey                        34\n#define TPM_ORD_KeyControlOwner                 35\n#define TPM_ORD_CMK_ConvertMigration            36\n#define TPM_ORD_MigrateKey                      37\n#define TPM_ORD_CreateMigrationBlob             40\n#define TPM_ORD_DAA_Join                        41\n#define TPM_ORD_ConvertMigrationBlob            42\n#define TPM_ORD_AuthorizeMigrationKey           43\n#define TPM_ORD_CreateMaintenanceArchive        44\n#define TPM_ORD_LoadMaintenanceArchive          45\n#define TPM_ORD_KillMaintenanceFeature          46\n#define TPM_ORD_LoadManuMaintPub                47\n#define TPM_ORD_ReadManuMaintPub                48\n#define TPM_ORD_DAA_Sign                        49\n#define TPM_ORD_CertifyKey                      50\n#define TPM_ORD_CertifyKey2                     51\n#define TPM_ORD_Sign                            60\n#define TPM_ORD_Sealx                           61\n#define TPM_ORD_Quote2                          62\n#define TPM_ORD_SetCapability                   63\n#define TPM_ORD_ResetLockValue                  64\n#define TPM_ORD_LoadKey2                        65\n#define TPM_ORD_GetRandom                       70\n#define TPM_ORD_StirRandom                      71\n#define TPM_ORD_SelfTestFull                    80\n#define TPM_ORD_ContinueSelfTest                83\n#define TPM_ORD_GetTestResult                   84\n#define TPM_ORD_Reset                           90\n#define TPM_ORD_OwnerClear                      91\n#define TPM_ORD_DisableOwnerClear               92\n#define TPM_ORD_ForceClear                      93\n#define TPM_ORD_DisableForceClear               94\n#define TPM_ORD_GetCapability                   101\n#define TPM_ORD_GetCapabilityOwner              102\n#define TPM_ORD_OwnerSetDisable                 110\n#define TPM_ORD_PhysicalEnable                  111\n#define TPM_ORD_PhysicalDisable                 112\n#define TPM_ORD_SetOwnerInstall                 113\n#define TPM_ORD_PhysicalSetDeactivated          114\n#define TPM_ORD_SetTempDeactivated              115\n#define TPM_ORD_SetOperatorAuth                 116\n#define TPM_ORD_SetOwnerPointer                 117\n#define TPM_ORD_CreateEndorsementKeyPair        120\n#define TPM_ORD_MakeIdentity                    121\n#define TPM_ORD_ActivateIdentity                122\n#define TPM_ORD_ReadPubek                       124\n#define TPM_ORD_OwnerReadPubek                  125\n#define TPM_ORD_DisablePubekRead                126\n#define TPM_ORD_CreateRevocableEK               127\n#define TPM_ORD_RevokeTrust                     128\n#define TPM_ORD_OwnerReadInternalPub            129\n#define TPM_ORD_GetAuditDigest                  133\n#define TPM_ORD_GetAuditDigestSigned            134\n#define TPM_ORD_SetOrdinalAuditStatus           141\n#define TPM_ORD_Terminate_Handle                150\n#define TPM_ORD_Init                            151\n#define TPM_ORD_SaveState                       152\n#define TPM_ORD_Startup                         153\n#define TPM_ORD_SetRedirection                  154\n#define TPM_ORD_SHA1Start                       160\n#define TPM_ORD_SHA1Update                      161\n#define TPM_ORD_SHA1Complete                    162\n#define TPM_ORD_SHA1CompleteExtend              163\n#define TPM_ORD_FieldUpgrade                    170\n#define TPM_ORD_SaveKeyContext                  180\n#define TPM_ORD_LoadKeyContext                  181\n#define TPM_ORD_SaveAuthContext                 182\n#define TPM_ORD_LoadAuthContext                 183\n#define TPM_ORD_SaveContext                     184\n#define TPM_ORD_LoadContext                     185\n#define TPM_ORD_FlushSpecific                   186\n#define TPM_ORD_PCR_Reset                       200\n#define TPM_ORD_NV_DefineSpace                  204\n#define TPM_ORD_NV_WriteValue                   205\n#define TPM_ORD_NV_WriteValueAuth               206\n#define TPM_ORD_NV_ReadValue                    207\n#define TPM_ORD_NV_ReadValueAuth                208\n#define TPM_ORD_Delegate_UpdateVerification     209\n#define TPM_ORD_Delegate_Manage                 210\n#define TPM_ORD_Delegate_CreateKeyDelegation    212\n#define TPM_ORD_Delegate_CreateOwnerDelegation  213\n#define TPM_ORD_Delegate_VerifyDelegation       214\n#define TPM_ORD_Delegate_LoadOwnerDelegation    216\n#define TPM_ORD_Delegate_ReadAuth               217\n#define TPM_ORD_Delegate_ReadTable              219\n#define TPM_ORD_CreateCounter                   220\n#define TPM_ORD_IncrementCounter                221\n#define TPM_ORD_ReadCounter                     222\n#define TPM_ORD_ReleaseCounter                  223\n#define TPM_ORD_ReleaseCounterOwner             224\n#define TPM_ORD_EstablishTransport              230\n#define TPM_ORD_ExecuteTransport                231\n#define TPM_ORD_ReleaseTransportSigned          232\n#define TPM_ORD_GetTicks                        241\n#define TPM_ORD_TickStampBlob                   242\n#define TPM_ORD_MAX                             256\n\n/*\n * TCS Ordinals ([TPM_Part2], Section 17.1)\n *\n * The TSC ordinals are optional in the main specification.\n * They are mandatory in the PC Client specification.\n *\n * The connection commands manage the TPM's connection to the TBB.\n */\n#define TSC_ORD_PhysicalPresence                (10 + TPM_CONNECTION_COMMAND)\n#define TSC_ORD_ResetEstablishmentBit           (11 + TPM_CONNECTION_COMMAND)\n\n/*\n * PCR Structures\n */\n\n/*\n * Number of PCRs of the TPM (must be a multiple of eight)\n */\n#define TPM_NUM_PCR 24\n\n/*\n * TPM_PCR_SELECTION ([TPM_Part2], Section 8.1)\n * Provides a standard method of specifying a list of PCR registers.\n * Note: An error is reported if sizeOfSelect > sizeof(pcrSelect).\n */\ntypedef struct tdTPM_PCR_SELECTION {\n  UINT16 sizeOfSelect;\n  BYTE pcrSelect[TPM_NUM_PCR/8];\n} TPM_PCR_SELECTION;\n#define sizeof_TPM_PCR_SELECTION(s) (2 + s.sizeOfSelect)\n\n/*\n * TPM_PCR_COMPOSITE ([TPM_Part2], Section 8.2)\n * The composite structure provides the index and value of the PCR register\n * to be used when creating the value that SEALS an entity to the composite.\n */\ntypedef struct tdTPM_PCR_COMPOSITE {\n  TPM_PCR_SELECTION select;\n  UINT32 valueSize;\n  TPM_PCRVALUE pcrValue[TPM_NUM_PCR];\n} TPM_PCR_COMPOSITE;\n#define sizeof_TPM_PCR_COMPOSITE(s) (sizeof_TPM_PCR_SELECTION(s.select) \\\n  + 4 + s.valueSize)\n\n/*\n * TPM_LOCALITY_SELECTION ([TPM_Part2], Section 8.6)\n * When used with localityAtCreation only one bit is set and it corresponds\n * to the locality of the command creating the structure.\n * When used with localityAtRelease the bits indicate which localities\n * CAN perform the release.\n */\ntypedef BYTE TPM_LOCALITY_SELECTION;\n/* 5-7 are reserved and must be 0 */\n#define TPM_LOC_FOUR    (1 << 4)\n#define TPM_LOC_THREE   (1 << 3)\n#define TPM_LOC_TWO     (1 << 2)\n#define TPM_LOC_ONE     (1 << 1)\n#define TPM_LOC_ZERO    (1 << 0)\n\n/*\n * TPM_PCR_INFO ([TPM_Part2], Section 8.3)\n * Contains the information related to the wrapping of a key or the sealing\n * of data, to a set of PCRs.\n *\n * TPM_PCR_INFO_LONG ([TPM_Part2], Section 8.4)\n * This structure includes information necessary to properly define the\n * configuration that creates the blob using the PCR selection.\n */\n#define TPM_TAG_PCR_INFO_LONG 0x0006\ntypedef struct tdTPM_PCR_INFO {\n  TPM_STRUCTURE_TAG tag;\n  TPM_LOCALITY_SELECTION localityAtCreation;\n  TPM_LOCALITY_SELECTION localityAtRelease;\n  TPM_PCR_SELECTION creationPCRSelection;\n  TPM_PCR_SELECTION releasePCRSelection;\n  TPM_COMPOSITE_HASH digestAtCreation;\n  TPM_COMPOSITE_HASH digestAtRelease;\n} TPM_PCR_INFO;\n#define sizeof_TPM_PCR_INFO(s) (2 + 1 + 1 \\\n  + sizeof_TPM_PCR_SELECTION(s.creationPCRSelection) \\\n  + sizeof_TPM_PCR_SELECTION(s.releasePCRSelection) + 20 + 20)\n\n/*\n * TPM_PCR_INFO_SHORT ([TPM_Part2], Section 8.5)\n * Defines a digest at release when the only information that is necessary\n * is the release configuration.\n */\ntypedef struct tdTPM_PCR_INFO_SHORT {\n  TPM_PCR_SELECTION pcrSelection;\n  TPM_LOCALITY_SELECTION localityAtRelease;\n  TPM_COMPOSITE_HASH digestAtRelease;\n} TPM_PCR_INFO_SHORT;\n#define sizeof_TPM_PCR_INFO_SHORT(s) ( \\\n  sizeof_TPM_PCR_SELECTION(s.pcrSelection) + 1 + 20)\n\n/*\n * TPM_PCR_ATTRIBUTES ([TPM_Part2], Section 8.8)\n * These attributes are available on a per PCR basis.\n */\ntypedef struct tdTPM_PCR_ATTRIBUTES {\n  BOOL pcrReset;\n  TPM_LOCALITY_SELECTION pcrExtendLocal;\n  TPM_LOCALITY_SELECTION pcrResetLocal;\n} TPM_PCR_ATTRIBUTES;\n#define sizeof_TPM_PCR_ATTRIBUTES(s) (1 + 1 + 1)\n\n/*\n * Storage Structures\n */\n\n/*\n * TPM_STORED_DATA ([TPM_Part2], Section 9.1)\n * TPM_STORED_DATA12 ([TPM_Part2], Section 9.2)\n * The definition of this structure is necessary to ensure\n * the enforcement of security properties.\n */\n#define TPM_TAG_STORED_DATA12 0x0016\ntypedef struct tdTPM_STORED_DATA {\n  TPM_STRUCTURE_TAG tag;\n  TPM_ENTITY_TYPE et;\n  UINT32 sealInfoSize;\n  TPM_PCR_INFO sealInfo;\n  UINT32 encDataSize;\n  BYTE* encData;\n} TPM_STORED_DATA;\n#define sizeof_TPM_STORED_DATA(s) (2 + 2 + 4 + s.sealInfoSize \\\n  + 4 + s.encDataSize)\n#define free_TPM_STORED_DATA(s) { \\\n  if (s.encDataSize > 0) tpm_free(s.encData); }\n\n/*\n * TPM_SEALED_DATA ([TPM_Part2], Section 9.3)\n * This structure contains confidential information related\n * to sealed data, including the data itself.\n */\ntypedef struct tdTPM_SEALED_DATA {\n  TPM_PAYLOAD_TYPE payload;\n  TPM_SECRET authData;\n  TPM_NONCE tpmProof;\n  TPM_DIGEST storedDigest;\n  UINT32 dataSize;\n  BYTE* data;\n} TPM_SEALED_DATA;\n#define sizeof_TPM_SEALED_DATA(s) (1 + 20 + 20 + 20 + 4 + s.dataSize)\n#define free_TPM_SEALED_DATA(s) { if (s.dataSize > 0) tpm_free(s.data); }\n\n/*\n * TPM_SYMMETRIC_KEY ([TPM_Part2], Section 9.4)\n * Describes a symmetric key.\n */\ntypedef struct tdTPM_SYMMETRIC_KEY {\n  TPM_ALGORITHM_ID algId;\n  TPM_ENC_SCHEME encScheme;\n  UINT16 size;\n  BYTE* data;\n} TPM_SYMMETRIC_KEY;\n#define sizeof_TPM_SYMMETRIC_KEY(s) (4 + 2 + 2 + s.size)\n#define free_TPM_SYMMETRIC_KEY(s) { if (s.size > 0) tpm_free(s.data); }\n\n/*\n * TPM_BOUND_DATA ([TPM_Part2], Section 9.5)\n * This structure is used by a TPM_UnBind command in a consistency check.\n */\ntypedef struct tdTPM_BOUND_DATA {\n  TPM_STRUCT_VER ver;\n  TPM_PAYLOAD_TYPE payload;\n  BYTE* payloadData;\n} TPM_BOUND_DATA;\n\n/*\n * TPM_KEY complex ([TPM_Part2], Section 10)\n * The TPA_KEY complex is where all of the information regarding keys\n * is kept. These structures combine to fully define and protect the\n * information regarding an asymmetric key.\n */\n\n/*\n * TPM_RSA_KEY_PARMS ([TPM_Part2], Section 10.1.1)\n * This structure describes the parameters of an RSA key.\n */\ntypedef struct tdTPM_RSA_KEY_PARMS {\n  UINT32 keyLength;\n  UINT32 numPrimes;\n  UINT32 exponentSize;\n  BYTE* exponent;\n} TPM_RSA_KEY_PARMS;\n#define sizeof_TPM_RSA_KEY_PARMS(s) (4 + 4 + 4 + s.exponentSize)\n#define free_TPM_RSA_KEY_PARMS(s) { \\\n  if (s.exponentSize > 0) tpm_free(s.exponent); }\n\n/*\n * TPM_SYMMETRIC_KEY_PARMS ([TPM_Part2], Section 10.1.2)\n * This structure describes the parameters for symmetric algorithms.\n */\ntypedef struct tdTPM_SYMMETRIC_KEY_PARMS {\n  UINT32 keyLength;\n  UINT32 blockSize;\n  UINT32 ivSize;\n  BYTE* IV;\n} TPM_SYMMETRIC_KEY_PARMS;\n#define sizeof_TPM_SYMMETRIC_KEY_PARMS(s) (4 + 4 + 4 + s.ivSize)\n#define free_TPM_SYMMETRIC_KEY_PARMS(s) { if (s.ivSize > 0) tpm_free(s.IV); }\n\n/*\n * TPM_KEY_PARMS ([TPM_Part2], Section 10.1)\n * This provides a standard mechanism to define the parameters used to\n * generate a key pair.\n */\ntypedef struct tdTPM_KEY_PARMS {\n  TPM_ALGORITHM_ID algorithmID;\n  TPM_ENC_SCHEME encScheme;\n  TPM_SIG_SCHEME sigScheme;\n  UINT32 parmSize;\n  union {\n    BYTE* raw;\n    TPM_RSA_KEY_PARMS rsa;\n    TPM_SYMMETRIC_KEY_PARMS skp;\n  } parms;\n} TPM_KEY_PARMS;\n#define sizeof_TPM_KEY_PARMS(s) (4 + 2 + 2 + 4 + s.parmSize)\n#define free_TPM_KEY_PARMS(s) { if (s.parmSize > 0) { \\\n  switch (s.algorithmID) { \\\n    case TPM_ALG_RSA: free_TPM_RSA_KEY_PARMS(s.parms.rsa); break; \\\n    case TPM_ALG_DES: case TPM_ALG_3DES: \\\n    case TPM_ALG_AES192: case TPM_ALG_AES256: \\\n    free_TPM_SYMMETRIC_KEY_PARMS(s.parms.skp); break; \\\n    default: tpm_free(s.parms.raw); } } }\n\n/*\n * TPM_STORE_PUBKEY ([TPM_Part2], Section 10.4)\n * This structure can be used in conjunction with a corresponding\n * TPM_KEY_PARMS to construct a public key which can be unambiguously used.\n */\ntypedef struct tdTPM_STORE_PUBKEY {\n  UINT32 keyLength;\n  BYTE* key;\n} TPM_STORE_PUBKEY;\n#define sizeof_TPM_STORE_PUBKEY(s) (4 + s.keyLength)\n#define free_TPM_STORE_PUBKEY(s) { if (s.keyLength > 0) tpm_free(s.key); }\n\n/*\n * TPM_KEY ([TPM_Part2], Section 10.2)\n * The TPM_KEY structure provides a mechanism to transport the entire\n * asymmetric key pair. The private portion of the key is always encrypted.\n * The TPM_KEY12 ([TPM_Part2], Section 10.3) structure uses the new\n * TPM_PCR_INFO_LONG structures and the new structure tagging.\n */\n\n#define TPM_TAG_KEY12 0x0028\ntypedef struct tdTPM_KEY {\n  TPM_STRUCTURE_TAG tag;\n  UINT16 fill;\n  TPM_KEY_USAGE keyUsage;\n  TPM_KEY_FLAGS keyFlags;\n  TPM_AUTH_DATA_USAGE authDataUsage;\n  TPM_KEY_PARMS algorithmParms;\n  UINT32 PCRInfoSize;\n  TPM_PCR_INFO PCRInfo;\n  TPM_STORE_PUBKEY pubKey;\n  UINT32 encDataSize;\n  BYTE* encData;\n} TPM_KEY;\n#define sizeof_TPM_KEY(s) (4 + 2 + 4 + 1 \\\n  + sizeof_TPM_KEY_PARMS(s.algorithmParms) \\\n  + 4 + s.PCRInfoSize + sizeof_TPM_STORE_PUBKEY(s.pubKey) \\\n  + 4 + s.encDataSize)\n#define free_TPM_KEY(s) { if (s.encDataSize > 0) tpm_free(s.encData); \\\n  free_TPM_KEY_PARMS(s.algorithmParms); free_TPM_STORE_PUBKEY(s.pubKey); }\n\n/*\n * TPM_PUBKEY ([TPM_Part2], Section 10.5)\n * Public portion of an asymmetric key pair.\n */\ntypedef struct tdTPM_PUBKEY {\n  TPM_KEY_PARMS algorithmParms;\n  TPM_STORE_PUBKEY pubKey;\n} TPM_PUBKEY;\n#define sizeof_TPM_PUBKEY(s) (sizeof_TPM_KEY_PARMS(s.algorithmParms) \\\n  + sizeof_TPM_STORE_PUBKEY(s.pubKey))\n#define free_TPM_PUBKEY(s) { free_TPM_KEY_PARMS(s.algorithmParms); \\\n  free_TPM_STORE_PUBKEY(s.pubKey); }\n\n/*\n * TPM_STORE_PRIVKEY ([TPM_Part2], Section 10.7)\n * This structure can be used in conjunction with a corresponding TPM_PUBKEY\n * to construct a private key which can be unambiguously used.\n */\ntypedef struct tdTPM_STORE_PRIVKEY {\n  UINT32 keyLength;\n  BYTE* key;\n} TPM_STORE_PRIVKEY;\n#define sizeof_TPM_STORE_PRIVKEY(s) (4 + s.keyLength)\n#define free_TPM_STORE_PRIVKEY(s) { if (s.keyLength > 0) tpm_free(s.key); }\n\n/*\n * TPM_STORE_ASYMKEY ([TPM_Part2], Section 10.6)\n * The TPM_STORE_ASYMKEY structure provides the area to identify the\n * confidential information related to a key.\n */\ntypedef struct tdTPM_STORE_ASYMKEY {\n  TPM_PAYLOAD_TYPE payload;\n  TPM_SECRET usageAuth;\n  TPM_SECRET migrationAuth;\n  TPM_DIGEST pubDataDigest;\n  TPM_STORE_PRIVKEY privKey;\n} TPM_STORE_ASYMKEY;\n#define sizeof_TPM_STORE_ASYMKEY(s) (1 + 20 + 20 + 20 \\\n  + sizeof_TPM_STORE_PRIVKEY(s.privKey))\n#define free_TPM_STORE_ASYMKEY(s) { free_TPM_STORE_PRIVKEY(s.privKey); }\n\n/*\n * TPM_MIGRATE_ASYMKEY ([TPM_Part2], Section 10.8)\n * The TPM_MIGRATE_ASYMKEY structure provides the area to identify the private\n * key factors of a asymmetric key while the key is migrating between TPM's.\n */\ntypedef struct tdTPM_MIGRATE_ASYMKEY {\n  TPM_PAYLOAD_TYPE payload;\n  TPM_SECRET usageAuth;\n  TPM_DIGEST pubDataDigest;\n  UINT32 partPrivKeyLen;\n  BYTE *partPrivKey;\n} TPM_MIGRATE_ASYMKEY;\n#define sizeof_TPM_MIGRATE_ASYMKEY(s) (1 + 20 + 20 + 4 + s.partPrivKeyLen)\n#define free_TPM_MIGRATE_ASYMKEY(s) { tpm_free(s.partPrivKey); }\n\n/*\n * TPM_MIGRATIONKEYAUTH ([TPM_Part2], Section 5.12)\n * Provides the proof that the associated public key has authorization to\n * be a migration key.\n */\ntypedef struct tdTPM_MIGRATIONKEYAUTH {\n  TPM_PUBKEY migrationKey;\n  TPM_MIGRATE_SCHEME migrationScheme;\n  TPM_DIGEST digest;\n} TPM_MIGRATIONKEYAUTH;\n#define sizeof_TPM_MIGRATIONKEYAUTH(s) (sizeof_TPM_PUBKEY(s.migrationKey) \\\n  + 2 + 20)\n#define free_TPM_MIGRATIONKEYAUTH(s) { free_TPM_PUBKEY(s.migrationKey); }\n\n/*\n * TPM_KEY_CONTROL ([TPM_Part2], Section 10.9)\n * Attributes that can control various aspects of key usage and manipulation.\n */\n/* 31:-1 reserved and must be 0 */\n#define TPM_KEY_CONTROL_OWNER_EVICT (1 << 0)\n\n/*\n * Signed Structures\n */\n\n/*\n * TPM_AUTH ([TPM_Part1], Section ??.?)\n * Authorization Protocol Input/Output Parameter\n */\ntypedef struct tdTPM_AUTH {\n  TPM_AUTHHANDLE authHandle;\n  TPM_NONCE nonceEven;\n  TPM_NONCE nonceOdd;\n  BOOL continueAuthSession;\n  TPM_AUTHDATA auth;\n  /* additional NOT marshalled parameters */\n  TPM_SECRET secret;\n  BYTE digest[20];\n  TPM_COMMAND_CODE ordinal;\n} TPM_AUTH;\n\n/*\n * TPM_CERTIFY_INFO Structure ([TPM_Part2], Section 11.1)\n * TPM_CERTIFY_INFO2 Structure ([TPM_Part2], Section 11.2)\n * This structure provides the mechanism to provide a signature with a TPM\n * identity key on information that describes that key.\n */\n#define TPM_TAG_CERTIFY_INFO2 0x0029\ntypedef struct tdTPM_CERTIFY_INFO {\n  TPM_STRUCTURE_TAG tag;\n  BYTE fill;\n  TPM_PAYLOAD_TYPE payloadType;\n  TPM_KEY_USAGE keyUsage;\n  TPM_KEY_FLAGS keyFlags;\n  TPM_AUTH_DATA_USAGE authDataUsage;\n  TPM_KEY_PARMS algorithmParms;\n  TPM_DIGEST pubkeyDigest;\n  TPM_NONCE data;\n  BOOL parentPCRStatus;\n  UINT32 PCRInfoSize;\n  TPM_PCR_INFO PCRInfo;\n  UINT32 migrationAuthoritySize;\n  BYTE* migrationAuthority;\n} TPM_CERTIFY_INFO;\n#define sizeof_TPM_CERTIFY_INFO(s) (4 + 2 + 4 + 1 + \\\n  sizeof_TPM_KEY_PARMS(s.algorithmParms) + 20 + 20 + 1 + 4 \\\n  + s.PCRInfoSize \\\n  + (s.tag == TPM_TAG_CERTIFY_INFO2 ? 4 + s.migrationAuthoritySize : 0))\n#define free_TPM_CERTIFY_INFO(s) { free_TPM_KEY_PARMS(s.algorithmParms); \\\n  if (s.migrationAuthoritySize > 0) tpm_free(s.migrationAuthority); }\n\n/*\n * TPM_QUOTE_INFO Structure ([TPM_Part2], Section 11.3)\n * This structure provides the mechanism for the TPM to quote the\n * current values of a list of PCRs.\n */\ntypedef struct tdTPM_QUOTE_INFO {\n  TPM_STRUCT_VER version;\n  BYTE fixed[4];\n  TPM_COMPOSITE_HASH digestValue;\n  TPM_NONCE externalData;\n} TPM_QUOTE_INFO;\n\n/*\n * TPM_QUOTE_INFO2 Structure ([TPM_Part2], Section 11.4)\n * This structure provides the mechanism for the TPM to quote the\n * current values of a list of PCRs.\n */\n#define TPM_TAG_QUOTE_INFO2 0x0036\ntypedef struct tdTPM_QUOTE_INFO2 {\n  TPM_STRUCTURE_TAG tag;\n  BYTE fixed[4];\n  TPM_NONCE externalData;\n  TPM_PCR_INFO_SHORT infoShort;\n} TPM_QUOTE_INFO2;\n#define sizeof_TPM_QUOTE_INFO2(s) (2 + 4 + 20 + \\\n  sizeof_TPM_PCR_INFO_SHORT(s.infoShort))\n\n/*\n * Identity Structures\n */\n\n/*\n * TPM_EK_BLOB ([TPM_Part2], Section 12.1)\n * This structure provides a wrapper to each type of structure that\n * will be in use when the endorsement key is in use.\n */\n#define TPM_TAG_EK_BLOB 0x000C\ntypedef struct tdTPM_EK_BLOB {\n  TPM_STRUCTURE_TAG tag;\n  TPM_EK_TYPE ekType;\n  UINT32 blobSize;\n  BYTE* blob;\n} TPM_EK_BLOB;\n\n/*\n * TPM_EK_BLOB_ACTIVATE ([TPM_Part2], Section 12.2)\n * This structure contains the symmetric key to encrypt the identity\n * credential. This structure always is contained in a TPM_EK_BLOB.\n */\n#define TPM_TAG_EK_BLOB_ACTIVATE 0x002B\ntypedef struct tdTPM_EK_BLOB_ACTIVATE {\n  TPM_STRUCTURE_TAG tag;\n  TPM_SYMMETRIC_KEY sessionKey;\n  TPM_DIGEST idDigest;\n  TPM_PCR_INFO_SHORT pcrInfo;\n} TPM_EK_BLOB_ACTIVATE;\n\n/*\n * TPM_EK_BLOB_AUTH ([TPM_Part2], Section 12.3)\n * This structure contains the symmetric key to encrypt the identity\n * credential. This structure always is contained in a TPM_EK_BLOB.\n */\n#define TPM_TAG_EK_BLOB_AUTH 0x000D\ntypedef struct tdTPM_EK_BLOB_AUTH {\n  TPM_STRUCTURE_TAG tag;\n  TPM_SECRET authValue;\n} TPM_EK_BLOB_AUTH;\n\n/*\n * TPM_IDENTITY_CONTENTS ([TPM_Part2], Section 12.5)\n * TPM_MakeIdentity uses this structure and the signature of this structure\n * goes to a privacy CA during the certification process.\n */\ntypedef struct tdTPM_IDENTITY_CONTENTS {\n  TPM_STRUCT_VER ver;\n  UINT32 ordinal;\n  TPM_CHOSENID_HASH labelPrivCADigest;\n  TPM_PUBKEY identityPubKey;\n} TPM_IDENTITY_CONTENTS;\n#define sizeof_TPM_IDENTITY_CONTENTS(s) (4 + 4 + 20 + \\\n  sizeof_TPM_PUBKEY(s.identityPubKey))\n\n/*\n * TPM_IDENTITY_REQ ([TPM_Part2], Section 12.6)\n * This structure is sent by the TSS to the Privacy CA to create the\n * identity credential. This structure is informative only.\n */\n\n/*\n * TPM_IDENTITY_PROOF ([TPM_Part2], Section 12.7)\n * Structure in use during the AIK credential process.\n */\n\n/*\n * TPM_ASYM_CA_CONTENTS ([TPM_Part2], Section 12.8)\n * Contains the symmetric key to encrypt the identity credential.\n */\ntypedef struct tdTPM_ASYM_CA_CONTENTS {\n  TPM_SYMMETRIC_KEY sessionKey;\n  TPM_DIGEST idDigest;\n} TPM_ASYM_CA_CONTENTS;\n\n/*\n * TPM_SYM_CA_ATTESTATION ([TPM_Part2], Section 12.9)\n * This structure returned by the Privacy CA with the encrypted\n * identity credential.\n */\n\n/*\n * Tick Structures\n */\n\n/*\n * TPM_CURRENT_TICKS ([TPM_Part2], Section 15.1)\n * This structure holds the current number of time ticks in the TPM.\n */\n#define TPM_TAG_CURRENT_TICKS 0x0014\ntypedef struct tdTPM_CURRENT_TICKS {\n  TPM_STRUCTURE_TAG tag;\n  UINT64 currentTicks;\n  UINT16 tickRate;\n  TPM_NONCE tickNonce;\n} TPM_CURRENT_TICKS;\n#define sizeof_TPM_CURRENT_TICKS(s) (2 + 8 + 2 + 20)\n\n/*\n * Transport Structures\n */\n\n/*\n * TPM_TRANSPORT_PUBLIC ([TPM_Part2], Section 13.1)\n * The public information relative to a transport session.\n */\n#define TPM_TAG_TRANSPORT_PUBLIC 0x001E\ntypedef struct tdTPM_TRANSPORT_PUBLIC {\n  TPM_STRUCTURE_TAG tag;\n  TPM_TRANSPORT_ATTRIBUTES transAttributes;\n  TPM_ALGORITHM_ID algID;\n  TPM_ENC_SCHEME encScheme;\n} TPM_TRANSPORT_PUBLIC;\n#define sizeof_TPM_TRANSPORT_PUBLIC(s) (2 + 4 + 4 + 2)\n\n/* TPM_TRANSPORT_ATTRIBUTES Definitions ([TPM_Part2], Section 13.1.1) */\n#define TPM_TRANSPORT_ENCRYPT   0x00000001\n#define TPM_TRANSPORT_LOG       0x00000002\n#define TPM_TRANSPORT_EXCLUSIVE 0x00000004\n\n/*\n * TPM_TRANSPORT_INTERNAL ([TPM_Part2], Section 13.2)\n * The internal information regarding transport session.\n */\n#define TPM_TAG_TRANSPORT_INTERNAL 0x000F\ntypedef struct tdTPM_TRANSPORT_INTERNAL {\n  TPM_STRUCTURE_TAG tag;\n  TPM_AUTHDATA authData;\n  TPM_TRANSPORT_PUBLIC transPublic;\n  TPM_TRANSHANDLE transHandle;\n  TPM_NONCE transNonceEven;\n  TPM_DIGEST transDigest;\n} TPM_TRANSPORT_INTERNAL;\n#define sizeof_TPM_TRANSPORT_INTERNAL(s) (2 + 20 + 4 + 20 + 20 \\\n  + sizeof_TPM_TRANSPORT_PUBLIC(s.transPublic))\n\n/*\n * TPM_TRANSPORT_LOG_IN structure ([TPM_Part2], Section 13.3)\n * This structure is in use for input log calculations.\n */\n#define TPM_TAG_TRANSPORT_LOG_IN 0x0010\ntypedef struct tdTPM_TRANSPORT_LOG_IN {\n  TPM_STRUCTURE_TAG tag;\n  TPM_DIGEST parameters;\n  TPM_DIGEST pubKeyHash;\n} TPM_TRANSPORT_LOG_IN;\n#define sizeof_TPM_TRANSPORT_LOG_IN(s) (2 + 20 + 20)\n\n/*\n * TPM_TRANSPORT_LOG_OUT structure ([TPM_Part2], Section 13.4)\n * This structure is in use for output log calculations.\n * This structure is in use for the INPUT logging during releaseTransport.\n */\n#define TPM_TAG_TRANSPORT_LOG_OUT 0x0011\ntypedef struct tdTPM_TRANSPORT_LOG_OUT {\n  TPM_STRUCTURE_TAG tag;\n  TPM_CURRENT_TICKS currentTicks;\n  TPM_DIGEST parameters;\n  TPM_MODIFIER_INDICATOR locality;\n} TPM_TRANSPORT_LOG_OUT;\n#define sizeof_TPM_TRANSPORT_LOG_OUT(s) (2 + 20 + 4 \\\n  + sizeof_TPM_CURRENT_TICKS(s.currentTicks))\n\n/*\n * TPM_TRANSPORT_AUTH structure ([TPM_Part2], Section 13.5)\n * Provides the validation for the encrypted authorization value.\n */\n#define TPM_TAG_TRANSPORT_AUTH 0x001D\ntypedef struct tdTPM_TRANSPORT_AUTH {\n  TPM_STRUCTURE_TAG tag;\n  TPM_AUTHDATA authData;\n} TPM_TRANSPORT_AUTH;\n#define sizeof_TPM_TRANSPORT_AUTH(s) (2 + 20)\n\n/*\n * Audit Structures\n */\n\n/*\n * TPM_AUDIT_EVENT_IN structure ([TPM_Part2], Section 14.1)\n * This structure provides the auditing of the command upon receipt of\n * the command. It provides the information regarding the input parameters.\n */\n#define TPM_TAG_AUDIT_EVENT_IN 0x0012\ntypedef struct tdTPM_AUDIT_EVENT_IN {\n  TPM_STRUCTURE_TAG tag;\n  TPM_DIGEST inputParms;\n  TPM_COUNTER_VALUE auditCount;\n} TPM_AUDIT_EVENT_IN;\n#define sizeof_TPM_AUDIT_EVENT_IN(s) (2 + 20 \\\n  + sizeof_TPM_COUNTER_VALUE(s.auditCount))\n\n/*\n * TPM_AUDIT_EVENT_OUT structure ([TPM_Part2], Section 14.2)\n * This structure reports the results of the command execution.\n * It includes the return code and the output parameters.\n */\n#define TPM_TAG_AUDIT_EVENT_OUT 0x0013\ntypedef struct tdTPM_AUDIT_EVENT_OUT {\n  TPM_STRUCTURE_TAG tag;\n  TPM_DIGEST outputParms;\n  TPM_COUNTER_VALUE auditCount;\n} TPM_AUDIT_EVENT_OUT;\n#define sizeof_TPM_AUDIT_EVENT_OUT(s) (2 + 20 \\\n  + sizeof_TPM_COUNTER_VALUE(s.auditCount))\n\n/*\n * TPM Return Codes ([TPM_Part2], Section 16)\n */\n#define TPM_NON_FATAL                   0x00000800\n#define TPM_BASE                        0x00000000\n\n#define TPM_SUCCESS                     (TPM_BASE + 0)\n#define TPM_AUTHFAIL                    (TPM_BASE + 1)\n#define TPM_BADINDEX                    (TPM_BASE + 2)\n#define TPM_BAD_PARAMETER               (TPM_BASE + 3)\n#define TPM_AUDITFAILURE                (TPM_BASE + 4)\n#define TPM_CLEAR_DISABLED              (TPM_BASE + 5)\n#define TPM_DEACTIVATED                 (TPM_BASE + 6)\n#define TPM_DISABLED                    (TPM_BASE + 7)\n#define TPM_DISABLED_CMD                (TPM_BASE + 8)\n#define TPM_FAIL                        (TPM_BASE + 9)\n#define TPM_BAD_ORDINAL                 (TPM_BASE + 10)\n#define TPM_INSTALL_DISABLED            (TPM_BASE + 11)\n#define TPM_INVALID_KEYHANDLE           (TPM_BASE + 12)\n#define TPM_KEYNOTFOUND                 (TPM_BASE + 13)\n#define TPM_INAPPROPRIATE_ENC           (TPM_BASE + 14)\n#define TPM_MIGRATEFAIL                 (TPM_BASE + 15)\n#define TPM_INVALID_PCR_INFO            (TPM_BASE + 16)\n#define TPM_NOSPACE                     (TPM_BASE + 17)\n#define TPM_NOSRK                       (TPM_BASE + 18)\n#define TPM_NOTSEALED_BLOB              (TPM_BASE + 19)\n#define TPM_OWNER_SET                   (TPM_BASE + 20)\n#define TPM_RESOURCES                   (TPM_BASE + 21)\n#define TPM_SHORTRANDOM                 (TPM_BASE + 22)\n#define TPM_SIZE                        (TPM_BASE + 23)\n#define TPM_WRONGPCRVAL                 (TPM_BASE + 24)\n#define TPM_BAD_PARAM_SIZE              (TPM_BASE + 25)\n#define TPM_SHA_THREAD                  (TPM_BASE + 26)\n#define TPM_SHA_ERROR                   (TPM_BASE + 27)\n#define TPM_FAILEDSELFTEST              (TPM_BASE + 28)\n#define TPM_AUTH2FAIL                   (TPM_BASE + 29)\n#define TPM_BADTAG                      (TPM_BASE + 30)\n#define TPM_IOERROR                     (TPM_BASE + 31)\n#define TPM_ENCRYPT_ERROR               (TPM_BASE + 32)\n#define TPM_DECRYPT_ERROR               (TPM_BASE + 33)\n#define TPM_INVALID_AUTHHANDLE          (TPM_BASE + 34)\n#define TPM_NO_ENDORSEMENT              (TPM_BASE + 35)\n#define TPM_INVALID_KEYUSAGE            (TPM_BASE + 36)\n#define TPM_WRONG_ENTITYTYPE            (TPM_BASE + 37)\n#define TPM_INVALID_POSTINIT            (TPM_BASE + 38)\n#define TPM_INAPPROPRIATE_SIG           (TPM_BASE + 39)\n#define TPM_BAD_KEY_PROPERTY            (TPM_BASE + 40)\n#define TPM_BAD_MIGRATION               (TPM_BASE + 41)\n#define TPM_BAD_SCHEME                  (TPM_BASE + 42)\n#define TPM_BAD_DATASIZE                (TPM_BASE + 43)\n#define TPM_BAD_MODE                    (TPM_BASE + 44)\n#define TPM_BAD_PRESENCE                (TPM_BASE + 45)\n#define TPM_BAD_VERSION                 (TPM_BASE + 46)\n#define TPM_NO_WRAP_TRANSPORT           (TPM_BASE + 47)\n#define TPM_AUDITFAIL_UNSUCCESSFUL      (TPM_BASE + 48)\n#define TPM_AUDITFAIL_SUCCESSFUL        (TPM_BASE + 49)\n#define TPM_NOTRESETABLE                (TPM_BASE + 50)\n#define TPM_NOTLOCAL                    (TPM_BASE + 51)\n#define TPM_BAD_TYPE                    (TPM_BASE + 52)\n#define TPM_INVALID_RESOURCE            (TPM_BASE + 53)\n#define TPM_NOTFIPS                     (TPM_BASE + 54)\n#define TPM_INVALID_FAMILY              (TPM_BASE + 55)\n#define TPM_NO_NV_PERMISSION            (TPM_BASE + 56)\n#define TPM_REQUIRES_SIGN               (TPM_BASE + 57)\n#define TPM_KEY_NOTSUPPORTED            (TPM_BASE + 58)\n#define TPM_AUTH_CONFLICT               (TPM_BASE + 59)\n#define TPM_AREA_LOCKED                 (TPM_BASE + 60)\n#define TPM_BAD_LOCALITY                (TPM_BASE + 61)\n#define TPM_READ_ONLY                   (TPM_BASE + 62)\n#define TPM_PER_NOWRITE                 (TPM_BASE + 63)\n#define TPM_FAMILYCOUNT                 (TPM_BASE + 64)\n#define TPM_WRITE_LOCKED                (TPM_BASE + 65)\n#define TPM_BAD_ATTRIBUTES              (TPM_BASE + 66)\n#define TPM_INVALID_STRUCTURE           (TPM_BASE + 67)\n#define TPM_KEY_OWNER_CONTROL           (TPM_BASE + 68)\n#define TPM_BAD_COUNTER                 (TPM_BASE + 69)\n#define TPM_NOT_FULLWRITE               (TPM_BASE + 70)\n#define TPM_CONTEXT_GAP                 (TPM_BASE + 71)\n#define TPM_MAXNVWRITES                 (TPM_BASE + 72)\n#define TPM_NOOPERATOR                  (TPM_BASE + 73)\n#define TPM_RESOURCEMISSING             (TPM_BASE + 74)\n#define TPM_DELEGATE_LOCK               (TPM_BASE + 75)\n#define TPM_DELEGATE_FAMILY             (TPM_BASE + 76)\n#define TPM_DELEGATE_ADMIN              (TPM_BASE + 77)\n#define TPM_TRANSPORT_NOTEXCLUSIVE      (TPM_BASE + 78)\n#define TPM_OWNER_CONTROL               (TPM_BASE + 79)\n#define TPM_DAA_RESOURCES               (TPM_BASE + 80)\n#define TPM_DAA_INPUT_DATA0             (TPM_BASE + 81)\n#define TPM_DAA_INPUT_DATA1             (TPM_BASE + 82)\n#define TPM_DAA_ISSUER_SETTINGS         (TPM_BASE + 83)\n#define TPM_DAA_TPM_SETTINGS            (TPM_BASE + 84)\n#define TPM_DAA_STAGE                   (TPM_BASE + 85)\n#define TPM_DAA_ISSUER_VALIDITY         (TPM_BASE + 86)\n#define TPM_DAA_WRONG_W                 (TPM_BASE + 87)\n#define TPM_BAD_HANDLE                  (TPM_BASE + 88)\n#define TPM_BAD_DELEGATE                (TPM_BASE + 89)\n#define TPM_BADCONTEXT                  (TPM_BASE + 90)\n#define TPM_TOOMANYCONTEXTS             (TPM_BASE + 91)\n#define TPM_MA_TICKET_SIGNATURE         (TPM_BASE + 92)\n#define TPM_MA_DESTINATION              (TPM_BASE + 93)\n#define TPM_MA_SOURCE                   (TPM_BASE + 94)\n#define TPM_MA_AUTHORITY                (TPM_BASE + 95)\n#define TPM_PERMANENTEK                 (TPM_BASE + 97)\n#define TPM_BAD_SIGNATURE               (TPM_BASE + 98)\n#define TPM_NOCONTEXTSPACE              (TPM_BASE + 99)\n#define TPM_RETRY                       (TPM_BASE + TPM_NON_FATAL)\n#define TPM_NEEDS_SELFTEST              (TPM_BASE + TPM_NON_FATAL + 1)\n#define TPM_DOING_SELFTEST              (TPM_BASE + TPM_NON_FATAL + 2)\n#define TPM_DEFEND_LOCK_RUNNING         (TPM_BASE + TPM_NON_FATAL + 3)\n\n/*\n * NV Storage Structures\n */\n\n/*\n * Required TPM_NV_INDEX values ([TPM_Part2], Section 19.1.1)\n * The required index values must be found on each TPM regardless\n * of platform. These areas are always present and do not require\n * a TPM_NV_DefineSpace command to allocate.\n */\n#define TPM_NV_INDEX_LOCK               0xFFFFFFFF\n#define TPM_NV_INDEX0                   0x00000000\n#define TPM_NV_INDEX_DIR                0x10000001\n\n#define TPM_NV_INDEX_T                  (1 << 31)\n#define TPM_NV_INDEX_P                  (1 << 30)\n#define TPM_NV_INDEX_U                  (1 << 29)\n#define TPM_NV_INDEX_D                  (1 << 28)\n\n/*\n * Reserved Index values ([TPM_Part2], Section 19.1.2)\n * The reserved values are defined to avoid index collisions. These\n * values are not in each and every TPM.\n */\n#define TPM_NV_INDEX_EKCert             0x0000F000\n#define TPM_NV_INDEX_TPM_CC             0x0000F001\n#define TPM_NV_INDEX_PlatformCert       0x0000F002\n#define TPM_NV_INDEX_Platform_CC        0x0000F003\n#define TPM_NV_INDEX_TRIAL              0x0000F004\n\n/*\n * TPM_NV_ATTRIBUTES ([TPM_Part2], Section 19.2)\n * This structure allows the TPM to keep track of the data and\n * permissions to manipulate the area.\n */\n#define TPM_TAG_NV_ATTRIBUTES 0x0017\ntypedef struct tdTPM_NV_ATTRIBUTES {\n  TPM_STRUCTURE_TAG tag;\n  UINT32 attributes;\n} TPM_NV_ATTRIBUTES;\n\n#define TPM_NV_PER_READ_STCLEAR             (1 << 31)\n/* bits 30-19 are reserved and must be 0 */\n#define TPM_NV_PER_AUTHREAD                 (1 << 18)\n#define TPM_NV_PER_OWNERREAD                (1 << 17)\n#define TPM_NV_PER_PPREAD                   (1 << 16)\n#define TPM_NV_PER_GLOBALLOCK               (1 << 15)\n#define TPM_NV_PER_WRITE_STCLEAR            (1 << 14)\n#define TPM_NV_PER_WRITEDEFINE              (1 << 13)\n#define TPM_NV_PER_WRITEALL                 (1 << 12)\n/* bits 11-3 are reserved and must be 0 */\n#define TPM_NV_PER_AUTHWRITE                (1 <<  2)\n#define TPM_NV_PER_OWNERWRITE               (1 <<  1)\n#define TPM_NV_PER_PPWRITE                  (1 <<  0)\n\n/*\n * TPM_NV_DATA_PUBLIC ([TPM_Part2], Section 19.3)\n * Represents the public description and controls on the NV area.\n */\n#define TPM_TAG_NV_DATA_PUBLIC 0x0018\ntypedef struct tdTPM_NV_DATA_PUBLIC {\n  TPM_STRUCTURE_TAG tag;\n  TPM_NV_INDEX nvIndex;\n  TPM_PCR_INFO_SHORT pcrInfoRead;\n  TPM_PCR_INFO_SHORT pcrInfoWrite;\n  TPM_NV_ATTRIBUTES permission;\n  BOOL bReadSTClear;\n  BOOL bWriteSTClear;\n  BOOL bWriteDefine;\n  UINT32 dataSize;\n} TPM_NV_DATA_PUBLIC;\n#define sizeof_TPM_NV_DATA_PUBLIC(s) (2 + 4 + 6 + 1 + 1 + 1 + 4 \\\n  + sizeof_TPM_PCR_INFO_SHORT(s.pcrInfoRead) \\\n  + sizeof_TPM_PCR_INFO_SHORT(s.pcrInfoWrite))\n\n/*\n * TPM_NV_DATA_SENSITIVE ([TPM_Part2], Section 19.4)\n * This is an internal structure that the TPM uses to keep the actual\n * NV data and the controls regarding the area.\n */\n#define TPM_TAG_NV_DATA_SENSITIVE 0x0019\ntypedef struct tdTPM_NV_DATA_SENSITIVE {\n  TPM_STRUCTURE_TAG tag;\n  TPM_NV_DATA_PUBLIC pubInfo;\n  TPM_AUTHDATA authValue;\n  UINT32 dataIndex;\n  /* additional data */\n  BOOL valid;\n} TPM_NV_DATA_SENSITIVE;\n#define sizeof_TPM_NV_DATA_SENSITIVE(s) (2 \\\n  + sizeof_TPM_NV_DATA_PUBLIC(s.pubInfo) + 20 + 4)\n\n/*\n * Max NV Size ([TPM_Part2], Section 19.5)\n * This is a value where the minimum value is set by the platform\n * specific specification. The TPM vendor can design a TPM with a\n * size that is larger than the minimum.\n */\n#define TPM_MAX_NV_SIZE 4096\n\n/*\n * Delegate Structures\n */\n\n/*\n * Delegate Definitions ([TPM_Part2], Section 20.2)\n * The delegations are in a 64-bit field. Each bit describes a capability\n * that the TPM Owner or an authorized key user can delegate to a trusted\n * process by setting that bit. Each delegation bit setting is independent\n * of any other delegation bit setting in a row.\n */\n#define TPM_DEL_OWNER_BITS      0x00000001\n#define TPM_DEL_KEY_BITS        0x00000002\n\n#define TPM_TAG_DELEGATIONS 0x001A\ntypedef struct tdTPM_DELEGATIONS {\n  TPM_STRUCTURE_TAG tag;\n  UINT32 delegateType;\n  UINT32 per1;\n  UINT32 per2;\n} TPM_DELEGATIONS;\n#define sizeof_TPM_DELEGATIONS(s) (2 + 4 + 4 + 4)\n\n/*\n * Owner Permission Settings ([TPM_Part2], Section 20.2.1)\n * Defines the order of bits in the permission array.\n */\n/* Per1 bits */\n/* 31 reserved and must be 0 */\n#define TPM_DELEGATE_SetOrdinalAuditStatus              (1 << 30)\n#define TPM_DELEGATE_DirWriteAuth                       (1 << 29)\n#define TPM_DELEGATE_CMK_ApproveMA                      (1 << 28)\n#define TPM_DELEGATE_NV_WriteValue                      (1 << 27)\n#define TPM_DELEGATE_CMK_CreateTicket                   (1 << 26)\n#define TPM_DELEGATE_NV_ReadValue                       (1 << 25)\n#define TPM_DELEGATE_Delegate_LoadOwnerDelegation       (1 << 24)\n#define TPM_DELEGATE_DAA_Join                           (1 << 23)\n#define TPM_DELEGATE_AuthorizeMigrationKey              (1 << 22)\n#define TPM_DELEGATE_CreateMaintenanceArchive           (1 << 21)\n#define TPM_DELEGATE_LoadMaintenanceArchive             (1 << 20)\n#define TPM_DELEGATE_KillMaintenanceFeature             (1 << 19)\n#define TPM_DELEGATE_OwnerReadInternalPub               (1 << 18)\n#define TPM_DELEGATE_ResetLockValue                     (1 << 17)\n#define TPM_DELEGATE_OwnerClear                         (1 << 16)\n#define TPM_DELEGATE_DisableOwnerClear                  (1 << 15)\n#define TPM_DELEGATE_NV_DefineSpace                     (1 << 14)\n#define TPM_DELEGATE_OwnerSetDisable                    (1 << 13)\n#define TPM_DELEGATE_SetCapability                      (1 << 12)\n#define TPM_DELEGATE_MakeIdentity                       (1 << 11)\n#define TPM_DELEGATE_ActivateIdentity                   (1 << 10)\n#define TPM_DELEGATE_OwnerReadPubek                     (1 <<  9)\n#define TPM_DELEGATE_DisablePubekRead                   (1 <<  8)\n#define TPM_DELEGATE_SetRedirection                     (1 <<  7)\n#define TPM_DELEGATE_FieldUpgrade                       (1 <<  6)\n#define TPM_DELEGATE_Delegate_UpdateVerification        (1 <<  5)\n#define TPM_DELEGATE_CreateCounter                      (1 <<  4)\n#define TPM_DELEGATE_ReleaseCounterOwner                (1 <<  3)\n#define TPM_DELEGATE_Delegate_Manage                    (1 <<  2)\n#define TPM_DELEGATE_Delegate_CreateOwnerDelegation     (1 <<  1)\n#define TPM_DELEGATE_DAA_Sign                           (1 <<  0)\n/* Per2 bits */\n/* 31-0 reserved and must be 0 */\n\n/*\n * Key Permission settings ([TPM_Part2], Section 20.2.3)\n * Defines the order of bits in the permission array.\n */\n/* Per1 bits */\n/* 31-29 reserved and must be 0 */\n#define TPM_KEY_DELEGATE_CMK_ConvertMigration           (1 << 28)\n#define TPM_KEY_DELEGATE_TickStampBlob                  (1 << 27)\n#define TPM_KEY_DELEGATE_ChangeAuthAsymStart            (1 << 26)\n#define TPM_KEY_DELEGATE_ChangeAuthAsymFinish           (1 << 25)\n#define TPM_KEY_DELEGATE_CMK_CreateKey                  (1 << 24)\n#define TPM_KEY_DELEGATE_MigrateKey                     (1 << 23)\n#define TPM_KEY_DELEGATE_LoadKey2                       (1 << 22)\n#define TPM_KEY_DELEGATE_EstablishTransport             (1 << 21)\n#define TPM_KEY_DELEGATE_ReleaseTransportSigned         (1 << 20)\n#define TPM_KEY_DELEGATE_Quote2                         (1 << 19)\n#define TPM_KEY_DELEGATE_Sealx                          (1 << 18)\n#define TPM_KEY_DELEGATE_MakeIdentity                   (1 << 17)\n#define TPM_KEY_DELEGATE_ActivateIdentity               (1 << 16)\n#define TPM_KEY_DELEGATE_GetAuditDigestSigned           (1 << 15)\n#define TPM_KEY_DELEGATE_Sign                           (1 << 14)\n#define TPM_KEY_DELEGATE_CertifyKey2                    (1 << 13)\n#define TPM_KEY_DELEGATE_CertifyKey                     (1 << 12)\n#define TPM_KEY_DELEGATE_CreateWrapKey                  (1 << 11)\n#define TPM_KEY_DELEGATE_CMK_CreateBlob                 (1 << 10)\n#define TPM_KEY_DELEGATE_CreateMigrationBlob            (1 <<  9)\n#define TPM_KEY_DELEGATE_ConvertMigrationBlob           (1 <<  8)\n#define TPM_KEY_DELEGATE_Delegate_CreateKeyDelegation   (1 <<  7)\n#define TPM_KEY_DELEGATE_ChangeAuth                     (1 <<  6)\n#define TPM_KEY_DELEGATE_GetPubKey                      (1 <<  5)\n#define TPM_KEY_DELEGATE_Unbind                         (1 <<  4)\n#define TPM_KEY_DELEGATE_Quote                          (1 <<  3)\n#define TPM_KEY_DELEGATE_Unseal                         (1 <<  2)\n#define TPM_KEY_DELEGATE_Seal                           (1 <<  1)\n#define TPM_KEY_DELEGATE_LoadKey                        (1 <<  0)\n/* Per2 bits */\n/* 31-0 reserved and must be 0 */\n\n/*\n * TPM_FAMILY_FLAGS ([TPM_Part2], Section 20.3)\n * These flags indicate the operational state of the delegation and\n * family table. These flags are additions to TPM_PERMANENT_FLAGS and\n * are not standalone values.\n */\n/* 31-2 reserved and must be 0 */\n#define TPM_DELEGATE_ADMIN_LOCK                         (1 << 1)\n#define TPM_FAMFLAG_ENABLED                             (1 << 0)\n\n/*\n * TPM_FAMILY_LABEL ([TPM_Part2], Section 20.4)\n * Used in the family table to hold a one-byte numeric value (sequence number)\n * that software can map to a string of bytes.\n */\ntypedef struct tdTPM_FAMILY_LABEL {\n  BYTE label;\n} TPM_FAMILY_LABEL;\n#define sizeof_TPM_FAMILY_LABEL(s) (1)\n\n/*\n * TPM_FAMILY_TABLE_ENTRY ([TPM_Part2], Section 20.5)\n * The family table entry is an individual row in the family table.\n */\n#define TPM_TAG_FAMILY_TABLE_ENTRY 0x0025\ntypedef struct tdTPM_FAMILY_TABLE_ENTRY {\n  TPM_STRUCTURE_TAG tag;\n  TPM_FAMILY_LABEL familyLabel;\n  TPM_FAMILY_ID familyID;\n  TPM_FAMILY_VERIFICATION verificationCount;\n  TPM_FAMILY_FLAGS flags;\n  /* only for internal use */\n  BOOL valid;\n} TPM_FAMILY_TABLE_ENTRY;\n#define sizeof_TPM_FAMILY_TABLE_ENTRY(s) (2 + 1 + 4 + 4 + 4)\n\n/*\n * TPM_FAMILY_TABLE ([TPM_Part2], Section 20.6)\n * The family table is stored in a TPM shielded location. There are no\n * confidential values in the family table. The family table contains\n * a minimum of 8 rows.\n */\n#define TPM_NUM_FAMILY_TABLE_ENTRY 16\ntypedef struct tdTPM_FAMILY_TABLE {\n  TPM_FAMILY_TABLE_ENTRY famRow[TPM_NUM_FAMILY_TABLE_ENTRY];\n} TPM_FAMILY_TABLE;\n\n/*\n * TPM_DELEGATE_LABEL ([TPM_Part2], Section 20.7)\n * Used in the delegate table to hold a byte that can be displayed or\n * used by applications.\n */\ntypedef struct tdTPM_DELEGATE_LABEL {\n  BYTE label;\n} TPM_DELEGATE_LABEL;\n#define sizeof_TPM_DELEGATE_LABEL(s) (1)\n\n/*\n * TPM_DELEGATE_PUBLIC ([TPM_Part2], Section 20.8)\n * The information of a delegate row that is public and does not have any\n * sensitive information.\n */\n#define TPM_TAG_DELEGATE_PUBLIC 0x001B\ntypedef struct tdTPM_DELEGATE_PUBLIC {\n  TPM_STRUCTURE_TAG tag;\n  TPM_DELEGATE_LABEL rowLabel;\n  TPM_PCR_INFO_SHORT pcrInfo;\n  TPM_DELEGATIONS permissions;\n  TPM_FAMILY_ID familyID;\n  TPM_FAMILY_VERIFICATION verificationCount;\n} TPM_DELEGATE_PUBLIC;\n#define sizeof_TPM_DELEGATE_PUBLIC(s) (2 + 1 \\\n  + sizeof_TPM_PCR_INFO_SHORT(s.pcrInfo) \\\n  + sizeof_TPM_DELEGATIONS(s.permissions) + 4 + 4)\n\n/*\n * TPM_DELEGATE_TABLE_ROW ([TPM_Part2], Section 20.9)\n * A row of the delegate table.\n */\n#define TPM_TAG_DELEGATE_TABLE_ROW 0x001C\ntypedef struct tdTPM_DELEGATE_TABLE_ROW {\n  TPM_STRUCTURE_TAG tag;\n  TPM_DELEGATE_PUBLIC pub;\n  TPM_SECRET authValue;\n  /* only for internal use */\n  BOOL valid;\n} TPM_DELEGATE_TABLE_ROW;\n#define sizeof_TPM_DELEGATE_TABLE_ROW(s) (2 \\\n  + sizeof_TPM_DELEGATE_PUBLIC(s.pub) + 20)\n\n/*\n * TPM_DELEGATE_TABLE ([TPM_Part2], Section 20.10)\n * This is the delegate table. The table contains a minimum of 2 rows.\n * This will be an entry in the TPM_PERSISTENT_DATA structure.\n */\n#define TPM_NUM_DELEGATE_TABLE_ENTRY 4\ntypedef struct tdTPM_DELEGATE_TABLE {\n  TPM_DELEGATE_TABLE_ROW delRow[TPM_NUM_DELEGATE_TABLE_ENTRY];\n} TPM_DELEGATE_TABLE;\n\n/*\n * TPM_DELEGATE_SENSITIVE ([TPM_Part2], Section 20.11)\n * The TPM_DELEGATE_SENSITIVE structure is the area of a delegate\n * blob that contains sensitive information.\n */\n#define TPM_TAG_DELEGATE_SENSITIVE 0x0026\ntypedef struct tdTPM_DELEGATE_SENSITIVE {\n  TPM_STRUCTURE_TAG tag;\n  TPM_SECRET authValue;\n} TPM_DELEGATE_SENSITIVE;\n#define sizeof_TPM_DELEGATE_SENSITIVE(s) (2 + 20)\n\n/*\n * TPM_DELEGATE_OWNER_BLOB ([TPM_Part2], Section 20.12)\n * This data structure contains all the information necessary to\n * externally store a set of owner delegation rights.\n */\n#define TPM_TAG_DELEGATE_OWNER_BLOB 0x002A\ntypedef struct tdTPM_DELEGATE_OWNER_BLOB {\n  TPM_STRUCTURE_TAG tag;\n  TPM_DELEGATE_PUBLIC pub;\n  TPM_DIGEST integrityDigest;\n  UINT32 additionalSize;\n  BYTE* additionalArea;\n  UINT32 sensitiveSize;\n  BYTE* sensitiveArea;\n} TPM_DELEGATE_OWNER_BLOB;\n#define sizeof_TPM_DELEGATE_OWNER_BLOB(s) (2 \\\n  + sizeof_TPM_DELEGATE_PUBLIC(s.pub) + 20 \\\n  + 4 + s.additionalSize + 4 + s.sensitiveSize)\n#define free_TPM_DELEGATE_OWNER_BLOB(s) { \\\n  if (s.additionalSize > 0) tpm_free(s.additionalArea); \\\n  if (s.sensitiveSize > 0) tpm_free(s.sensitiveArea); }\n\n/*\n * TPM_DELEGATE_KEY_BLOB ([TPM_Part2], Section 20.13)\n * A structure identical to TPM_DELEGATE_OWNER_BLOB but which stores\n * delegation information for user keys.\n */\n#define TPM_TAG_DELEGATE_KEY_BLOB 0x0027\ntypedef struct tdTPM_DELEGATE_KEY_BLOB {\n  TPM_STRUCTURE_TAG tag;\n  TPM_DELEGATE_PUBLIC pub;\n  TPM_DIGEST integrityDigest;\n  TPM_DIGEST pubKeyDigest;\n  UINT32 additionalSize;\n  BYTE* additionalArea;\n  UINT32 sensitiveSize;\n  BYTE* sensitiveArea;\n} TPM_DELEGATE_KEY_BLOB;\n#define sizeof_TPM_DELEGATE_KEY_BLOB(s) (2 \\\n  + sizeof_TPM_DELEGATE_PUBLIC(s.pub) + 20 + 20 \\\n  + 4 + s.additionalSize + 4 + s.sensitiveSize)\n#define free_TPM_DELEGATE_KEY_BLOB(s) { \\\n  if (s.additionalSize > 0) tpm_free(s.additionalArea); \\\n  if (s.sensitiveSize > 0) tpm_free(s.sensitiveArea); }\n\n/*\n * TPM_FAMILY_OPERATION Values ([TPM_Part2], Section 20.14)\n * These are the opFlag values used by TPM_Delegate_Manage.\n */\n#define TPM_FAMILY_CREATE       0x00000001\n#define TPM_FAMILY_ENABLE       0x00000002\n#define TPM_FAMILY_ADMIN        0x00000003\n#define TPM_FAMILY_INVALIDATE   0x00000004\n\n/*\n * TPM_CAPABILITY_AREA Values for TPM_GetCapability ([TPM_Part2], Section 21.1)\n */\n#define TPM_CAP_ORD                     0x00000001\n#define TPM_CAP_ALG                     0x00000002\n#define TPM_CAP_PID                     0x00000003\n#define TPM_CAP_FLAG                    0x00000004\n#define TPM_CAP_PROPERTY                0x00000005\n#define TPM_CAP_VERSION                 0x00000006\n#define TPM_CAP_KEY_HANDLE              0x00000007\n#define TPM_CAP_CHECK_LOADED            0x00000008\n#define TPM_CAP_SYM_MODE                0x00000009\n#define TPM_CAP_KEY_STATUS              0x0000000C\n#define TPM_CAP_NV_LIST                 0x0000000D\n#define TPM_CAP_MFR                     0x00000010\n#define TPM_CAP_NV_INDEX                0x00000011\n#define TPM_CAP_TRANS_ALG               0x00000012\n#define TPM_CAP_HANDLE                  0x00000014\n#define TPM_CAP_TRANS_ES                0x00000015\n#define TPM_CAP_AUTH_ENCRYPT            0x00000017\n#define TPM_CAP_SELECT_SIZE             0x00000018\n#define TPM_CAP_DA_LOGIC                0x00000019\n#define TPM_CAP_VERSION_VAL             0x0000001A\n\n/* subCap definitions ([TPM_Part2], Section 21.2) */\n#define TPM_CAP_PROP_PCR                0x00000101\n#define TPM_CAP_PROP_DIR                0x00000102\n#define TPM_CAP_PROP_MANUFACTURER       0x00000103\n#define TPM_CAP_PROP_KEYS               0x00000104\n#define TPM_CAP_PROP_MIN_COUNTER        0x00000107\n#define TPM_CAP_FLAG_PERMANENT          0x00000108\n#define TPM_CAP_FLAG_VOLATILE           0x00000109\n#define TPM_CAP_PROP_AUTHSESS           0x0000010A\n#define TPM_CAP_PROP_TRANSESS           0x0000010B\n#define TPM_CAP_PROP_COUNTERS           0x0000010C\n#define TPM_CAP_PROP_MAX_AUTHSESS       0x0000010D\n#define TPM_CAP_PROP_MAX_TRANSESS       0x0000010E\n#define TPM_CAP_PROP_MAX_COUNTERS       0x0000010F\n#define TPM_CAP_PROP_MAX_KEYS           0x00000110\n#define TPM_CAP_PROP_OWNER              0x00000111\n#define TPM_CAP_PROP_CONTEXT            0x00000112\n#define TPM_CAP_PROP_MAX_CONTEXT        0x00000113\n#define TPM_CAP_PROP_FAMILYROWS         0x00000114\n#define TPM_CAP_PROP_TIS_TIMEOUT        0x00000115\n#define TPM_CAP_PROP_STARTUP_EFFECT     0x00000116\n#define TPM_CAP_PROP_DELEGATE_ROW       0x00000117\n#define TPM_CAP_PROP_MAX_DAASESS        0x00000119\n#define TPM_CAP_PROP_DAASESS            0x0000011A\n#define TPM_CAP_PROP_CONTEXT_DIST       0x0000011B\n#define TPM_CAP_PROP_DAA_INTERRUPT      0x0000011C\n#define TPM_CAP_PROP_SESSIONS           0x0000011D\n#define TPM_CAP_PROP_MAX_SESSIONS       0x0000011E\n#define TPM_CAP_PROP_CMK_RESTRICTION    0x0000011F\n#define TPM_CAP_PROP_DURATION           0x00000120\n#define TPM_CAP_PROP_ACTIVE_COUNTER     0x00000122\n#define TPM_CAP_PROP_MAX_NV_AVAILABLE   0x00000123\n#define TPM_CAP_PROP_INPUT_BUFFER       0x00000124\n\n/*\n * TPM_CAPABILITY_AREA Values for TPM_SetCapability ([TPM_Part2], Section 21.4)\n */\n#define TPM_SET_PERM_FLAGS              0x00000001\n#define TPM_SET_PERM_DATA               0x00000002\n#define TPM_SET_STCLEAR_FLAGS           0x00000003\n#define TPM_SET_STCLEAR_DATA            0x00000004\n#define TPM_SET_STANY_FLAGS             0x00000005\n#define TPM_SET_STANY_DATA              0x00000006\n#define TPM_SET_VENDOR                  0x00000007\n\n/*\n * TPM_CAP_VERSION_INFO ([TPM_Part2], Section 21.6)\n * This structure is an output from a TPM_GetCapability request.\n * The TPM returns the current version and revision of the TPM.\n */\n#define TPM_TAG_CAP_VERSION_INFO 0x0030\ntypedef struct tdTPM_CAP_VERSION_INFO {\n  TPM_STRUCTURE_TAG tag;\n  TPM_VERSION version;\n  UINT16 specLevel;\n  BYTE errataRev;\n  BYTE tpmVendorID[4];\n  UINT16 vendorSpecificSize;\n  BYTE* vendorSpecific;\n} TPM_CAP_VERSION_INFO;\n#define sizeof_TPM_CAP_VERSION_INFO(s) (sizeof(TPM_STRUCTURE_TAG) \\\n  + sizeof(TPM_VERSION) + sizeof(UINT16) + sizeof(BYTE) + 4*sizeof(BYTE) \\\n  + sizeof(UINT16) + s.vendorSpecificSize)\n\n/* TPM_DA_ACTION_TYPE ([TPM_Part2], Section 21.10)\n * This structure indicates the action taken when the dictionary attack\n * mitigation logic is active, when TPM_DA_STATE is TPM_DA_STATE_ACTIVE.\n */\n#define TPM_TAG_DA_ACTION_TYPE 0x0039\ntypedef struct tdTPM_DA_ACTION_TYPE {\n  TPM_STRUCTURE_TAG tag;\n  UINT32 actions;\n} TPM_DA_ACTION_TYPE;\n\n#define TPM_DA_ACTION_FAILURE_MODE        (1 << 3)\n#define TPM_DA_ACTION_DEACTIVATE          (1 << 2)\n#define TPM_DA_ACTION_DISABLE             (1 << 1)\n#define TPM_DA_ACTION_TIMEOUT             (1 << 0)\n\n/*\n * TPM_DA_INFO ([TPM_Part2], Section 21.7)\n * This structure is an output from a TPM_GetCapability->TPM_CAP_DA_LOGIC\n * request if TPM_PERMANENT_FLAGS->disableFullDALogicInfo is FALSE.\n */\n#define TPM_TAG_DA_INFO 0x0037\ntypedef struct tdTPM_DA_INFO {\n  TPM_STRUCTURE_TAG tag;\n  TPM_DA_STATE state;\n  UINT16 currentCount;\n  UINT16 thresholdCount;\n  TPM_DA_ACTION_TYPE actionAtThreshold;\n  UINT32 actionDependValue;\n  UINT32 vendorDataSize;\n  BYTE* vendorData;\n} TPM_DA_INFO;\n#define sizeof_TPM_DA_INFO(s) (sizeof(TPM_STRUCTURE_TAG) \\\n  + sizeof(TPM_DA_STATE) + 2*sizeof(UINT16) + sizeof(TPM_DA_ACTION_TYPE) \\\n  + 2*sizeof(UINT32) + s.vendorDataSize)\n\n/*\n * TPM_DA_INFO_LIMITED ([TPM_Part2], Section 21.8)\n * This structure is an output from a TPM_GetCapability->TPM_CAP_DA_LOGIC\n * request if TPM_PERMANENT_FLAGS->disableFullDALogicInfo is TRUE.\n */\n#define TPM_TAG_DA_INFO_LIMITED 0x0038\ntypedef struct tdTPM_DA_INFO_LIMITED {\n  TPM_STRUCTURE_TAG tag;\n  TPM_DA_STATE state;\n  TPM_DA_ACTION_TYPE actionAtThreshold;\n  UINT32 vendorDataSize;\n  BYTE* vendorData;\n} TPM_DA_INFO_LIMITED;\n#define sizeof_TPM_DA_INFO_LIMITED(s) (sizeof(TPM_STRUCTURE_TAG) \\\n  + sizeof(TPM_DA_STATE) + sizeof(TPM_DA_ACTION_TYPE) \\\n  + sizeof(UINT32) + s.vendorDataSize)\n\n/*\n * TPM_DA_STATE ([TPM_Part2], Section 21.9)\n * TPM_DA_STATE enumerates the possible states of the dictionary attack\n * mitigation logic.\n */\n#define TPM_DA_STATE_INACTIVE      0x00\n#define TPM_DA_STATE_ACTIVE        0x01\n\n\n/*\n * DAA Structures ([TPM_Part2], Section 22)\n */\n\n/*\n * Size and constant definitions ([TPM_Part2], Section 22.1 and 22.2)\n */\n#define DAA_SIZE_r0             43\n#define DAA_SIZE_r1             43\n#define DAA_SIZE_r2             128\n#define DAA_SIZE_r3             168\n#define DAA_SIZE_r4             219\n#define DAA_SIZE_NT             20\n#define DAA_SIZE_v0             128\n#define DAA_SIZE_v1             192\n#define DAA_SIZE_NE             256\n#define DAA_SIZE_w              256\n#define DAA_SIZE_issuerModulus  256\n\n#define DAA_power0              104\n#define DAA_power1              1024\n\n/*\n * TPM_DAA_ISSUER ([TPM_Part2], Section 22.3)\n * This structure is the abstract representation of non-secret\n * settings controlling a DAA context.\n */\n#define TPM_TAG_DAA_ISSUER 0x002F\ntypedef struct tdTPM_DAA_ISSUER {\n  TPM_STRUCTURE_TAG tag;\n  TPM_DIGEST DAA_digest_R0;\n  TPM_DIGEST DAA_digest_R1;\n  TPM_DIGEST DAA_digest_S0;\n  TPM_DIGEST DAA_digest_S1;\n  TPM_DIGEST DAA_digest_n;\n  TPM_DIGEST DAA_digest_gamma;\n  BYTE DAA_generic_q[26];\n} TPM_DAA_ISSUER;\n#define sizeof_TPM_DAA_ISSUER(s) (2 + (6 * 20) + 26)\n\n/*\n * TPM_DAA_TPM ([TPM_Part2], Section 22.4)\n * This structure is the abstract representation of TPM specific\n * parameters used during a DAA context.\n */\n#define TPM_TAG_DAA_TPM 0x0032\ntypedef struct tdTPM_DAA_TPM {\n  TPM_STRUCTURE_TAG tag;\n  TPM_DIGEST DAA_digestIssuer;\n  TPM_DIGEST DAA_digest_v0;\n  TPM_DIGEST DAA_digest_v1;\n  TPM_DIGEST DAA_rekey;\n  UINT32 DAA_count;\n} TPM_DAA_TPM;\n#define sizeof_TPM_DAA_TPM(s) (2 + (4 * 20) + 4)\n\n/*\n * TPM_DAA_CONTEXT ([TPM_Part2], Section 22.5)\n * This structure is created and used inside a TPM, and never leaves it.\n */\n#define TPM_TAG_DAA_CONTEXT 0x002D\ntypedef struct tdTPM_DAA_CONTEXT {\n  TPM_STRUCTURE_TAG tag;\n  TPM_DIGEST DAA_digestContext;\n  TPM_DIGEST DAA_digest;\n  TPM_DAA_CONTEXT_SEED DAA_contextSeed;\n  BYTE DAA_scratch[256];\n  BYTE DAA_stage;\n} TPM_DAA_CONTEXT;\n#define sizeof_TPM_DAA_CONTEXT(s) (2 + (3 * 20) + 256 + 1)\n\n/*\n * TPM_DAA_JOINDATA ([TPM_Part2], Section 22.6)\n * This structure is the abstract representation of data that\n * exists only during a specific JOIN session.\n */\ntypedef struct tdTPM_DAA_JOINDATA {\n  BYTE DAA_join_u0[128];\n  BYTE DAA_join_u1[138];\n  TPM_DIGEST DAA_digest_n0;\n} TPM_DAA_JOINDATA;\n#define sizeof_TPM_DAA_JOINDATA(s) (128 + 138 + 20)\n\n/*\n * TPM_DAA_BLOB ([TPM_Part2], Section 22.8)\n * The structure passed during the join process.\n */\n#define TPM_TAG_DAA_BLOB 0x002C\ntypedef struct tdTPM_DAA_BLOB {\n  TPM_STRUCTURE_TAG tag;\n  TPM_RESOURCE_TYPE resourceType;\n  BYTE label[16];\n  TPM_DIGEST blobIntegrity;\n  UINT32 additionalSize;\n  BYTE* additionalData;\n  UINT32 sensitiveSize;\n  BYTE* sensitiveData;\n} TPM_DAA_BLOB;\n#define sizeof_TPM_DAA_BLOB(s) (sizeof(TPM_STRUCTURE_TAG) \\\n  + sizeof(TPM_RESOURCE_TYPE) + sizeof(s.label) + sizeof(TPM_DIGEST) \\\n  + 2*sizeof(UINT32) + s.additionalSize + s.sensitiveSize)\n\n/*\n * TPM_DAA_SENSITIVE ([TPM_Part2], Section 22.9)\n * The encrypted area for the DAA parameters.\n */\n#define TPM_TAG_DAA_SENSITIVE 0x0031\ntypedef struct tdTPM_DAA_SENSITIVE {\n  TPM_STRUCTURE_TAG tag;\n  UINT32 internalSize;\n  BYTE* internalData;\n} TPM_DAA_SENSITIVE;\n#define sizeof_TPM_DAA_SENSITIVE(s) (sizeof(TPM_STRUCTURE_TAG) \\\n  + sizeof(UINT32) + s.internalSize)\n\n/*\n * Redirection ([TPM_Part2], Section 23)\n */\n\n/*\n * TPM_REDIR_COMMAND ([TPM_Part2], Section 23.1)\n * The types of redirections.\n */\ntypedef UINT32 TPM_REDIR_COMMAND;\n\n/*\n * Internal Data Held By TPM ([TPM_Part2], Section 7)\n */\n\n/*\n * TPM_PERMANENT_FLAGS ([TPM_Part2], Section 7.1)\n * These flags maintain state information for the TPM. The values are not\n * affected by any TPM_Startup command.\n */\n#define TPM_TAG_PERMANENT_FLAGS 0x001F\ntypedef struct tdTPM_PERMANENT_FLAGS {\n  TPM_STRUCTURE_TAG tag;\n  BOOL disable;\n  BOOL ownership;\n  BOOL deactivated;\n  BOOL readPubek;\n  BOOL disableOwnerClear;\n  BOOL allowMaintenance;\n  BOOL physicalPresenceLifetimeLock;\n  BOOL physicalPresenceHWEnable;\n  BOOL physicalPresenceCMDEnable;\n  BOOL CEKPUsed;\n  BOOL TPMpost;\n  BOOL TPMpostLock;\n  BOOL FIPS;\n  BOOL operator;\n  BOOL enableRevokeEK;\n  BOOL nvLocked;\n  BOOL readSRKPub;\n  BOOL tpmEstablished;\n  BOOL maintenanceDone;\n  BOOL disableFullDALogicInfo;\n  /* additional, not marshalled flags */\n  BOOL selfTestSucceeded;\n  BOOL owned;\n  BOOL dataRestored;\n} TPM_PERMANENT_FLAGS;\n#define sizeof_TPM_PERMANENT_FLAGS(s) (2 + 20)\n\n/*\n * TPM_STCLEAR_FLAGS ([TPM_Part2], Section 7.2)\n * These flags maintain state that is reset on each TPM_Startup(ST_Clear)\n * command. The values are not affected by TPM_Startup(ST_State) commands.\n */\n#define TPM_TAG_STCLEAR_FLAGS 0x0020\ntypedef struct tdTPM_STCLEAR_FLAGS {\n  TPM_STRUCTURE_TAG tag;\n  BOOL deactivated;\n  BOOL disableForceClear;\n  BOOL physicalPresence;\n  BOOL physicalPresenceLock;\n  BOOL bGlobalLock;\n} TPM_STCLEAR_FLAGS;\n#define sizeof_TPM_STCLEAR_FLAGS(s) (2 + 5)\n\n/*\n * TPM_STANY_FLAGS ([TPM_Part2], Section 7.3)\n * These flags reset on any TPM_Startup command.\n */\n#define TPM_TAG_STANY_FLAGS 0x0021\ntypedef struct tdTPM_STANY_FLAGS {\n  TPM_STRUCTURE_TAG tag;\n  BOOL postInitialise;\n  TPM_MODIFIER_INDICATOR localityModifier;\n  BOOL transportExclusive;\n  BOOL TOSPresent;\n} TPM_STANY_FLAGS;\n#define sizeof_TPM_STANY_FLAGS(s) (2 + 1 + 4 + 1 + 1)\n\n/*\n * TPM_KEY_DATA\n * This structure contains the data for stored RSA keys.\n */\ntypedef struct tdTPM_KEY_DATA {\n  TPM_PAYLOAD_TYPE payload;\n  TPM_KEY_USAGE keyUsage;\n  TPM_KEY_FLAGS keyFlags;\n  TPM_KEY_CONTROL keyControl;\n  TPM_AUTH_DATA_USAGE authDataUsage;\n  TPM_ENC_SCHEME encScheme;\n  TPM_SIG_SCHEME sigScheme;\n  TPM_SECRET usageAuth;\n  TPM_SECRET migrationAuth;\n  TPM_PCR_INFO pcrInfo;\n  BOOL parentPCRStatus;\n  tpm_rsa_private_key_t key;\n} TPM_KEY_DATA;\n#define sizeof_RSA(s) (6 + tpm_rsa_modulus_length(&s) \\\n + tpm_rsa_exponent_length(&s) + tpm_rsa_prime1_length(&s))\n#define sizeof_TPM_KEY_DATA(s) (1 + 2 + 4 + 4 + 1 + 2 + 2 + 20 + 20 \\\n  + ((s.keyFlags & TPM_KEY_FLAG_HAS_PCR) ? sizeof_TPM_PCR_INFO(s.pcrInfo) : 0) \\\n  + 1 + sizeof_RSA(s.key))\n#define free_TPM_KEY_DATA(s) { tpm_rsa_release_private_key(&s.key); }\n\n/*\n * TPM_PUBKEY_DATA\n * This structure contains the data for stored RSA public keys.\n */\ntypedef struct tdTPM_PUBKEY_DATA {\n  BOOL valid;\n  TPM_ENC_SCHEME encScheme;\n  TPM_SIG_SCHEME sigScheme;\n  tpm_rsa_public_key_t key;\n} TPM_PUBKEY_DATA;\n#define sizeof_RSAPub(s) (4 + tpm_rsa_public_modulus_length(&s) \\\n + tpm_rsa_public_exponent_length(&s))\n#define sizeof_TPM_PUBKEY_DATA(s) (1 + 2 + 2 + sizeof_RSAPub(s.key))\n#define free_TPM_PUBKEY_DATA(s) { tpm_rsa_release_public_key(&s.key); }\n\n/*\n * TPM_PERMANENT_DATA ([TPM_Part2], Section 7.4)\n * This structure contains the data fields that are permanently held in\n * the TPM and not affected by TPM_Startup(any).\n *\n * This is an informative structure and not normative.\n */\n#define TPM_TAG_PERMANENT_DATA          0x0022\n#define TPM_MAX_COUNTERS                4\n#define TPM_DELEGATE_KEY                TPM_KEY\n#define TPM_MAX_NV_WRITE_NOOWNER        64\n#define TPM_MAX_KEYS                    10\n#define TPM_SYM_KEY_SIZE                32\n#define TPM_MAX_NV_BUF_SIZE             1024\n#define TPM_MAX_NVS                     20\n#define TPM_NUM_TIS_TIMEOUTS            4\n#define TPM_NUM_CMD_DURATIONS           3\ntypedef struct tdTPM_PERMANENT_DATA {\n  TPM_STRUCTURE_TAG tag;\n  TPM_VERSION version;\n  TPM_NONCE tpmProof;\n  TPM_NONCE ekReset;\n  TPM_SECRET ownerAuth;\n  TPM_SECRET operatorAuth;\n  TPM_DAA_TPM_SEED tpmDAASeed;\n  TPM_NONCE daaProof;\n  TPM_PUBKEY_DATA manuMaintPub;\n  tpm_rsa_private_key_t endorsementKey;\n  TPM_KEY_DATA srk;\n  BYTE contextKey[TPM_SYM_KEY_SIZE];\n  BYTE delegateKey[TPM_SYM_KEY_SIZE];\n  BYTE daaKey[TPM_SYM_KEY_SIZE];\n  TPM_ACTUAL_COUNT auditMonotonicCounter;\n  TPM_COUNTER_VALUE counters[TPM_MAX_COUNTERS];\n  TPM_PCR_ATTRIBUTES pcrAttrib[TPM_NUM_PCR];\n  TPM_PCRVALUE pcrValue[TPM_NUM_PCR];\n  BYTE ordinalAuditStatus[TPM_ORD_MAX / 8];\n  BYTE rngState[16];\n  TPM_FAMILY_TABLE familyTable;\n  TPM_DELEGATE_TABLE delegateTable;\n  UINT32 lastFamilyID;\n  TPM_CMK_DELEGATE restrictDelegate;\n  UINT32 maxNVBufSize;\n  UINT32 noOwnerNVWrite;\n  UINT32 nvDataSize;\n  BYTE nvData[TPM_MAX_NV_SIZE];\n  TPM_NV_DATA_SENSITIVE nvStorage[TPM_MAX_NVS];\n  TPM_KEY_DATA keys[TPM_MAX_KEYS];\n  UINT32 tis_timeouts[TPM_NUM_TIS_TIMEOUTS];\n  UINT32 cmd_durations[TPM_NUM_CMD_DURATIONS];\n  const char *testResult;\n} TPM_PERMANENT_DATA;\n\nstatic inline int sizeof_TPM_PERMANENT_DATA(TPM_PERMANENT_DATA *s) {\n  int i, size = 2 + 4 + 6*20;\n  size += (s->manuMaintPub.valid) ? sizeof_TPM_PUBKEY_DATA((s->manuMaintPub)) : 1;\n  size += sizeof_RSA(s->endorsementKey);\n  size += (s->srk.payload != TPM_PT_NONE) ? sizeof_TPM_KEY_DATA(s->srk) : 1;\n  size += 3*TPM_SYM_KEY_SIZE + 4;\n  for (i = 0; i < TPM_MAX_COUNTERS; i++) {\n    size += sizeof_TPM_COUNTER_VALUE2((s->counters[i]));\n  }\n  size += TPM_NUM_PCR*(sizeof_TPM_PCR_ATTRIBUTES(x) + 20) + TPM_ORD_MAX/8 + 16;\n  for (i = 0; i < TPM_NUM_FAMILY_TABLE_ENTRY; i++) {\n    size += 1;\n    if (s->familyTable.famRow[i].valid)\n      size += sizeof_TPM_FAMILY_TABLE_ENTRY((s->familyTable.famRow[i]));\n  }\n  for (i = 0; i < TPM_NUM_DELEGATE_TABLE_ENTRY; i++) {\n    size += 1;\n    if (s->delegateTable.delRow[i].valid)\n      size += sizeof_TPM_DELEGATE_TABLE_ROW((s->delegateTable.delRow[i]));\n  }\n  size += 5*4 + TPM_MAX_NV_SIZE;\n  for (i = 0; i < TPM_MAX_NVS; i++) {\n    size += 1;\n    if (s->nvStorage[i].valid)\n      size += sizeof_TPM_NV_DATA_SENSITIVE((s->nvStorage[i]));\n  }\n  for (i = 0; i < TPM_MAX_KEYS; i++) {\n    if (s->keys[i].payload != TPM_PT_NONE)\n      size += sizeof_TPM_KEY_DATA((s->keys[i]));\n    else\n      size += 1;\n  }\n  size += TPM_NUM_TIS_TIMEOUTS * 4;\n  size += TPM_NUM_CMD_DURATIONS * 4;\n  return size;\n}\n\nstatic inline void free_TPM_PERMANENT_DATA(TPM_PERMANENT_DATA *s)\n{\n  int i;\n  /* release the EK, SRK as well as all other rsa keys */\n  if (s->endorsementKey.size > 0) tpm_rsa_release_private_key(&s->endorsementKey);\n  if (s->srk.payload) free_TPM_KEY_DATA(s->srk);\n  if (s->manuMaintPub.valid) free_TPM_PUBKEY_DATA(s->manuMaintPub);\n  for (i = 0; i < TPM_MAX_KEYS; i++)\n    if (s->keys[i].payload) free_TPM_KEY_DATA(s->keys[i]);\n}\n\n/*\n * TPM_STCLEAR_DATA ([TPM_Part2], Section 7.5)\n * Most of the data in this structure resets on TPM_Startup(ST_Clear).\n *\n * This is an informative structure and not normative.\n */\n#define TPM_TAG_STCLEAR_DATA 0x0023\ntypedef struct tdTPM_STCLEAR_DATA {\n  TPM_STRUCTURE_TAG tag;\n  TPM_NONCE contextNonceKey;\n  TPM_COUNT_ID countID;\n  UINT32 ownerReference;\n  BOOL disableResetLock;\n  UINT32 deferredPhysicalPresence;\n} TPM_STCLEAR_DATA;\n#define sizeof_TPM_STCLEAR_DATA(s) (2 + 20 + 4 + 4 + 1 + 4)\n\n/*\n * TPM_SESSION_DATA\n * This structure contains the data for authorization and transport sessions.\n */\n#define TPM_ST_INVALID    0\n#define TPM_ST_OIAP       1\n#define TPM_ST_OSAP       2\n#define TPM_ST_TRANSPORT  4\n#define TPM_ST_DAA        8\n#define TPM_ST_DSAP      16\ntypedef struct tdTPM_SESSION_DATA {\n  BYTE type;\n  TPM_NONCE nonceEven;\n  TPM_NONCE lastNonceEven;\n  TPM_SECRET sharedSecret;\n  TPM_HANDLE handle;\n  TPM_ENTITY_TYPE entityType;\n  TPM_DELEGATIONS permissions;\n  TPM_FAMILY_ID familyID;\n  TPM_TRANSPORT_INTERNAL transInternal;\n} TPM_SESSION_DATA;\n#define sizeof_TPM_SESSION_DATA(s) (1 + 3*20 + 4 + 2 \\\n  + ((s.type == TPM_ST_DSAP) ? \\\n     sizeof_TPM_DELEGATIONS(s.delegations) + 4 : 0) \\\n  + ((s.type == TPM_ST_TRANSPORT) ? \\\n     sizeof_TPM_TRANSPORT_INTERNAL(s.transInternal) : 0))\n\n/*\n * TPM_DAA_SESSION_DATA\n * This structure contains the data for DAA sessions.\n */\ntypedef UINT32 TPM_DAAHANDLE;\ntypedef struct tdTPM_DAA_SESSION_DATA {\n  BYTE type;\n  TPM_DAA_ISSUER DAA_issuerSettings;\n  TPM_DAA_TPM DAA_tpmSpecific;\n  TPM_DAA_CONTEXT DAA_session;\n  TPM_DAA_JOINDATA DAA_joinSession;\n  TPM_HANDLE handle;\n} TPM_DAA_SESSION_DATA;\n#define sizeof_TPM_DAA_SESSION_DATA(s) (1 \\\n  + sizeof_TPM_DAA_ISSUER(s.DAA_issuerSettings) \\\n  + sizeof_TPM_DAA_TPM(s.DAA_tpmSpecific) \\\n  + sizeof_TPM_DAA_CONTEXT(s.DAA_session) \\\n  + sizeof_TPM_DAA_JOINDATA(s.DAA_joinSession) + 4)\n\n/*\n * TPM_STANY_DATA ([TPM_Part2], Section 7.6)\n * Most of the data in this structure resets on TPM_Startup(ST_State).\n *\n * This is an informative structure and not normative.\n */\n#define TPM_TAG_STANY_DATA        0x0024\n#define TPM_MAX_SESSIONS          4\n#define TPM_MAX_SESSION_LIST      16\n#define TPM_MAX_SESSIONS_DAA      1\ntypedef struct tdTPM_STANY_DATA {\n  TPM_STRUCTURE_TAG tag;\n  TPM_NONCE contextNonceSession;\n  TPM_DIGEST auditDigest;\n  BOOL auditSession;\n  TPM_CURRENT_TICKS currentTicks;\n  UINT32 contextCount;\n  UINT32 contextList[TPM_MAX_SESSION_LIST];\n  TPM_SESSION_DATA sessions[TPM_MAX_SESSIONS];\n  TPM_DAA_SESSION_DATA sessionsDAA[TPM_MAX_SESSIONS_DAA];\n  TPM_DAAHANDLE currentDAA;\n  TPM_TRANSHANDLE transExclusive;\n} TPM_STANY_DATA;\n#define sizeof_TPM_STANY_DATA(s) (2 + 20 + 20 + 1 \\\n  + sizeof_TPM_CURRENT_TICKS(s.currentTicks) \\\n  + 4 + (4 * TPM_MAX_SESSION_LIST) \\\n  + (sizeof_TPM_SESSION_DATA(s.sessions[0]) * TPM_MAX_SESSIONS) \\\n  + (sizeof_TPM_DAA_SESSION_DATA(s.sessionsDAA[0]) * TPM_MAX_SESSIONS_DAA) \\\n  + 4 + 4)\n\n/*\n * TPM_DATA\n * Internal data of the TPM\n */\ntypedef struct tdTPM_DATA {\n  struct {\n    TPM_PERMANENT_FLAGS flags;\n    TPM_PERMANENT_DATA data;\n  } permanent;\n  struct {\n    TPM_STCLEAR_FLAGS flags;\n    TPM_STCLEAR_DATA data;\n  } stclear;\n  struct {\n    TPM_STANY_FLAGS flags;\n    TPM_STANY_DATA data;\n  } stany;\n} TPM_DATA;\n#define sizeof_TPM_DATA(s) ( \\\n  sizeof_TPM_PERMANENT_FLAGS(s.permanent.flags) + 2 \\\n  + sizeof_TPM_PERMANENT_DATA(&s.permanent.data) \\\n  + sizeof_TPM_STCLEAR_FLAGS(s.stclear.flags) \\\n  + sizeof_TPM_STCLEAR_DATA(s.stclear.data) \\\n  + sizeof_TPM_STANY_DATA(s.stany.data))\n#define free_TPM_DATA(s) { free_TPM_PERMANENT_DATA(&s.permanent.data); }\n\n/*\n * Context Structures\n */\n\n/*\n * TPM_CONTEXT_BLOB ([TPM_Part2], Section 18.1)\n * This is the header for the wrapped context. The blob contains all\n * information necessary to reload the context back into the TPM.\n */\n#define TPM_TAG_CONTEXTBLOB 0x0001\ntypedef struct tdTPM_CONTEXT_BLOB {\n  TPM_STRUCTURE_TAG tag;\n  TPM_RESOURCE_TYPE resourceType;\n  TPM_HANDLE handle;\n  BYTE label[16];\n  UINT32 contextCount;\n  TPM_DIGEST integrityDigest;\n  UINT32 additionalSize;\n  BYTE* additionalData;\n  UINT32 sensitiveSize;\n  BYTE* sensitiveData;\n} TPM_CONTEXT_BLOB;\n#define sizeof_TPM_CONTEXT_BLOB(s) (2 + 4 + 4 + 16 + 4 + 20 \\\n  + 4 + s.additionalSize + 4 + s.sensitiveSize)\n#define free_TPM_CONTEXT_BLOB(s) { \\\n  if (s.additionalSize > 0) tpm_free(s.additionalData); \\\n  if (s.sensitiveSize > 0) tpm_free(s.sensitiveData); }\n\n/*\n * TPM_CONTEXT_SENSITIVE ([TPM_Part2], Section 18.2)\n * The internal areas that the TPM needs to encrypt and store off the TPM.\n * This is an informative structure and the TPM can implement in any\n * manner they wish.\n */\n#define TPM_TAG_CONTEXT_SENSITIVE 0x0002\ntypedef struct tdTPM_CONTEXT_SENSITIVE {\n  TPM_STRUCTURE_TAG tag;\n  TPM_NONCE contextNonce;\n  UINT32 internalSize;\n  TPM_RESOURCE_TYPE resourceType;\n  union {\n    TPM_KEY_DATA key;\n    TPM_SESSION_DATA session;\n    TPM_DAA_SESSION_DATA sessionDAA;\n  } internalData;\n} TPM_CONTEXT_SENSITIVE;\n#define sizeof_TPM_CONTEXT_SENSITIVE(s) (2 + 20 + 4 + 4 + s.internalSize)\n\n/*\n * TPM communication packets\n */\n\n/*\n * TPM_REQUEST \n * TPM command request\n */\ntypedef struct tdTPM_REQUEST {\n  TPM_TAG tag;\n  UINT32 size;\n  TPM_COMMAND_CODE ordinal;\n  BYTE *param;\n  UINT32 paramSize;\n  TPM_AUTH auth1;\n  TPM_AUTH auth2;\n} TPM_REQUEST;\n\n/*\n * TPM_RESPONSE\n * TPM command response\n */\ntypedef struct tdTPM_RESPONSE {\n  TPM_TAG tag;\n  UINT32 size;\n  TPM_RESULT result;\n  BYTE *param;\n  UINT32 paramSize;\n  TPM_AUTH *auth1;\n  TPM_AUTH *auth2;\n} TPM_RESPONSE;\n\n#endif /* _TPM_STRUCTURES_H_ */\n"
  },
  {
    "path": "tpm/tpm_testing.c",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: tpm_testing.c 364 2010-02-11 10:24:45Z mast $\n */\n\n#include \"tpm_emulator.h\"\n#include \"tpm_commands.h\"\n#include \"tpm_data.h\"\n#include \"crypto/sha1.h\"\n#include \"crypto/hmac.h\"\n#include \"crypto/rsa.h\"\n\n#define INTERVAL(x,a,b) ((a) <= (x) && (x) <= (b))\nstatic int tpm_test_prng(void)\n{\n  int ones[16] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 }; \n  int run_len0 = 0;\n  int run_len1 = 0;\n  int monobit = 0;\n  int poker[16] = {0};\n  int run0[6] = {0};\n  int run1[6] = {0};\n  int run_34 = 0;\n  unsigned long x = 0;\n  unsigned int i, j, k;\n  BYTE buf[25];\n  \n  debug(\"tpm_test_prng()\");\n  /* Statistical random number generator tests according to FIPS 140-1 */\n  for (i = 0; i < 2500 / sizeof(buf); i++) {\n    tpm_get_random_bytes(buf, sizeof(buf));\n    for (j = 0; j < sizeof(buf); j++) {\n      BYTE hi = (buf[j] >> 4) & 0x0f;\n      BYTE lo = buf[j] & 0x0f;\n      monobit += ones[hi] + ones[lo];\n      poker[hi]++; poker[lo]++;\n      for (k = 0; k < 8; k++) {\n        if ((buf[j] >> k) & 0x01) {\n          run_len1++;\n          if (run_len0 >= 34) run_34 = 1;\n          if (run_len0 >= 6) run0[5]++;\n          else if (run_len0 > 0) run0[run_len0 - 1]++;\n          run_len0 = 0;\n        } else {\n          run_len0++;  \n          if (run_len1 >= 34) run_34 = 1;\n          if (run_len1 >= 6) run1[5]++;\n          else if (run_len1 > 0) run1[run_len1 - 1]++;\n          run_len1 = 0;\n        }\n      }    \n    }\n  }\n  /* evaluate result */\n  /* x = sum(poker[i]^2) * 16 / 5000 - 5000 */\n  for (i = 0; i < 16; i++) x += 16 * poker[i] * poker[i] / 50;\n  x -= 5000 * 100;\n  debug(\"Monobit: %d\", monobit);\n  debug(\"Poker:   %d.%d\", (int)(x/100), (int)(x/10)%10);\n  debug(\"run_1:   %d, %d\", run0[0], run1[0]); \n  debug(\"run_2:   %d, %d\", run0[1], run1[1]);\n  debug(\"run_3:   %d, %d\", run0[2], run1[2]);\n  debug(\"run_4:   %d, %d\", run0[3], run1[3]);\n  debug(\"run_5:   %d, %d\", run0[4], run1[4]);\n  debug(\"run_6+:  %d, %d\", run0[5], run1[5]); \n  debug(\"run_34:  %d\", run_34);\n  if (INTERVAL(monobit, 9654, 10346) && INTERVAL(x, 103, 5740)\n      && INTERVAL(run0[0], 2267, 2733) && INTERVAL(run1[0], 2267, 2733)\n      && INTERVAL(run0[1], 1079, 1421) && INTERVAL(run1[1], 1079, 1421)\n      && INTERVAL(run0[2],  502,  748) && INTERVAL(run1[2],  502,  748)\n      && INTERVAL(run0[3],  223,  402) && INTERVAL(run1[3],  223,  402)\n      && INTERVAL(run0[4],   90,  223) && INTERVAL(run1[4],   90,  223)\n      && INTERVAL(run0[5],   90,  223) && INTERVAL(run1[5],   90,  223)\n      && !run_34) return 0;\n  return -1;\n}\n\nstatic int tpm_test_sha1(void)\n{\n  tpm_sha1_ctx_t ctx;\n  BYTE digest[SHA1_DIGEST_LENGTH];\n  unsigned int i, j;\n  /* test cases for SHA-1 given in FIPS PUB 180-1 */\n  struct {\n    const char *data; uint32_t repetitions; const char *digest;\n  } test_cases[] =  {{\n    \"abc\", 1,\n    \"\\xA9\\x99\\x3E\\x36\\x47\\x06\\x81\\x6A\\xBA\\x3E\\x25\\x71\\x78\\x50\\xC2\\x6C\\x9C\\xD0\\xD8\\x9D\"\n  }, {\n    \"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq\", 1,\n    \"\\x84\\x98\\x3E\\x44\\x1C\\x3B\\xD2\\x6E\\xBA\\xAE\\x4A\\xA1\\xF9\\x51\\x29\\xE5\\xE5\\x46\\x70\\xF1\"\n  }, {\n    \"a\", 1000000,\n    \"\\x34\\xAA\\x97\\x3C\\xD4\\xC4\\xDA\\xA4\\xF6\\x1E\\xEB\\x2B\\xDB\\xAD\\x27\\x31\\x65\\x34\\x01\\x6F\"\n  }, {\n    \"0123456701234567012345670123456701234567012345670123456701234567\", 10,\n    \"\\xDE\\xA3\\x56\\xA2\\xCD\\xDD\\x90\\xC7\\xA7\\xEC\\xED\\xC5\\xEB\\xB5\\x63\\x93\\x4F\\x46\\x04\\x52\"\n  }};\n\n  debug(\"tpm_test_sha1()\");\n  for (i = 0; i < sizeof(test_cases) / sizeof(test_cases[0]); i++) {\n    tpm_sha1_init(&ctx);\n    for (j = 0; j < test_cases[i].repetitions; j++)\n      tpm_sha1_update(&ctx, (uint8_t*)test_cases[i].data, strlen(test_cases[i].data));\n    tpm_sha1_final(&ctx, digest);\n    if (memcmp(digest, test_cases[i].digest, SHA1_DIGEST_LENGTH) != 0) return -1;\n  }\n  return 0;\n}\n\nstatic int tpm_test_hmac(void)\n{\n  tpm_hmac_ctx_t ctx;\n  uint8_t digest[SHA1_DIGEST_LENGTH];\n  unsigned int i, j;\n  /* test cases for HMAC-SHA-1 given in RFC 2202 */\n  struct {\n    const char *key; uint8_t key_len;\n    const char *data; uint8_t data_len;\n    const char *digest;\n  } test_cases[] = {{\n    \"\\x0b\", 20, \"Hi There\", 8,\n    \"\\xb6\\x17\\x31\\x86\\x55\\x05\\x72\\x64\\xe2\\x8b\\xc0\\xb6\\xfb\\x37\\x8c\\x8e\\xf1\\x46\\xbe\\x00\"\n  }, {\n    \"Jefe\", 4, \"what do ya want for nothing?\", 28,\n    \"\\xef\\xfc\\xdf\\x6a\\xe5\\xeb\\x2f\\xa2\\xd2\\x74\\x16\\xd5\\xf1\\x84\\xdf\\x9c\\x25\\x9a\\x7c\\x79\"\n  }, {\n    \"\\xaa\", 20, \"\\xdd\", 50,\n    \"\\x12\\x5d\\x73\\x42\\xb9\\xac\\x11\\xcd\\x91\\xa3\\x9a\\xf4\\x8a\\xa1\\x7b\\x4f\\x63\\xf1\\x75\\xd3\"\n  }, {\n    \"\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0a\\x0b\\x0c\\x0d\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\"\n    \"\\x15\\x16\\x17\\x18\\x19\", 25, \"\\xcd\", 50,\n    \"\\x4c\\x90\\x07\\xf4\\x02\\x62\\x50\\xc6\\xbc\\x84\\x14\\xf9\\xbf\\x50\\xc8\\x6c\\x2d\\x72\\x35\\xda\"\n  }, {\n    \"\\x0c\", 20, \"Test With Truncation\", 20,\n    \"\\x4c\\x1a\\x03\\x42\\x4b\\x55\\xe0\\x7f\\xe7\\xf2\\x7b\\xe1\\xd5\\x8b\\xb9\\x32\\x4a\\x9a\\x5a\\x04\"\n  }, {\n    \"\\xaa\", 80, \"Test Using Larger Than Block-Size Key - Hash Key First\", 54,\n    \"\\xaa\\x4a\\xe5\\xe1\\x52\\x72\\xd0\\x0e\\x95\\x70\\x56\\x37\\xce\\x8a\\x3b\\x55\\xed\\x40\\x21\\x12\"\n  }, {\n    \"\\xaa\", 80,\n    \"Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data\", 73,\n    \"\\xe8\\xe9\\x9d\\x0f\\x45\\x23\\x7d\\x78\\x6d\\x6b\\xba\\xa7\\x96\\x5c\\x78\\x08\\xbb\\xff\\x1a\\x91\"\n  }};\n\n  debug(\"tpm_test_hmac()\");\n  for (i = 0; i < sizeof(test_cases) / sizeof(test_cases[0]); i++) {\n    if (strlen(test_cases[i].key) < test_cases[i].key_len) {\n      uint8_t key[test_cases[i].key_len];\n      memset(key, test_cases[i].key[0], test_cases[i].key_len);\n      tpm_hmac_init(&ctx, (uint8_t*)key, test_cases[i].key_len);\n    } else {\n      tpm_hmac_init(&ctx, (uint8_t*)test_cases[i].key, test_cases[i].key_len);\n    }\n    for (j = 0; j < test_cases[i].data_len; j += strlen(test_cases[i].data)) {\n      tpm_hmac_update(&ctx, (uint8_t *)test_cases[i].data, strlen(test_cases[i].data));\n    }\n    tpm_hmac_final(&ctx, digest);\n    if (memcmp(digest, test_cases[i].digest, SHA1_DIGEST_LENGTH) != 0) return -1;\n  }\n  return 0;\n}\n\nstatic int tpm_test_rsa_EK(void)\n{\n  int res = 0;\n  uint8_t *data = (uint8_t*)\"RSA PKCS #1 v1.5 Test-String\";\n  uint8_t buf[256];\n  size_t buf_len, data_len = strlen((char*)data);\n  tpm_rsa_private_key_t priv_key;\n  tpm_rsa_public_key_t pub_key;\n\n  debug(\"tpm_test_rsa_EK()\");\n  /* generate and test key-pair */\n  debug(\"tpm_rsa_generate_key()\");\n  res = tpm_rsa_generate_key(&priv_key, 512);\n  tpm_rsa_release_private_key(&priv_key);\n  if (res) return res;\n  /* test endorsement key */\n  debug(\"testing endorsement key\");\n  do {\n    priv_key = tpmData.permanent.data.endorsementKey;\n    if (!priv_key.size) return 0;\n    TPM_RSA_EXTRACT_PUBLIC_KEY(priv_key, pub_key);\n    /* test sign and verify functions */\n    debug(\"tpm_rsa_sign(RSA_SSA_PKCS1_SHA1)\");\n    res = tpm_rsa_sign(&priv_key, RSA_SSA_PKCS1_SHA1, data, data_len, buf);\n    if (res) break;\n    debug(\"tpm_rsa_verify(RSA_SSA_PKCS1_SHA1)\");\n    res = tpm_rsa_verify(&pub_key, RSA_SSA_PKCS1_SHA1, data, data_len, buf);\n    if (res) break;\n    debug(\"tpm_rsa_sign(RSA_SSA_PKCS1_DER)\");\n    res = tpm_rsa_sign(&priv_key, RSA_SSA_PKCS1_DER, data, data_len, buf);\n    if (res) break;\n    debug(\"tpm_rsa_verify(RSA_SSA_PKCS1_DER)\");\n    res = tpm_rsa_verify(&pub_key, RSA_SSA_PKCS1_DER, data, data_len, buf);\n    if (res) break;\n    /* test encryption and decryption */\n    debug(\"tpm_rsa_encrypt(RSA_ES_PKCSV15)\");\n    res = tpm_rsa_encrypt(&pub_key, RSA_ES_PKCSV15,\n      data, data_len, buf, &buf_len);\n    if (res) break;\n    debug(\"tpm_rsa_decrypt(RSA_ES_PKCSV15)\");\n    res = tpm_rsa_decrypt(&priv_key, RSA_ES_PKCSV15,\n      buf, buf_len, buf, &buf_len);\n    if (res) break;\n    debug(\"verify plain text\");\n    res = !((buf_len == data_len) && !memcmp(buf, data, buf_len));\n    if (res) break;\n    debug(\"tpm_rsa_encrypt(RSA_ES_OAEP_SHA1)\");\n    res = tpm_rsa_encrypt(&pub_key, RSA_ES_OAEP_SHA1,\n      data, data_len/2, buf, &buf_len);\n    if (res) break;\n    debug(\"tpm_rsa_decrypt(RSA_ES_OAEP_SHA1)\");\n    res = tpm_rsa_decrypt(&priv_key, RSA_ES_OAEP_SHA1,\n      buf, buf_len, buf, &buf_len);\n    if (res) break;\n    debug(\"verify plain text\");\n    res = !(buf_len == data_len/2 && !memcmp(buf, data, buf_len));\n  } while (0);\n  /* release public key and exit */\n  tpm_rsa_release_public_key(&pub_key);\n  return res;\n}\n\n/*\n * Admin Testing ([TPM_Part3], Section 4)\n */\n\nTPM_RESULT TPM_SelfTestFull(void)\n{\n  info(\"TPM_SelfTestFull()\");\n  if (tpm_test_prng() != 0) {\n    tpmData.permanent.data.testResult = \"tpm_test_prng() failed\";\n    tpmData.permanent.flags.selfTestSucceeded = FALSE;\n  } else if (tpm_test_sha1() != 0) {\n    tpmData.permanent.data.testResult = \"tpm_test_sha1() failed\";\n    tpmData.permanent.flags.selfTestSucceeded = FALSE;\n  } else if (tpm_test_hmac() != 0) {\n    tpmData.permanent.data.testResult = \"tpm_test_hmac() failed\";\n    tpmData.permanent.flags.selfTestSucceeded = FALSE;\n  } else if (tpm_test_rsa_EK() != 0) {\n    tpmData.permanent.data.testResult = \"tpm_test_rsa_EK() failed\";\n    tpmData.permanent.flags.selfTestSucceeded = FALSE;\n  } else {\n    tpmData.permanent.data.testResult = \"Success\";\n    tpmData.permanent.flags.selfTestSucceeded = TRUE;\n  }\n  if (tpmData.permanent.flags.selfTestSucceeded) {\n    info(\"Self-Test succeeded\");\n  } else {\n    error(\"Self-Test failed: %s\", tpmData.permanent.data.testResult);\n  }\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_ContinueSelfTest(void)\n{\n  info(\"TPM_ContinueSelfTest()\");\n  /* we just run a complete self-test */\n  return TPM_SelfTestFull();\n}\n\nTPM_RESULT TPM_GetTestResult(UINT32 *outDataSize, BYTE **outData)\n{\n  info(\"TPM_GetTestResult()\");\n  if (tpmData.permanent.data.testResult == NULL) return TPM_FAIL;\n  *outDataSize = strlen(tpmData.permanent.data.testResult) + 1;\n  *outData = tpm_malloc(*outDataSize);\n  if (*outData == NULL) return TPM_FAIL;\n  memcpy(*outData, tpmData.permanent.data.testResult, *outDataSize);\n  return TPM_SUCCESS;;\n}\n\n"
  },
  {
    "path": "tpm/tpm_ticks.c",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: tpm_ticks.c 453 2010-09-11 11:00:58Z mast $\n */\n\n#include \"tpm_emulator.h\"\n#include \"tpm_commands.h\"\n#include \"tpm_data.h\"\n#include \"tpm_handles.h\"\n#include \"tpm_marshalling.h\"\n\n/*\n * Timing Ticks ([TPM_Part3], Section 23)\n * The TPM timing ticks are always available for use. The association of \n * timing ticks to actual time is a protocol that occurs outside of the TPM. \n * See the design document for details. \n */\n\nTPM_RESULT TPM_GetTicks(TPM_CURRENT_TICKS *currentTime)\n{\n  info(\"TPM_GetTicks()\");\n  memcpy(currentTime, &tpmData.stany.data.currentTicks, \n    sizeof(TPM_CURRENT_TICKS));\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_TickStampBlob(TPM_KEY_HANDLE keyHandle, TPM_NONCE *antiReplay,\n                             TPM_DIGEST *digestToStamp, TPM_AUTH *auth1,  \n                             TPM_CURRENT_TICKS *currentTicks, \n                             UINT32 *sigSize, BYTE **sig)\n{\n  TPM_RESULT res;\n  TPM_KEY_DATA *key;\n  BYTE *info_buffer, *ptr;\n  UINT32 info_length, len;\n  info(\"TPM_TickStampBlob()\");\n  /* get key */\n  key = tpm_get_key(keyHandle);\n  if (key == NULL) return TPM_INVALID_KEYHANDLE;\n  /* verify authorization */\n  if (auth1->authHandle != TPM_INVALID_HANDLE\n      || key->authDataUsage != TPM_AUTH_NEVER) {\n    res = tpm_verify_auth(auth1, key->usageAuth, keyHandle);\n    if (res != TPM_SUCCESS) return res;\n  }\n  if (key->keyUsage != TPM_KEY_SIGNING && key->keyUsage != TPM_KEY_LEGACY\n      && key->keyUsage != TPM_KEY_IDENTITY) return TPM_INVALID_KEYUSAGE;\n  if (key->sigScheme != TPM_SS_RSASSAPKCS1v15_SHA1)\n    return TPM_INAPPROPRIATE_SIG;\n  /* get current ticks */\n  TPM_GetTicks(currentTicks);\n  /* sign data using signature scheme PKCS1_SHA1 and TPM_SIGN_INFO container */\n  *sigSize = key->key.size >> 3;\n  *sig = tpm_malloc(*sigSize);\n  if (*sig == NULL) return TPM_FAIL; \n  /* setup TPM_SIGN_INFO structure */\n  info_length = 30 + sizeof(TPM_DIGEST) + sizeof_TPM_CURRENT_TICKS(currentTicks);\n  info_buffer = tpm_malloc(info_length);\n  if (info_buffer == NULL) {\n    tpm_free(*sig);\n    return TPM_FAIL;\n  }\n  memcpy(&info_buffer[0], \"\\x00\\x05TSTP\", 6);\n  memcpy(&info_buffer[6], antiReplay->nonce, 20);\n  ptr = &info_buffer[26]; len = info_length - 26;\n  tpm_marshal_UINT32(&ptr, &len, info_length - 30);\n  memcpy(ptr, digestToStamp->digest, sizeof(TPM_DIGEST));\n  ptr += sizeof(TPM_DIGEST); len -= sizeof(TPM_DIGEST);\n  if (tpm_marshal_TPM_CURRENT_TICKS(&ptr, &len, currentTicks)\n      || tpm_rsa_sign(&key->key, RSA_SSA_PKCS1_SHA1,\n                      info_buffer, info_length, *sig)) {\n    tpm_free(*sig);\n    tpm_free(info_buffer);\n    return TPM_FAIL;\n  }\n  return TPM_SUCCESS;\n}\n\nvoid tpm_update_ticks(void)\n{\n  if (tpmData.stany.data.currentTicks.tag == 0) {\n    tpmData.stany.data.currentTicks.tag = TPM_TAG_CURRENT_TICKS;\n    tpmData.stany.data.currentTicks.currentTicks += tpm_get_ticks();\n    tpm_get_random_bytes(tpmData.stany.data.currentTicks.tickNonce.nonce, \n      sizeof(TPM_NONCE));\n    tpmData.stany.data.currentTicks.tickRate = 1;\n  } else {\n    tpmData.stany.data.currentTicks.currentTicks += tpm_get_ticks();\n  }\n}\n\n"
  },
  {
    "path": "tpm/tpm_transport.c",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: tpm_transport.c 367 2010-02-13 15:52:18Z mast $\n */\n\n/* \n * Thanks go to Edison Su (<sudison@gmail.com>) for providing\n * the initial Transport Session patch.\n */\n\n#include \"tpm_emulator.h\"\n#include \"tpm_commands.h\"\n#include \"tpm_handles.h\"\n#include \"tpm_marshalling.h\"\n#include \"tpm_data.h\"\n#include \"crypto/rsa.h\"\n#include \"crypto/sha1.h\"\n\n/*\n * Transport Sessions ([TPM_Part3], Section 24)\n */\n\nstatic void debug_buf(const char *str, uint8_t *buf, size_t buf_len)\n{\n  static char map[] = \"0123456789abcdef\";\n  char hex[buf_len * 3];\n  size_t i;\n  for (i = 0; i < buf_len; i++) {\n    hex[i*3 + 0] = map[buf[i] >> 4];\n    hex[i*3 + 1] = map[buf[i] & 0x0f];\n    hex[i*3 + 2] = ' ';\n  }\n  hex[sizeof(hex) - 1] = 0;\n  debug(\"%s%s\", str, hex);\n}\n\nstatic int decrypt_transport_auth(TPM_KEY_DATA *key, BYTE *enc, UINT32 enc_size,\n                                  TPM_TRANSPORT_AUTH *trans_auth) \n{\n  BYTE *buf;\n  size_t buf_size;\n  int scheme;\n  switch (key->encScheme) {\n    case TPM_ES_RSAESOAEP_SHA1_MGF1: scheme = RSA_ES_OAEP_SHA1; break;\n    case TPM_ES_RSAESPKCSv15: scheme = RSA_ES_PKCSV15; break;\n    default: return -1;\n  }\n  buf = tpm_malloc(key->key.size);\n  if (buf == NULL\n      || tpm_rsa_decrypt(&key->key, scheme, enc, enc_size, buf, &buf_size)\n      || buf_size != sizeof_TPM_TRANSPORT_AUTH(x)\n      || (((UINT16)buf[0] << 8) | buf[1]) != TPM_TAG_TRANSPORT_AUTH) {\n    tpm_free(buf);\n    return -1;\n  }\n  trans_auth->tag = TPM_TAG_TRANSPORT_AUTH;\n  memcpy(trans_auth->authData, &buf[2], sizeof(TPM_AUTHDATA));\n  tpm_free(buf);\n  return 0;\n}\n\nstatic void transport_log_in(BYTE *params, BYTE *pubKeyHash,\n                             TPM_DIGEST *transDigest)\n{\n  BYTE *ptr, buf[sizeof_TPM_TRANSPORT_LOG_IN(x)];\n  UINT32 len;\n  tpm_sha1_ctx_t sha1;\n\n  ptr = buf; len = sizeof(buf);\n  tpm_marshal_TPM_TAG(&ptr, &len, TPM_TAG_TRANSPORT_LOG_IN);\n  tpm_marshal_BLOB(&ptr, &len, params, SHA1_DIGEST_LENGTH);\n  tpm_marshal_BLOB(&ptr, &len, pubKeyHash, SHA1_DIGEST_LENGTH);\n  tpm_sha1_init(&sha1);\n  tpm_sha1_update(&sha1, transDigest->digest, sizeof(transDigest->digest));\n  tpm_sha1_update(&sha1, buf, sizeof(buf));\n  tpm_sha1_final(&sha1, transDigest->digest);\n  debug_buf(\"LogIn: transDigest: \", transDigest->digest, sizeof(transDigest->digest));\n}\n\nstatic void transport_log_out(BYTE *params, TPM_DIGEST *transDigest)\n{\n  BYTE *ptr, buf[sizeof_TPM_TRANSPORT_LOG_OUT(x)];\n  UINT32 len;\n  tpm_sha1_ctx_t sha1;\n\n  ptr = buf; len = sizeof(buf);\n  tpm_marshal_TPM_TAG(&ptr, &len, TPM_TAG_TRANSPORT_LOG_OUT);\n  tpm_marshal_TPM_CURRENT_TICKS(&ptr, &len, &tpmData.stany.data.currentTicks);\n  tpm_marshal_BLOB(&ptr, &len, params, SHA1_DIGEST_LENGTH);\n  tpm_marshal_TPM_MODIFIER_INDICATOR(&ptr, &len, tpmData.stany.flags.localityModifier);\n  tpm_sha1_init(&sha1);\n  tpm_sha1_update(&sha1, transDigest->digest, sizeof(transDigest->digest));\n  tpm_sha1_update(&sha1, buf, sizeof(buf));\n  tpm_sha1_final(&sha1, transDigest->digest);\n  debug_buf(\"LogOut: transDigest: \", transDigest->digest, sizeof(transDigest->digest));\n}\n\nTPM_RESULT TPM_EstablishTransport(TPM_KEY_HANDLE encHandle,\n                                  TPM_TRANSPORT_PUBLIC *transPublic,\n                                  UINT32 secretSize, BYTE *secret,\n                                  TPM_AUTH *auth1,\n                                  TPM_TRANSHANDLE *transHandle,\n                                  TPM_MODIFIER_INDICATOR *locality,\n                                  TPM_CURRENT_TICKS *currentTicks,\n                                  TPM_NONCE *transNonceEven)\n{\n  TPM_RESULT res;\n  TPM_KEY_DATA *key;\n  TPM_TRANSPORT_AUTH trans_auth;\n  TPM_SESSION_DATA *session;\n\n  info(\"TPM_EstablishTransport()\");\n  /* setup authorization data */\n  if (encHandle == TPM_KH_TRANSPORT) {\n    if (auth1->authHandle != TPM_INVALID_HANDLE) return TPM_BADTAG;\n    if (transPublic->transAttributes & TPM_TRANSPORT_ENCRYPT) return TPM_BAD_SCHEME;\n    if (secretSize != 20) return TPM_BAD_PARAM_SIZE;\n    memcpy(trans_auth.authData, secret, 20);\n  } else {\n    /* get key and verify its usage */\n    key = tpm_get_key(encHandle);\n    if (key == NULL) return TPM_INVALID_KEYHANDLE;\n    if (key->keyUsage != TPM_KEY_STORAGE && key->keyUsage != TPM_KEY_LEGACY)\n        return TPM_INVALID_KEYUSAGE;\n    /* verify authorization */ \n    if (key->authDataUsage != TPM_AUTH_NEVER) {\n      res = tpm_verify_auth(auth1, key->usageAuth, encHandle);\n      if (res != TPM_SUCCESS) return res;\n      if (decrypt_transport_auth(key, secret, secretSize, &trans_auth))\n        return TPM_DECRYPT_ERROR;\n    }\n  }\n  /* check whether the transport has to be encrypted */\n  if (transPublic->transAttributes & TPM_TRANSPORT_ENCRYPT) {\n    if (tpmData.permanent.flags.FIPS\n        && transPublic->algID == TPM_ALG_MGF1) return TPM_INAPPROPRIATE_ENC;\n    /* until now, only MGF1 is supported */\n    if (transPublic->algID != TPM_ALG_MGF1) return TPM_BAD_KEY_PROPERTY;\n  }\n  /* initialize transport session */\n  tpm_get_random_bytes(transNonceEven->nonce, sizeof(transNonceEven->nonce));\n  *transHandle = tpm_get_free_session(TPM_ST_TRANSPORT);\n  session = tpm_get_transport(*transHandle);\n  if (session == NULL) return TPM_RESOURCES;\n  session->transInternal.transHandle = *transHandle;\n  memset(&session->transInternal.transDigest, 0, sizeof(TPM_DIGEST));\n  memcpy(&session->transInternal.transPublic, transPublic,\n    sizeof_TPM_TRANSPORT_PUBLIC((*transPublic)));\n  memcpy(&session->transInternal.transNonceEven, transNonceEven, sizeof(TPM_NONCE));\n  memcpy(&session->nonceEven, transNonceEven, sizeof(TPM_NONCE));\n  memcpy(&session->transInternal.authData, trans_auth.authData, sizeof(TPM_AUTHDATA));\n  *locality = tpmData.stany.flags.localityModifier;\n  memcpy(currentTicks, &tpmData.stany.data.currentTicks, sizeof(TPM_CURRENT_TICKS));\n  /* perform transport logging */\n  if (transPublic->transAttributes & TPM_TRANSPORT_LOG) {\n    tpm_sha1_ctx_t sha1;\n    BYTE *ptr, buf[4 + 4 + 4 + sizeof_TPM_CURRENT_TICKS(x) + 20];\n    UINT32 len;\n    /* log input */\n    memset(buf, 0, sizeof(buf));\n    transport_log_in(auth1->digest, buf, &session->transInternal.transDigest);\n    /* compute digest of output parameters and log output */\n    ptr = buf; len = sizeof(buf);\n    tpm_marshal_UINT32(&ptr, &len, TPM_SUCCESS);\n    tpm_marshal_TPM_COMMAND_CODE(&ptr, &len, TPM_ORD_EstablishTransport);\n    tpm_marshal_TPM_MODIFIER_INDICATOR(&ptr, &len, *locality);\n    tpm_marshal_TPM_CURRENT_TICKS(&ptr, &len, currentTicks);\n    tpm_marshal_TPM_NONCE(&ptr, &len, transNonceEven);\n    tpm_sha1_init(&sha1);\n    tpm_sha1_update(&sha1, buf, sizeof(buf));\n    tpm_sha1_final(&sha1, buf);\n    transport_log_out(buf, &session->transInternal.transDigest);\n  }\n  /* check whether this is a exclusive transport session */\n  if (transPublic->transAttributes & TPM_TRANSPORT_EXCLUSIVE) {\n    tpmData.stany.flags.transportExclusive = TRUE;\n    tpmData.stany.data.transExclusive = *transHandle;\n  }\n  auth1->continueAuthSession = FALSE;\n  return TPM_SUCCESS;\n}\n\nextern UINT32 tpm_get_in_param_offset(TPM_COMMAND_CODE ordinal);\nextern UINT32 tpm_get_out_param_offset(TPM_COMMAND_CODE ordinal);\nextern void tpm_compute_in_param_digest(TPM_REQUEST *req);\nextern void tpm_execute_command(TPM_REQUEST *req, TPM_RESPONSE *rsp);\nextern void tpm_compute_out_param_digest(TPM_COMMAND_CODE ordinal, TPM_RESPONSE *rsp);\n\nstatic void decrypt_wrapped_command(BYTE *buf, UINT32 buf_len, TPM_AUTH *auth,\n                                    TPM_SESSION_DATA *session)\n\n{\n  UINT32 i, j;\n  BYTE mask[SHA1_DIGEST_LENGTH];\n  tpm_sha1_ctx_t sha1;\n  for (i = 0; buf_len > 0; i++) {\n    tpm_sha1_init(&sha1);\n    tpm_sha1_update(&sha1, session->nonceEven.nonce, sizeof(session->nonceEven.nonce));\n    tpm_sha1_update(&sha1, auth->nonceOdd.nonce, sizeof(auth->nonceOdd.nonce));\n    tpm_sha1_update(&sha1, (uint8_t*)\"in\", 2);\n    tpm_sha1_update(&sha1, session->transInternal.authData, sizeof(TPM_SECRET));\n    tpm_sha1_update_be32(&sha1, i);\n    tpm_sha1_final(&sha1, mask);\n    for (j = 0; j < sizeof(mask) && buf_len > 0; j++) { \n      *buf++ ^= mask[j];\n      buf_len--;\n    }\n  }\n}\n\nstatic void encrypt_wrapped_command(BYTE *buf, UINT32 buf_len, TPM_AUTH *auth,\n                                    TPM_SESSION_DATA *session)\n{\n  UINT32 i, j;\n  BYTE mask[SHA1_DIGEST_LENGTH];\n  tpm_sha1_ctx_t sha1;\n  for (i = 0; buf_len > 0; i++) {\n    tpm_sha1_init(&sha1);\n    tpm_sha1_update(&sha1, session->nonceEven.nonce, sizeof(session->nonceEven.nonce));\n    tpm_sha1_update(&sha1, auth->nonceOdd.nonce, sizeof(auth->nonceOdd.nonce));\n    tpm_sha1_update(&sha1, (uint8_t*)\"out\", 3);\n    tpm_sha1_update(&sha1, session->transInternal.authData, sizeof(TPM_SECRET));\n    tpm_sha1_update_be32(&sha1, i);\n    tpm_sha1_final(&sha1, mask);\n    for (j = 0; j < sizeof(mask) && buf_len > 0; j++) { \n      *buf++ ^= mask[j];\n      buf_len--;\n    }\n  }\n}\n\nstatic void compute_key_digest(TPM_REQUEST *req, TPM_DIGEST *digest)\n{\n  tpm_sha1_ctx_t ctx;\n  TPM_HANDLE h1, h2;\n  TPM_KEY_DATA *k1, *k2;\n  BYTE *ptr;\n  UINT32 len, offset = tpm_get_in_param_offset(req->ordinal);\n  /* handle some exceptions */\n  if (req->ordinal == TPM_ORD_FlushSpecific) offset = 0;\n  else if (req->ordinal == TPM_ORD_OwnerReadInternalPub) offset = 4;\n  /* compute public key digests */\n  if (offset == 0) {\n    debug(\"no handles\");\n    memset(digest, 0, sizeof(TPM_DIGEST));\n  } else if (offset == 4) {\n    debug(\"one handle\");\n    ptr = req->param; len = 4;\n    tpm_unmarshal_TPM_HANDLE(&ptr, &len, &h1);\n    k1 = tpm_get_key(h1);\n    if (k1 != NULL && tpm_compute_key_data_digest(k1, digest) == 0) {\n      debug(\"key found\");\n      /* compute outer hash */\n      tpm_sha1_init(&ctx);\n      tpm_sha1_update(&ctx, digest->digest, sizeof(digest->digest));\n      tpm_sha1_final(&ctx, digest->digest);\n    } else {\n      memset(digest, 0, sizeof(TPM_DIGEST));\n    }\n  } else if (offset == 8) {\n    TPM_DIGEST digest2;\n    debug(\"two handles\");\n    ptr = req->param; len = 8;\n    tpm_unmarshal_TPM_HANDLE(&ptr, &len, &h1);\n    tpm_unmarshal_TPM_HANDLE(&ptr, &len, &h2);\n    k1 = tpm_get_key(h1);\n    k2 = tpm_get_key(h2);\n    if (k1 != NULL && tpm_compute_key_data_digest(k1, digest) == 0\n        && k2 != NULL && tpm_compute_key_data_digest(k2, &digest2) == 0) {\n      debug(\"two keys found\");\n      /* compute outer hash */\n      tpm_sha1_init(&ctx);\n      tpm_sha1_update(&ctx, digest->digest, sizeof(digest->digest));\n      tpm_sha1_update(&ctx, digest2.digest, sizeof(digest2.digest));\n      tpm_sha1_final(&ctx, digest->digest);\n    } else {\n      memset(digest, 0, sizeof(TPM_DIGEST));\n    }\n  } else {\n    memset(digest, 0, sizeof(TPM_DIGEST));\n  }\n}\n\nTPM_RESULT TPM_ExecuteTransport(UINT32 inWrappedCmdSize, BYTE *inWrappedCmd,\n                                TPM_AUTH *auth1, UINT64 *currentTicks,\n                                TPM_MODIFIER_INDICATOR *locality,\n                                UINT32 *outWrappedCmdSize, BYTE **outWrappedCmd)\n{\n  TPM_RESULT res;\n  TPM_SESSION_DATA *session;\n  TPM_REQUEST req;\n  TPM_RESPONSE rsp;\n  BYTE *ptr, buf[4 * 4 + 8 + 20];\n  UINT32 len, offset;\n  tpm_sha1_ctx_t sha1;\n  info(\"TPM_ExecuteTransport()\");\n  /* get transport session */\n  session = tpm_get_transport(auth1->authHandle);\n  if (session == NULL) return TPM_BAD_PARAMETER;\n  /* unmarshal wrapped command */\n  len = inWrappedCmdSize;\n  ptr = inWrappedCmd;\n  if (tpm_unmarshal_TPM_REQUEST(&ptr, &len, &req)) return TPM_FAIL;\n  /* decrypt wrapped command if needed */\n  ptr = tpm_malloc(req.paramSize);\n  if (ptr == NULL) return TPM_FAIL;\n  memcpy(ptr, req.param, req.paramSize);\n  if (session->transInternal.transPublic.transAttributes & TPM_TRANSPORT_ENCRYPT) {\n    if (req.ordinal == TPM_ORD_OIAP || req.ordinal == TPM_ORD_OSAP) {\n      offset = req.paramSize;\n    } else if (req.ordinal == TPM_ORD_DSAP) {\n      offset = 30;\n    } else {\n      offset = tpm_get_in_param_offset(req.ordinal);\n    }\n    debug(\"decrypting %d bytes, starting at pos %d\", req.paramSize - offset, offset);\n    decrypt_wrapped_command(ptr + offset, req.paramSize - offset, auth1, session);\n  }\n  req.param = ptr;\n  /* verify authorization */\n  tpm_compute_in_param_digest(&req);\n  tpm_sha1_init(&sha1);\n  tpm_sha1_update_be32(&sha1, TPM_ORD_ExecuteTransport);\n  tpm_sha1_update_be32(&sha1, inWrappedCmdSize);\n  tpm_sha1_update(&sha1, req.auth1.digest, sizeof(req.auth1.digest));\n  tpm_sha1_final(&sha1, auth1->digest);\n  res = tpm_verify_auth(auth1, session->transInternal.authData, TPM_INVALID_HANDLE);\n  if (res != TPM_SUCCESS) {\n    tpm_free(req.param);\n    return res;\n  }\n  /* nested transport sessions are not allowed */\n  if (req.ordinal == TPM_ORD_EstablishTransport\n      || req.ordinal == TPM_ORD_ExecuteTransport\n      || req.ordinal == TPM_ORD_ReleaseTransportSigned) {\n    tpm_free(req.param);\n    return TPM_NO_WRAP_TRANSPORT;\n  }\n  /* log input parameters */\n  if (session->transInternal.transPublic.transAttributes & TPM_TRANSPORT_LOG) {\n    TPM_DIGEST keyDigest;\n    compute_key_digest(&req, &keyDigest);\n    transport_log_in(req.auth1.digest, keyDigest.digest,\n                     &session->transInternal.transDigest);\n  }\n  /* execute and audit command*/\n  tpm_audit_request(req.ordinal, &req);\n  tpm_execute_command(&req, &rsp);\n  tpm_audit_response(req.ordinal, &rsp);\n  tpm_free(req.param);\n  /* get locality and ticks */\n  *locality = tpmData.stany.flags.localityModifier;\n  *currentTicks = tpmData.stany.data.currentTicks.currentTicks;\n  /* if required, compute digest of internal output parameters */\n  debug(\"result = %d\", rsp.result);\n  if (rsp.result == TPM_SUCCESS) {\n    if (rsp.tag == TPM_TAG_RSP_COMMAND) {\n      rsp.auth1 = &req.auth1;\n      tpm_compute_out_param_digest(req.ordinal, &rsp);\n    }\n    /* encrypt parameters */\n    if (session->transInternal.transPublic.transAttributes & TPM_TRANSPORT_ENCRYPT) {\n      if (req.ordinal == TPM_ORD_OIAP || req.ordinal == TPM_ORD_OSAP) {\n        offset = rsp.paramSize;\n      } else if (req.ordinal == TPM_ORD_DSAP) {\n        offset = rsp.paramSize;\n      } else {\n        offset = tpm_get_out_param_offset(req.ordinal);\n      }\n      debug(\"encrypting %d bytes, starting at pos %d\", rsp.paramSize - offset, offset);\n      encrypt_wrapped_command(rsp.param + offset, rsp.paramSize - offset, auth1, session);\n    }\n  } else {\n    rsp.auth1 = &req.auth1;\n    memset(rsp.auth1->digest, 0, sizeof(*rsp.auth1->digest));\n  }\n  /* marshal response */\n  *outWrappedCmdSize = len = rsp.size;\n  *outWrappedCmd = ptr = tpm_malloc(len);\n  if (ptr == NULL) {\n    tpm_free(rsp.param);\n    return TPM_FAIL;\n  }\n  tpm_marshal_TPM_RESPONSE(&ptr, &len, &rsp);\n  debug(\"marshalling done.\");\n  /* log output parameters */\n  if (session->transInternal.transPublic.transAttributes & TPM_TRANSPORT_LOG) {\n    transport_log_out(rsp.auth1->digest, &session->transInternal.transDigest);\n  }\n  tpm_free(rsp.param);\n  /* compute digest of output parameters */\n  ptr = buf; len = sizeof(buf);\n  tpm_marshal_UINT32(&ptr, &len, TPM_SUCCESS);\n  tpm_marshal_TPM_COMMAND_CODE(&ptr, &len, TPM_ORD_ExecuteTransport);\n  tpm_marshal_UINT64(&ptr, &len, *currentTicks);\n  tpm_marshal_TPM_MODIFIER_INDICATOR(&ptr, &len, *locality);\n  tpm_marshal_UINT32(&ptr, &len, *outWrappedCmdSize);\n  memcpy(ptr, rsp.auth1->digest, sizeof(rsp.auth1->digest));\n  tpm_sha1_init(&sha1);\n  tpm_sha1_update(&sha1, buf, sizeof(buf));\n  tpm_sha1_final(&sha1, auth1->digest);\n  return TPM_SUCCESS;\n}\n\nTPM_RESULT TPM_ReleaseTransportSigned(TPM_KEY_HANDLE keyHandle,\n                                      TPM_NONCE *antiReplay,\n                                      TPM_AUTH *auth1, TPM_AUTH *auth2,\n                                      TPM_MODIFIER_INDICATOR *locality,\n                                      TPM_CURRENT_TICKS *currentTicks,\n                                      UINT32 *sigSize, BYTE **sig)\n{\n  TPM_RESULT res;\n  TPM_KEY_DATA *key;\n  TPM_SESSION_DATA *session;\n  BYTE buf[30 + 20];\n  info(\"TPM_ReleaseTransportSigned()\");\n  /* get key */\n  key = tpm_get_key(keyHandle);\n  if (key == NULL) return TPM_INVALID_KEYHANDLE;\n  /* verify authorization */ \n  if (auth2->authHandle != TPM_INVALID_HANDLE\n      || key->authDataUsage != TPM_AUTH_NEVER) {\n    res = tpm_verify_auth(auth1, key->usageAuth, keyHandle);\n    if (res != TPM_SUCCESS) return res;\n    session = tpm_get_transport(auth2->authHandle);\n    if (session == NULL) return TPM_INVALID_AUTHHANDLE;\n    res = tpm_verify_auth(auth2, session->transInternal.authData, TPM_INVALID_HANDLE);\n    if (res != TPM_SUCCESS) return (res == TPM_AUTHFAIL) ? TPM_AUTH2FAIL : res;\n  } else {\n    session = tpm_get_transport(auth1->authHandle);\n    if (session == NULL) return TPM_INVALID_AUTHHANDLE;\n    res = tpm_verify_auth(auth1, session->transInternal.authData, TPM_INVALID_HANDLE);\n    if (res != TPM_SUCCESS) return res;\n  }\n  /* invalidate transport session */\n  auth1->continueAuthSession = FALSE;\n  /* logging must be enabled */\n  if (!(session->transInternal.transPublic.transAttributes & TPM_TRANSPORT_LOG))\n    return TPM_BAD_MODE;\n  *locality = tpmData.stany.flags.localityModifier;\n  memcpy(currentTicks, &tpmData.stany.data.currentTicks, sizeof(TPM_CURRENT_TICKS));\n  transport_log_out(auth1->digest, &session->transInternal.transDigest);\n  /* setup a TPM_SIGN_INFO structure */\n  memcpy(&buf[0], (uint8_t*)\"\\x00\\x05TRAN\", 6);\n  memcpy(&buf[6], antiReplay->nonce, 20);\n  memcpy(&buf[26], (uint8_t*)\"\\x00\\x00\\x00\\x14\", 4);\n  memcpy(&buf[30], session->transInternal.transDigest.digest, 20);\n  /* sign info structure */ \n  if (key->sigScheme == TPM_SS_RSASSAPKCS1v15_SHA1) {\n    tpm_sha1_ctx_t ctx;\n    debug(\"TPM_SS_RSASSAPKCS1v15_SHA1\");\n    tpm_sha1_init(&ctx);\n    tpm_sha1_update(&ctx, buf, sizeof(buf));\n    tpm_sha1_final(&ctx, buf);\n    res = tpm_sign(key, auth1, FALSE, buf, SHA1_DIGEST_LENGTH, sig, sigSize);\n  } else if (key->sigScheme == TPM_SS_RSASSAPKCS1v15_INFO) {\n    debug(\"TPM_SS_RSASSAPKCS1v15_INFO\");\n    res = tpm_sign(key, auth1, TRUE, buf, sizeof(buf), sig, sigSize);\n  } else {\n    debug(\"unsupported signature scheme: %02x\", key->sigScheme);\n    res = TPM_INVALID_KEYUSAGE;\n  }\n  return res;\n}\n"
  },
  {
    "path": "tpmd/CMakeLists.txt",
    "content": "# Software-based Trusted Platform Module (TPM) Emulator\n# Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n#\n# $Id: CMakeLists.txt 364 2010-02-11 10:24:45Z mast $\n\nif(UNIX)\n\nadd_subdirectory(unix)\n\nelseif(WIN32)\n\nadd_subdirectory(windows)\n\nendif()\n\n"
  },
  {
    "path": "tpmd/unix/CMakeLists.txt",
    "content": "# Software-based Trusted Platform Module (TPM) Emulator\n# Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n#\n# $Id: CMakeLists.txt 464 2011-07-09 14:57:41Z mast $\n\ninclude_directories(\"${PROJECT_SOURCE_DIR}/tpm\")\n\nfile(GLOB tpmd_SRCS \"*.[h|c]\")\nadd_executable(tpmd ${tpmd_SRCS})\nif(MTM_EMULATOR)\nadd_definitions(-DMTM_EMULATOR)\ntarget_link_libraries(tpmd mtm tpm tpm_crypto)\nelse()\ntarget_link_libraries(tpmd tpm tpm_crypto)\nendif()\ninstall(TARGETS tpmd RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})\n\n"
  },
  {
    "path": "tpmd/unix/tpmd.c",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: tpmd.c 463 2011-06-08 14:25:04Z mast $\n */\n\n#define _GNU_SOURCE\n#include <stdio.h>\n#include <stdlib.h>\n#include <unistd.h>\n#include <signal.h>\n#include <string.h>\n#include <errno.h>\n#include <syslog.h>\n#include <stdarg.h>\n#include <fcntl.h>\n#include <poll.h>\n#include <sys/ioctl.h>\n#include <sys/stat.h>\n#include <sys/socket.h>\n#include <sys/un.h>\n#include <pwd.h>\n#include <grp.h>\n#include \"config.h\"\n#include \"tpm/tpm_emulator.h\"\n\n#define TPM_COMMAND_TIMEOUT 30\n\nstatic volatile int stopflag = 0;\nstatic int is_daemon = 0;\nstatic int opt_debug = 0;\nstatic int opt_foreground = 0;\nstatic const char default_socket_name[] = TPM_SOCKET_NAME;\nstatic const char *opt_socket_name = default_socket_name;\nstatic const char default_dev_name[] = \"/dev/tpm_emul\";\nstatic const char *opt_dev_name = default_dev_name;\nstatic uid_t opt_uid = 0;\nstatic gid_t opt_gid = 0;\nstatic int tpm_startup = 2;\nstatic uint32_t tpm_config = 0;\nextern const char *tpm_storage_file;\n\nvoid my_log(int priority, const char *fmt, ...)\n{\n    va_list ap, bp;\n    va_start(ap, fmt);\n    va_copy(bp, ap);\n    switch (priority) {\n      case TPM_LOG_DEBUG:\n        vsyslog(LOG_DEBUG, fmt, ap);\n        break;\n      case TPM_LOG_ERROR:\n        vsyslog(LOG_ERR, fmt, ap);\n        break;\n      case TPM_LOG_INFO:\n      default:\n        vsyslog(LOG_INFO, fmt, ap);\n        break;\n    }\n    va_end(ap);\n    if (!is_daemon && (priority != TPM_LOG_DEBUG || opt_debug)) {\n        vprintf(fmt, bp);\n    }\n    va_end(bp);\n}\n\nstatic void print_usage(char *name)\n{\n    printf(\"usage: %s [-d] [-f] [-s storage file] [-u unix socket name] \"\n           \"[-o user name] [-g group name] [-h] [startup mode]\\n\", name);\n    printf(\"  d : enable debug mode\\n\");\n    printf(\"  f : forces the application to run in the foreground\\n\");\n    printf(\"  s : storage file to use (default: %s)\\n\", tpm_storage_file);\n    printf(\"  u : unix socket name to use (default: %s)\\n\", default_socket_name);\n    printf(\"  U : don't use unix socket\\n\");\n    printf(\"  e : emulation device to use (default: %s)\\n\", default_dev_name);\n    printf(\"  E : don't use emulation device\\n\");\n    printf(\"  o : effective user the application should run as\\n\");\n    printf(\"  g : effective group the application should run as\\n\");\n    printf(\"  h : print this help message\\n\");\n    printf(\"  startup mode : must be 'clear', \"\n           \"'save' (default) or 'deactivated\\n\");\n}\n\nstatic void parse_options(int argc, char **argv)\n{\n    int c, set_dev = 0;\n    struct passwd *pwd;\n    struct group *grp;\n    opt_uid = getuid();\n    opt_gid = getgid();\n    info(\"parsing options\");\n    while ((c = getopt (argc, argv, \"dfs:u:Ue:Eo:g:c:h\")) != -1) {\n        debug(\"handling option '-%c'\", c);\n        switch (c) {\n            case 'd':\n                opt_debug = 1;\n                setlogmask(setlogmask(0) | LOG_MASK(LOG_DEBUG));\n                debug(\"debug mode enabled\");\n                break;\n            case 'f':\n                debug(\"application is forced to run in foreground\");\n                opt_foreground = 1;\n                break;\n            case 's':\n                tpm_storage_file = optarg;\n                debug(\"using storage file '%s'\", tpm_storage_file);\n                break;\n            case 'u':\n                opt_socket_name = optarg;\n                debug(\"using unix socket '%s'\", opt_socket_name);\n                break;\n            case 'U':\n                opt_socket_name = NULL;\n                break;\n            case 'e':\n                opt_dev_name = optarg;\n                set_dev = 1;\n                debug(\"using emulation device '%s'\", opt_dev_name);\n                break;\n            case 'E':\n                opt_dev_name = NULL;\n                set_dev = 0;\n                break;\n            case 'o':\n                pwd  = getpwnam(optarg);\n                if (pwd == NULL) {\n                    error(\"invalid user name '%s'\\n\", optarg);\n                    exit(EXIT_FAILURE);\n                }\n                opt_uid = pwd->pw_uid;\n                break;\n            case 'g':\n                grp  = getgrnam(optarg);\n                if (grp == NULL) {\n                    error(\"invalid group name '%s'\\n\", optarg);\n                    exit(EXIT_FAILURE);\n                }\n                opt_gid = grp->gr_gid;\n                break;\n            case 'c':\n                tpm_config = strtol(optarg, NULL, 0);\n                debug(\"tpm_config = %04x\", tpm_config);\n                break;\n            case '?':\n                error(\"unknown option '-%c'\", optopt);\n                print_usage(argv[0]);\n                exit(EXIT_FAILURE);\n            case 'h':\n            default:\n                print_usage(argv[0]);\n                exit(EXIT_SUCCESS);\n        }\n    }\n\n    if (set_dev == 0 && access(opt_dev_name, F_OK) < 0)\n        opt_dev_name = NULL;\n    if (!opt_socket_name && !opt_dev_name) {\n            error(\"both socket and emulator device are unavailable\\n\");\n            print_usage(argv[0]);\n            exit(EXIT_FAILURE);\n    }\n\n    if (optind < argc) {\n        debug(\"startup mode = '%s'\", argv[optind]);\n        if (!strcmp(argv[optind], \"clear\")) {\n            tpm_startup = 1;\n        } else if (!strcmp(argv[optind], \"save\")) {\n            tpm_startup = 2;\n        } else if (!strcmp(argv[optind], \"deactivated\")) {\n            tpm_startup = 3;\n        } else {\n            error(\"invalid startup mode '%s'; must be 'clear', \"\n                  \"'save' (default) or 'deactivated\", argv[optind]);\n            print_usage(argv[0]);\n            exit(EXIT_SUCCESS);\n        }\n    } else {\n        /* if no startup mode is given assume save if a configuration\n           file is available, clear otherwise */\n        int fh = open(tpm_storage_file, O_RDONLY);\n        if (fh < 0) {\n            tpm_startup = 1;\n            info(\"no startup mode was specified; asuming 'clear'\");\n        } else {\n            tpm_startup = 2;\n            close(fh);\n        }\n    }\n}\n\nstatic void switch_uid_gid(void)\n{\n    if (opt_gid != getgid()) {\n        info(\"switching effective group ID to %d\", opt_gid);\n        if (setgid(opt_gid) == -1) {\n            error(\"switching effective group ID to %d failed: %s\", opt_gid, strerror(errno));\n            exit(EXIT_FAILURE);\n        }\n    }\n    if (opt_uid != getuid()) {\n        info(\"switching effective user ID to %d\", opt_uid);\n        if (setuid(opt_uid) == -1) {\n            error(\"switching effective user ID to %d failed: %s\", opt_uid, strerror(errno));\n            exit(EXIT_FAILURE);\n        }\n    }\n}\n\nstatic void signal_handler(int sig)\n{\n    info(\"signal received: %d\", sig);\n    if (sig == SIGTERM || sig == SIGQUIT || sig == SIGINT) stopflag = 1;\n}\n\nstatic void init_signal_handler(void)\n{\n    info(\"installing signal handlers\");\n    if (signal(SIGTERM, signal_handler) == SIG_ERR) {\n        error(\"signal(SIGTERM) failed: %s\", strerror(errno));\n        exit(EXIT_FAILURE);\n    }\n    if (signal(SIGQUIT, signal_handler) == SIG_ERR) {\n        error(\"signal(SIGQUIT) failed: %s\", strerror(errno));\n        exit(EXIT_FAILURE);\n    }\n    if (signal(SIGINT, signal_handler) == SIG_ERR) {\n        error(\"signal(SIGINT) failed: %s\", strerror(errno));\n        exit(EXIT_FAILURE);\n    }\n    if (signal(SIGPIPE, signal_handler) == SIG_ERR) {\n        error(\"signal(SIGPIPE) failed: %s\", strerror(errno));\n        exit(EXIT_FAILURE);\n    }\n}\n\nstatic void daemonize(void)\n{\n    pid_t sid, pid, fd;\n    info(\"daemonizing process\");\n    pid = fork();\n    if (pid < 0) {\n        error(\"fork() failed: %s\", strerror(errno));\n        exit(EXIT_FAILURE);\n    }\n    if (pid > 0) exit(EXIT_SUCCESS);\n    pid = getpid();\n    sid = setsid();\n    if (sid < 0) {\n        error(\"setsid() failed: %s\", strerror(errno));\n        exit(EXIT_FAILURE);\n    }\n    if (chdir(\"/\") < 0) {\n        error(\"chdir() failed: %s\", strerror(errno));\n        exit(EXIT_FAILURE);\n    }\n\n    fd = open(\"/dev/null\", O_RDWR);\n    if (fd < 0) {\n        error(\"open(/dev/null) failed: %s\\n\", strerror(errno));\n        exit(EXIT_FAILURE);\n    }\n    dup2(fd, STDIN_FILENO);\n    dup2(fd, STDOUT_FILENO);\n    dup2(fd, STDERR_FILENO);\n    close(fd);\n    is_daemon = 1;\n    info(\"process was successfully daemonized: pid=%d sid=%d\", pid, sid);\n}\n\nstatic int mkdirs(const char *path)\n{\n    char *copy = strdup(path);\n    char *p = strchr(copy + 1, '/');\n    while (p != NULL) {\n        *p = '\\0';\n        if ((mkdir(copy, 0755) == -1) && (errno != EEXIST)) {\n            free(copy);\n            return errno;\n        }\n        *p = '/';\n        p = strchr(p + 1, '/');\n    }\n    free(copy);\n    return 0;\n}\n\nstatic int init_socket(const char *name)\n{\n    int sock;\n    struct sockaddr_un addr;\n    info(\"initializing socket %s\", name);\n    sock = socket(AF_UNIX, SOCK_STREAM, 0);\n    if (sock < 0) {\n        error(\"socket(AF_UNIX) failed: %s\", strerror(errno));\n        return -1;\n    }\n    mkdirs(name);\n    addr.sun_family = AF_UNIX;\n    strncpy(addr.sun_path, name, sizeof(addr.sun_path)-1);\n    umask(0177);\n    if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) {\n        error(\"bind(%s) failed: %s\", addr.sun_path, strerror(errno));\n        close(sock);\n        return -1;\n    }\n    listen(sock, 1);\n    return sock;\n}\n\nstatic int init_device(const char *name)\n{\n    int devfd, flags;\n\n    info(\"initializing device %s\", name);\n    devfd = open(name, O_RDWR);\n    if (devfd < 0) {\n        error(\"open(%s) failed: %s\", name, strerror(errno));\n        return -1;\n    }\n\n    flags = fcntl(devfd, F_GETFL);\n    if (flags == -1) {\n        error(\"fcntl(%s, F_GETFL) failed: %s\", name, strerror(errno));\n        close(devfd);\n        return -1;\n    }\n    if (fcntl(devfd, F_SETFL, flags | O_NONBLOCK) == -1) {\n        error(\"fcntl(%s, F_SETFL) failed: %s\", name, strerror(errno));\n        close(devfd);\n        return -1;\n    }\n\n    return devfd;\n}\n\nstatic int handle_emuldev_command(int devfd)\n{\n    ssize_t in_len;\n    uint32_t out_len;\n    uint8_t in[TPM_CMD_BUF_SIZE], *out;\n    int res;\n\n    debug(\"waiting for commands...\");\n    in_len = read(devfd, in, sizeof(in));\n    debug(\"received %d bytes\", in_len);\n    if (in_len <= 0)\n        return errno == -EAGAIN ? 0 : in_len;\n\n    out = NULL;\n    res = tpm_handle_command(in, in_len, &out, &out_len);\n    if (res < 0) {\n        error(\"tpm_handle_command() failed\");\n        if (ioctl(devfd, 0, 0) < 0)\n            return -1;\n    } else {\n        debug(\"sending %d bytes\", out_len);\n        res = write(devfd, out, out_len);\n        if (res < 0) {\n            error(\"write(%d) failed: %s\", out_len, strerror(errno));\n            if (errno != ECANCELED)\n                return -1;\n        }\n    }\n    tpm_free(out);\n    return 0;\n}\n\nstatic void main_loop(void)\n{\n    int sock = -1, devfd = -1, fh, res, npoll;\n    int32_t in_len;\n    uint32_t out_len;\n    uint8_t in[TPM_CMD_BUF_SIZE], *out;\n    struct sockaddr_un addr;\n    socklen_t addr_len;\n    struct pollfd poll_table[2];\n\n    info(\"staring main loop\");\n    /* open UNIX socket */\n    if (opt_socket_name) {\n        sock = init_socket(opt_socket_name);\n        if (sock < 0) exit(EXIT_FAILURE);\n    }\n\n    if (opt_dev_name) {\n        devfd = init_device(opt_dev_name);\n        if (devfd < 0)\n            exit(EXIT_FAILURE);\n    }\n\n    /* init tpm emulator */\n    debug(\"initializing TPM emulator\");\n    if (tpm_emulator_init(tpm_startup, tpm_config) != 0) {\n        error(\"tpm_emulator_init() failed\");\n        if (sock >= 0)\n            close(sock);\n        if (opt_socket_name)\n            unlink(opt_socket_name);\n        exit(EXIT_FAILURE);\n    }\n\n    /* start command processing */\n    while (!stopflag) {\n        /* wait for incomming connections */\n        debug(\"waiting for connections...\");\n        npoll = 0;\n        if (sock != -1) {\n            poll_table[npoll].fd = sock;\n            poll_table[npoll].events = POLLIN;\n            poll_table[npoll++].revents = 0;\n        }\n        if (devfd != -1) {\n            poll_table[npoll].fd = devfd;\n            poll_table[npoll].events = POLLIN | POLLERR;\n            poll_table[npoll++].revents = 0;\n        }\n        res = poll(poll_table, npoll, -1);\n        if (res < 0) {\n            error(\"poll(sock,dev) failed: %s\", strerror(errno));\n            break;\n        }\n\n        if (devfd != -1 && poll_table[npoll - 1].revents) {\n            /* if POLLERR was set, let read() handle it */\n            if (handle_emuldev_command(devfd) < 0)\n                break;\n        }\n        if (sock == -1 || !poll_table[0].revents)\n            continue;\n\n        /* Beyond this point, npoll will always be 1 if the emulator device is\n         * not open and 2 if it is, so we can just fill in the second slot of\n         * the poll table unconditionally and rely on passing npoll to poll().\n         */\n\n        addr_len = sizeof(addr);\n        fh = accept(sock, (struct sockaddr*)&addr, &addr_len);\n        if (fh < 0) {\n            error(\"accept() failed: %s\", strerror(errno));\n            continue;\n        }\n        /* receive and handle commands */\n        in_len = 0;\n        do {\n            debug(\"waiting for commands...\");\n            poll_table[0].fd = fh;\n            poll_table[0].events = POLLIN;\n            poll_table[0].revents = 0;\n            poll_table[1].fd = devfd;\n            poll_table[1].events = POLLIN | POLLERR;\n            poll_table[1].revents = 0;\n\n            res = poll(poll_table, npoll, TPM_COMMAND_TIMEOUT);\n            if (res < 0) {\n                error(\"poll(fh) failed: %s\", strerror(errno));\n                break;\n            } else if (res == 0) {\n#ifdef TPMD_DISCONNECT_IDLE_CLIENTS\n                info(\"connection closed due to inactivity\");\n                break;\n#else\n                continue;\n#endif\n            }\n\n            if (devfd != -1 && poll_table[1].revents) {\n                /* if POLLERR was set, let read() handle it */\n                if (handle_emuldev_command(devfd) < 0)\n                    break;\n            }\n            if (!poll_table[0].revents)\n                continue;\n\n            in_len = read(fh, in, sizeof(in));\n            if (in_len > 0) {\n                debug(\"received %d bytes\", in_len);\n                out = NULL;\n                res = tpm_handle_command(in, in_len, &out, &out_len);\n                if (res < 0) {\n                    error(\"tpm_handle_command() failed\");\n                } else {\n                    debug(\"sending %d bytes\", out_len);\n                    uint32_t len = 0;\n                    while (len < out_len) {\n                        res = write(fh, &out[len], out_len - len);\n                        if (res < 0) {\n                            error(\"write(%d) failed: %s\",\n                                  out_len - len, strerror(errno));\n                            break;\n                        }\n                        len += res;\n                    }\n                    tpm_free(out);\n                }\n            }\n        } while (in_len > 0);\n        close(fh);\n    }\n    /* shutdown tpm emulator */\n    tpm_emulator_shutdown();\n    /* close socket */\n    if (sock >= 0)\n        close(sock);\n    if (opt_socket_name)\n        unlink(opt_socket_name);\n    if (devfd >= 0)\n        close(devfd);\n    info(\"main loop stopped\");\n}\n\nint main(int argc, char **argv)\n{\n    openlog(argv[0], 0, LOG_DAEMON);\n    setlogmask(~LOG_MASK(LOG_DEBUG));\n    syslog(LOG_INFO, \"--- separator ---\\n\");\n    tpm_log = my_log;\n    info(\"starting TPM Emulator daemon (1.2.%d.%d-%d)\",\n         VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD);\n    parse_options(argc, argv);\n    /* switch uid/gid if required */\n    switch_uid_gid();\n    /* init signal handlers */\n    init_signal_handler();\n    /* unless requested otherwiese, fork and daemonize process */\n    if (!opt_foreground) daemonize();\n    /* start main processing loop */\n    main_loop();\n    info(\"stopping TPM Emulator daemon\");\n    closelog();\n    return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "tpmd/windows/CMakeLists.txt",
    "content": "# Software-based Trusted Platform Module (TPM) Emulator\n# Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n#\n# $Id: CMakeLists.txt 464 2011-07-09 14:57:41Z mast $\n\ninclude_directories(\"${PROJECT_SOURCE_DIR}/tpm\")\n\nfile(GLOB tpmd_SRCS \"*.[h|c]\")\nadd_executable(tpmd ${tpmd_SRCS})\nif(MTM_EMULATOR)\nadd_definitions(-DMTM_EMULATOR)\ntarget_link_libraries(tpmd mtm tpm tpm_crypto)\nelse()\ntarget_link_libraries(tpmd tpm tpm_crypto)\nendif()\ninstall(TARGETS tpmd RUNTIME DESTINATION .)\n\ninstall(FILES control_tpmd.bat DESTINATION .)\n\n"
  },
  {
    "path": "tpmd/windows/control_tpmd.bat",
    "content": ":: Software-based Trusted Platform Module (TPM) Emulator\r\n:: Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\r\n::\r\n:: $Id: CMakeLists.txt 390 2010-02-18 10:04:12Z mast $\r\n\r\n@echo off\r\n\r\nset SERVICE_ID=tpmd\r\nset SERVICE_NAME=TPM Emulator\r\nset SERVICE_DIR=%~dp0\r\nset SERVICE_EXE=%SERVICE_DIR%\\tpmd.exe\r\n\r\nif /i \"%1\" == \"\"        goto usage\r\nif /i \"%1\" == \"install\" goto install\r\nif /i \"%1\" == \"remove\"  goto remove\r\nif /i \"%1\" == \"start\"   goto start\r\nif /i \"%1\" == \"stop\"    goto stop\r\nif /i \"%1\" == \"status\"  goto status\r\ngoto usage\r\n\r\n:usage\r\necho Usage: %0 (install, remove, start, stop, status)\r\ngoto :eof\r\n\r\n:install\r\nif not exist \"%SERVICE_EXE%\" goto missing\r\nsc create %SERVICE_ID% binpath= \"%SERVICE_EXE% \\\"%SERVICE_CONF%\\\"\" DisplayName= \"%SERVICE_NAME%\" start= demand\r\ngoto :eof\r\n:missing\r\necho \"Error: file '%SERVICE_EXE%' does not exists.\"\r\ngoto :eof\r\n\r\n:remove\r\nsc delete %SERVICE_ID%\r\ngoto :eof\r\n\r\n:start\r\nsc start %SERVICE_ID%\r\ngoto :eof\r\n\r\n:stop\r\nsc stop %SERVICE_ID%\r\ngoto :eof\r\n\r\n:status\r\nsc query %SERVICE_ID%\r\ngoto :eof\r\n\r\n"
  },
  {
    "path": "tpmd/windows/tpmd.c",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n * Copyright (C) 2009 Domenic Schroeder\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: tpmd.c 389 2010-02-18 09:52:11Z mast $\n */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <unistd.h>\n#include <string.h>\n#include <errno.h>\n#include <stdarg.h>\n#include <fcntl.h>\n#include <sys/stat.h>\n#include <sys/time.h>\n#include <time.h>\n#include <windows.h>\n#include <wincrypt.h>\n#include \"config.h\"\n#include \"tpm/tpm_emulator.h\"\n\n#define SERVICE_NAME \"tpmd\"\n\nstatic volatile int stopflag = 0;\nstatic int is_service = 0;\nstatic int opt_debug = 0;\nstatic int opt_foreground = 0;\nstatic const char *opt_pipe_name = TPM_DEVICE_NAME;\nstatic int tpm_startup = 2;\nstatic uint32_t tpm_config = 0;\nextern const char *tpm_storage_file;\nextern const char *tpm_log_file;\nstatic SERVICE_STATUS_HANDLE status_handle;\nstatic DWORD current_status;\n\nvoid my_log(int priority, const char *fmt, ...)\n{\n    FILE *fh;\n    va_list ap, bp;\n    time_t tv;\n    struct tm t;\n    time(&tv);\n    memcpy(&t, localtime(&tv), sizeof(t));\n    va_start(ap, fmt);\n    va_copy(bp, ap);\n    fh = fopen(tpm_log_file, \"a\");\n    if (fh != NULL) {\n        fprintf(fh, \"%04d-%02d-%02d %02d:%02d:%02d \",\n            t.tm_year + 1900, t.tm_mon + 1, t.tm_mday,\n            t.tm_hour, t.tm_min, t.tm_sec);\n        vfprintf(fh, fmt, ap);\n        fclose(fh);\n    }\n    va_end(ap);\n    if (!is_service && (priority != TPM_LOG_DEBUG || opt_debug)) {\n        printf(\"%04d-%02d-%02d %02d:%02d:%02d \",\n            t.tm_year + 1900, t.tm_mon + 1, t.tm_mday,\n            t.tm_hour, t.tm_min, t.tm_sec);\n        vprintf(fmt, bp);\n    }\n    va_end(bp);\n}\n\nstatic void print_usage(char *name)\n{\n    printf(\"usage: %s [-d] [-f] [-s storage file] [-u windows pipe name] \"\n           \"[-l log file] [-h] [startup mode]\\n\", name);\n    printf(\"  d : enable debug mode\\n\");\n    printf(\"  f : forces the application to run in the foreground\\n\");\n    printf(\"  s : storage file to use (default: %s)\\n\", tpm_storage_file);\n    printf(\"  u : windows named pipe name to use (default: %s)\\n\", opt_pipe_name);\n    printf(\"  l : name of the log file (default: %s)\\n\", tpm_log_file);\n    printf(\"  h : print this help message\\n\");\n    printf(\"  startup mode : must be 'clear', \"\n           \"'save' (default) or 'deactivated\\n\");\n}\n\nstatic int parse_options(int argc, char **argv)\n{\n    char c;\n    info(\"parsing options\");\n    while ((c = getopt (argc, argv, \"dfs:u:o:g:c:h\")) != -1) {\n        debug(\"handling option '-%c'\", c);\n        switch (c) {\n            case 'd':\n                opt_debug = 1;\n                debug(\"debug mode enabled\");\n                break;\n            case 'f':\n                debug(\"application is forced to run in foreground\");\n                opt_foreground = 1;\n                break;\n            case 's':\n                tpm_storage_file = optarg;\n                debug(\"using storage file '%s'\", tpm_storage_file);\n                break;\n            case 'u':\n                opt_pipe_name = optarg;\n                debug(\"using named pipe '%s'\", opt_pipe_name);\n                break;\n            case 'l':\n                tpm_log_file = optarg;\n                debug(\"using log file '%s'\", tpm_log_file);\n                break;\n            case 'c':\n                tpm_config = strtol(optarg, NULL, 0);\n                break;\n            case '?':\n                error(\"unknown option '-%c'\", optopt);\n                print_usage(argv[0]);\n                return -1;\n            case 'h':\n            default:\n                print_usage(argv[0]);\n                return -1;\n        }\n    }\n    if (optind < argc && argv[optind][0] != 0) {\n        debug(\"startup mode = '%s'\", argv[optind]);\n        if (!strcmp(argv[optind], \"clear\")) {\n            tpm_startup = 1;\n        } else if (!strcmp(argv[optind], \"save\")) {\n            tpm_startup = 2;\n        } else if (!strcmp(argv[optind], \"deactivated\")) {\n            tpm_startup = 3;\n        } else {\n            error(\"invalid startup mode '%s'; must be 'clear', \"\n                  \"'save' (default) or 'deactivated\", argv[optind]);\n            print_usage(argv[0]);\n            return 0;\n        }\n    } else {\n        /* if no startup mode is given assume save if a configuration\n           file is available, clear otherwise */\n        int fh = open(tpm_storage_file, O_RDONLY);\n        if (fh < 0) {\n            tpm_startup = 1;\n            info(\"no startup mode was specified; asuming 'clear'\");\n        } else {\n            tpm_startup = 2;\n            close(fh);\n        }\n    }\n    return 0;\n}\n\nstatic const char *get_error(void)\n{\n    static char buf[512];\n    memset(buf, 0, sizeof(buf));\n    FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,\n                  \"\", GetLastError(), 0, buf, sizeof(buf), NULL);\n    return buf;\n}\n\nBOOL signal_handler(DWORD event)\n{\n    info(\"signal received: %d\", event);\n    stopflag = 1;\n    /* unblock ConnectNamedPipe() */\n    HANDLE ph = CreateFile(opt_pipe_name, GENERIC_READ | GENERIC_WRITE,\n        0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);\n    if (ph != INVALID_HANDLE_VALUE) CloseHandle(ph);\n    return TRUE;\n}\n\nstatic int init_signal_handler(void)\n{\n    info(\"installing signal handler\");\n    if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE)signal_handler,TRUE)) {\n        error(\"SetConsoleCtrlHandler() failed: %s\", get_error());\n        return -1;\n    }\n    return 0;\n}\n\nstatic void main_loop(void)\n{\n    HANDLE ph;\n    DWORD in_len;\n    uint32_t out_len;\n    BYTE in[TPM_CMD_BUF_SIZE];\n    uint8_t *out;\n\n    info(\"staring main loop\");\n    /* open named pipe */\n    ph = CreateNamedPipe(opt_pipe_name, PIPE_ACCESS_DUPLEX,\n      PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,\n      PIPE_UNLIMITED_INSTANCES, TPM_CMD_BUF_SIZE,\n      TPM_CMD_BUF_SIZE, 0, NULL);\n    if (ph == INVALID_HANDLE_VALUE) {\n        error(\"CreateNamedPipe() failed: %s\", get_error());\n        return;\n    }\n    /* init tpm emulator */\n    debug(\"initializing TPM emulator\");\n    if (tpm_emulator_init(tpm_startup, tpm_config) != 0) {\n        error(\"tpm_emulator_init() failed\");\n        CloseHandle(ph);\n        return;\n    }\n    /* start command processing */\n    while (!stopflag) {\n        /* wait for incomming connections */\n        debug(\"waiting for connections...\");\n        if (!ConnectNamedPipe(ph, NULL)) {\n            error(\"ConnectNamedPipe() failed: %s\", get_error());\n            break;\n        }\n        if (stopflag) break;\n        /* receive and handle commands */\n        in_len = 0;\n        do {\n            if (!ReadFile(ph, in, sizeof(in), &in_len, NULL)) {\n                error(\"ReadFile() failed: %s\", get_error());\n            }\n            if (in_len > 0) {\n                debug(\"received %d bytes\", in_len);\n                out = NULL;\n                if (tpm_handle_command(in, in_len, &out, &out_len) != 0) {\n                    error(\"tpm_handle_command() failed\");\n                } else {\n                    debug(\"sending %d bytes\", out_len);\n                    DWORD res, len = 0;\n                    while (len < out_len) {\n                        if (!WriteFile(ph, out, out_len, &res, NULL)) {\n                            error(\"WriteFile(%d) failed: %s\",\n                                  out_len - len, strerror(errno));\n                            break;\n                        }\n                        len += res;\n                    }\n                    tpm_free(out);\n                }\n            }\n        } while (in_len > 0 && !stopflag);\n        DisconnectNamedPipe(ph);\n    }\n    /* shutdown tpm emulator */\n    tpm_emulator_shutdown();\n    /* close socket */\n    CloseHandle(ph);\n    info(\"main loop stopped\");\n}\n\nBOOL updateServiceStatus(DWORD currentState, DWORD winExitCode,\n                         DWORD exitCode, DWORD checkPoint, DWORD waitHint)\n{ \n   SERVICE_STATUS status;\n  \n   /* if this is a service update the status, otherwise return success */\n   if (!is_service) return TRUE;\n   current_status = currentState;\n   status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;\n   status.dwCurrentState = currentState;\n   /* once the service is up and running, it accepts\n      the events stop and shutdown */\n   if (currentState == SERVICE_START_PENDING) {\n      status.dwControlsAccepted = 0;\n   } else {\n      status.dwControlsAccepted = SERVICE_ACCEPT_STOP \n                                  | SERVICE_ACCEPT_SHUTDOWN;\n   }\n   status.dwWin32ExitCode = winExitCode;\n   status.dwServiceSpecificExitCode = exitCode;\n   status.dwCheckPoint = checkPoint;\n   status.dwWaitHint = waitHint;\n   return SetServiceStatus(status_handle, &status);\n}\n\nvoid serviceCtrlHandler(DWORD code)\n{\n    switch (code) {\n        /* stop service if told so or in the case of a system shutdown */\n        case SERVICE_CONTROL_STOP:\n        case SERVICE_CONTROL_SHUTDOWN:\n            updateServiceStatus(SERVICE_STOP_PENDING, NO_ERROR, 0, 1, 5000);\n            signal_handler(CTRL_CLOSE_EVENT);\n            break;\n        /* report the current status of the service to the SCM */\n        case SERVICE_CONTROL_INTERROGATE:\n            updateServiceStatus(current_status, NO_ERROR, 0, 0, 0);\n            break;\n    }\n}\n\nvoid serviceMain(int argc, char **argv)\n{\n    info(\"starting TPM Emulator daemon (1.2.%d.%d-%d)\",\n         VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD);\n    /* first of all register the control handler function of the service */\n    if (is_service) {\n        status_handle = RegisterServiceCtrlHandler(\n            SERVICE_NAME, (LPHANDLER_FUNCTION)serviceCtrlHandler);\n    }\n    if (argc > 0 && parse_options(argc, argv) != 0) {\n        updateServiceStatus(SERVICE_STOPPED,\n                            ERROR_SERVICE_SPECIFIC_ERROR, 1, 0, 0);\n        return;\n    }\n    tpm_log = my_log;\n    /* init signal handler */\n    if (init_signal_handler() != 0) {\n        updateServiceStatus(SERVICE_STOPPED,\n                            ERROR_SERVICE_SPECIFIC_ERROR, 1, 0, 0);\n        return;\n    }\n    /* start main processing loop */\n    updateServiceStatus(SERVICE_RUNNING, NO_ERROR, 0, 0, 0);\n    main_loop();\n    info(\"stopping TPM Emulator daemon\");\n    updateServiceStatus(SERVICE_STOPPED, NO_ERROR, 0, 0, 0);\n}\n\nint main(int argc, char **argv)\n{\n    if (parse_options(argc, argv) != 0) return EXIT_FAILURE;\n    if (opt_foreground) {\n        is_service = 0;\n        serviceMain(0, NULL);\n        return EXIT_SUCCESS;\n    } else {\n        SERVICE_TABLE_ENTRY service_table[] = {\n            { (LPTSTR)SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION)serviceMain },\n            { NULL, NULL } };\n        is_service = 1;\n        StartServiceCtrlDispatcher(service_table);\n        return GetLastError();\n    }\n}\n\n"
  },
  {
    "path": "tpmd_dev/CMakeLists.txt",
    "content": "# Software-based Trusted Platform Module (TPM) Emulator\n# Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n#\n# $Id: CMakeLists.txt 453 2010-09-11 11:00:58Z mast $\n\n# select matching module sources\nif(CMAKE_SYSTEM_NAME STREQUAL \"Linux\")\n\nset(tpmd_dev_SOURCE_DIR \"${CMAKE_CURRENT_SOURCE_DIR}/linux\")\nset(tpmd_dev_BINARY_DIR \"${CMAKE_CURRENT_BINARY_DIR}/linux\")\nset(tpmd_dev_OBJ \"${tpmd_dev_BINARY_DIR}/tpmd_dev.ko\")\nif(CMAKE_COMPILER_IS_GNUCC)\n  set(tpmd_dev_BUILD_CMD make -C ${tpmd_dev_BINARY_DIR} CC=${CMAKE_C_COMPILER} LD=${CMAKE_LINKER})\n  set(tpmd_dev_INSTALL_CMD make -C ${tpmd_dev_BINARY_DIR} CC=${CMAKE_C_COMPILER} LD=${CMAKE_LINKER} install)\nelse()\n  set(tpmd_dev_BUILD_CMD make -C ${tpmd_dev_BINARY_DIR})\n  set(tpmd_dev_INSTALL_CMD make -C ${tpmd_dev_BINARY_DIR} install)\nendif()\n\nelseif(CMAKE_SYSTEM_NAME STREQUAL \"OpenBSD\")\n\nset(tpmd_dev_SOURCE_DIR \"${CMAKE_CURRENT_SOURCE_DIR}/openbsd\")\nset(tpmd_dev_BINARY_DIR \"${CMAKE_CURRENT_BINARY_DIR}/openbsd\")\nset(tpmd_dev_OBJ \"${tpmd_dev_BINARY_DIR}/tpmd_dev.o\")\nset(tpmd_dev_BUILD_CMD gmake -C ${tpmd_dev_BINARY_DIR})\nset(tpmd_dev_INSTALL_CMD gmake -C ${tpmd_dev_BINARY_DIR} install)\n\nelseif(CMAKE_SYSTEM_NAME STREQUAL \"Darwin\")\n\nset(tpmd_dev_SOURCE_DIR \"${CMAKE_CURRENT_SOURCE_DIR}/darwin\")\nset(tpmd_dev_BINARY_DIR \"${CMAKE_CURRENT_BINARY_DIR}/darwin\")\nset(tpmd_dev_OBJ \"${tpmd_dev_BINARY_DIR}/build/Release/tpm_bridge.kext\")\nset(tpmd_dev_BUILD_CMD make -C ${tpmd_dev_BINARY_DIR})\nset(tpmd_dev_INSTALL_CMD make -C ${tpmd_dev_BINARY_DIR} install)\n\nendif()\n\n# compile module\nif(tpmd_dev_OBJ)\n\nfile(GLOB tpmd_dev_SRCS \"${tpmd_dev_SOURCE_DIR}/*\")\n\nadd_custom_command(OUTPUT ${tpmd_dev_OBJ}\n                   COMMAND cp -rf ${tpmd_dev_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}\n                   COMMAND cp ${CMAKE_BINARY_DIR}/config.h ${tpmd_dev_BINARY_DIR}\n                   COMMAND ${tpmd_dev_BUILD_CMD}\n                   DEPENDS ${tpmd_dev_SRCS})\n\nadd_custom_target(tpmd_dev ALL DEPENDS ${tpmd_dev_OBJ})\n\ninstall(CODE \"EXECUTE_PROCESS(COMMAND ${tpmd_dev_INSTALL_CMD})\")\n\nendif()\n\n"
  },
  {
    "path": "tpmd_dev/darwin/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>English</string>\n\t<key>CFBundleExecutable</key>\n\t<string>tpm_bridge</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>com.osxbook.kext.tpmbridge</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>TPM Emulator Bridge</string>\n\t<key>CFBundlePackageType</key>\n\t<string>KEXT</string>\n\t<key>CFBundleVersion</key>\n\t<string>1.0.0d1</string>\n\t<key>NSHumanReadableCopyright</key>\n\t<string>© Amit Singh, 2009-2010</string>\n\t<key>OSBundleLibraries</key>\n\t<dict>\n\t\t<key>com.apple.kpi.bsd</key>\n\t\t<string>9.0.0</string>\n\t\t<key>com.apple.kpi.libkern</key>\n\t\t<string>9.0.0</string>\n\t</dict>\n</dict>\n</plist>\n"
  },
  {
    "path": "tpmd_dev/darwin/Makefile",
    "content": "# Software-based Trusted Platform Module (TPM) Emulator\n# Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n#\n# $Id: Makefile 423 2010-02-22 16:32:22Z mast $\n\nKEXT_NAME = tpm_bridge.kext\nKEXT_BIN  = build/Release/$(KEXT_NAME)\nKEXT_DIR  = $(DESTDIR)/System/Library/Extensions\n\nall:\n\t@xcodebuild > /dev/null\n\nclean:\n\t@xcodebuild clean > /dev/null\n\nTPM_OWNER ?= root\nTPM_GROUP ?= wheel\n\ninstall: $(KEXT_BIN)\n\t@mkdir -p $(KEXT_DIR)\n\t@cp -Rp $(KEXT_BIN) $(KEXT_DIR)\n\t@chown -R $(TPM_OWNER):$(TPM_GROUP) $(KEXT_DIR)/$(KEXT_NAME)\n\n.PHONY: all clean install\n"
  },
  {
    "path": "tpmd_dev/darwin/tpm_bridge.c",
    "content": "/*\n * Copyright (c) 2009-2010 Amit Singh. All Rights Reserved.\n * http://osxbook.com\n *\n * TPM Emulator Device Bridge for Mac OS X\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n *   1. Redistributions of source code must retain the above copyright notice,\n *      this list of conditions and the following disclaimer.\n *   2. Redistributions in binary form must reproduce the above copyright\n *      notice, this list of conditions and the following disclaimer in the\n *      documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR “AS IS” AND ANY EXPRESS OR IMPLIED\n * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO\n * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\n * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <sys/types.h>\n#include <sys/fcntl.h>\n#include <sys/systm.h>\n#include <sys/conf.h>\n#include <sys/ioctl.h>\n#include <sys/param.h>\n#include <sys/unistd.h>\n#include <sys/malloc.h>\n#include <sys/kpi_socket.h>\n#include <sys/kpi_mbuf.h>\n#include <sys/un.h>\n#include <kern/locks.h>\n#include <miscfs/devfs/devfs.h>\n#include <mach/mach_types.h>\n#include <libkern/OSAtomic.h>\n#include \"config.h\"\n\n/* configurable */\n\n#define TPM_BRIDGE_NAME    \"tpm\"     /* bridge device file name (/dev/tpm) */\n#define TPM_BRIDGE_MODE    0666      /* world readable/writable by default */\n#define TPM_BRIDGE_UID     UID_ROOT  /* bridge device file owner ID */\n#define TPM_BRIDGE_GID     GID_WHEEL /* bridge device file group ID */\n\n/* buffer */\n\nstatic char tpm_buffer[TPM_CMD_BUF_SIZE] = { 0 };\n\n/* locking */\n\nstatic lck_grp_attr_t* tpm_mtx_grp_attr = NULL;\nstatic lck_grp_t*      tpm_mtx_grp = NULL;\nstatic lck_attr_t*     tpm_mtx_attr = NULL;\nstatic lck_mtx_t*      tpm_mtx = NULL;\n\n/* user socket */\n\nerrno_t sock_nointerrupt(socket_t sock, int on);\n\nstatic SInt32   tpm_activity = 0;\nstatic UInt32   tpm_in_io = 0;\nstatic socket_t tpmd_socket = 0;\n\nstatic struct sockaddr_un tpmd_socket_addr = {\n    sizeof(struct sockaddr_un),\n    AF_LOCAL,\n    TPM_SOCKET_NAME,\n};\n\n/* device */\n\nstatic int       dev_tpm_index = -1;\nstatic const int dev_tpm_minor = 0;\nstatic void*     dev_tpm_node = NULL;\n\nd_open_t   tpm_dev_open;\nd_read_t   tpm_dev_read;\nd_write_t  tpm_dev_write;\nextern int seltrue(dev_t, int, struct proc*);\n\nstatic struct cdevsw cdev_tpm = {\n    tpm_dev_open,\n    (d_close_t*)&nulldev,\n    tpm_dev_read,\n    tpm_dev_write,\n    (d_ioctl_t*)&enodev,\n    (d_stop_t*)&nulldev,\n    (d_reset_t*)&nulldev,\n    0,\n    (select_fcn_t*)seltrue,\n    eno_mmap,\n    eno_strat,\n    eno_getc,\n    eno_putc,\n    D_TTY,\n};\n\nstatic int    tpmd_connect(void);\nstatic void   tpmd_disconnect(void);\nkern_return_t tpm_bridge_start(kmod_info_t* ki, void* d);\nkern_return_t tpm_bridge_stop(kmod_info_t* ki, void* d);\nstatic int    tpm_bridge_locking_start(void);\nstatic int    tpm_bridge_locking_stop(void);\nstatic int    tpm_bridge_devfs_start(void);\nstatic int    tpm_bridge_devfs_stop(void);\n\nint\ntpm_dev_open(dev_t dev, int flags, int devtype, struct proc* p)\n{\n    (void)OSIncrementAtomic(&tpm_activity);\n\n    int error = 0;\n\n    lck_mtx_lock(tpm_mtx);\n\n    if ((tpmd_socket == NULL) || !sock_isconnected(tpmd_socket)) {\n        if (tpmd_connect() != 0) {\n            tpmd_socket = NULL;\n            lck_mtx_unlock(tpm_mtx);\n            error = ECONNREFUSED;\n            goto out;\n        }\n    }\n\n    lck_mtx_unlock(tpm_mtx);\n\nout:\n\n    (void)OSDecrementAtomic(&tpm_activity);\n    \n    return error;\n}\n\nint \ntpm_dev_read(dev_t dev, struct uio* uio, int ioflag)\n{\n    (void)OSIncrementAtomic(&tpm_activity);\n\n    errno_t error = 0;\n    size_t recvlen;\n    struct msghdr msg;\n    struct iovec aiov[1];\n\n    lck_mtx_lock(tpm_mtx);\n\n    if ((tpmd_socket == NULL) || !sock_isconnected(tpmd_socket)) {\n        lck_mtx_unlock(tpm_mtx);\n        error = ENOTCONN;\n        goto out;\n    }\n\n    if (tpm_in_io) {\n        error = msleep(&tpm_in_io, tpm_mtx, PCATCH, \"tpm_in_io\", NULL);\n        if (error != 0) {\n            lck_mtx_unlock(tpm_mtx);\n            error = EAGAIN;\n            goto out;\n        }\n    }\n\n    tpm_in_io = 1;\n\n    lck_mtx_unlock(tpm_mtx);\n\n    (void)sock_nointerrupt(tpmd_socket, 1);\n\n    recvlen = (uint32_t)uio_resid(uio);\n\n    memset(&msg, 0, sizeof(msg));\n    aiov[0].iov_base = (caddr_t)tpm_buffer;\n    aiov[0].iov_len = TPM_CMD_BUF_SIZE;\n    if (recvlen < TPM_CMD_BUF_SIZE) {\n        aiov[0].iov_len = recvlen;\n    }\n    msg.msg_iovlen = 1;\n    msg.msg_iov = aiov;\n\n    if ((error = sock_receive(tpmd_socket, &msg, 0, (size_t*)&recvlen)) == 0) {\n        error = uiomove64((addr64_t)(uintptr_t)tpm_buffer, (int)recvlen, uio);\n    }\n\n    lck_mtx_lock(tpm_mtx);\n    tpm_in_io = 0;\n    wakeup_one((caddr_t)&tpm_in_io);\n    lck_mtx_unlock(tpm_mtx);\n\nout:\n\n    (void)OSDecrementAtomic(&tpm_activity);\n\n    return error;\n}\n\nint                           \ntpm_dev_write(dev_t dev, struct uio* uio, int ioflag)\n{\n    (void)OSIncrementAtomic(&tpm_activity);\n\n    errno_t error = 0;\n    size_t sentlen;\n    struct msghdr msg;\n    struct iovec aiov[1];\n\n    lck_mtx_lock(tpm_mtx);\n\n    if ((tpmd_socket == NULL) || !sock_isconnected(tpmd_socket)) {\n        lck_mtx_unlock(tpm_mtx);\n        error = ENOTCONN;\n        goto out;\n    }\n\n    if (tpm_in_io) {\n        error = msleep(&tpm_in_io, tpm_mtx, PCATCH, \"tpm_in_io\", NULL);\n        if (error != 0) {\n            lck_mtx_unlock(tpm_mtx);\n            error = EAGAIN;\n            goto out;\n        }\n    }\n\n    tpm_in_io = 1;\n\n    lck_mtx_unlock(tpm_mtx);\n\n    sentlen = min((uint32_t)uio_resid(uio), TPM_CMD_BUF_SIZE);\n\n    if ((error = uiomove64((addr64_t)(uintptr_t)tpm_buffer,\n                           (int)sentlen, uio)) == 0) {\n        memset(&msg, 0, sizeof(msg));\n        aiov[0].iov_base = (caddr_t)tpm_buffer;\n        aiov[0].iov_len = sentlen;\n        msg.msg_iovlen = 1;\n        msg.msg_iov = aiov;\n        error = sock_send(tpmd_socket, &msg, 0, &sentlen);\n    }\n\n    lck_mtx_lock(tpm_mtx);\n    tpm_in_io = 0;\n    wakeup_one((caddr_t)&tpm_in_io);\n    lck_mtx_unlock(tpm_mtx);\n\nout:\n\n    (void)OSDecrementAtomic(&tpm_activity);\n\n    return error;\n}\n\nstatic int\ntpmd_connect(void)\n{\n    errno_t error;\n    struct timeval tv;\n\n    error = sock_socket(PF_LOCAL, SOCK_STREAM, 0, NULL, NULL, &tpmd_socket);\n    if (error != 0) {\n        tpmd_socket = NULL;\n        return error;\n    }\n\n    tv.tv_sec = 10;\n    tv.tv_usec = 0;\n    error = sock_setsockopt(tpmd_socket, SOL_SOCKET, SO_RCVTIMEO, &tv,\n                            sizeof(struct timeval));\n    if (error != 0) {\n        sock_close(tpmd_socket);\n        tpmd_socket = NULL;\n        return error;\n    }\n\n    error = sock_connect(tpmd_socket,\n                         (const struct sockaddr*)&tpmd_socket_addr, 0);\n    if (error != 0) {\n        sock_close(tpmd_socket);\n        tpmd_socket = NULL;\n        return error;\n    }\n\n    return 0;\n}\n\nstatic void\ntpmd_disconnect(void)\n{\n    if (tpmd_socket != NULL) {\n        sock_shutdown(tpmd_socket, SHUT_RDWR);\n        sock_close(tpmd_socket);\n        tpmd_socket = NULL;\n    }\n}\n\nstatic int\ntpm_bridge_locking_start(void)\n{\n    tpm_mtx_grp_attr = lck_grp_attr_alloc_init();\n    if (tpm_mtx_grp_attr == NULL) {\n        goto failed;\n    }\n\n    tpm_mtx_grp = lck_grp_alloc_init(\"tpm_mtx\", tpm_mtx_grp_attr);\n    if (tpm_mtx_grp == NULL) {\n        goto failed;\n    }\n\n    tpm_mtx_attr = lck_attr_alloc_init();\n    if (tpm_mtx_attr == NULL) {\n        goto failed;\n    }\n\n    tpm_mtx = lck_mtx_alloc_init(tpm_mtx_grp, tpm_mtx_attr);\n    if (tpm_mtx == NULL) {\n        goto failed;\n    }\n\n    return KERN_SUCCESS;\n\nfailed:\n\n    (void)tpm_bridge_locking_stop();\n\n    return KERN_FAILURE;\n}\n\nstatic int\ntpm_bridge_locking_stop(void)\n{\n    if (tpm_mtx != NULL) {\n        lck_mtx_free(tpm_mtx, tpm_mtx_grp);\n        tpm_mtx = NULL;\n    }\n\n    if (tpm_mtx_attr != NULL) {\n        lck_attr_free(tpm_mtx_attr);\n        tpm_mtx_attr = NULL;\n    }\n\n    if (tpm_mtx_grp != NULL) {\n        lck_grp_free(tpm_mtx_grp);\n        tpm_mtx_grp = NULL;\n    }\n\n    if (tpm_mtx_grp_attr != NULL) {\n        lck_grp_attr_free(tpm_mtx_grp_attr);\n        tpm_mtx_grp_attr = NULL;\n    }\n\n    return KERN_SUCCESS;\n}\n\nstatic int\ntpm_bridge_devfs_start(void)\n{\n    dev_tpm_index = cdevsw_add(-1, &cdev_tpm);\n    if (dev_tpm_index == -1) {\n        return KERN_FAILURE;\n    }\n\n    dev_tpm_node = devfs_make_node(makedev(dev_tpm_index, dev_tpm_minor),\n                                   DEVFS_CHAR, TPM_BRIDGE_UID, TPM_BRIDGE_GID,\n                                   TPM_BRIDGE_MODE, TPM_BRIDGE_NAME);\n    if (dev_tpm_node == NULL) {\n        (void)tpm_bridge_devfs_stop();\n        return KERN_FAILURE;\n    }\n\n    return KERN_SUCCESS;\n}\n\nstatic int\ntpm_bridge_devfs_stop(void)\n{\n    int ret = KERN_SUCCESS;\n\n    if (dev_tpm_node != NULL) {\n        devfs_remove(dev_tpm_node);\n        dev_tpm_node = NULL;\n    }\n\n    if (dev_tpm_index != -1) {\n        ret = cdevsw_remove(dev_tpm_index, &cdev_tpm);\n        if (ret != dev_tpm_index) {\n            ret = KERN_FAILURE;\n        } else {\n            dev_tpm_index = -1;\n            ret = KERN_SUCCESS;\n        }\n    }\n\n    return ret;\n}\n\nkern_return_t\ntpm_bridge_start(kmod_info_t* ki, void* d)\n{\n    if (tpm_bridge_locking_start() != KERN_SUCCESS) {\n        return KERN_FAILURE;\n    }\n\n    if (tpm_bridge_devfs_start() != KERN_SUCCESS) {\n        tpm_bridge_locking_stop();\n        return KERN_FAILURE;\n    }\n\n#ifndef SUN_LEN\n#define SUN_LEN(su) \\\n        (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))\n#define SUN_LEN_PRIVATELY_DEFINED 1\n#endif\n\n    tpmd_socket_addr.sun_len = SUN_LEN(&tpmd_socket_addr);\n\n#if SUN_LEN_PRIVATELY_DEFINED\n#undef SUN_LEN\n#endif\n\n    return KERN_SUCCESS;\n}\n\nkern_return_t\ntpm_bridge_stop(kmod_info_t* ki, void* d)\n{\n    lck_mtx_lock(tpm_mtx);\n\n    (void)tpm_bridge_devfs_stop();\n\n    if ((tpmd_socket != NULL) && sock_isconnected(tpmd_socket)) {\n        tpmd_disconnect();\n        tpmd_socket = NULL;\n    }\n\n    lck_mtx_unlock(tpm_mtx);\n\n    do {\n        struct timespec ts = { 1, 0 };\n        (void)msleep(&tpm_activity, NULL, PUSER, \"tpm_activity\", &ts);\n    } while (tpm_activity > 0);\n\n\n    (void)tpm_bridge_locking_stop();\n\n    return KERN_SUCCESS;\n}\n"
  },
  {
    "path": "tpmd_dev/darwin/tpm_bridge.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t32A4FEBC0562C75700D090E7 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C167DFE841241C02AAC07 /* InfoPlist.strings */; };\n\t\t32A4FEBE0562C75700D090E7 /* tpm_bridge.c in Sources */ = {isa = PBXBuildFile; fileRef = 1A224C3CFF42312311CA2CB7 /* tpm_bridge.c */; settings = {ATTRIBUTES = (); }; };\n/* End PBXBuildFile section */\n\n/* Begin PBXFileReference section */\n\t\t089C167EFE841241C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = \"<group>\"; };\n\t\t1A224C3CFF42312311CA2CB7 /* tpm_bridge.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tpm_bridge.c; sourceTree = \"<group>\"; };\n\t\t32A4FEC30562C75700D090E7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\t32A4FEC40562C75800D090E7 /* tpm_bridge.kext */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = tpm_bridge.kext; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tD27513B306A6225300ADB3A4 /* Kernel.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Kernel.framework; path = /System/Library/Frameworks/Kernel.framework; sourceTree = \"<absolute>\"; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\t32A4FEBF0562C75700D090E7 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t089C166AFE841209C02AAC07 /* tpm_bridge */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t247142CAFF3F8F9811CA285C /* Source */,\n\t\t\t\t089C167CFE841241C02AAC07 /* Resources */,\n\t\t\t\tD27513B306A6225300ADB3A4 /* Kernel.framework */,\n\t\t\t\t19C28FB6FE9D52B211CA2CBB /* Products */,\n\t\t\t);\n\t\t\tname = tpm_bridge;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t089C167CFE841241C02AAC07 /* Resources */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t32A4FEC30562C75700D090E7 /* Info.plist */,\n\t\t\t\t089C167DFE841241C02AAC07 /* InfoPlist.strings */,\n\t\t\t);\n\t\t\tname = Resources;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t19C28FB6FE9D52B211CA2CBB /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t32A4FEC40562C75800D090E7 /* tpm_bridge.kext */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t247142CAFF3F8F9811CA285C /* Source */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t1A224C3CFF42312311CA2CB7 /* tpm_bridge.c */,\n\t\t\t);\n\t\t\tname = Source;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXHeadersBuildPhase section */\n\t\t32A4FEBA0562C75700D090E7 /* Headers */ = {\n\t\t\tisa = PBXHeadersBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXHeadersBuildPhase section */\n\n/* Begin PBXNativeTarget section */\n\t\t32A4FEB80562C75700D090E7 /* tpm_bridge */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 1DEB91C308733DAC0010E9CD /* Build configuration list for PBXNativeTarget \"tpm_bridge\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t32A4FEBA0562C75700D090E7 /* Headers */,\n\t\t\t\t32A4FEBB0562C75700D090E7 /* Resources */,\n\t\t\t\t32A4FEBD0562C75700D090E7 /* Sources */,\n\t\t\t\t32A4FEBF0562C75700D090E7 /* Frameworks */,\n\t\t\t\t32A4FEC00562C75700D090E7 /* Rez */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = tpm_bridge;\n\t\t\tproductInstallPath = \"$(SYSTEM_LIBRARY_DIR)/Extensions\";\n\t\t\tproductName = tpm_bridge;\n\t\t\tproductReference = 32A4FEC40562C75800D090E7 /* tpm_bridge.kext */;\n\t\t\tproductType = \"com.apple.product-type.kernel-extension\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\t089C1669FE841209C02AAC07 /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tLastUpgradeCheck = 0420;\n\t\t\t};\n\t\t\tbuildConfigurationList = 1DEB91C708733DAC0010E9CD /* Build configuration list for PBXProject \"tpm_bridge\" */;\n\t\t\tcompatibilityVersion = \"Xcode 3.2\";\n\t\t\tdevelopmentRegion = English;\n\t\t\thasScannedForEncodings = 1;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t);\n\t\t\tmainGroup = 089C166AFE841209C02AAC07 /* tpm_bridge */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\t32A4FEB80562C75700D090E7 /* tpm_bridge */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\t32A4FEBB0562C75700D090E7 /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t32A4FEBC0562C75700D090E7 /* InfoPlist.strings in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXRezBuildPhase section */\n\t\t32A4FEC00562C75700D090E7 /* Rez */ = {\n\t\t\tisa = PBXRezBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXRezBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\t32A4FEBD0562C75700D090E7 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t32A4FEBE0562C75700D090E7 /* tpm_bridge.c in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin PBXVariantGroup section */\n\t\t089C167DFE841241C02AAC07 /* InfoPlist.strings */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t089C167EFE841241C02AAC07 /* English */,\n\t\t\t);\n\t\t\tname = InfoPlist.strings;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXVariantGroup section */\n\n/* Begin XCBuildConfiguration section */\n\t\t1DEB91C408733DAC0010E9CD /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_MODEL_TUNING = G5;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\t\"HEADER_SEARCH_PATHS[arch=*]\" = (\n\t\t\t\t\t\"./**\",\n\t\t\t\t\t\"/usr/local/include/**\",\n\t\t\t\t\t\"/opt/local/include/**\",\n\t\t\t\t\t\"../**\",\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = Info.plist;\n\t\t\t\tINSTALL_PATH = \"$(SYSTEM_LIBRARY_DIR)/Extensions\";\n\t\t\t\t\"LIBRARY_SEARCH_PATHS[arch=*]\" = (\n\t\t\t\t\t\"/opt/local/lib/**\",\n\t\t\t\t\t\"/usr/local/lib/**\",\n\t\t\t\t);\n\t\t\t\tMODULE_NAME = com.yourcompany.kext.tpm_bridge;\n\t\t\t\tMODULE_START = tpm_bridge_start;\n\t\t\t\tMODULE_STOP = tpm_bridge_stop;\n\t\t\t\tMODULE_VERSION = 1.0.0d1;\n\t\t\t\tPRODUCT_NAME = tpm_bridge;\n\t\t\t\tWRAPPER_EXTENSION = kext;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t1DEB91C508733DAC0010E9CD /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tGCC_MODEL_TUNING = G5;\n\t\t\t\t\"HEADER_SEARCH_PATHS[arch=*]\" = (\n\t\t\t\t\t\"/opt/local/include/**\",\n\t\t\t\t\t\"/usr/local/include/**\",\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = Info.plist;\n\t\t\t\tINSTALL_PATH = \"$(SYSTEM_LIBRARY_DIR)/Extensions\";\n\t\t\t\t\"LIBRARY_SEARCH_PATHS[arch=*]\" = (\n\t\t\t\t\t\"/opt/local/lib/**\",\n\t\t\t\t\t\"/usr/local/lib/**\",\n\t\t\t\t);\n\t\t\t\tMODULE_NAME = com.yourcompany.kext.tpm_bridge;\n\t\t\t\tMODULE_START = tpm_bridge_start;\n\t\t\t\tMODULE_STOP = tpm_bridge_stop;\n\t\t\t\tMODULE_VERSION = 1.0.0d1;\n\t\t\t\tPRODUCT_NAME = tpm_bridge;\n\t\t\t\tWRAPPER_EXTENSION = kext;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t1DEB91C808733DAC0010E9CD /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tARCHS = \"$(ARCHS_STANDARD)\";\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = c99;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;\n\t\t\t\tGCC_TREAT_NONCONFORMANT_CODE_ERRORS_AS_WARNINGS = YES;\n\t\t\t\tGCC_TREAT_WARNINGS_AS_ERRORS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_MISSING_NEWLINE = YES;\n\t\t\t\tGCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES;\n\t\t\t\tGCC_WARN_CHECK_SWITCH_STATEMENTS = YES;\n\t\t\t\tGCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;\n\t\t\t\tGCC_WARN_MISSING_PARENTHESES = YES;\n\t\t\t\tGCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES;\n\t\t\t\tGCC_WARN_PROTOTYPE_CONVERSION = NO;\n\t\t\t\tGCC_WARN_SHADOW = YES;\n\t\t\t\tGCC_WARN_SIGN_COMPARE = YES;\n\t\t\t\tGCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES;\n\t\t\t\tGCC_WARN_UNKNOWN_PRAGMAS = YES;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_LABEL = YES;\n\t\t\t\tGCC_WARN_UNUSED_PARAMETER = NO;\n\t\t\t\tGCC_WARN_UNUSED_VALUE = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tSDKROOT = macosx;\n\t\t\t\t\"SDKROOT[arch=x86_64]\" = macosx10.6;\n\t\t\t\tSTRINGS_FILE_OUTPUT_ENCODING = \"UTF-8\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t1DEB91C908733DAC0010E9CD /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tARCHS = \"$(ARCHS_STANDARD)\";\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = c99;\n\t\t\t\tGCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;\n\t\t\t\tGCC_TREAT_NONCONFORMANT_CODE_ERRORS_AS_WARNINGS = YES;\n\t\t\t\tGCC_TREAT_WARNINGS_AS_ERRORS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_MISSING_NEWLINE = YES;\n\t\t\t\tGCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES;\n\t\t\t\tGCC_WARN_CHECK_SWITCH_STATEMENTS = YES;\n\t\t\t\tGCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;\n\t\t\t\tGCC_WARN_MISSING_PARENTHESES = YES;\n\t\t\t\tGCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES;\n\t\t\t\tGCC_WARN_PROTOTYPE_CONVERSION = NO;\n\t\t\t\tGCC_WARN_SHADOW = YES;\n\t\t\t\tGCC_WARN_SIGN_COMPARE = YES;\n\t\t\t\tGCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES;\n\t\t\t\tGCC_WARN_UNKNOWN_PRAGMAS = YES;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_LABEL = YES;\n\t\t\t\tGCC_WARN_UNUSED_PARAMETER = NO;\n\t\t\t\tGCC_WARN_UNUSED_VALUE = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tSDKROOT = macosx;\n\t\t\t\t\"SDKROOT[arch=x86_64]\" = macosx10.6;\n\t\t\t\tSTRINGS_FILE_OUTPUT_ENCODING = \"UTF-8\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t1DEB91C308733DAC0010E9CD /* Build configuration list for PBXNativeTarget \"tpm_bridge\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t1DEB91C408733DAC0010E9CD /* Debug */,\n\t\t\t\t1DEB91C508733DAC0010E9CD /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t1DEB91C708733DAC0010E9CD /* Build configuration list for PBXProject \"tpm_bridge\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t1DEB91C808733DAC0010E9CD /* Debug */,\n\t\t\t\t1DEB91C908733DAC0010E9CD /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = 089C1669FE841209C02AAC07 /* Project object */;\n}\n"
  },
  {
    "path": "tpmd_dev/darwin/tpm_bridge.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:tpm_bridge.xcodeproj\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "tpmd_dev/darwin/tpm_bridge.xcodeproj/project.xcworkspace/xcuserdata/admin.xcuserdatad/WorkspaceSettings.xcsettings",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>IDEWorkspaceUserSettings_HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges</key>\n\t<true/>\n\t<key>IDEWorkspaceUserSettings_SnapshotAutomaticallyBeforeSignificantChanges</key>\n\t<true/>\n</dict>\n</plist>\n"
  },
  {
    "path": "tpmd_dev/darwin/tpm_bridge.xcodeproj/xcuserdata/admin.xcuserdatad/xcschemes/tpm_bridge.xcscheme",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   version = \"1.3\">\n   <BuildAction\n      parallelizeBuildables = \"YES\"\n      buildImplicitDependencies = \"YES\">\n      <BuildActionEntries>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"32A4FEB80562C75700D090E7\"\n               BuildableName = \"tpm_bridge.kext\"\n               BlueprintName = \"tpm_bridge\"\n               ReferencedContainer = \"container:tpm_bridge.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n      </BuildActionEntries>\n   </BuildAction>\n   <TestAction\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.GDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.GDB\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      buildConfiguration = \"Debug\">\n      <Testables>\n      </Testables>\n   </TestAction>\n   <LaunchAction\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.GDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.GDB\"\n      launchStyle = \"0\"\n      useCustomWorkingDirectory = \"NO\"\n      buildConfiguration = \"Debug\"\n      debugDocumentVersioning = \"YES\"\n      allowLocationSimulation = \"YES\">\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </LaunchAction>\n   <ProfileAction\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      savedToolIdentifier = \"\"\n      useCustomWorkingDirectory = \"NO\"\n      buildConfiguration = \"Release\"\n      debugDocumentVersioning = \"YES\">\n   </ProfileAction>\n   <AnalyzeAction\n      buildConfiguration = \"Debug\">\n   </AnalyzeAction>\n   <ArchiveAction\n      buildConfiguration = \"Release\"\n      revealArchiveInOrganizer = \"YES\">\n   </ArchiveAction>\n</Scheme>\n"
  },
  {
    "path": "tpmd_dev/darwin/tpm_bridge.xcodeproj/xcuserdata/admin.xcuserdatad/xcschemes/xcschememanagement.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>SchemeUserState</key>\n\t<dict>\n\t\t<key>tpm_bridge.xcscheme</key>\n\t\t<dict>\n\t\t\t<key>orderHint</key>\n\t\t\t<integer>0</integer>\n\t\t</dict>\n\t</dict>\n\t<key>SuppressBuildableAutocreation</key>\n\t<dict>\n\t\t<key>32A4FEB80562C75700D090E7</key>\n\t\t<dict>\n\t\t\t<key>primary</key>\n\t\t\t<true/>\n\t\t</dict>\n\t</dict>\n</dict>\n</plist>\n"
  },
  {
    "path": "tpmd_dev/linux/Makefile",
    "content": "# Software-based Trusted Platform Module (TPM) Emulator\n# Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n#\n# $Id: Makefile 364 2010-02-11 10:24:45Z mast $\n\n# kernel settingsRCH settings\nARCH\t\t?= $(shell uname -m)\n\nKERNEL_RELEASE := $(shell uname -r)\nKERNEL_BUILD   ?= /lib/modules/$(KERNEL_RELEASE)/build\nMOD_SUBDIR     := misc\n\n# module settings\nMODULE_NAME    := tpmd_dev\nobj-m          := $(MODULE_NAME).o\n\n# do not print \"Entering directory ...\"\nMAKEFLAGS      += --no-print-directory\nEXTRA_CFLAGS   += -Wall -Werror\n\nall:\n\t@$(MAKE) LD=$(LD) CC=$(CC) ARCH=$(ARCH) -C $(KERNEL_BUILD) M=$(CURDIR) modules\n\nclean:\n\t@$(MAKE) LD=$(LD) CC=$(CC) ARCH=$(ARCH) -C $(KERNEL_BUILD) M=$(CURDIR) clean\n\t@rm -f Modules.symvers tpmd_dev.rules\n\nTPM_GROUP ?= tss\nINSTALL ?= install\n\ntpmd_dev.rules: tpmd_dev.rules.in\n\t@sed -e \"s/\\$$TPM_GROUP/$(TPM_GROUP)/g\" tpmd_dev.rules.in > tpmd_dev.rules\n\ninstall: tpmd_dev.rules\n\t@$(MAKE) LD=$(LD) CC=$(CC) ARCH=$(ARCH) -C $(KERNEL_BUILD) M=$(CURDIR) INSTALL_MOD_PATH=$(DESTDIR) modules_install\n\t@$(INSTALL) -m 644 -D tpmd_dev.rules $(DESTDIR)/etc/udev/rules.d/80-tpmd_dev.rules\n\n.PHONY: all clean install\n\n"
  },
  {
    "path": "tpmd_dev/linux/tpmd_dev.c",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id: tpmd_dev.c 469 2011-09-15 15:14:13Z mast $\n */\n\n#include <linux/module.h>\n#include <linux/kernel.h>\n#include <linux/init.h>\n#include <linux/miscdevice.h>\n#include <linux/poll.h>\n#include <linux/slab.h>\n\n#include <linux/socket.h>\n#include <linux/net.h>\n#include <linux/un.h>\n\n#include <linux/version.h>\n\n#include \"config.h\"\n\n#define TPM_DEVICE_MINOR  224\n#define TPM_DEVICE_ID     \"tpm\"\n#define TPM_MODULE_NAME   \"tpmd_dev\"\n\n#define TPM_STATE_IS_OPEN 0\n\n#ifdef DEBUG\n#define debug(fmt, ...) printk(KERN_DEBUG \"%s %s:%d: Debug: \" fmt \"\\n\", \\\n                        TPM_MODULE_NAME, __FILE__, __LINE__, ## __VA_ARGS__)\n#else\n#define debug(fmt, ...)\n#endif\n#define info(fmt, ...)  printk(KERN_INFO \"%s %s:%d: Info: \" fmt \"\\n\", \\\n                        TPM_MODULE_NAME, __FILE__, __LINE__, ## __VA_ARGS__)\n#define error(fmt, ...) printk(KERN_ERR \"%s %s:%d: Error: \" fmt \"\\n\", \\\n                        TPM_MODULE_NAME, __FILE__, __LINE__, ## __VA_ARGS__)\n#define alert(fmt, ...) printk(KERN_ALERT \"%s %s:%d: Alert: \" fmt \"\\n\", \\\n                        TPM_MODULE_NAME, __FILE__, __LINE__, ## __VA_ARGS__)\n\nMODULE_LICENSE(\"GPL\");\nMODULE_AUTHOR(\"Mario Strasser <mast@gmx.net>\");\nMODULE_DESCRIPTION(\"Trusted Platform Module (TPM) Emulator\");\nMODULE_SUPPORTED_DEVICE(TPM_DEVICE_ID);\n\n/* module parameters */\nchar *tpmd_socket_name = TPM_SOCKET_NAME;\nmodule_param(tpmd_socket_name, charp, 0444);\nMODULE_PARM_DESC(tpmd_socket_name, \" Sets the name of the TPM daemon socket.\");\n\n/* TPM lock */\nstatic struct semaphore tpm_mutex;\n\n/* TPM request buffer */\nstatic char req_buf[TPM_CMD_BUF_SIZE];\n\n/* TPM command response */\nstatic struct {\n  uint8_t *data;\n  uint32_t size;\n} tpm_response;\n\n/* module state */\nstatic uint32_t module_state;\nstatic struct socket *tpmd_sock;\nstatic struct sockaddr_un addr;\n\nstatic int tpmd_connect(char *socket_name)\n{\n  int res;\n  res = sock_create(PF_UNIX, SOCK_STREAM, 0, &tpmd_sock);\n  if (res != 0) {\n    error(\"sock_create() failed: %d\\n\", res);\n    tpmd_sock = NULL;\n    return res;\n  }\n  addr.sun_family = AF_UNIX;\n  strncpy(addr.sun_path, socket_name, sizeof(addr.sun_path)-1);\n  res = tpmd_sock->ops->connect(tpmd_sock,\n    (struct sockaddr*)&addr, sizeof(struct sockaddr_un), 0);\n  if (res != 0) {\n    error(\"sock_connect() failed: %d\\n\", res);\n    sock_release(tpmd_sock);\n    tpmd_sock = NULL;\n    return res;\n  }\n  return 0;\n}\n\nstatic void tpmd_disconnect(void)\n{\n  if (tpmd_sock != NULL) sock_release(tpmd_sock);\n  tpmd_sock = NULL;\n}\n\nstatic int tpmd_handle_command(const uint8_t *in, uint32_t in_size)\n{\n  int res;\n  struct msghdr msg;\n  struct kvec vec;\n  /* send command to tpmd */\n  memset(&msg, 0, sizeof(msg));\n  vec.iov_base = (void*)in;\n  vec.iov_len = in_size;\n  res = kernel_sendmsg(tpmd_sock, &msg, &vec, 1, in_size);\n  if (res < 0) {\n    error(\"sock_sendmsg() failed: %d\\n\", res);\n    return res;\n  }\n  /* receive response from tpmd */\n  tpm_response.size = TPM_CMD_BUF_SIZE;\n  tpm_response.data = kmalloc(tpm_response.size, GFP_KERNEL);\n  if (tpm_response.data == NULL) return -1;\n  memset(&msg, 0, sizeof(msg));\n  vec.iov_base = (void*)tpm_response.data;\n  vec.iov_len = tpm_response.size;\n  res = kernel_recvmsg(tpmd_sock, &msg, &vec, 1, tpm_response.size, 0);\n  if (res < 0) {\n    error(\"sock_recvmsg() failed: %d\\n\", res);\n    tpm_response.data = NULL;\n    return res;\n  }\n  tpm_response.size = res;\n  return 0;\n}\n\nstatic int tpm_open(struct inode *inode, struct file *file)\n{\n  int res;\n  debug(\"%s()\", __FUNCTION__);\n  if (test_and_set_bit(TPM_STATE_IS_OPEN, (void*)&module_state)) return -EBUSY;\n  down(&tpm_mutex);\n  res = tpmd_connect(tpmd_socket_name);\n  up(&tpm_mutex);\n  if (res != 0) {\n    clear_bit(TPM_STATE_IS_OPEN, (void*)&module_state);\n    return -EIO;\n  }\n  return 0;\n}\n\nstatic int tpm_release(struct inode *inode, struct file *file)\n{\n  debug(\"%s()\", __FUNCTION__);\n  down(&tpm_mutex);\n  if (tpm_response.data != NULL) {\n    kfree(tpm_response.data);\n    tpm_response.data = NULL;\n  }\n  tpmd_disconnect();\n  up(&tpm_mutex);\n  clear_bit(TPM_STATE_IS_OPEN, (void*)&module_state);\n  return 0;\n}\n\nstatic ssize_t tpm_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)\n{\n  debug(\"%s(%zd)\", __FUNCTION__, count);\n  down(&tpm_mutex);\n  if (tpm_response.data != NULL) {\n    count = min(count, (size_t)tpm_response.size - (size_t)*ppos);\n    count -= copy_to_user(buf, &tpm_response.data[*ppos], count);\n    *ppos += count;\n    if ((size_t)tpm_response.size == (size_t)*ppos) {\n      kfree(tpm_response.data);\n      tpm_response.data = NULL;\n    }\n  } else {\n    count = 0;\n  }\n  up(&tpm_mutex);\n  return count;\n}\n\nstatic ssize_t tpm_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)\n{\n  debug(\"%s(%zd)\", __FUNCTION__, count);\n\n  if (count > sizeof(req_buf))\n    return -EFAULT;\n\n  down(&tpm_mutex);\n  *ppos = 0;\n  if (tpm_response.data != NULL) {\n    kfree(tpm_response.data);\n    tpm_response.data = NULL;\n  }\n\n  if (copy_from_user(req_buf, buf, count)) {\n    up(&tpm_mutex);\n    return -EFAULT;\n  }\n\n  if (tpmd_handle_command(req_buf, count) != 0) {\n    count = -EILSEQ;\n    tpm_response.data = NULL;\n  }\n  up(&tpm_mutex);\n  return count;\n}\n\n#define TPMIOC_CANCEL   _IO('T', 0x00)\n#define TPMIOC_TRANSMIT _IO('T', 0x01)\n\nstatic long tpm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)\n{\n  debug(\"%s(%d, %p)\", __FUNCTION__, cmd, (char*)arg);\n  if (cmd == TPMIOC_TRANSMIT) {\n    uint32_t count;\n\n    if (get_user(count, (uint32_t __user *)(arg+2)))\n      return -EFAULT;\n\n    count = be32_to_cpu(count);\n    if (count > sizeof(req_buf))\n      return -EFAULT;\n\n    down(&tpm_mutex);\n    if (copy_from_user(req_buf, (void __user *)arg, count)) {\n      up(&tpm_mutex);\n      return -EFAULT;\n    }\n\n    if (tpm_response.data != NULL) {\n      kfree(tpm_response.data);\n      tpm_response.data = NULL;\n    }\n    if (tpmd_handle_command(req_buf, count) == 0) {\n      tpm_response.size -= copy_to_user((char*)arg, tpm_response.data, tpm_response.size);\n      kfree(tpm_response.data);\n      tpm_response.data = NULL;\n    } else {\n      tpm_response.size = 0;\n      tpm_response.data = NULL;\n    }\n    up(&tpm_mutex);\n    return tpm_response.size;\n  }\n  return -1;\n}\n\nstruct file_operations fops = {\n  .owner   = THIS_MODULE,\n  .open    = tpm_open,\n  .release = tpm_release,\n  .read    = tpm_read,\n  .write   = tpm_write,\n  .unlocked_ioctl = tpm_ioctl,\n};\n\nstatic struct miscdevice tpm_dev = {\n  .minor      = TPM_DEVICE_MINOR,\n  .name       = TPM_DEVICE_ID,\n  .fops       = &fops,\n};\n\nint __init init_tpm_module(void)\n{\n  int res = misc_register(&tpm_dev);\n  if (res != 0) {\n    error(\"misc_register() failed for minor %d\\n\", TPM_DEVICE_MINOR);\n    return res;\n  }\n  /* initialize variables */\n  sema_init(&tpm_mutex, 1);\n  module_state = 0;\n  tpm_response.data = NULL;\n  tpm_response.size = 0;\n  tpmd_sock = NULL;\n  return 0;\n}\n\nvoid __exit cleanup_tpm_module(void)\n{\n  misc_deregister(&tpm_dev);\n  tpmd_disconnect();\n  if (tpm_response.data != NULL) kfree(tpm_response.data);\n}\n\nmodule_init(init_tpm_module);\nmodule_exit(cleanup_tpm_module);\n\n"
  },
  {
    "path": "tpmd_dev/linux/tpmd_dev.rules.in",
    "content": "KERNEL==\"tpm\", NAME=\"%k\", SYMLINK+=\"tpm0\", GROUP=\"$TPM_GROUP\", MODE=\"0660\"\n"
  },
  {
    "path": "tpmd_dev/openbsd/Makefile",
    "content": "# Software-based Trusted Platform Module (TPM) Emulator\n# Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n# Copyright (C) 2007 Sebastian Schuetz <sebastian_schuetz@genua.de>\n#\n# $Id$\n\nCFLAGS= -D_KERNEL -I/usr/src/sys\nSRC=\ttpmd_dev.c\nOBJ=    tpmd_dev.obj\nMODULE= tpmd_dev.o\n\nall:\n\tcc -o $(OBJ) -c $(SRC) $(CFLAGS)\n\tld -r -o $(MODULE) $(OBJ)\n\nclean:\n\trm -rf $(OBJ)\n\trm -f $(MODULE)\n\nload:\tall mknod\n\tmodload -o tpm.o -etpm $(MODULE)\n\nunload: rknod\n\tmodunload -n tpm\n\nmknod:\n\tmknod -m 644 /dev/tpm c 29 0\n\nrmnod:\n\trm /dev/tpm\n\ninstall:\n\t\n"
  },
  {
    "path": "tpmd_dev/openbsd/tpmd_dev.c",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n * Copyright (C) 2007 Sebastian Schuetz <sebastian_schuetz@genua.de>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id$\n */\n\n#include <sys/param.h>\n#include <sys/fcntl.h>\n#include <sys/systm.h>\n#include <sys/ioctl.h>\n#include <sys/exec.h>\n#include <sys/conf.h>\n#include <sys/lkm.h>\n#include <sys/malloc.h>\n#include <sys/socket.h>\n#include <sys/mbuf.h>\n#include <sys/un.h>\n#include <sys/socketvar.h>\n#include <sys/errno.h>\n#include <sys/lock.h>\n#include <sys/proc.h>\n#include <machine/intr.h>\n\n#include \"tpmd_dev.h\"\n\n\nint\ttpmopen __P((dev_t dev, int oflags, int devtype, struct proc *p));\nint \ttpmclose __P((dev_t dev, int fflag, int devtype, struct proc *p));\nint\ttpmread __P((dev_t dev, struct uio *uio, int ioflag));\nint\ttpmioctl __P((dev_t dev, u_long cmd, caddr_t data, int fflag,\n\t\t\tstruct proc *p));\nint\ttpmwrite __P((dev_t dev,struct uio *uio, int ioflag));\nint\ttpm_handler __P((struct lkm_table *lkmtp, int cmd));\n\n\n/*\n * Provides a lkm which forwards all requests to /dev/tpm to\n * a local unix domain socket, reads the reply from the tpmd\n * and writes back to the user (tcsd)\n */\n\n\n\n\n/* declare our character device */\ncdev_decl(tpm);\n\n/* define our cdev struct containing the functions */\nstatic struct cdevsw cdev_tpm = cdev_tpmd_init(1,tpm);\n\n/* fill in the lkm_dev structure */\nMOD_DEV(\"tpm\",LM_DT_CHAR,-1,&cdev_tpm);\n\n\n/* code starts */\n\n/* test and set the bit bit on addy\n * there is no guarantee that this function\n * works on other purposes as the tpm_emulator\n */\nint\ntest_and_set_bit(uint32_t bit, uint32_t *addy)\n{\n\tint rbit = 0;\n\tuint32_t tmp, mask;\n\n\ttmp = *addy;\n\ttmp >>=bit;\n\tif (tmp & 0x1) {\n\t\trbit = 1;\n\t}\n\tmask = 1 << bit;\n\t*addy |= mask;\n\treturn rbit;\n}\n\nint\nclear_bit(uint32_t bit, uint32_t *addy)\n{\n\tuint32_t mask = 0x1;\n\n\tmask = ~(mask << bit);\n\t*addy &= mask;\n\n\treturn 0;\n}\n\n/*\n * create a connection to our local socket file\n * named by socket_name\n */\nstatic int\ntpmd_connect(char *socket_name)\n{\n\tint res;\n\tstruct sockaddr_un *saddr;\n\n\tdebug(\"%s()\", __FUNCTION__);\n\tres = socreate(AF_UNIX, &tpmd_sock, SOCK_STREAM, 0);\n\tif (res != 0) {\n\t\terror(\"sock_create() failed: %d\", res);\n\t\ttpmd_sock = NULL;\n\t\treturn res;\n\t}\n\tnm = m_get(M_WAITOK,M_MBUF);\n\tif (nm == NULL) {\n\t\terror(\"malloc() failed\");\n\t\treturn -1;\n\t}\n\tnm->m_len = sizeof(struct sockaddr_un);\n\tsaddr = mtod(nm, struct sockaddr_un *);\n\tsaddr->sun_family = AF_UNIX;\n\tsaddr->sun_len = sizeof(*saddr);\n\tstrlcpy(saddr->sun_path,socket_name,sizeof(saddr->sun_path));\n\tres = soconnect(tpmd_sock,nm);\n\tif (res != 0) {\n\t\terror(\"sock_connect() failed: %d\", res);\n\t\tm_free(nm);\n\t\tnm = NULL;\n\t\tsoclose(tpmd_sock);\n\t\ttpmd_sock = NULL;\n\t}\n\n\treturn res;\n}\n\n/*\n * shut down the socket and free the\n * mbuf struct\n */\nstatic void\ntpmd_disconnect(void)\n{\n\tdebug(\"%s()\",__FUNCTION__);\n\tif (tpmd_sock != NULL) {\n\t\tsoshutdown(tpmd_sock,SHUT_RDWR);\n\t\tsoclose(tpmd_sock);\n\t\ttpmd_sock = NULL;\n\t}\n\tif (nm != NULL) {\n\t\tm_free(nm);\n\t\tnm = NULL;\n\t}\n}\n\n\n\nint\noutputData(const char *str, uint8_t *d, int len)\n{\n\tint i = 0;\n\n\tprintf(\"%s\",str);\n\tfor (i = 0; i < len; i++) {\n\t\tprintf(\"%.2x \",d[i]);\n\t}\n\tprintf(\"\\n\");\n}\n\n\nint\ntpmopen(dev_t dev, int oflags, int devtype, struct proc *p)\n{\n\tdebug(\"%s()\", __FUNCTION__);\n\tsimple_lock(&slock);\n\tif (test_and_set_bit(TPM_STATE_IS_OPEN, (void*)&module_state))\n\t\treturn -EBUSY;\n\tif (tpmd_connect(tpmd_socket_name)) {\n\t\ttpmclose(dev,oflags,devtype,p);\n\t\tsimple_unlock(&slock);\n\t\treturn -1;\n\t}\n\tsimple_unlock(&slock);\n\tdebug(\"connected\");\n  \treturn 0;\n}\n\nint\ntpmclose(dev_t dev, int oflags, int devtype, struct proc *p)\n{\n\tsimple_lock(&slock);\n\tdebug(\"%s()\", __FUNCTION__);\n\ttpmd_disconnect();\n\tclear_bit(TPM_STATE_IS_OPEN, (void*)&module_state);\n\tsimple_unlock(&slock);\n\n\treturn 0;\n}\n\n\n/*\n *  read the data and write it back\n */\nint\ntpmread(dev_t dev, struct uio *uio, int ioflag)\n{\n\tint error;\n\tdebug(\"%s(%u)\",__FUNCTION__,uio->uio_resid);\n\tsimple_lock(&slock);\n\n\t/* this flag is neccessary, otherwise soreceive\n \t * sometime returns EINTR\n\t */\n\ttpmd_sock->so_rcv.sb_flags |= SB_NOINTR;\n\terror = soreceive(tpmd_sock,NULL,uio,NULL,NULL,NULL,0);\n\n\tif (error) {\n\t\tdebug(\"soreceive() failed %i\",error);\n\t}\n\tsimple_unlock(&slock);\n\n\treturn error;\n}\n\n/*\n * write the data through the socket\n */\nint\ntpmwrite(dev_t dev, struct uio *uio, int ioflag)\n{\n\tint error;\n\tdebug(\"%s(%d)\", __FUNCTION__, uio->uio_resid);\n\tsimple_lock(&slock);\n\n\t/* ok send the command to our socket */\n\tif (tpmd_sock == NULL ||\n \t    !(tpmd_sock->so_state & SS_ISCONNECTED)) {\n\t\treturn ENOTCONN;\n        }\n\terror = sosend(tpmd_sock, nm ,uio ,NULL,NULL,0);\n\tif (error) {\n\t\terror(\"sosend() failed %i\",error);\n\t\treturn error;\n        }\n\tsimple_unlock(&slock);\n\n\treturn error;\n}\n\n\n/*\n * The goal was not to do any \"tddl\" related modifications in trousers.\n * However I don`t  know how to get the correct len of our data without\n * modifying the trousers ioctl call. Well trousers provides some fallback to\n * read/write methods, so it is not that much important to provide some\n * ioctl infrastructure\n */\nint\ntpmioctl(dev_t dev, u_long cmd, caddr_t data, int fflag,struct proc *p)\n{\n\t/* tell trousers that this is not supported */\n\treturn ENODEV;\n}\n\n/* tpm_handler for loading/unloading */\nint\ntpm_handler(struct lkm_table *lkmtp, int cmd)\n{\n\tswitch (cmd) {\n\t\tcase LKM_E_LOAD:\n\t\t\tsimple_lock_init(&slock);\n\t\t\tbreak;\n\t\tcase LKM_E_UNLOAD:\n\t\t\tsimple_unlock(&slock);\n\t\t\ttpmclose(0,0,0,NULL);\n\t\t\tbreak;\n\t}\n\treturn 0;\n}\n\n/* our main entry point */\nint\ntpm(struct lkm_table *lkmtp, int cmd, int ver)\n{\n\tDISPATCH(lkmtp,cmd,ver,tpm_handler,tpm_handler,lkm_nofunc);\n}\n\n\n\n"
  },
  {
    "path": "tpmd_dev/openbsd/tpmd_dev.h",
    "content": "/* Software-based Trusted Platform Module (TPM) Emulator\n * Copyright (C) 2004-2010 Mario Strasser <mast@gmx.net>\n * Copyright (C) 2007 Sebastian Schuetz <sebastian_schuetz@genua.de>\n *\n * This module is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published\n * by the Free Software Foundation; either version 2 of the License,\n * or (at your option) any later version.\n *\n * This module is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * $Id$\n */\n\n#ifndef _TPM_DEV_HEADER_\n#define _TPM_DEV_HEADER_\n\n#include \"config.h\"\n\n#define cdev_tpmd_init(c,n) { \\\n    dev_init(c,n,open),dev_init(c,n,close),dev_init(c,n,read), \\\n    dev_init(c,n,write), dev_init(c,n,ioctl),(dev_type_stop((*))) lkmenodev, \\\n    0,(dev_type_poll((*))) lkmenodev,(dev_type_mmap((*))) lkmenodev }\n\n\n/* This code is from linux_module.c */\n\n/* module state */\nstatic uint32_t module_state;\nstatic struct socket *tpmd_sock = NULL;\nstatic struct mbuf *nm = NULL;\nstatic struct simplelock slock;\n\nchar tpmd_socket_name[] = TPM_SOCKET_NAME;\n\n#define TPM_MODULE_NAME   \"tpm_dev\"\n#define TPM_STATE_IS_OPEN 0\n\n\n#ifdef DEBUG\n#define debug(fmt, ...) printf(\"%s %s:%d: Debug: \" fmt \"\\n\", \\\n                        TPM_MODULE_NAME, __FILE__, __LINE__, ## __VA_ARGS__)\n#else\n#define debug(fmt, ...)\n#endif\n#define error(fmt, ...) printf(\"%s %s:%d: Error: \" fmt \"\\n\", \\\n                        TPM_MODULE_NAME, __FILE__, __LINE__, ## __VA_ARGS__)\n\n#endif /* _TPM_DEV_HEADER_ */\n"
  }
]